feat: Add Tag component for React Native#1053
Conversation
📖 Storybook Preview |
📖 Storybook Preview |
|
|
||
| figma.connect( | ||
| Tag, | ||
| 'https://www.figma.com/design/1D6tnzXqWgnUC3spaAOELN/%F0%9F%A6%8A-MMDS-Components?node-id=12339-6553', |
There was a problem hiding this comment.
Added this so there is better connection between code:design. It'll help with maintainability in the long term. I can remove it if this is premature at this stage of our DS.
If/when this PR is approved, I'll need to add the code link in Figma.
📖 Storybook Preview |
📖 Storybook Preview |
| Warning: 'warning', | ||
| Info: 'info', | ||
| } as const; | ||
| export type TagVariant = (typeof TagVariant)[keyof typeof TagVariant]; |
There was a problem hiding this comment.
This should be in the shared package (you can get Cursor to help you align these props with cursor rules
| flexDirection: BoxFlexDirection.Row, | ||
| alignItems: BoxAlignItems.Center, | ||
| twClassName: 'rounded-md self-start gap-0.5', | ||
| } as const; |
There was a problem hiding this comment.
these styling should not be stored as consts. It should just be used inline
There was a problem hiding this comment.
| /** | ||
| * Visual emphasis (background and default text color for label / plain-text children). | ||
| */ | ||
| variant?: TagVariant; |
There was a problem hiding this comment.
A lot of these props can be extracted to shared (you can get cursor to do this)
There was a problem hiding this comment.
| /** | ||
| * Visual emphasis (background and default text color for label / plain-text children). | ||
| */ | ||
| variant?: TagVariant; |
There was a problem hiding this comment.
Additionally I think this prop should be named either severity or semantic cc @georgewrmarshall
There was a problem hiding this comment.
| /** | ||
| * Optional prop for a custom element to show at the start of the tag when no start icon is shown. | ||
| */ | ||
| startAccessory?: React.ReactNode; |
There was a problem hiding this comment.
label, start Accessory, and endAccessory can be reused with BoxRow
There was a problem hiding this comment.
Should be fixed in refactor: rerender text to use BoxRow, remove label and textProps
| const horizontalPaddingTw = [ | ||
| finalStartIconName ? 'pl-1' : 'pl-1.5', | ||
| finalEndIconName ? 'pr-1' : 'pr-1.5', | ||
| ].join(' '); |
There was a problem hiding this comment.
don't store these consts. just use inline
There was a problem hiding this comment.
brianacnguyen
left a comment
There was a problem hiding this comment.
I suggest to run each individual file through cursor to align with cursor rules
|
@georgewrmarshall @amandaye0h should this component also includes a prop called includesSemanticIcon? |
There was a problem hiding this comment.
Hi Amanda, great first component PR 🎉 this is a well structured component and it's clear you've put real thought into the API design! The render helper pattern, variant color mapping, and accessory/icon separation are all clean. There are a few architectural requirements from our cursor rules and some alignment gaps with the Figma design to address before this is ready to merge. I've walked through each one with full context and included Cursor/Claude prompts where they can help. Nothing here is a fundamental problem — just refinements to get it fully aligned with our standards.
| TextColor, | ||
| } from '../../types'; | ||
|
|
||
| export const TagVariant = { |
There was a problem hiding this comment.
Per ADR-0004, this const assertion should live in @metamask/design-system-shared/src/types/Tag/ rather than the React Native package. This matters because when a React (web) Tag component is built later, both platforms need to share the same const object — if it's defined in the platform package there's a risk they drift out of sync.
The mapping constants below (MAP_TAG_VARIANT_BACKGROUND, etc.) are fine to keep here since they reference React Native-specific tokens.
You can prompt Cursor/Claude to handle the migration:
Following .cursor/rules/component-architecture.md ADR-0004 pattern, move TagVariant
from Tag.constants.ts into packages/design-system-shared/src/types/Tag/Tag.types.ts,
create a TagPropsShared type there, update Tag.types.ts to import and extend it,
and update index.ts to export TagVariant directly from @metamask/design-system-shared.
Reference BadgeStatus as the golden path example.
There was a problem hiding this comment.
| }; | ||
|
|
||
| /** Vertical padding (Tailwind `py-*`) */ | ||
| export const TAG_PADDING_VERTICAL_TW = 'py-0'; |
There was a problem hiding this comment.
TAG_PADDING_VERTICAL_TW = 'py-0' has no effect — py-0 is the Tailwind default, so this is a no-op. Remove it.
TAG_LAYOUT below is used in exactly one place. Single-use constants like this add indirection without benefit — a future engineer has to jump between files to understand the layout. Move these values inline into Tag.tsx directly.
There was a problem hiding this comment.
| /** | ||
| * Visual emphasis (background and default text color for label / plain-text children). | ||
| */ | ||
| variant?: TagVariant; |
There was a problem hiding this comment.
Curious on your thought here, I'm leaning towards two things here:
-
Renaminh
varianttoseverity.BannerAlertandIconAlertuseseverityfor similar semantic set of states (neutral/info/success/error/warning). Keeping the prop name consistent across components makes the design system more predictable for consumers. -
The Figma component currently has
primarywhere the code hasInfo— there is noinfoin Figma and noprimaryin the code. I'd recommend keepingInfo(to stay consistent withBannerAlert) and updating the Figma component, but we could discuss before making this change
There was a problem hiding this comment.
| /** | ||
| * Label string; when set, shown instead of string/number `children`. Matches Figma `Label` in Code Connect. | ||
| */ | ||
| label?: string; |
There was a problem hiding this comment.
suggestion: I realize label was in the original insight report but I think we can temove the label prop and textProps prop. BoxRow (which Tag will be used alongside) uses a TextOrChildren pattern — children is rendered as a Text component automatically when passed a string/number, and rendered as-is when passed a node. Tag should follow the same pattern. Having both label and children serve the same purpose creates a confusing API where two props compete.
In Tag.tsx and Tag.types.ts, remove the label and textProps props.
Update the component to render string/number children using the TextOrChildren
pattern from BoxRow — wrap string/number children in a Text component with
the severity's textColor, TextVariant.BodyXs, and FontWeight.Medium.
Node children should render as-is.
There was a problem hiding this comment.
| const meta: Meta<typeof Tag> = { | ||
| title: 'Components/Tag', | ||
| component: Tag, | ||
| }; |
There was a problem hiding this comment.
Per our component documentation standards, the first story must always be Default with minimal args and all controls wired up via argTypes. This powers the Storybook controls panel.
const meta: Meta<typeof Tag> = {
title: 'Components/Tag',
component: Tag,
argTypes: {
severity: {
control: 'select',
options: Object.values(TagSeverity),
},
startIconName: { control: 'select', options: Object.values(IconName) },
endIconName: { control: 'select', options: Object.values(IconName) },
},
};
export const Default: Story = {
args: {
children: 'Tag',
severity: TagSeverity.Neutral,
},
};non-blocking: TagVariant is imported from './Tag.constants' — once moved to shared, import from '.' (the index) to match the pattern used across the codebase.
There was a problem hiding this comment.
| 'https://www.figma.com/design/1D6tnzXqWgnUC3spaAOELN/%F0%9F%A6%8A-MMDS-Components?node-id=12339-6553', | ||
| { | ||
| props: { | ||
| variant: figma.enum('variant', { |
There was a problem hiding this comment.
The Figma property is mistmatched type not variant. This mapping will silently produce no output in Dev Mode. Based on what the outcome is for variant/severity update to:
severity: figma.enum('severity', {
neutral: TagSeverity.Neutral,
info: TagSeverity.Info,
success: TagSeverity.Success,
error: TagSeverity.Error,
warning: TagSeverity.Warning,
})Hold off on publishing (yarn figma:connect:publish) until the severity/variant prop rename and info/primary Figma alignment are resolved. Once those are confirmed, run yarn figma:connect:publish:dry-run first to validate.
There was a problem hiding this comment.
Screen.Recording.2026-04-16.at.8.07.16.PM.mov
| export { BannerAlert, BannerAlertSeverity } from './BannerAlert'; | ||
| export type { BannerAlertProps } from './BannerAlert'; | ||
|
|
||
| export { Tag, TagVariant, type TagProps } from './Tag'; |
There was a problem hiding this comment.
non-blocking: Every other component in this file uses separate export and export type statements. The inline type pattern here is the only instance of this style in the file:
// current
export { Tag, TagVariant, type TagProps } from './Tag';
// consistent with rest of file
export { Tag, TagSeverity } from './Tag';
export type { TagProps } from './Tag';Note: once TagSeverity is moved to shared, this export will change anyway — tackle after the shared types migration.
…d padding constant
georgewrmarshall
left a comment
There was a problem hiding this comment.
This has come a long way through the review rounds and the component is looking strong overall. The API is much clearer now, the shared type split looks good, and I think this is in a good place to merge.
I have a couple of small non-blocking follow-ups, but they feel better suited to a separate PR than holding this up.
| const iconColor = MAP_TAG_SEVERITY_ICON_COLOR[severity]; | ||
|
|
||
| return ( | ||
| <Box |
There was a problem hiding this comment.
non-blocking: This works, but I think the container styling would be a bit easier to read and maintain if we used tw.style(...) here instead of building the class list with a template literal. We do this in other components in design-system-react-native, and I think it would make this component a bit clearer as a reference example.
There was a problem hiding this comment.
Resolved here: chore: update container styling to use tw.style
| {...endIconProps} | ||
| /> | ||
| ); | ||
| })()} |
There was a problem hiding this comment.
non-blocking: I don’t think we need to support numeric children here. In practice our client usage is text content, and this branch adds a little extra behavior for a case we don’t really model elsewhere. I’d lean toward just passing children through directly unless we want number support to be an intentional part of the component contract.
There was a problem hiding this comment.
cdbff40
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
📖 Storybook Preview |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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 c464af6. Configure here.
📖 Storybook Preview |
georgewrmarshall
left a comment
There was a problem hiding this comment.
Great job on this. This has come a long way through the review rounds, the API is much clearer now, and the follow-up cleanup on Tag.tsx landed well. I think this is in a good place to merge.
📖 Storybook Preview |
## Release 35.0.0 This release adds new React Native title primitives, continues the enum-to-const-object/string-union migration for public type exports, and updates the release documentation so breaking changes are consumer-focused and migration-oriented. ### Package Versions - `@metamask/design-system-shared`: **0.13.0** - `@metamask/design-system-react`: **0.18.0** - `@metamask/design-system-react-native`: **0.20.0** - `@metamask/design-system-tailwind-preset`: **0.6.2** ### Shared Type Updates (0.13.0) #### Added (#1051, #1053, #1059) **What Changed:** - Added `TitleStandardPropsShared` and `TitleSubpagePropsShared` - Added `TagSeverity` and `TagPropsShared` **Impact:** - Supports the new React Native `TitleStandard`, `TitleSubpage`, and `Tag` APIs #### Changed (#1026, #1042) **What Changed:** - **BREAKING:** Updated shared `Box` and `Icon` exports from enums to const objects with derived string-union types - Removed stale Box `WarningAlternative`, `SuccessAlternative`, and `InfoAlternative` color entries that no longer map to design tokens **Impact:** - Affects consumers of `@metamask/design-system-shared` directly - Platform package consumers should continue importing from `@metamask/design-system-react` or `@metamask/design-system-react-native` ### React Web Updates (0.18.0) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042, #1101) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### React Native Updates (0.20.0) #### Added - Added `TitleStandard` for mobile title layouts with optional top and bottom accessory rows (#1051) - Added `TitleSubpage` for subpage headers with avatar, title, subtitle, amount, and bottom-label layouts (#1059) - Added `Tag` for compact severity-based metadata labels with optional icons or custom accessories (#1053) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - `Box` now forwards refs to the underlying `View` (#1102) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### Tailwind Preset Updates (0.6.2) #### Changed - No consumer-facing API or behavior changes in this release; this patch republishes the existing preset without requiring changes in consuming apps ### Breaking Changes #### Icon and Box enum exports migrated to const objects plus string unions (Both Platforms) **What Changed:** - `IconName`, `IconColor`, and `IconSize` now use const objects with derived string-union types instead of enums - `BoxFlexDirection`, `BoxFlexWrap`, `BoxAlignItems`, `BoxJustifyContent`, `BoxBackgroundColor`, `BoxBorderColor`, `BoxSpacing`, and `BoxBorderWidth` now use const objects with derived string-union types instead of enums - Removed stale Box color entries with no backing design token: - `BoxBackgroundColor.WarningAlternative` - `BoxBackgroundColor.SuccessAlternative` - `BoxBorderColor.WarningAlternative` - `BoxBorderColor.SuccessAlternative` - `BoxBorderColor.InfoAlternative` **Migration:** ```tsx // Before import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningAlternative} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> // After import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningDefault} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> ``` **Impact:** - Affects consumers relying on enum-specific TypeScript behavior for `Icon*` and `Box*` exports - Import paths stay the same for platform-package consumers - Any use of the removed Box `*Alternative` color entries will need to switch to the corresponding `*Default` or `*Muted` token See migration guides for complete instructions: - [React Migration Guide](./packages/design-system-react/MIGRATION.md#from-version-0170-to-0180) - [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0190-to-0200) ### Validation - `yarn changelog:validate` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it publishes new versions with **breaking TypeScript surface changes** (Box/Icon enums → const-object/string-union and removal of stale Box color members), which can break downstream builds despite minimal runtime behavior changes. > > **Overview** > Bumps the monorepo release to `35.0.0` and publishes new package versions for `@metamask/design-system-react` (`0.18.0`), `@metamask/design-system-react-native` (`0.20.0`), and `@metamask/design-system-shared` (`0.13.0`). > > Updates changelogs/migration guides to reflect the release: adds React Native primitives (`TitleStandard`, `TitleSubpage`, `Tag`) and shared prop contracts, and documents **breaking** shifts of `Box*` and `Icon*` exports from enums to const-object + string-union types (plus removal of stale `*Alternative` Box color entries) with consumer-facing migration steps. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit addbae5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** ### What is the goal of this PR? - Creates a tag component that can be used in `ListItems`, `Sections`, and `KeyValues` ### What are the key updates? - Adds a React Native Tag component with the variants, start/end icons props and conditional horizontal padding when icons are shown/not shown - Adds Code Connect (`Tag.figma.tsx`), stories, tests, and README/Figma link docs ## **Related issues** JIRA: - https://consensyssoftware.atlassian.net/browse/DSYS-568 This is a dependency for these migration PRs: - [chore: Add deprecation messages for Tag and StockBadge components](MetaMask/metamask-mobile#28918) - [chore: Modify Cursor guidelines to include Tag specs](MetaMask/metamask-mobile#28923) ## **Manual testing steps** 1. Run `yarn install && yarn build && yarn storybook:ios` to see changes ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** Component did not exist before this. ### **After** https://github.com/user-attachments/assets/6aa3f7c3-7e2f-4a13-a4a1-880f24553c74 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/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](https://jsdoc.app/) format if applicable - [ ] 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** > Primarily additive design-system UI work (new component + shared types) with minimal impact outside new exports; risk is limited to potential styling/prop API integration issues for consumers. > > **Overview** > Adds a new React Native `Tag` component with shared `TagSeverity` semantics, optional start/end icons or custom accessories, and automatic padding adjustments based on icon presence. > > Introduces shared `TagSeverity`/`TagPropsShared` in `design-system-shared`, wires exports in both shared and RN component indexes, and includes Storybook stories, Code Connect (`Tag.figma.tsx`), unit tests, and README documentation. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7d5d89b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Amanda <amanda@Amandas-MacBook-Pro.local>
## Release 35.0.0 This release adds new React Native title primitives, continues the enum-to-const-object/string-union migration for public type exports, and updates the release documentation so breaking changes are consumer-focused and migration-oriented. ### Package Versions - `@metamask/design-system-shared`: **0.13.0** - `@metamask/design-system-react`: **0.18.0** - `@metamask/design-system-react-native`: **0.20.0** - `@metamask/design-system-tailwind-preset`: **0.6.2** ### Shared Type Updates (0.13.0) #### Added (#1051, #1053, #1059) **What Changed:** - Added `TitleStandardPropsShared` and `TitleSubpagePropsShared` - Added `TagSeverity` and `TagPropsShared` **Impact:** - Supports the new React Native `TitleStandard`, `TitleSubpage`, and `Tag` APIs #### Changed (#1026, #1042) **What Changed:** - **BREAKING:** Updated shared `Box` and `Icon` exports from enums to const objects with derived string-union types - Removed stale Box `WarningAlternative`, `SuccessAlternative`, and `InfoAlternative` color entries that no longer map to design tokens **Impact:** - Affects consumers of `@metamask/design-system-shared` directly - Platform package consumers should continue importing from `@metamask/design-system-react` or `@metamask/design-system-react-native` ### React Web Updates (0.18.0) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042, #1101) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### React Native Updates (0.20.0) #### Added - Added `TitleStandard` for mobile title layouts with optional top and bottom accessory rows (#1051) - Added `TitleSubpage` for subpage headers with avatar, title, subtitle, amount, and bottom-label layouts (#1059) - Added `Tag` for compact severity-based metadata labels with optional icons or custom accessories (#1053) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - `Box` now forwards refs to the underlying `View` (#1102) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### Tailwind Preset Updates (0.6.2) #### Changed - No consumer-facing API or behavior changes in this release; this patch republishes the existing preset without requiring changes in consuming apps ### Breaking Changes #### Icon and Box enum exports migrated to const objects plus string unions (Both Platforms) **What Changed:** - `IconName`, `IconColor`, and `IconSize` now use const objects with derived string-union types instead of enums - `BoxFlexDirection`, `BoxFlexWrap`, `BoxAlignItems`, `BoxJustifyContent`, `BoxBackgroundColor`, `BoxBorderColor`, `BoxSpacing`, and `BoxBorderWidth` now use const objects with derived string-union types instead of enums - Removed stale Box color entries with no backing design token: - `BoxBackgroundColor.WarningAlternative` - `BoxBackgroundColor.SuccessAlternative` - `BoxBorderColor.WarningAlternative` - `BoxBorderColor.SuccessAlternative` - `BoxBorderColor.InfoAlternative` **Migration:** ```tsx // Before import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningAlternative} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> // After import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningDefault} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> ``` **Impact:** - Affects consumers relying on enum-specific TypeScript behavior for `Icon*` and `Box*` exports - Import paths stay the same for platform-package consumers - Any use of the removed Box `*Alternative` color entries will need to switch to the corresponding `*Default` or `*Muted` token See migration guides for complete instructions: - [React Migration Guide](./packages/design-system-react/MIGRATION.md#from-version-0170-to-0180) - [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0190-to-0200) ### Validation - `yarn changelog:validate` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it publishes new versions with **breaking TypeScript surface changes** (Box/Icon enums → const-object/string-union and removal of stale Box color members), which can break downstream builds despite minimal runtime behavior changes. > > **Overview** > Bumps the monorepo release to `35.0.0` and publishes new package versions for `@metamask/design-system-react` (`0.18.0`), `@metamask/design-system-react-native` (`0.20.0`), and `@metamask/design-system-shared` (`0.13.0`). > > Updates changelogs/migration guides to reflect the release: adds React Native primitives (`TitleStandard`, `TitleSubpage`, `Tag`) and shared prop contracts, and documents **breaking** shifts of `Box*` and `Icon*` exports from enums to const-object + string-union types (plus removal of stale `*Alternative` Box color entries) with consumer-facing migration steps. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit addbae5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
## Release 35.0.0 This release adds new React Native title primitives, continues the enum-to-const-object/string-union migration for public type exports, and updates the release documentation so breaking changes are consumer-focused and migration-oriented. ### Package Versions - `@metamask/design-system-shared`: **0.13.0** - `@metamask/design-system-react`: **0.18.0** - `@metamask/design-system-react-native`: **0.20.0** - `@metamask/design-system-tailwind-preset`: **0.6.2** ### Shared Type Updates (0.13.0) #### Added (#1051, #1053, #1059) **What Changed:** - Added `TitleStandardPropsShared` and `TitleSubpagePropsShared` - Added `TagSeverity` and `TagPropsShared` **Impact:** - Supports the new React Native `TitleStandard`, `TitleSubpage`, and `Tag` APIs #### Changed (#1026, #1042) **What Changed:** - **BREAKING:** Updated shared `Box` and `Icon` exports from enums to const objects with derived string-union types - Removed stale Box `WarningAlternative`, `SuccessAlternative`, and `InfoAlternative` color entries that no longer map to design tokens **Impact:** - Affects consumers of `@metamask/design-system-shared` directly - Platform package consumers should continue importing from `@metamask/design-system-react` or `@metamask/design-system-react-native` ### React Web Updates (0.18.0) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042, #1101) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### React Native Updates (0.20.0) #### Added - Added `TitleStandard` for mobile title layouts with optional top and bottom accessory rows (#1051) - Added `TitleSubpage` for subpage headers with avatar, title, subtitle, amount, and bottom-label layouts (#1059) - Added `Tag` for compact severity-based metadata labels with optional icons or custom accessories (#1053) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - `Box` now forwards refs to the underlying `View` (#1102) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### Tailwind Preset Updates (0.6.2) #### Changed - No consumer-facing API or behavior changes in this release; this patch republishes the existing preset without requiring changes in consuming apps ### Breaking Changes #### Icon and Box enum exports migrated to const objects plus string unions (Both Platforms) **What Changed:** - `IconName`, `IconColor`, and `IconSize` now use const objects with derived string-union types instead of enums - `BoxFlexDirection`, `BoxFlexWrap`, `BoxAlignItems`, `BoxJustifyContent`, `BoxBackgroundColor`, `BoxBorderColor`, `BoxSpacing`, and `BoxBorderWidth` now use const objects with derived string-union types instead of enums - Removed stale Box color entries with no backing design token: - `BoxBackgroundColor.WarningAlternative` - `BoxBackgroundColor.SuccessAlternative` - `BoxBorderColor.WarningAlternative` - `BoxBorderColor.SuccessAlternative` - `BoxBorderColor.InfoAlternative` **Migration:** ```tsx // Before import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningAlternative} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> // After import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningDefault} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> ``` **Impact:** - Affects consumers relying on enum-specific TypeScript behavior for `Icon*` and `Box*` exports - Import paths stay the same for platform-package consumers - Any use of the removed Box `*Alternative` color entries will need to switch to the corresponding `*Default` or `*Muted` token See migration guides for complete instructions: - [React Migration Guide](./packages/design-system-react/MIGRATION.md#from-version-0170-to-0180) - [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0190-to-0200) ### Validation - `yarn changelog:validate` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it publishes new versions with **breaking TypeScript surface changes** (Box/Icon enums → const-object/string-union and removal of stale Box color members), which can break downstream builds despite minimal runtime behavior changes. > > **Overview** > Bumps the monorepo release to `35.0.0` and publishes new package versions for `@metamask/design-system-react` (`0.18.0`), `@metamask/design-system-react-native` (`0.20.0`), and `@metamask/design-system-shared` (`0.13.0`). > > Updates changelogs/migration guides to reflect the release: adds React Native primitives (`TitleStandard`, `TitleSubpage`, `Tag`) and shared prop contracts, and documents **breaking** shifts of `Box*` and `Icon*` exports from enums to const-object + string-union types (plus removal of stale `*Alternative` Box color entries) with consumer-facing migration steps. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit addbae5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** ### What is the goal of this PR? - Creates a tag component that can be used in `ListItems`, `Sections`, and `KeyValues` ### What are the key updates? - Adds a React Native Tag component with the variants, start/end icons props and conditional horizontal padding when icons are shown/not shown - Adds Code Connect (`Tag.figma.tsx`), stories, tests, and README/Figma link docs ## **Related issues** JIRA: - https://consensyssoftware.atlassian.net/browse/DSYS-568 This is a dependency for these migration PRs: - [chore: Add deprecation messages for Tag and StockBadge components](MetaMask/metamask-mobile#28918) - [chore: Modify Cursor guidelines to include Tag specs](MetaMask/metamask-mobile#28923) ## **Manual testing steps** 1. Run `yarn install && yarn build && yarn storybook:ios` to see changes ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** Component did not exist before this. ### **After** https://github.com/user-attachments/assets/6aa3f7c3-7e2f-4a13-a4a1-880f24553c74 ## **Pre-merge author checklist** - [ ] I've followed [MetaMask Contributor Docs](https://github.com/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](https://jsdoc.app/) format if applicable - [ ] 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** > Primarily additive design-system UI work (new component + shared types) with minimal impact outside new exports; risk is limited to potential styling/prop API integration issues for consumers. > > **Overview** > Adds a new React Native `Tag` component with shared `TagSeverity` semantics, optional start/end icons or custom accessories, and automatic padding adjustments based on icon presence. > > Introduces shared `TagSeverity`/`TagPropsShared` in `design-system-shared`, wires exports in both shared and RN component indexes, and includes Storybook stories, Code Connect (`Tag.figma.tsx`), unit tests, and README documentation. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 7d5d89b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Amanda <amanda@Amandas-MacBook-Pro.local>
## Release 35.0.0 This release adds new React Native title primitives, continues the enum-to-const-object/string-union migration for public type exports, and updates the release documentation so breaking changes are consumer-focused and migration-oriented. ### Package Versions - `@metamask/design-system-shared`: **0.13.0** - `@metamask/design-system-react`: **0.18.0** - `@metamask/design-system-react-native`: **0.20.0** - `@metamask/design-system-tailwind-preset`: **0.6.2** ### Shared Type Updates (0.13.0) #### Added (#1051, #1053, #1059) **What Changed:** - Added `TitleStandardPropsShared` and `TitleSubpagePropsShared` - Added `TagSeverity` and `TagPropsShared` **Impact:** - Supports the new React Native `TitleStandard`, `TitleSubpage`, and `Tag` APIs #### Changed (#1026, #1042) **What Changed:** - **BREAKING:** Updated shared `Box` and `Icon` exports from enums to const objects with derived string-union types - Removed stale Box `WarningAlternative`, `SuccessAlternative`, and `InfoAlternative` color entries that no longer map to design tokens **Impact:** - Affects consumers of `@metamask/design-system-shared` directly - Platform package consumers should continue importing from `@metamask/design-system-react` or `@metamask/design-system-react-native` ### React Web Updates (0.18.0) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042, #1101) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### React Native Updates (0.20.0) #### Added - Added `TitleStandard` for mobile title layouts with optional top and bottom accessory rows (#1051) - Added `TitleSubpage` for subpage headers with avatar, title, subtitle, amount, and bottom-label layouts (#1059) - Added `Tag` for compact severity-based metadata labels with optional icons or custom accessories (#1053) #### Changed - **BREAKING:** Updated `IconName`, `IconColor`, and `IconSize` exports to use const-object + string-union types instead of enums (#1042) - **BREAKING:** Updated `Box` type exports to use const-object + string-union types and removed stale Box color entries (#1026) - `Box` now forwards refs to the underlying `View` (#1102) - Updated `ButtonTertiary` to use the default text color for more consistent contrast across states (#1099) ### Tailwind Preset Updates (0.6.2) #### Changed - No consumer-facing API or behavior changes in this release; this patch republishes the existing preset without requiring changes in consuming apps ### Breaking Changes #### Icon and Box enum exports migrated to const objects plus string unions (Both Platforms) **What Changed:** - `IconName`, `IconColor`, and `IconSize` now use const objects with derived string-union types instead of enums - `BoxFlexDirection`, `BoxFlexWrap`, `BoxAlignItems`, `BoxJustifyContent`, `BoxBackgroundColor`, `BoxBorderColor`, `BoxSpacing`, and `BoxBorderWidth` now use const objects with derived string-union types instead of enums - Removed stale Box color entries with no backing design token: - `BoxBackgroundColor.WarningAlternative` - `BoxBackgroundColor.SuccessAlternative` - `BoxBorderColor.WarningAlternative` - `BoxBorderColor.SuccessAlternative` - `BoxBorderColor.InfoAlternative` **Migration:** ```tsx // Before import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningAlternative} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> // After import { BoxBackgroundColor, IconColor, IconName, } from '@metamask/design-system-react-native'; <Box backgroundColor={BoxBackgroundColor.WarningDefault} /> <Icon name={IconName.Add} color={IconColor.IconDefault} /> ``` **Impact:** - Affects consumers relying on enum-specific TypeScript behavior for `Icon*` and `Box*` exports - Import paths stay the same for platform-package consumers - Any use of the removed Box `*Alternative` color entries will need to switch to the corresponding `*Default` or `*Muted` token See migration guides for complete instructions: - [React Migration Guide](./packages/design-system-react/MIGRATION.md#from-version-0170-to-0180) - [React Native Migration Guide](./packages/design-system-react-native/MIGRATION.md#from-version-0190-to-0200) ### Validation - `yarn changelog:validate` <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Medium risk because it publishes new versions with **breaking TypeScript surface changes** (Box/Icon enums → const-object/string-union and removal of stale Box color members), which can break downstream builds despite minimal runtime behavior changes. > > **Overview** > Bumps the monorepo release to `35.0.0` and publishes new package versions for `@metamask/design-system-react` (`0.18.0`), `@metamask/design-system-react-native` (`0.20.0`), and `@metamask/design-system-shared` (`0.13.0`). > > Updates changelogs/migration guides to reflect the release: adds React Native primitives (`TitleStandard`, `TitleSubpage`, `Tag`) and shared prop contracts, and documents **breaking** shifts of `Box*` and `Icon*` exports from enums to const-object + string-union types (plus removal of stale `*Alternative` Box color entries) with consumer-facing migration steps. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit addbae5. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->


Description
What is the goal of this PR?
ListItems,Sections, andKeyValuesWhat are the key updates?
Tag.figma.tsx), stories, tests, and README/Figma link docsRelated issues
JIRA:
This is a dependency for these migration PRs:
Manual testing steps
yarn install && yarn build && yarn storybook:iosto see changesScreenshots/Recordings
Before
Component did not exist before this.
After
Screen.Recording.2026-04-16.at.7.53.17.PM.mov
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Medium Risk
Mostly additive, but it introduces new public exports in both
design-system-react-nativeanddesign-system-shared, which can affect downstream consumers and bundling if misconfigured.Overview
Adds a new React Native
Tagcomponent with severity-based styling and optional start/end icons or accessories, including conditional horizontal padding when icons are present.Introduces shared
TagSeverityandTagPropsSharedindesign-system-sharedand exports them through package indexes, plus supporting Storybook stories, tests, Figma Code Connect mapping (Tag.figma.tsx), and README documentation.Reviewed by Cursor Bugbot for commit ca8046c. Bugbot is set up for automated code reviews on this repo. Configure here.