Skip to content

feat: Added SelectButton, SegmentButton, and SegmentGroup to DSRN#1172

Merged
brianacnguyen merged 8 commits into
mainfrom
dsrn/segment-select-group
May 14, 2026
Merged

feat: Added SelectButton, SegmentButton, and SegmentGroup to DSRN#1172
brianacnguyen merged 8 commits into
mainfrom
dsrn/segment-select-group

Conversation

@brianacnguyen

@brianacnguyen brianacnguyen commented May 14, 2026

Copy link
Copy Markdown
Contributor

Description

This PR adds segmented control and companion UI primitives to the MetaMask Design System for React Native (DSRN), aligned with shared cross-platform contracts.

What changed

  • SegmentGroup — Controlled horizontal group with value / onChange, horizontal scrolling when content overflows, optional default variant for children, and React Native-specific props layered on the shared SegmentGroupPropsShared type.
  • SegmentButton — Single segment: primary/secondary variants, optional value for group coordination or standalone isSelected, loading and icon support consistent with existing button patterns.
  • SelectButton — Compact row for picker/menu-style actions: placeholder / value, configurable chevron direction (SelectButtonEndArrow), variants (SelectButtonVariant), built on ButtonBase with shared SelectButtonPropsShared fields.

Related issues

Fixes: https://consensyssoftware.atlassian.net/browse/DSYS-563, https://consensyssoftware.atlassian.net/browse/DSYS-562, https://consensyssoftware.atlassian.net/browse/DSYS-672

Manual testing steps

  1. From the repo root, run React Native Storybook (e.g. yarn storybook:ios or yarn storybook:android per project docs).
  2. Open Components → SegmentGroup and confirm controlled selection, scrolling with many segments, and combined SegmentButton + SelectButton layouts.
  3. Open Components → SegmentButton and Components → SelectButton and verify variants, loading/disabled states, and chevron / label behavior match expectations.

Screenshots/Recordings

Before

After

SelectButton

Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-05-13.at.21.27.44.mov

SegmentButton

Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-05-13.at.21.29.52.mov

SegmentGroup

Simulator.Screen.Recording.-.iPhone.15.Pro.Max.-.2026-05-13.at.21.42.03.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

Medium Risk
Adds new exported UI primitives with shared contracts and context-driven selection logic, expanding the public API surface and interaction behavior. Risk is mainly around styling/pressed-state behavior and selection updates when used in consumer apps.

Overview
Adds three new React Native components—SegmentButton, SegmentGroup, and SelectButton—built on ButtonBase, with Storybook stories, README docs, and comprehensive tests.

SegmentGroup provides a controlled, horizontally scrolling container that exposes a SegmentGroupContext so child SegmentButtons derive selection from the group value and can trigger onChange when a new segment is pressed (with optional group-level variant). SelectButton adds a compact picker/menu row with placeholder vs value label resolution, optional trailing chevron direction/defaulting, and variant-based styling including tertiary alternative text/icon treatment.

Exports are wired through design-system-react-native and new shared contracts (SegmentButtonVariant, SelectButtonVariant, SelectButtonEndArrow, SegmentGroupPropsShared, and SegmentGroupContext) are added to design-system-shared, including new react-test-renderer dev deps for context tests.

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

@brianacnguyen brianacnguyen self-assigned this May 14, 2026
@brianacnguyen brianacnguyen requested a review from a team as a code owner May 14, 2026 05:01
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react-native/src/components/SelectButton/README.md Outdated
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

Comment thread packages/design-system-react-native/src/components/SegmentButton/README.md Outdated
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@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 2 potential issues.

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 8e10e47. Configure here.

vinnyhoward
vinnyhoward previously approved these changes May 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@brianacnguyen brianacnguyen merged commit 5809a2d into main May 14, 2026
44 checks passed
@brianacnguyen brianacnguyen deleted the dsrn/segment-select-group branch May 14, 2026 18:51
@brianacnguyen brianacnguyen mentioned this pull request May 15, 2026
17 tasks
brianacnguyen added a commit that referenced this pull request May 15, 2026
## Release 40.0.0

This release updates the shared layer and both UI packages: new
extension-aligned primitives and form helpers on web, new selection and
multi-line input components on React Native, shared types and context
for those APIs, coordinated **`BannerBase`** close behavior, and
**`ButtonBase`** defaults driven by **`size`** (with migration guidance
for wrappers that overrode label, icon, or spacing).

### Package versions

- `@metamask/design-system-shared`: **0.18.0**
- `@metamask/design-system-react`: **0.23.0**
- `@metamask/design-system-react-native`: **0.25.0**

### Shared type updates (0.18.0)

