React Native Paper: MD3 Component Review #4949
adrcotfas
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Systematic review of each component against the current Material Design 3 guidelines.
Important
Baseline: This audit is done on top of the changes from Add dynamic material themes.
In the meantime more changes were added to the
v6branch, like theme tokens which should be used for all components.Review axes:
corner.*)Reference implementation: Behavior (especially animations not always described in written spec) should be cross-checked against https://github.com/material-components/material-components-android
General notes:
4 * roundness,7 * roundness) with no named constants. Atheme.shapesobject with named entries (extraSmall,small,medium,large,extraLarge,full) would make shape intent explicit, allow global overrides, and eliminate the scattered multiplier magic throughout component code.src/components/. Currently some components are loose files (e.g.,Divider.tsx,Badge.tsx) while others have directories. Standardize to one directory per component.src/components/Buttons/directory, matching the MD3 spec grouping. This includesButton,IconButton,SegmentedButtons,ToggleButton, andFAB(the MD3 spec groups FAB under Buttons).List.AccordionGroup,List.Section,Surface) should be moved to a separate directory such assrc/components/custom/or clearly marked as library extensions, so the MD3 surface area is unambiguous.Components were reviewed according to the order they appear in the Example app.
Activity Indicator
MD3 spec: Progress indicators (Circular)
Specs link: https://m3.material.io/components/progress-indicators/specs
Color tokens
secondaryContainer); onlyprimaryis renderedSpacing / sizing
size / 10(2.4dp @ small, 4.8dp @ large). MD3 specifies a fixed 4dp stroke for both indicator and trackBehavior
Notes
CircularProgressIndicatorand move to a “Progress Indicators” directory together with Linear Progress Indicator.Animated FAB
MD3 spec: Extended FAB
Specs link: https://m3.material.io/components/extended-fab/specs
Color tokens
surfacevariant (surfaceContainerHighbg /primaryfg) does not exist in the MD3 Extended FAB spec. Onlyprimary,secondary, andtertiaryare definedprimary,secondary,tertiaryvariants map to correct MD3 container/on-container token pairs ✅Spacing / sizing
SIZE / 3.5) instead of derived fromtheme.roundnesslikeFABdoes (4 * roundness)extendedWidth = textWidth + SIZE + borderRadiusleaves 16dp)SIZE = 56). Spec defines three sizes: small (56dp), medium (80dp), large (96dp), each with different corner radii and icon sizesBehavior
iconMode: 'dynamic'(default) slides the icon during collapse/extend. MD3 keeps the icon on the leading side; only the label fades in/outborderRadiusmorphs between FAB (28dp) and Extended FAB (16dp) as part of the transform sequenceEasing.linear. MD3 motion tokens require standard easing (emphasizedDecelerate / emphasizedAccelerate)Notes
ExtendedFABAppbar
MD3 spec: App bars (Top app bar)
Specs link: https://m3.material.io/components/app-bars/specs
Color tokens
surface(flat) ✅surfaceContainerwhenelevatedprop is set ✅onSurface✅onSurfaceVariant✅onSurface✅Spacing / sizing
titleLarge/headlineSmall/headlineMedium) ✅Behavior
Searchbarcomponent)mediumandlargemodes implement the baseline variants, which are explicitly not recommended in M3 Expressive. Flexible counterparts should be added and baselines deprecatedcenter-alignedis a separatemodevalue. M3 Expressive merges it intosmallas a text-alignment configurationelevatedis a static boolean. MD3 specifies the container color transitions reactively on scroll (surfacetosurfaceContainer); no scroll-reactive API is provided@deprecatedin v5. M3 Expressive medium flexible and large flexible variants restore subtitle as a supported elementNotes
Avatar
MD3 spec: N/A (no Avatar component in MD3 specs)
Badge
MD3 spec: Badges
Specs link: https://m3.material.io/components/badges/specs
Color tokens
error✅onError✅Spacing / sizing
sizeis 20dp. MD3 defines small badge at 6dp (no label) and large badge at 16dp (with label)paddingHorizontal: 3. Spec requires 4dp between badge edge and textfontSize = size * 0.5yields 8sp at 16dp. Spec requires 11sp for large badge label textBehavior
Banner
MD3 spec: N/A (no Banner component in MD3 specs)
Bottom Navigation
MD3 spec: Navigation bar
Specs link: https://m3.material.io/components/navigation-bar/specs
Notes
BottomNavigationis a router-aware wrapper aroundBottomNavigation.Barthat handles scene management and tab transitions. MD3 compliance is governed byBottomNavigation.Barbelow.Bottom Navigation Bar
MD3 spec: Navigation bar
Specs link: https://m3.material.io/components/navigation-bar/specs
Color tokens
surfaceContainer✅onSecondaryContainer✅secondaryContainer✅onSurfaceVariant✅onSurfaceVariant✅onSurface. Spec tokenNav bar item active label text colormaps tosecondarySpacing / sizing
marginBottom: 4on icon container) ✅v3NoLabelContainerheight is hardcoded to 80dp. Spec requires 64dpBAR_HEIGHT = 56constant is used for label height styling. Spec bar height is 64dpBehavior
shiftingmode (inactive tabs hide labels) is an MD2 pattern not present in MD3labeled={false}hides all labels (not in MD3 spec, but a deliberate extension used by Google’s own products e.g. Gmail) ✅rippleColor: 'transparent'suppresses state layer feedback. MD3 requires visible state layers (8% hovered, 10% focused/pressed)Notes
NavigationBarButton
MD3 spec: Buttons
Specs link: https://m3.material.io/components/buttons/specs
Color tokens
surfaceContainerLowbg /primarylabel ✅contained):primarybg /onPrimarylabel ✅contained-tonal):secondaryContainerbg /onSecondaryContainerlabel ✅primarylabel ✅outlineVariant. Spec token isoutlineprimary. Spec token isonSurfaceVariantSpacing / sizing
marginVertical: 10+labelLargeline height) ✅5 * roundness= 20dp (fully rounded for small) ✅md3LabelmarginHorizontal). Spec recommends 16dp; 24dp is explicitly marked as no longer recommendedBehavior
containedshould befilled,contained-tonalshould betonalNotes
modeis'text'; MD3 hierarchy impliesfilledas the primary/default button styleCard
MD3 spec: Cards
Specs link: https://m3.material.io/components/cards/specs
Color tokens
Surfaceelevation=1 forsurfaceContainerLowbg (verify Surface implements this correctly)surfacebg ✅contained(filled) usessurfaceVariant. Spec requiressurfaceContainerHighestcolors.outline. Spec token isoutlineVariant(#CAC4D0)Spacing / sizing
3 * roundness= 12dp ✅CardContenthorizontal padding 16dp ✅Behavior
containedshould befilledto match MD3Pressabledirectly instead ofTouchableRipple. No MD3 ripple / state layer feedback on pressCheckbox
MD3 spec: Checkbox
Specs link: https://m3.material.io/components/checkbox/specs
Color tokens
onSurfaceVariant✅ (Android only; iOS has no outline at all)primary✅ (used as icon tint, not as a real filled container)onSurfaceat 38% opacity ✅checkbox-markedglyph withprimarytint achieves the correct visual (filled box + white checkmark baked into the glyph) ✅errortokens for unselected error outline and selected error container (md.sys.color.error), andonErrorfor the error iconSpacing / sizing
MaterialCommunityIconglyphs that carry their own shapeBehavior
Checkboxcomponent switches implementation based on platform (CheckboxIOSvsCheckboxAndroid) — this should be unified into a single cross-platform MD3 implementationCheckboxIOSrenders no visible box for the unchecked state — just a floating check icon that fades in/out. MD3 requires a visible 2dp outline box when uncheckedCheckboxIOSlacks anuncheckedColorprop present onCheckboxAndroid— API inconsistency between the two implementationsminus-boxglyph (filled box + minus), iOS uses a plainminusicon. Both should match MD3’s filled-container-with-dash appearanceCheckbox Item
MD3 spec: N/A (library-specific compound component: Checkbox + label row)
Notes
Chip
MD3 spec: Chips (Assist, Filter, Input, Suggestion)
Specs link: https://m3.material.io/components/chips/specs
Color tokens
outlinedmode borderoutlineVariant✅outlinedmode labelonSurfaceVariant✅flatmode background is alwayssecondaryContainerregardless ofselectedstate. Unselected assist/suggestion chips should have no fill (transparent); only selected filter chips usesecondaryContainerelevated=trueprop only animates elevation, never changes the background color. Elevated chip background should besurfaceContainerLowprimaryfor all non-disabled chips regardless of chip type or selected state. Filter chip unselected icon should beonSurfaceVariant; selected filter/input chip icon should beonSecondaryContainershowSelectedOverlayprop is declared but never consumed in the render path; selected overlay has no effectSpacing / sizing
marginVertical: 6+labelLarge20dp line height)2 * roundness) ✅borderRadius: 12(full circle) ✅compactmode reduces horizontal label margins from 16dp to 12dp (reasonable extension, not in spec)Behavior
Chipcomponent covers all four MD3 chip types (assist, filter, input, suggestion) but does not expose atypeprop. Each type has distinct color semantics (label, icon, selected container) that the current implementation does not fully modelselectedstate inflatmode:getSelectedBackgroundColorreturns the same value as the unselected background (secondaryContainer). No background color transition occurs; selection is only visible via the checkmark icononClose) is rendered inside a barePressablewith noTouchableRipplestate layershowSelectedOverlay(declared prop) is unused; no selected overlay is appliedNotes
selected/onClose; filter chip ~selected; input chip ~onClose; suggestion chip ~ outlined with no selection. Proper separation would need atypeorvariantprop with distinct color logic per typeData Table
Dialog
MD3 spec: Dialogs
Specs link: https://m3.material.io/components/dialogs/specs
Color tokens
surfaceContainerHigh✅secondary✅onSurface✅headlineSmall✅primary✅ (viaButtontext mode)Dialog.ScrollAreadivider border color usessurfaceVariant; spec token isoutlineSpacing / sizing
7 * roundness= 28dp (corner.extra-large) ✅marginTop: 24,marginHorizontal: 24; actionspaddingBottom: 24,paddingHorizontal: 24)DialogTitlemarginBottom: 16)DialogTitlemarginTop: 16as non-first child)marginHorizontal: Math.max(left, right, 26)onlyDialog.Iconis the first child, Dialog injectsmarginTop: 24on it (the injection applies to all first children), stacking on top ofDialogIcon’s ownpaddingTop: 24. Total gap from dialog edge to icon becomes 48dp instead of 24dpBehavior
Dialog.Titledoes not detect whetherDialog.Iconis present. Spec requires center-aligned title when an icon is shown; text alignment is not automatically adjustedDivider
MD3 spec: Divider
Specs link: https://m3.material.io/components/divider/specs
Color tokens
outlineVariant✅Spacing / sizing
leftInsetmargin-left 16dp ✅horizontalInsetmargin 16dp both sides ✅StyleSheet.hairlineWidth(sub-pixel on most platforms). Spec requires 1dp. Only theboldprop produces a 1dp divider, butboldis not an MD3 conceptFAB
MD3 spec: Floating action button
Specs link: https://m3.material.io/components/floating-action-button/specs
Color tokens
primaryvariant:primaryContainerbg /onPrimaryContainerfg ✅secondaryvariant:secondaryContainerbg /onSecondaryContainerfg ✅tertiaryvariant:tertiaryContainerbg /onTertiaryContainerfg ✅surfacevariant (surfaceContainerHighbg /primaryfg) is not defined in the MD3 FAB specprimary,secondary, andtertiarycolor styles that use the actual role colors (primary/onPrimary, etc.) rather than their container counterparts. The current variant names map to container colors onlySpacing / sizing
3 * roundness= 12dp radius (corner.medium) ✅4 * roundness= 16dp radius (corner.large) ✅7 * roundness= 28dp radius (corner.extra-large) ✅corner.large-increased, 28dp icon) not implemented. Currentsize='medium'maps to the standard 56dp FAB, not the Expressive 80dp sizeBehavior
Surfaceelevation system (flat= 0,elevated= level 3) ✅TouchableRipple✅size='small'Notes
labelprop) andAnimatedFABshare the same visual spec but are implemented in separate files with no code sharing.AnimatedFAB.tsxdoes not reuseFAB.tsx. Recommend consolidating into a single component tree with shared layout primitives after the audit.FAB Menu
MD3 spec: FAB menu
Specs link: https://m3.material.io/components/fab-menu/specs
Color tokens
primarybg /onPrimaryfg for the primary variant – current code passesvariantto<FAB>which resolves toprimaryContainer/onPrimaryContainerprimaryContainerbg /onPrimaryContainericon+label for primary variant –stackedFABBackgroundColoris alwayssurfaceContainerHighregardless ofvariantonSurface; spec requires variant-specificonPrimaryContainer/onSecondaryContainer/onTertiaryContainerSpacing / sizing
corner.full(28dp for 56dp container); current FAB medium usescorner.large= 16dpcorner.full; current FAB small/medium usescorner.medium(12dp) /corner.large(16dp)titleMedium✅marginHorizontalon the item wrapper ✅styles.itemhasmarginBottom: 16marginBottom: 16on item rowsBehavior
TouchableRipple✅Card mode="contained"with hardcodedborderRadius: 5; spec treats label as an inline part of the menu item row, not a separate cardAnimatedPressablewiththeme.colors.backgroundat 0.95 opacity) is not part of the MD3 FAB menu spec and should be removedsurfaceContainerHighbackgroundNotes
FABGroupinternally but maps to the MD3 “FAB menu” patternvariantfor list items entirelyIcon
No direct MD3 equivalent. Internal primitive reused by other components. Skipped.
Icon Button
MD3 spec: Icon buttons
Specs link: https://m3.material.io/components/icon-buttons/specs
Color tokens
Filled (
mode="contained")primarybg /onPrimaryicon ✅surfaceContainerbg /onSurfaceVarianticon; current issurfaceVariantbg /primaryicon – wrong token and wrong icon colorselectedprop): indistinguishable from toggle unselected at the API level; a non-toggle filled button should always showprimarybg /onPrimaryicon but currently shows the wrong unselected colorsTonal (
mode="contained-tonal")secondaryContainerbg /onSecondaryContainericon; current issurfaceVariantbg /onSurfaceVarianticon ❌secondarybg /onSecondaryicon; current issecondaryContainerbg /onSecondaryContainericon ❌ (selected/unselected tokens are swapped)Outlined (
mode="outlined")outlineVariantborder /onSurfaceVarianticon ✅inverseSurfacebg /inverseOnSurfaceicon ✅Standard (no mode)
onSurfaceVarianticon ✅primaryicon ✅Disabled
onSurfaceatstateOpacity.disabled(0.38) ✅stateOpacity.disabled(0.38); spec requires 0.1 for the containerSpacing / sizing
size + 2 * PADDINGwherePADDING = 8) ✅buttonSize / 2=corner.full✅xsmallsize (32dp container, 20dp icon)mediumsize (56dp container, 24dp icon)largesize (96dp container, 32dp icon)xlargesize (136dp container, 40dp icon)corner.medium/corner.large/corner.extra-largedepending on size)Behavior
TouchableRipple✅selectedprop ✅corner.smallon press (spring animation); not implementedNotes
selectedprop conflates “non-toggle enabled” with “toggle unselected” – both result inselected=false. The spec defines distinct color tokens for these two states (especially for filled). A nullableselected(or a separatetoggleprop) would fix the API ambiguity.List Accordion
MD3 spec: Lists (expand interaction)
Specs link: https://m3.material.io/components/lists/specs
Color tokens
onSurfaceVariant✅primary; spec label text usesonSurfaceregardless of expand stateprimary; spec usesonSurfaceVariantfor leading iconstheme.colors.background; should besurfaceprimaryContainerbg /onPrimaryContainertext/icon) ❌Spacing / sizing
paddingVertical: 8(container) +marginVertical: 6(row) = 14dp each side; spec 1-line item is 56dp total height, requiring 16dp top/bottom padding ❌paddingRight: 24trailing ✅paddingLeft: 16✅fontSize: 16/fontSize: 14; should usetheme.fonts.bodyLarge/theme.fonts.bodyMediumBehavior
Notes
List Accordion Group
MD3 spec: Lists (expand interaction – single-expand group)
Specs link: https://m3.material.io/components/lists/specs
Color tokens
No color logic of its own – delegates to
List.Accordion. ✅Spacing / sizing
No sizing logic of its own. ✅
Behavior
Notes
List.AccordionList Item
MD3 spec: Lists
Specs link: https://m3.material.io/components/lists/specs
Color tokens
onSurface✅onSurfaceVariant✅onSurfaceVariant✅surface✅primaryContainerbg /onPrimaryContainerlabel+icon for selected itemsSpacing / sizing
paddingVertical: 8(container) +marginVertical: 6(row) = 14dp each side; spec 1-line is 56dp requiring 16dp padding each side ❌paddingRight: 24trailing ✅paddingLeft: 16✅fontSize: 16; should usetheme.fonts.bodyLargefontSize: 14; should usetheme.fonts.bodyMediumBehavior
TouchableRipple✅Notes
left/rightrender-prop API is flexible but predates the MD3 slot model (leading / content / trailing); a typed slot API would be more aligned and enable correct padding calculationsList Section
MD3 spec: Lists (section grouping / subheader)
Specs link: https://m3.material.io/components/lists/specs
Color tokens
No color logic; delegates to
ListSubheader. SeeListSubheaderfor token review.Spacing / sizing
marginVertical: 8on the section container – MD3 does not prescribe margin between sections; acceptable as a layout aidBehavior
Notes
ListSubheaderis not audited separately; its token usage should be verified against the MD3 subheader specMenu
MD3 spec: Menus
Specs link: https://m3.material.io/components/menus/specs
Color tokens
theme.colors.elevation[level2]which resolves tosurfaceContainerLow✅ (standard color scheme)Menu.Itemlabel text:onSurface✅Menu.Itemleading/trailing icon:onSurfaceVariant✅Menu.Itemdisabled opacity:stateOpacity.disabled(0.38) ✅tertiaryContainerbg /onTertiaryContainertext+icon for selected menu itemstertiaryContainercontainer /onTertiaryContainericons+labels /tertiaryselected bg /onTertiaryselected text+iconSpacing / sizing
paddingVertical: 8✅paddingHorizontal: 12✅Menu.Itemlabel text usesbodyLarge; spec requireslabelLargeMenu.Itemhas no supporting text slot (bodySmall); spec anatomy includes optional supporting text per itemMenu.Itemhas no trailing supporting text slot (labelLarge); spec anatomy includes optional trailing text per itemShape
borderRadius: theme.roundness= 4dp; speccorner.large=4 * roundness= 16dp ❌corner.mediumtop corners; not implementedcorner.mediumbottom corners; not implementedcorner.medium; not implementedBehavior
Easing.bezier(0.4, 0, 0.2, 1)from old M3 motion guidelines; M3 Expressive uses spring-based motion)Dividerwhich is not the spec-aligned grouping mechanism for vertical menusNotes
borderRadius: theme.roundnessbug is a significant visual regression vs spec – the container should be visibly rounded.Progress Bar
MD3 spec: Linear progress indicator
Specs link: https://m3.material.io/components/progress-indicators/specs
Color tokens
color || theme.colors.primary✅theme.colors.surfaceVariant; spec requiressecondaryContainer❌primary)Spacing / sizing
borderRadius; speccorner.fullrequiresborderRadius: 2for 4dp heightborderRadius; same issue as trackBehavior
scaleX✅Notes
LinearProgressIndicatorand placed in a sharedProgressIndicator/directory alongsideActivityIndicator(circular), matching MD3 namingProgressBarname and thecolorprop (which bypasses the token system) are library-level issues to address at rename timeRadio Button
MD3 spec: Radio button
Specs link: https://m3.material.io/components/radio-button/specs
Color tokens
primary✅onSurfaceVariant✅onSurfaceat 0.38 opacity ✅onSurfacestate layer, unselected pressed =primarystate layer – currentTouchableRippleuses a default ripple color, not these per-state valuesonSurface; currently staysonSurfaceVariantSpacing / sizing
margin: 8gives 36dp container (20 + 8*2); spec requires 40dp; fix:margin: 10,borderRadius: 20Behavior
radioAnim1.2 -> 1) ✅borderWidthcollapses from 10 to 2 ✅TouchableRipple✅RadioButtonGroup✅Notes
RadioButton.tsxis a platform dispatcher toRadioButtonAndroid/RadioButtonIOS; the Android implementation is the cross-platform referencecoloranduncheckedColorprops bypass the token system – library-level issue to addressRadio Button Group
MD3 spec: Radio button (group behavior)
Specs link: https://m3.material.io/components/radio-button/specs
Notes
valueandonValueChange; no rendering of its ownRadioButtonRadio Button Item
MD3 spec: Radio button (with label)
Specs link: https://m3.material.io/components/radio-button/specs
Color tokens
onSurface✅ (spec: adjacent label usesonSurfaceregardless of selection state)stateOpacity.disabled(0.38) ✅RadioButtonSpacing / sizing
paddingVertical: 8, paddingHorizontal: 16– functional but no spec measurement for the item row; consistent with list item convention ✅flexShrink: 1, flexGrow: 1fills available space ✅Behavior
TouchableRipple✅positionprop supports leading/trailing radio placement ✅labelVariantdefaults tobodyLarge✅Searchbar
MD3 spec: Search
Specs link: https://m3.material.io/components/search/specs
Color tokens
surfaceContainerHigh✅onSurfaceVariant✅onSurfaceVariant✅primary✅onSurfaceVariant; should beonSurfaceonSurface; should beonSurfaceVariant– these two are swapped ❌Spacing / sizing
minHeight: 56✅7 * roundness= 28dp (corner.extra-large) ✅ for baseline stylecorner.none) ✅ for divided stylebodyLarge(16sp, overridesfontSize: 18inStyleSheet) ✅Behavior
rightrender prop ✅mode="bar"maps to divided/baseline style with elevation ✅mode="view"maps to divided search view with bottomDivider✅IconButton+TouchableRipple✅modevalues ("bar"/"view") do not align with M3 spec terminology ("contained"/"divided (baseline)")Notes
dividedstyle is deprecated in M3 Expressive in favor ofcontained;mode="view"implements the divided styleSegmented Button
MD3 spec: Segmented buttons (deprecated in M3 Expressive – use Connected Button Group)
Specs link: https://m3.material.io/components/segmented-buttons/overview
Color tokens
secondaryContainer✅onSecondaryContainer✅onSurface✅outline✅Spacing / sizing
paddingVertical: 9+labelLargeline-height (20dp) = 38dp ❌; fix:paddingVertical: 10paddingHorizontal: 16✅marginRight: 5❌5 * roundness= 20dp (corner.full) ✅borderRadius: 0✅labelLarge✅Behavior
showSelectedCheckis true) ✅TouchableRipple✅Notes
src/components/Buttons/alongside the other button types.Snackbar
MD3 spec: Snackbar
Specs link: https://m3.material.io/components/snackbar/specs
Color tokens
inverseSurface✅inverseOnSurface✅inversePrimary✅inverseOnSurface✅Spacing / sizing
borderRadius: roundness= 4dp (corner.extra-small) ✅marginHorizontal: 16, marginVertical: 14✅minHeight: 48✅margin: 8✅bodyMedium✅Behavior
duration✅duration={Infinity}✅Portalby default: spec places the snackbar above all content; users must wrap with<Portal>manually, which is error-proneNotes
borderRadius: 4is hardcoded redundantly inStyleSheetand then overridden byborderRadius: roundness– the StyleSheet value can be removedSurface
MD3 spec: Elevation (no standalone Surface component in MD3)
Specs link: https://m3.material.io/styles/elevation/overview
Color tokens
theme.colors.elevation.levelN✅LightTheme:level3andlevel4both resolve topalette.neutral92– correct per spec (both “Surface at +3” and “Surface at +4” map tosurfaceContainer) ✅MD3Colors.primary0(black constant); should usetheme.colors.shadowso custom themes can override itShape
No shape logic – shape is delegated to consumers. ✅
Spacing / sizing
No sizing logic of its own. ✅
Behavior
elevationlevels 0-5 ✅mode="elevated"adds shadow;mode="flat"suppresses it ✅Animated.Value✅[0, 3, 6, 9, 12, 15]; MD3 spec dp values for levels 0-5 are[0, 1, 3, 6, 8, 12]– all non-zero levels are wrongAnimation
No animation logic of its own beyond interpolating
Animated.Valueinputs. ✅Notes
containerprop is an internal layout workaround for iOS two-layer shadow rendering; not exposed in the public API and not spec-relatedsurfaceContainerLowest / Low / Container / High / Highestcolor roles directly rather than numeric elevation levels for static surfaces;Surfacewith numericelevationis appropriate for interactive elevation changes onlySwitch
MD3 spec: https://m3.material.io/components/switch/specs
Currently wraps the platform-native
Switch. A custom cross-platform implementation is needed: even after facebook/react-native#56484 lands it only modernizes Android, so iOS still requires a custom component to achieve consistent MD3 appearance on all platforms.Text
MD3 spec: Typography
Specs link: https://m3.material.io/styles/typography/overview
Library primitive that wraps the RN
Textcomponent and appliestheme.fonts[variant]styles. No direct MD3 component equivalent – it surfaces the MD3 type scale defined insrc/styles/themes/v3/tokens.tsxandsrc/types.tsx.Color tokens
onSurface✅Spacing / sizing
displayLargethroughbodySmall) ✅displayLargeletterSpacing should be -0.25; currently inheritsregularType.letterSpacing = 0bodyLargeletterSpacing should be 0.5; currently inheritsmediumType.letterSpacing = 0.15(fontWeight/fontFamily are overridden but letterSpacing is not)Behavior
variantprop maps directly totheme.fonts[variant]✅Textvariant/style override logic handled ✅Animation
N/A
Notes
md.sys.typescale.emphasized.*):displayLargeEmphasized,displayMediumEmphasized,displaySmallEmphasized,headlineLargeEmphasized,headlineMediumEmphasized,headlineSmallEmphasized,titleLargeEmphasized,titleMediumEmphasized,titleSmallEmphasized,labelLargeEmphasized,labelMediumEmphasized,labelSmallEmphasized,bodyLargeEmphasized,bodyMediumEmphasized,bodySmallEmphasized. These need to be added toMD3TypescaleKey,typescale, and exposed asvariantoptions on theTextcomponentText Input
MD3 spec: Text fields
Specs link: https://m3.material.io/components/text-fields/specs
Tracked separately: Implement a new TextInput component
Toggle Button
No standalone MD3 equivalent. The toggle behavior (selected/unselected state) is part of Icon button in the MD3 spec. This component should be folded into the
IconButtonimplementation or removed in favor ofIconButtonwith aselectedprop.Tooltip
MD3 spec: Tooltips
Specs link: https://m3.material.io/components/tooltips/specs
Color tokens
theme.colors.onSurface; spec requiresinverseSurfacetheme.colors.surface; spec requiresinverseOnSurfaceShape
borderRadius: theme.roundness= 4dp matchescorner.extraSmall✅Spacing / sizing
labelLarge(14sp); spec requiresbodySmall(12sp)Behavior
title: stringprop cannot support rich contentAnimation
Touchable Ripple
Library primitive that wraps
Pressable(Android) and a custom ripple view (iOS/web) to provide MD3 state-layer feedback. No direct MD3 component equivalent.Notes
TouchableRippledoes not supportPlatformColor, which blocks dynamic theme support for ripple colors. The MD3 spec requires per-component ripple colors (e.g.primaryat pressed opacity for filled buttons,onSurfacefor others), but expressing those asPlatformColorvalues is not yet possiblestateLayerPressedvalue (onSurfaceatmd.sys.state.pressed.state-layer-opacity) is used as the ripple color uniformly across all components in bothLightThemeandDarkTheme. This diverges from spec but is the only viable approach until facebook/react-native#56395 landsBeta Was this translation helpful? Give feedback.
All reactions