Skip to content

feat(shared): migrate Box to ADR-0003 and ADR-0004 shared types (DSYS-482)#1026

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

feat(shared): migrate Box to ADR-0003 and ADR-0004 shared types (DSYS-482)#1026
cursor[bot] wants to merge 1 commit intomainfrom
cursor/enum-shared-type-migration-8196

Conversation

@cursor
Copy link
Copy Markdown
Contributor

@cursor cursor bot commented Apr 1, 2026

Description

Migrates the Box component to follow ADR-0003 (String Unions) and ADR-0004 (Centralized Types Architecture) as part of the DSYS-468 epic.

What changed:

  • Created packages/design-system-shared/src/types/Box/Box.types.ts with:
    • BoxFlexDirection, BoxFlexWrap, BoxAlignItems, BoxJustifyContent, BoxBackgroundColor, BoxBorderColor converted from enums to const objects (ADR-0003)
    • BoxSpacing, BoxBorderWidth type aliases (unchanged — already primitive literal types)
    • BoxPropsShared new shared props type with all platform-independent properties (ADR-0004)
  • Exported all Box types from @metamask/design-system-shared index
  • Updated React package Box.types.ts to extend BoxPropsShared from shared
  • Updated React package Box/index.ts to export const objects from shared (single source of truth)
  • Updated React Native package Box.types.ts to extend BoxPropsShared from shared
  • Updated React Native package Box/index.ts to export const objects from shared
  • Removed old Box enums from both platform src/types/index.ts files
  • Updated all files importing Box types directly from ../../types to import from @metamask/design-system-shared (BannerBase, BannerAlert, BoxHorizontal, BoxVertical, and various story files)

All enum values are identical across React and React Native (both use Tailwind class strings), so all enums qualify for ADR-0003 migration.

Related issues

Fixes: DSYS-482

Manual testing steps

  1. Run yarn build from repo root — should succeed
  2. Run yarn test from repo root — all Box tests should pass with 100% coverage
  3. Run yarn lint from repo root — no new lint errors

Screenshots/Recordings

Before

BoxFlexDirection, BoxFlexWrap, BoxAlignItems, BoxJustifyContent, BoxBackgroundColor, BoxBorderColor were enums duplicated in both design-system-react/src/types/index.ts and design-system-react-native/src/types/index.ts with no shared source.

After

All Box enums are now const objects in @metamask/design-system-shared, with a single BoxPropsShared type containing all platform-independent props. Both React and React Native packages extend BoxPropsShared and add their platform-specific props (className/asChild for React, twClassName for React Native).

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

Medium Risk
Medium risk because it replaces duplicated Box enums/types across React and React Native with new shared exports and updates many imports, which can cause downstream type/Storybook breakage if any consumer relied on the old enum shapes.

Overview
Migrates Box type definitions to @metamask/design-system-shared by introducing new shared Box exports (including BoxPropsShared) and converting several Box* enums to const object + string-union types.

Updates React and React Native Box component types to extend BoxPropsShared, re-exports Box types from shared in each package, and removes the legacy Box* types from each platform’s src/types/index.ts. Related components/tests/stories (e.g., BannerBase, BannerAlert, BoxHorizontal/Vertical, and Storybook stories) are adjusted to import Box types/colors from shared instead of local types.

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

📖 Storybook Preview

@georgewrmarshall georgewrmarshall self-assigned this Apr 1, 2026
@georgewrmarshall
Copy link
Copy Markdown
Contributor

@metamaskbot publish-preview

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 2, 2026

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/design-system-react": "0.13.0-preview.69c659c",
  "@metamask-previews/design-system-react-native": "0.13.0-preview.69c659c",
  "@metamask-previews/design-system-shared": "0.6.0-preview.69c659c",
  "@metamask-previews/design-system-tailwind-preset": "0.6.1-preview.69c659c",
  "@metamask-previews/design-system-twrnc-preset": "0.4.0-preview.69c659c",
  "@metamask-previews/design-tokens": "8.3.0-preview.69c659c"
}

…-482)

- Create packages/design-system-shared/src/types/Box/Box.types.ts with:
  - BoxFlexDirection, BoxFlexWrap, BoxAlignItems, BoxJustifyContent,
    BoxBackgroundColor, BoxBorderColor converted from enums to const objects (ADR-0003)
  - BoxSpacing, BoxBorderWidth type aliases (unchanged primitive types)
  - BoxPropsShared new shared props type with platform-independent properties (ADR-0004)
- Export Box types from @metamask/design-system-shared index
- Update React package Box.types.ts to extend BoxPropsShared from shared
- Update React package Box/index.ts to export const objects from shared
- Update React Native package Box.types.ts to extend BoxPropsShared from shared
- Update React Native package Box/index.ts to export const objects from shared
- Remove old Box enums from both platform type indices
- Update all files importing Box types to import from @metamask/design-system-shared

Co-authored-by: George Marshall <georgewrmarshall@users.noreply.github.com>
@georgewrmarshall georgewrmarshall force-pushed the cursor/enum-shared-type-migration-8196 branch from 69c659c to a73a010 Compare April 8, 2026 21:19
@georgewrmarshall
Copy link
Copy Markdown
Contributor

@metamaskbot publish-preview

*/
export const BoxBorderColor = {
/** Background default for cut out effect */
BackgroundDefault: 'border-background-default',
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.

ADR-0003: const objects are runtime backwards-compatible with the old enums.

The old enum BoxFlexDirection { Row = 'flex-row' } and the new const BoxFlexDirection = { Row: 'flex-row' } as const produce identical runtime values — BoxFlexDirection.Row === 'flex-row' in both. Consumers who access members by name (BoxFlexDirection.Row) require no code changes. The only behavioral difference is TypeScript narrows the derived union type ('flex-row' | 'flex-row-reverse' | ...) instead of treating it as an opaque enum — which is strictly more permissive for string literal assignments.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

📖 Storybook Preview

* The background color of the component.
*/
backgroundColor?: BoxBackgroundColor;
};
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 are className, twClassName, and asChild absent from BoxPropsShared?

These are platform-specific concerns: className is web-only CSS, twClassName is React Native TWRNC, and asChild is the Radix UI polymorphic pattern used only in React web. Per ADR-0004, shared props must be platform-independent — only layout/spacing/color props that map to the same Tailwind class names on both platforms belong here. Each platform's BoxProps adds its own extension props on top.

* @default false
*/
asChild?: boolean;
};
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.

~130 lines collapsed to ~17: the full reduction enabled by ADR-0004.

All spacing/layout/color prop declarations now live in BoxPropsShared in the shared package. The React BoxProps only needs to add the two web-specific props: className (Tailwind CSS override) and asChild (Radix UI slot pattern for polymorphic rendering). This is the intended outcome of the centralized types architecture — platform files become thin extension layers.

type BoxBorderWidth,
} from '@metamask/design-system-shared';
export { Box } from './Box';
export type { BoxProps } from './Box.types';
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 BoxBorderWidth is now exported from index.ts when it wasn't before.

The React package previously only re-exported BoxSpacing (not BoxBorderWidth) from its index.ts. Now that both types live in the shared package, both are exported here to maintain a complete public API from the component barrel. This brings React into parity with React Native, which already needed BoxBorderWidth for its constants file.

} from '../../types';
} from '@metamask/design-system-shared';

import { IconColor, IconName } from '../../types';
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 split-import pattern is the correct ADR-0004 boundary in practice.

BannerAlertSeverity, BoxBackgroundColor, and BoxBorderColor are cross-platform design system tokens → imported from @metamask/design-system-shared. IconColor and IconName are still platform-specific (React Native Icon enum values differ from React) → stay in ../../types. This file is a good example of where the shared/platform boundary sits for a real consuming component.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Preview builds have been published. See these instructions for more information about preview builds.

Expand for full list of packages and versions.
{
  "@metamask-previews/design-system-react": "0.15.0-preview.a73a010",
  "@metamask-previews/design-system-react-native": "0.15.0-preview.a73a010",
  "@metamask-previews/design-system-shared": "0.8.0-preview.a73a010",
  "@metamask-previews/design-system-tailwind-preset": "0.6.1-preview.a73a010",
  "@metamask-previews/design-system-twrnc-preset": "0.4.1-preview.a73a010",
  "@metamask-previews/design-tokens": "8.3.0-preview.a73a010"
}

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