#### Component type additions
([#1172](#1172),
[#1164](#1164),
[#1169](#1169),
[#1141](#1141))

**What changed**

- **`SelectButton`** shared props and variants
(`SelectButtonPropsShared`, `SelectButtonVariant`,
`SelectButtonEndArrow`).
- **`SegmentGroup`** shared props and **`SegmentGroupContext`**
(`SegmentGroupPropsShared`, `SegmentGroupContext`,
`SegmentGroupContextValue`).
- **`SensitiveText`** shared types (`SensitiveTextLength`,
`SensitiveTextPropsShared`, and related exports).
- **`HelpText`** shared types (`HelpTextSeverity`,
`HelpTextPropsShared`, and related exports).
- **`TextAreaPropsShared`** for multi-line input wrappers.

**Impact**

- React and React Native stay aligned on the same ADR-0003/0004-style
contracts for the new and updated surfaces above.

### React web updates (0.23.0)

#### Added

- **`PopoverHeader`** — popover title rows and trailing actions,
extension migration patterns
([#1158](#1158)).
- **`ModalHeader`** — modal title rows and accessory slots
([#1144](#1144)).
- **`Label`** — captions paired with form controls
([#1152](#1152)).
- **`SensitiveText`** — mask/reveal for sensitive strings with
configurable visible length
([#1164](#1164)).
- **`HelpText`** — helper, success, warning, and error copy under inputs
and controls
([#1169](#1169)).

#### Changed

- **`ButtonBase`** — label **`Text`** variant, start/end icon sizes, and
internal spacing are derived from **`size`** for each
**`ButtonBaseSize`**
([#1150](#1150)).
See [Migration guide —
ButtonBase](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#buttonbase-size-defaults).
- **`BannerBase`** — close behavior uses **`onClose`** only;
**`closeButtonProps.onClick`** is not the dismiss API;
**`closeButtonProps`** is for customization
([#1166](#1166)).

### React Native updates (0.25.0)

#### Added

- **`SelectButton`**, **`SegmentButton`**, **`SegmentGroup`**
([#1172](#1172)).
- **`SensitiveText`**, aligned with the shared contract
([#1164](#1164)).
- **`HeaderStandardAnimated`** and **`useHeaderStandardAnimated`**
([#1151](#1151)).
- **`TextArea`**
([#1141](#1141)).

#### Changed

- **`ButtonBase`** — same size-driven defaults as web
([#1150](#1150)).
See [Migration guide —
ButtonBase](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#buttonbase-size-defaults).
- **`BannerBase`** — close behavior uses **`onClose`** only;
**`closeButtonProps.onPress`** is not the dismiss API
([#1166](#1166)).

### Breaking changes

#### `BannerBase` close API (both platforms)

**What changed**

- **React:** Use **`onClose`** for dismiss behavior.
**`closeButtonProps.onClick`** is removed from that role. The close
control is tied to **`onClose`**. **`closeButtonProps`** remains for
non-behavioral customization (e.g. **`data-testid`**, accessibility,
styling hooks).
- **React Native:** Same pattern: **`onClose`** instead of
**`closeButtonProps.onPress`** for dismiss behavior.

**Migration**

- Move any close action from **`closeButtonProps.onClick`** /
**`closeButtonProps.onPress`** to **`onClose`**.
- If you previously forced a close button with only
**`closeButtonProps`**, also provide **`onClose`**.

**Impact**

- Call sites that dismissed via **`closeButtonProps`** or showed a close
button without **`onClose`** must be updated.

See:

- [React — From version 0.22.0 to
0.x.0](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react/MIGRATION.md#from-version-0220-to-0x0)
- [React Native — From version 0.24.0 to
0.x.0](https://github.com/MetaMask/metamask-design-system/blob/main/packages/design-system-react-native/MIGRATION.md#from-version-0240-to-0x0)

**`ButtonBase`:** not called out here as a semver-breaking API change;
consumers who overrode typography, icon size, or spacing on
**`ButtonBase`** wrappers should follow the ButtonBase migration
sections linked above.

### Checklist

- [x] Changelogs updated with human-readable descriptions
- [x] `yarn changelog:validate` passes
- [x] Version bumps follow semantic versioning
- [x] `@metamask/design-system-shared`: **minor** (0.17.x → 0.18.0) —
new shared exports for select/segment, sensitive text, help text, text
area
- [x] `@metamask/design-system-react`: **minor** (0.22.x → 0.23.0) — new
components; **`BannerBase`** / **`ButtonBase`** behavior
- [x] `@metamask/design-system-react-native`: **minor** (0.24.x →
0.25.0) — new components; **`BannerBase`** / **`ButtonBase`** behavior
- [x] Breaking changes documented (**`BannerBase`**) in MIGRATION with
before/after examples
- [x] PR references present in changelog entries

## Pre-merge author checklist

- [ ] [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs)
- [ ] [Release
Workflow](https://github.com/MetaMask/metamask-design-system/blob/main/.cursor/rules/release-workflow.md)
- [ ] `yarn build && yarn test && yarn lint`
- [ ] `yarn changelog:validate`

## Pre-merge reviewer checklist

- [ ] [Reviewing Release
PRs](https://github.com/MetaMask/metamask-design-system/blob/main/docs/reviewing-release-prs.md)
- [ ] Package versions and semver match what this PR actually publishes
- [ ] Changelogs are consumer-facing
- [ ] Breaking changes covered in MIGRATION.md
- [ ] No unpublished package is missing from the changelogs / version
list for **this** PR
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