Skip to content

feat: [DSRN] Added TitleHub#1052

Merged
brianacnguyen merged 15 commits into
mainfrom
dsrn/titlehub
Apr 20, 2026
Merged

feat: [DSRN] Added TitleHub#1052
brianacnguyen merged 15 commits into
mainfrom
dsrn/titlehub

Conversation

@brianacnguyen

@brianacnguyen brianacnguyen commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds TitleHub to @metamask/design-system-react-native: a layout component for a title row, an optional amount line with optional amountAccessory, an optional bottom label row with bottomLabelAccessory, and an optional bottomAccessory when the bottom label row is not used.

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-674

Manual testing steps

  1. From the repo root, run React Native Storybook (e.g. yarn storybook:ios or yarn storybook:android per your setup).
  2. Open Components → TitleHub and review Default, Amount, Title / TitleAccessory, BottomLabel / BottomLabelAccessory, BottomAccessory, and AmountAccessory.
  3. Confirm layout and typography match expectations on light/dark backgrounds if applicable.

Screenshots/Recordings

Before

After

Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-04-07.at.23.26.18.mov

Pre-merge author checklist

  • I've followed MetaMask Contributor Docs
  • I've completed the PR template to the best of my ability
  • I’ve included tests if applicable
  • I’ve documented my code using JSDoc format if applicable
  • I’ve applied the right labels on the PR (see labeling guidelines). Not required for external contributors.

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.

Note

Low Risk
Primarily additive UI component work with new exports, stories, and tests; low risk aside from potential minor layout/typography regressions where newly adopted.

Overview
Introduces new TitleHub layout component to @metamask/design-system-react-native, rendering a stacked header with a required title row plus optional amount, bottomLabel, and a mutually exclusive bottomAccessory, each supporting inline end accessories.

Exports the component and shared props (TitleHubPropsShared) from both design-system-react-native and design-system-shared, adds Storybook stories for the new component, and includes a comprehensive test suite verifying conditional row rendering and prop passthrough (*Props, *WrapperProps, twClassName, style).

Reviewed by Cursor Bugbot for commit e5505ab. Bugbot is set up for automated code reviews on this repo. Configure here.

@brianacnguyen brianacnguyen self-assigned this Apr 8, 2026
@brianacnguyen brianacnguyen requested a review from a team as a code owner April 8, 2026 06:32
@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.tsx Outdated
@brianacnguyen brianacnguyen marked this pull request as draft April 8, 2026 06:39
@github-actions

github-actions Bot commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@amandaye0h

amandaye0h commented Apr 9, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-04-10 at 1 10 16 AM

Spacing/Gap between the bottomLabel components here is a bit too big — can the default be updated to 8px?

@amandaye0h amandaye0h left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comments re: spacing and icon sizes

import type { TitleHubProps } from './TitleHub.types';

/** Pill badge: dot + label (e.g. network), for `titleAccessory`. */
const TestnetBadge = () => (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo this testnet badge shouldn't be part of the docs, since it's visually dissimilar from the rest of the components in our library. We can include it temporarily, but it should be updated to a component with squareish borders.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a TODO comment

@brianacnguyen

Copy link
Copy Markdown
Contributor Author
Screenshot 2026-04-10 at 1 10 16 AM Spacing/Gap between the `bottomLabel` components here is a bit too big — can the default be updated to 8px?

This is a story, and ironically the gap is 8px right now. Removed the gap
Simulator Screenshot - iPhone 15 Pro Max - 2026-04-09 at 16 40 59

@github-actions

github-actions Bot commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

github-actions Bot commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@brianacnguyen brianacnguyen marked this pull request as ready for review April 10, 2026 04:45
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! The End suffix on the accessory props (titleEndAccessory, amountEndAccessory, bottomLabelEndAccessory) is the right call — makes slot position explicit even without a start counterpart and aligns with our discussed naming convention.

I'll follow up Figma Code Connect file and the React Web equivalent with cursor automations. A few non-blocking items inline.

Comment thread packages/design-system-react-native/src/components/TitleHub/README.md Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.stories.tsx Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.types.ts Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.stories.tsx Outdated
@georgewrmarshall

georgewrmarshall commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

After reviewing this PR, I did a deeper investigation into isReactNodeRenderable and found it's solving a problem that doesn't exist? React already handles null, undefined, and false uniformly at render time, rendering all of them as nothing. The original null check (children !== null && children !== undefined) was unnecessary to begin with, and the utility was built on top of that same misunderstanding.

I've created:

TitleHub should follow the same approach. The isReactNodeRenderable calls can be replaced with direct conditionals — e.g. if (title || titleEndAccessory) rather than isReactNodeRenderable(title) || isReactNodeRenderable(titleEndAccessory) — and the || undefined normalisations on the accessory nodes can be removed entirely since passing false or undefined to a slot renders nothing either way.

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.tsx Outdated

@georgewrmarshall georgewrmarshall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good after the latest simplification pass. A few more suggestions inline — mix of blocking and non-blocking.

Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.tsx Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.tsx Outdated
Comment thread packages/design-system-shared/src/types/TitleHub/TitleHub.types.ts Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.tsx Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/TitleHub.stories.tsx Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/README.md Outdated
Comment thread packages/design-system-react-native/src/components/TitleHub/README.md Outdated
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great after the latest changes 🚀

The component is in a much better place now:

  • the prop naming is clearer and more consistent with the *EndAccessory pattern
  • the root layout behavior and row structure are simpler and easier to reason about
  • the docs are much stronger now, especially around row rendering behavior and the wrapper prop surfaces
  • the README examples are cleaner and more aligned with component conventions
  • the tests cover the key conditional rendering paths and prop passthrough behavior well
  • the Storybook stories feel much more representative after the simplification pass

Overall this looks like a solid additive component and the historical review feedback appears to have been addressed well.

@brianacnguyen brianacnguyen enabled auto-merge (squash) April 20, 2026 15:57
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit e5505ab. Configure here.

@brianacnguyen brianacnguyen merged commit 8a90403 into main Apr 20, 2026
44 checks passed
@brianacnguyen brianacnguyen deleted the dsrn/titlehub branch April 20, 2026 16:15
@georgewrmarshall georgewrmarshall mentioned this pull request Apr 20, 2026
19 tasks
georgewrmarshall added a commit that referenced this pull request Apr 21, 2026
## Release 34.0.0

This release adds new shared `TitleHub` and `Checkbox` type contracts,
expands React 19 support for web and shared packages, and publishes a
React Native release that aligns its supported runtime with the React
Native 0.76 / Storybook 10 stack.

### 📦 Package Versions

- `@metamask/design-system-shared`: **0.12.0**
- `@metamask/design-system-react`: **0.17.1**
- `@metamask/design-system-react-native`: **0.19.0**
- `@metamask/design-system-twrnc-preset`: **0.4.2**

### 🔄 Shared Type Updates (0.12.0)

#### Shared contract additions and API cleanup
([#1052](#1052),
[#1040](#1040),
[#1076](#1076),
[#1089](#1089))

**What Changed:**

- Added `TitleHubPropsShared` and `CheckboxPropsShared` to
`@metamask/design-system-shared`
- Removed `isReactNodeRenderable` from the public shared API
- Expanded the shared package `react` peer dependency range to support
React 19

**Impact:**

- Enables consistent `TitleHub` and `Checkbox` implementations across
React and React Native
- Consumers importing `isReactNodeRenderable` must replace that import
with plain truthy checks
- Shared consumers on React 19 can now satisfy peer dependency
requirements without overrides

### 🌐 React Web Updates (0.17.1)

#### Changed

- Expanded the `react` and `react-dom` peer dependency ranges to support
React 19 consumers without changing the public component API
([#1089](#1089))

### 📱 React Native Updates (0.19.0)

#### Added

- Added `TitleHub` for stacked title, amount, and bottom-label layouts
with optional accessory slots
([#1052](#1052))

#### Changed

- **BREAKING:** Raised the minimum supported peer dependency versions to
React Native `>=0.76.0`, `react-native-gesture-handler >=2.25.0`,
`react-native-reanimated >=3.17.0`, and `react-native-safe-area-context
>=5.0.0`
([#844](#844))
- **BREAKING:** `HeaderRoot` now renders `titleAccessory` only when
`title` is present; use `children` for fully custom accessory-only title
rows
([#1076](#1076))
- **BREAKING:** `IconProps` now align with the underlying SVG component
props instead of `ViewProps`; move `View`-specific props to a wrapper
view if TypeScript flags them after upgrading
([#1090](#1090))

### 🎨 TWRNC Preset Updates (0.4.2)

#### Changed

- Expanded the `react` peer dependency range to `>=18.2.0`, allowing the
preset to install alongside newer React Native 0.76 and React 19 app
stacks
([#844](#844))

### ⚠️ Breaking Changes

#### `isReactNodeRenderable` removal (Shared)

**What Changed:**

- Removed `isReactNodeRenderable` from `@metamask/design-system-shared`
- Shared consumers should replace this helper with standard truthy
checks

**Migration:**

```tsx
// Before (0.11.0)
import { isReactNodeRenderable } from '@metamask/design-system-shared';

if (isReactNodeRenderable(title)) {
  return <Header title={title} />;
}

// After (0.12.0)
if (title) {
  return <Header title={title} />;
}
```

**Impact:**

- Any import of `isReactNodeRenderable` will fail after upgrading to
`0.12.0`
- See [Shared Migration
Guide](./packages/design-system-shared/MIGRATION.md#from-version-0110-to-0120)

#### React Native 0.76 peer minimums (React Native)

**What Changed:**

- Raised the minimum supported peer dependency versions to the React
Native 0.76 family used by the Storybook 10 migration

**Migration:**

```tsx
// Before (0.18.0)
// Compatible with older app stacks such as:
// react-native: 0.72.x
// react-native-gesture-handler: 2.12.x
// react-native-reanimated: 3.3.x
// react-native-safe-area-context: 4.x

// After (0.19.0)
// Consumers must be on at least:
// react-native: 0.76.x
// react-native-gesture-handler: 2.25.x
// react-native-reanimated: 3.17.x
// react-native-safe-area-context: 5.x
```

**Impact:**

- Apps on older React Native stacks will no longer satisfy peer
dependency requirements
- See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0180-to-0190)

#### `HeaderRoot` accessory rendering and `IconProps` typing (React
Native)

**What Changed:**

- `HeaderRoot` no longer renders `titleAccessory` unless `title` is
present
- `IconProps` now align with SVG props instead of `ViewProps`

**Migration:**

```tsx
// Before (0.18.0)
<HeaderRoot titleAccessory={<Icon name={IconName.Info} />} />
<Icon name={IconName.Lock} onLayout={handleLayout} />

// After (0.19.0)
<HeaderRoot title="Settings" titleAccessory={<Icon name={IconName.Info} />} />
<View onLayout={handleLayout}>
  <Icon name={IconName.Lock} />
</View>
```

**Impact:**

- Accessory-only `HeaderRoot` title rows must switch to `children` or
provide `title`
- `View`-specific props on `Icon` must move to a wrapper `View`
- See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0180-to-0190)

### ✅ Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] Changelog validation passed (`yarn changelog:validate`)
- [x] Version bumps follow semantic versioning
- [x] design-system-shared: minor (`0.11.0` → `0.12.0`) - pre-1.0
breaking shared API cleanup plus new shared type exports
- [x] design-system-react: patch (`0.17.0` → `0.17.1`) - non-breaking
compatibility update that widens React peer support to include v19
- [x] design-system-react-native: minor (`0.18.0` → `0.19.0`) - pre-1.0
breaking peer minimum and API behavior/type changes
- [x] design-system-twrnc-preset: patch (`0.4.1` → `0.4.2`) -
non-breaking peer range expansion
- [x] Breaking changes documented with migration guidance
- [x] Migration guides updated with before/after examples (if breaking
changes)
- [x] PR references included in changelog entries

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've reviewed the [Release
Workflow](./.cursor/rules/release-workflow.md) cursor rule
- [x] All tests pass (`yarn build && yarn test && yarn lint`)
- [x] Changelog validation passes (`yarn changelog:validate`)

## **Pre-merge reviewer checklist**

- [ ] I've reviewed the [Reviewing Release
PRs](./docs/reviewing-release-prs.md) guide
- [ ] Package versions follow semantic versioning
- [ ] Changelog entries are consumer-facing (not commit message
regurgitation)
- [ ] Breaking changes are documented in MIGRATION.md with examples
- [ ] All unreleased changes are accounted for in changelogs
georgewrmarshall pushed a commit that referenced this pull request Apr 27, 2026
## **Description**

This PR adds **TitleHub** to `@metamask/design-system-react-native`: a
layout component for a **title row**, an optional **amount** line with
optional **amountAccessory**, an optional **bottom label** row with
**bottomLabelAccessory**, and an optional **bottomAccessory** when the
bottom label row is not used.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-674

## **Manual testing steps**

1. From the repo root, run React Native Storybook (e.g. `yarn
storybook:ios` or `yarn storybook:android` per your setup).
2. Open **Components → TitleHub** and review **Default**, **Amount**,
**Title / TitleAccessory**, **BottomLabel / BottomLabelAccessory**,
**BottomAccessory**, and **AmountAccessory**.
3. Confirm layout and typography match expectations on light/dark
backgrounds if applicable.

## **Screenshots/Recordings**

### **Before**

<!-- N/A — new component, or attach “before” if replacing an old pattern
in an app. -->

### **After**


https://github.com/user-attachments/assets/e457a1cd-a45b-4793-b38c-de102d5cbaad

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Purely additive UI component, stories, and types with no changes to
existing business logic; main risk is minor layout/typography
regressions if consumed incorrectly.
> 
> **Overview**
> Adds a new `TitleHub` component to
`@metamask/design-system-react-native` that composes a stacked header
with a required title row, optional amount row, and an optional bottom
row that can be either a label or custom accessory content, each
supporting inline end-accessories.
> 
> Exports `TitleHub` (and new shared `TitleHubPropsShared` types) from
the React Native and shared packages, and wires it into Storybook with a
dedicated story set plus a comprehensive test suite covering conditional
row rendering and prop passthroughs (`*Props`, `*WrapperProps`,
`twClassName`, and `style`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9abdfb5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
georgewrmarshall added a commit that referenced this pull request Apr 27, 2026
## Release 34.0.0

This release adds new shared `TitleHub` and `Checkbox` type contracts,
expands React 19 support for web and shared packages, and publishes a
React Native release that aligns its supported runtime with the React
Native 0.76 / Storybook 10 stack.

### 📦 Package Versions

- `@metamask/design-system-shared`: **0.12.0**
- `@metamask/design-system-react`: **0.17.1**
- `@metamask/design-system-react-native`: **0.19.0**
- `@metamask/design-system-twrnc-preset`: **0.4.2**

### 🔄 Shared Type Updates (0.12.0)

#### Shared contract additions and API cleanup
([#1052](#1052),
[#1040](#1040),
[#1076](#1076),
[#1089](#1089))

**What Changed:**

- Added `TitleHubPropsShared` and `CheckboxPropsShared` to
`@metamask/design-system-shared`
- Removed `isReactNodeRenderable` from the public shared API
- Expanded the shared package `react` peer dependency range to support
React 19

**Impact:**

- Enables consistent `TitleHub` and `Checkbox` implementations across
React and React Native
- Consumers importing `isReactNodeRenderable` must replace that import
with plain truthy checks
- Shared consumers on React 19 can now satisfy peer dependency
requirements without overrides

### 🌐 React Web Updates (0.17.1)

#### Changed

- Expanded the `react` and `react-dom` peer dependency ranges to support
React 19 consumers without changing the public component API
([#1089](#1089))

### 📱 React Native Updates (0.19.0)

#### Added

- Added `TitleHub` for stacked title, amount, and bottom-label layouts
with optional accessory slots
([#1052](#1052))

#### Changed

- **BREAKING:** Raised the minimum supported peer dependency versions to
React Native `>=0.76.0`, `react-native-gesture-handler >=2.25.0`,
`react-native-reanimated >=3.17.0`, and `react-native-safe-area-context
>=5.0.0`
([#844](#844))
- **BREAKING:** `HeaderRoot` now renders `titleAccessory` only when
`title` is present; use `children` for fully custom accessory-only title
rows
([#1076](#1076))
- **BREAKING:** `IconProps` now align with the underlying SVG component
props instead of `ViewProps`; move `View`-specific props to a wrapper
view if TypeScript flags them after upgrading
([#1090](#1090))

### 🎨 TWRNC Preset Updates (0.4.2)

#### Changed

- Expanded the `react` peer dependency range to `>=18.2.0`, allowing the
preset to install alongside newer React Native 0.76 and React 19 app
stacks
([#844](#844))

### ⚠️ Breaking Changes

#### `isReactNodeRenderable` removal (Shared)

**What Changed:**

- Removed `isReactNodeRenderable` from `@metamask/design-system-shared`
- Shared consumers should replace this helper with standard truthy
checks

**Migration:**

```tsx
// Before (0.11.0)
import { isReactNodeRenderable } from '@metamask/design-system-shared';

if (isReactNodeRenderable(title)) {
  return <Header title={title} />;
}

// After (0.12.0)
if (title) {
  return <Header title={title} />;
}
```

**Impact:**

- Any import of `isReactNodeRenderable` will fail after upgrading to
`0.12.0`
- See [Shared Migration
Guide](./packages/design-system-shared/MIGRATION.md#from-version-0110-to-0120)

#### React Native 0.76 peer minimums (React Native)

**What Changed:**

- Raised the minimum supported peer dependency versions to the React
Native 0.76 family used by the Storybook 10 migration

**Migration:**

```tsx
// Before (0.18.0)
// Compatible with older app stacks such as:
// react-native: 0.72.x
// react-native-gesture-handler: 2.12.x
// react-native-reanimated: 3.3.x
// react-native-safe-area-context: 4.x

// After (0.19.0)
// Consumers must be on at least:
// react-native: 0.76.x
// react-native-gesture-handler: 2.25.x
// react-native-reanimated: 3.17.x
// react-native-safe-area-context: 5.x
```

**Impact:**

- Apps on older React Native stacks will no longer satisfy peer
dependency requirements
- See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0180-to-0190)

#### `HeaderRoot` accessory rendering and `IconProps` typing (React
Native)

**What Changed:**

- `HeaderRoot` no longer renders `titleAccessory` unless `title` is
present
- `IconProps` now align with SVG props instead of `ViewProps`

**Migration:**

```tsx
// Before (0.18.0)
<HeaderRoot titleAccessory={<Icon name={IconName.Info} />} />
<Icon name={IconName.Lock} onLayout={handleLayout} />

// After (0.19.0)
<HeaderRoot title="Settings" titleAccessory={<Icon name={IconName.Info} />} />
<View onLayout={handleLayout}>
  <Icon name={IconName.Lock} />
</View>
```

**Impact:**

- Accessory-only `HeaderRoot` title rows must switch to `children` or
provide `title`
- `View`-specific props on `Icon` must move to a wrapper `View`
- See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0180-to-0190)

### ✅ Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] Changelog validation passed (`yarn changelog:validate`)
- [x] Version bumps follow semantic versioning
- [x] design-system-shared: minor (`0.11.0` → `0.12.0`) - pre-1.0
breaking shared API cleanup plus new shared type exports
- [x] design-system-react: patch (`0.17.0` → `0.17.1`) - non-breaking
compatibility update that widens React peer support to include v19
- [x] design-system-react-native: minor (`0.18.0` → `0.19.0`) - pre-1.0
breaking peer minimum and API behavior/type changes
- [x] design-system-twrnc-preset: patch (`0.4.1` → `0.4.2`) -
non-breaking peer range expansion
- [x] Breaking changes documented with migration guidance
- [x] Migration guides updated with before/after examples (if breaking
changes)
- [x] PR references included in changelog entries

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've reviewed the [Release
Workflow](./.cursor/rules/release-workflow.md) cursor rule
- [x] All tests pass (`yarn build && yarn test && yarn lint`)
- [x] Changelog validation passes (`yarn changelog:validate`)

## **Pre-merge reviewer checklist**

- [ ] I've reviewed the [Reviewing Release
PRs](./docs/reviewing-release-prs.md) guide
- [ ] Package versions follow semantic versioning
- [ ] Changelog entries are consumer-facing (not commit message
regurgitation)
- [ ] Breaking changes are documented in MIGRATION.md with examples
- [ ] All unreleased changes are accounted for in changelogs
cursor Bot pushed a commit that referenced this pull request Apr 28, 2026
## **Description**

This PR adds **TitleHub** to `@metamask/design-system-react-native`: a
layout component for a **title row**, an optional **amount** line with
optional **amountAccessory**, an optional **bottom label** row with
**bottomLabelAccessory**, and an optional **bottomAccessory** when the
bottom label row is not used.

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-674

## **Manual testing steps**

1. From the repo root, run React Native Storybook (e.g. `yarn
storybook:ios` or `yarn storybook:android` per your setup).
2. Open **Components → TitleHub** and review **Default**, **Amount**,
**Title / TitleAccessory**, **BottomLabel / BottomLabelAccessory**,
**BottomAccessory**, and **AmountAccessory**.
3. Confirm layout and typography match expectations on light/dark
backgrounds if applicable.

## **Screenshots/Recordings**

### **Before**

<!-- N/A — new component, or attach “before” if replacing an old pattern
in an app. -->

### **After**


https://github.com/user-attachments/assets/e457a1cd-a45b-4793-b38c-de102d5cbaad

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Purely additive UI component, stories, and types with no changes to
existing business logic; main risk is minor layout/typography
regressions if consumed incorrectly.
> 
> **Overview**
> Adds a new `TitleHub` component to
`@metamask/design-system-react-native` that composes a stacked header
with a required title row, optional amount row, and an optional bottom
row that can be either a label or custom accessory content, each
supporting inline end-accessories.
> 
> Exports `TitleHub` (and new shared `TitleHubPropsShared` types) from
the React Native and shared packages, and wires it into Storybook with a
dedicated story set plus a comprehensive test suite covering conditional
row rendering and prop passthroughs (`*Props`, `*WrapperProps`,
`twClassName`, and `style`).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
9abdfb5. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
cursor Bot pushed a commit that referenced this pull request Apr 28, 2026
## Release 34.0.0

This release adds new shared `TitleHub` and `Checkbox` type contracts,
expands React 19 support for web and shared packages, and publishes a
React Native release that aligns its supported runtime with the React
Native 0.76 / Storybook 10 stack.

### 📦 Package Versions

- `@metamask/design-system-shared`: **0.12.0**
- `@metamask/design-system-react`: **0.17.1**
- `@metamask/design-system-react-native`: **0.19.0**
- `@metamask/design-system-twrnc-preset`: **0.4.2**

### 🔄 Shared Type Updates (0.12.0)

#### Shared contract additions and API cleanup
([#1052](#1052),
[#1040](#1040),
[#1076](#1076),
[#1089](#1089))

**What Changed:**

- Added `TitleHubPropsShared` and `CheckboxPropsShared` to
`@metamask/design-system-shared`
- Removed `isReactNodeRenderable` from the public shared API
- Expanded the shared package `react` peer dependency range to support
React 19

**Impact:**

- Enables consistent `TitleHub` and `Checkbox` implementations across
React and React Native
- Consumers importing `isReactNodeRenderable` must replace that import
with plain truthy checks
- Shared consumers on React 19 can now satisfy peer dependency
requirements without overrides

### 🌐 React Web Updates (0.17.1)

#### Changed

- Expanded the `react` and `react-dom` peer dependency ranges to support
React 19 consumers without changing the public component API
([#1089](#1089))

### 📱 React Native Updates (0.19.0)

#### Added

- Added `TitleHub` for stacked title, amount, and bottom-label layouts
with optional accessory slots
([#1052](#1052))

#### Changed

- **BREAKING:** Raised the minimum supported peer dependency versions to
React Native `>=0.76.0`, `react-native-gesture-handler >=2.25.0`,
`react-native-reanimated >=3.17.0`, and `react-native-safe-area-context
>=5.0.0`
([#844](#844))
- **BREAKING:** `HeaderRoot` now renders `titleAccessory` only when
`title` is present; use `children` for fully custom accessory-only title
rows
([#1076](#1076))
- **BREAKING:** `IconProps` now align with the underlying SVG component
props instead of `ViewProps`; move `View`-specific props to a wrapper
view if TypeScript flags them after upgrading
([#1090](#1090))

### 🎨 TWRNC Preset Updates (0.4.2)

#### Changed

- Expanded the `react` peer dependency range to `>=18.2.0`, allowing the
preset to install alongside newer React Native 0.76 and React 19 app
stacks
([#844](#844))

### ⚠️ Breaking Changes

#### `isReactNodeRenderable` removal (Shared)

**What Changed:**

- Removed `isReactNodeRenderable` from `@metamask/design-system-shared`
- Shared consumers should replace this helper with standard truthy
checks

**Migration:**

```tsx
// Before (0.11.0)
import { isReactNodeRenderable } from '@metamask/design-system-shared';

if (isReactNodeRenderable(title)) {
  return <Header title={title} />;
}

// After (0.12.0)
if (title) {
  return <Header title={title} />;
}
```

**Impact:**

- Any import of `isReactNodeRenderable` will fail after upgrading to
`0.12.0`
- See [Shared Migration
Guide](./packages/design-system-shared/MIGRATION.md#from-version-0110-to-0120)

#### React Native 0.76 peer minimums (React Native)

**What Changed:**

- Raised the minimum supported peer dependency versions to the React
Native 0.76 family used by the Storybook 10 migration

**Migration:**

```tsx
// Before (0.18.0)
// Compatible with older app stacks such as:
// react-native: 0.72.x
// react-native-gesture-handler: 2.12.x
// react-native-reanimated: 3.3.x
// react-native-safe-area-context: 4.x

// After (0.19.0)
// Consumers must be on at least:
// react-native: 0.76.x
// react-native-gesture-handler: 2.25.x
// react-native-reanimated: 3.17.x
// react-native-safe-area-context: 5.x
```

**Impact:**

- Apps on older React Native stacks will no longer satisfy peer
dependency requirements
- See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0180-to-0190)

#### `HeaderRoot` accessory rendering and `IconProps` typing (React
Native)

**What Changed:**

- `HeaderRoot` no longer renders `titleAccessory` unless `title` is
present
- `IconProps` now align with SVG props instead of `ViewProps`

**Migration:**

```tsx
// Before (0.18.0)
<HeaderRoot titleAccessory={<Icon name={IconName.Info} />} />
<Icon name={IconName.Lock} onLayout={handleLayout} />

// After (0.19.0)
<HeaderRoot title="Settings" titleAccessory={<Icon name={IconName.Info} />} />
<View onLayout={handleLayout}>
  <Icon name={IconName.Lock} />
</View>
```

**Impact:**

- Accessory-only `HeaderRoot` title rows must switch to `children` or
provide `title`
- `View`-specific props on `Icon` must move to a wrapper `View`
- See [React Native Migration
Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0180-to-0190)

### ✅ Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] Changelog validation passed (`yarn changelog:validate`)
- [x] Version bumps follow semantic versioning
- [x] design-system-shared: minor (`0.11.0` → `0.12.0`) - pre-1.0
breaking shared API cleanup plus new shared type exports
- [x] design-system-react: patch (`0.17.0` → `0.17.1`) - non-breaking
compatibility update that widens React peer support to include v19
- [x] design-system-react-native: minor (`0.18.0` → `0.19.0`) - pre-1.0
breaking peer minimum and API behavior/type changes
- [x] design-system-twrnc-preset: patch (`0.4.1` → `0.4.2`) -
non-breaking peer range expansion
- [x] Breaking changes documented with migration guidance
- [x] Migration guides updated with before/after examples (if breaking
changes)
- [x] PR references included in changelog entries

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [x] I've reviewed the [Release
Workflow](./.cursor/rules/release-workflow.md) cursor rule
- [x] All tests pass (`yarn build && yarn test && yarn lint`)
- [x] Changelog validation passes (`yarn changelog:validate`)

## **Pre-merge reviewer checklist**

- [ ] I've reviewed the [Reviewing Release
PRs](./docs/reviewing-release-prs.md) guide
- [ ] Package versions follow semantic versioning
- [ ] Changelog entries are consumer-facing (not commit message
regurgitation)
- [ ] Breaking changes are documented in MIGRATION.md with examples
- [ ] All unreleased changes are accounted for in changelogs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants