Pilot

RN-universal Button pilot

Scaffolded

The left column renders the existing shadcn/Radix Button (DOM-only). The right column renders a React Native Button authored against View / Text / Pressable, served on the web via react-native-web. Both read from the same tokens and respond to the brand-theme switcher — proof that the RN-universal chain is compatible with the existing Vite + Tailwind v4 showcase.

Side-by-side variants

Variant
shadcn (DOM)
RN (via RN Web)
Primary
Secondary
Outline
Ghost
Destructive
Link

Sizes (primary only)

Size
shadcn (DOM)
RN (via RN Web)
sm
default
lg

Disabled state

shadcn
RN

Accessibility parity

Concernshadcn approachRN approach
RoleNative <button>accessibilityRole="button" (→ ARIA on web, native role on iOS/Android)
LabelInline children / aria-labelaccessibilityLabel prop (required for icon variant)
Disableddisabled attr + aria-disableddisabled prop + accessibilityState.disabled
Focus ringfocus-visible:ring-[3px]Same Tailwind class on web; native uses system focus ring in Phase 7
Press/active:active pseudo-classPressable style fn ({ pressed }) — works on web and native

What this pilot proves

  • react-native resolves to react-native-web via the Vite alias, so View / Text / Pressable render as semantic DOM elements.
  • Tailwind v4 utilities applied to RN primitives via className — the existing token bridge (bg-primary, text-foreground, …) works on the right column identically to the left.
  • Brand switching (navy → orange → coral → teal → purple) re-themes both columns simultaneously, because they share the same semantic tokens.
  • The right column's source file is ready to bundle with Metro in Phase 7 to render on iOS and Android.