Skip to content

feat: migrate BadgeIcon to ADR-0004 shared types (DSYS-479)#1010

Draft
cursor[bot] wants to merge 1 commit intomainfrom
cursor/enum-shared-type-migration-5ff7
Draft

feat: migrate BadgeIcon to ADR-0004 shared types (DSYS-479)#1010
cursor[bot] wants to merge 1 commit intomainfrom
cursor/enum-shared-type-migration-5ff7

Conversation

@cursor
Copy link
Copy Markdown
Contributor

@cursor cursor bot commented Mar 29, 2026

Description

This PR migrates the BadgeIcon component to follow ADR-0004 (Centralized Types Architecture) by creating a shared BadgeIconPropsShared type in @metamask/design-system-shared and updating both React and React Native platform packages to extend it.

What changed:

  • Created packages/design-system-shared/src/types/BadgeIcon/BadgeIcon.types.ts with BadgeIconPropsShared (platform-independent iconName: string prop)
  • Added packages/design-system-shared/src/types/BadgeIcon/index.ts and exported from shared package index
  • Updated packages/design-system-react/src/components/BadgeIcon/BadgeIcon.types.ts to import and extend BadgeIconPropsShared, narrowing iconName to the platform-specific IconName enum
  • Updated packages/design-system-react-native/src/components/BadgeIcon/BadgeIcon.types.ts to import and extend BadgeIconPropsShared, narrowing iconName to the platform-specific IconName enum

This is a non-breaking internal refactor — the component APIs remain identical to consumers.

Related issues

Fixes: DSYS-479

Manual testing steps

  1. Run yarn build — should complete without errors
  2. Run yarn test — all tests should pass with 100% coverage
  3. Run yarn lint — should pass with no issues

Screenshots/Recordings

N/A — internal type refactor with no visual changes.

Before

No visual changes

After

No visual changes

badgeicon.after.720.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.
Open in Web View Automation 

Note

Low Risk
Low risk type-only refactor that centralizes BadgeIcon props in @metamask/design-system-shared while keeping the public component APIs effectively the same. Main risk is minor TypeScript incompatibilities for downstream builds if any consumers relied on the previous local type shapes.

Overview
Migrates BadgeIcon to ADR-0004 centralized typing by introducing a new shared BadgeIconPropsShared (with iconName: string) in @metamask/design-system-shared and exporting it from the shared package index.

Updates both React and React Native BadgeIconProps to extend BadgeIconPropsShared (omitting and re-declaring iconName as the platform-specific IconName), keeping platform-only props (className/style for React and twClassName/ViewProps for RN) intact.

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

@github-actions
Copy link
Copy Markdown
Contributor

📖 Storybook Preview

@georgewrmarshall georgewrmarshall self-assigned this Mar 30, 2026
georgewrmarshall added a commit that referenced this pull request Apr 7, 2026
…ignment (#994)

## **Description**

### Why

Cursor Automations are configured in the Cursor product UI and are
**not** version-controlled in git. We need an in-repo **canonical spec**
for the DSYS-468 / ADR-0003–0004 internal migration workflow (Jira
pickup, which rules to follow, verification, PR expectations) so it can
be reviewed in PRs and linked or copy-pasted into **Private** or **Team
Visible** automations.

### What changed

- **Added** `.cursor/automations/enum-shared-type-migration.md` — JQL
(interactive vs scheduled unassigned backlog), Jira pickup steps, Cursor
Cloud Automation notes (billing/identity, tools), implementation
pointers to `CLAUDE.md` and Layer 2 rules
(`component-enum-union-migration`, etc.), verification (`yarn build`,
`yarn test`, `yarn lint`), and a **paste-ready** cloud prompt.
- **Updated** `docs/ai-agents.md` — **Cursor Cloud Automations**
subsection aligned with repo agent principles (*reference over
duplication*, checklists, context efficiency, verification) and explicit
note that **`.cursor/automations/`** is the VCS source of truth because
the Automations UI has no native version control.
- **Removed** unrelated migration tracking artifacts from this branch:
`.cursor/rules/component-migration-tracking.md`,
`.cursor/rules/enum-shared-type-migration.mdc`, and docs
`component-migration-project.md`, `extension-migration-tracker.md`,
`jira-ticket-creation.md`, `mobile-migration-tracker.md`. Automation is
invoked via `@.cursor/automations/enum-shared-type-migration.md` only
(no companion `.mdc` rule).
- **Chore** — Prettier on touched markdown where required by hooks.

### Linking specs from Cursor Automations (for reviewers)

There is **no official Cursor documentation** that guarantees a cloud
agent will **fetch and follow** an arbitrary GitHub blob URL.
**Recommended:** configure the automation with a **repository + branch**
that contains this file, and instruct the agent to read
**`.cursor/automations/enum-shared-type-migration.md` in the
workspace**. A **GitHub link** (especially `raw.githubusercontent.com`
or a **pinned commit**) is still useful for humans, pinning a frozen
spec, or external tooling—but treat it as **supplementary** to the
checked-out file.

## **Related issues**

Fixes: (none — contributor workflow / tooling only)

## **Manual testing steps**

1. On this branch, open
`.cursor/automations/enum-shared-type-migration.md` and confirm
structure, JQL blocks, and links render as expected.
2. In Cursor Chat, `@`-mention
`.cursor/automations/enum-shared-type-migration.md` and confirm the
agent is directed to `docs/ai-agents.md` and the listed
`@.cursor/rules/*.md` files for implementation (not
`component-migration.md` for this epic).
3. Confirm no remaining references to deleted paths (e.g.
`component-migration-tracking`, removed tracker docs) via repo search.
4. (Optional) Create or edit a **Private** test automation: paste the
**cloud prompt** snippet from the automation doc and run against a
branch that includes this file; confirm the agent can see
`.cursor/automations/enum-shared-type-migration.md` on disk.

## **Example PRs**

PRs that have been successfully created with this automation

- #996
- #1009
- #1010
- #1015

## **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 (N/A — docs only)
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable (N/A)
- [ ] 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**
> Low risk: documentation-only changes that add guidance for Cursor
Automations and do not affect runtime code paths.
> 
> **Overview**
> Adds a version-controlled Cursor Automation spec at
`.cursor/automations/enum-shared-type-migration.md` that defines the
DSYS-468 Jira pickup workflow (JQL for interactive vs scheduled runs),
required tools/identity notes, which `.cursor/rules/` to follow for the
migration, and a paste-ready automation prompt (plus post-merge
Jira-closing guidance).
> 
> Updates `docs/ai-agents.md` to explicitly document how Cursor Cloud
Automations should follow the repo’s agent principles (*reference over
duplication*, checklists, verification) and to treat
`.cursor/automations/` as the canonical, reviewable source of truth for
automation prompts.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2594fa9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: cursor[bot] <206951365+cursor[bot]@users.noreply.github.com>
- Create BadgeIconPropsShared in packages/design-system-shared
- Export from shared package index
- Update React package BadgeIcon.types.ts to extend shared props
- Update React Native package BadgeIcon.types.ts to extend shared props

Co-authored-by: George Marshall <georgewrmarshall@users.noreply.github.com>
@georgewrmarshall georgewrmarshall force-pushed the cursor/enum-shared-type-migration-5ff7 branch from 628c733 to c060291 Compare April 8, 2026 21:22
* Required prop to specify an icon to show.
* Use the platform-specific `IconName` type to provide values.
*/
iconName: string;
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.

Why is iconName typed as string instead of IconName?

The shared package has no knowledge of platform-specific icon enums — IconName is defined separately in @metamask/design-system-react and @metamask/design-system-react-native and importing either would violate the dependency direction of ADR-0004. Using string keeps the shared contract platform-neutral. Each platform then overrides it with its own strongly-typed IconName via the Omit + redeclaration pattern in their respective BadgeIconProps.

style?: React.CSSProperties;
};
export type BadgeIconProps = ComponentProps<'div'> &
Omit<BadgeIconPropsShared, 'iconName'> & {
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.

Why Omit<BadgeIconPropsShared, 'iconName'> instead of a straight intersection?

BadgeIconPropsShared declares iconName: string (the widest type the shared layer can express). A plain intersection would widen the React iconName: IconName back to string since TypeScript resolves conflicting members to the broader type. The Omit drops the loose string definition first, letting the platform re-declare iconName: IconName with full type safety.

} from './types/AvatarToken';

// BadgeIcon types (ADR-0004)
export { type BadgeIconPropsShared } from './types/BadgeIcon';
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.

Why is only a type exported here with no const objects?

BadgeIcon has no variants, sizes, or other enum-like props — the only shared prop is iconName. Unlike BadgeStatus or BannerAlert, there are no ADR-0003 const objects to centralise. A type-only export is correct for this component.

* Extends shared props from @metamask/design-system-shared with React Native specific platform concerns
*/
export type BadgeIconProps = {
export type BadgeIconProps = Omit<BadgeIconPropsShared, 'iconName'> & {
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.

Why is iconProps not in BadgeIconPropsShared?

iconProps is typed as Omit<IconProps, 'name'> where IconProps is the platform-specific icon component's props type. Since both platforms have different IconProps definitions, this prop can't be expressed in the shared layer without introducing a platform dependency. It correctly stays in each platform's extension.

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.

This may change once we migrate Icon

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

📖 Storybook Preview

@georgewrmarshall georgewrmarshall marked this pull request as ready for review April 8, 2026 21:27
@georgewrmarshall georgewrmarshall requested a review from a team as a code owner April 8, 2026 21:27
@georgewrmarshall georgewrmarshall enabled auto-merge (squash) April 8, 2026 21:27
@georgewrmarshall georgewrmarshall marked this pull request as draft April 8, 2026 21:29
auto-merge was automatically disabled April 8, 2026 21:29

Pull request was converted to draft

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants