Rams MCP · The full engine, now in your coding agent
callstack on GitHub

callstack/react-native-paper

Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.

30 files reviewed·July 29, 2026

View on GitHub

Low

Design risk in this codebase.

4issues
Serious & Moderate · top 3 shown below

Top fix

Add a visible or aria label to the icon search input

See the fix

Verdict

Screenshots and search fields look polished but say nothing to assistive tech, a naming gap, not a layout one. Rendering both light and dark galleries at once is the real structural slop, everything else here is a cheap accessibility-attribute fix.

Files Rams reviewed

docs/src/components/BannerExample.tsx

docs/src/components/DynamicColorTheme.tsx

docs/src/components/GooglePlayIcon.tsx

docs/src/components/IconsList.tsx

docs/src/components/PaperHomeShowcase.tsx

docs/src/components/PaperVersionSelector.tsx

docs/src/components/PrereleaseNotice.tsx

docs/src/components/PropTable.tsx

docs/src/components/ScreenshotTabs.tsx

docs/src/components/Showcase.tsx

docs/src/components/ThemeColorsTable.tsx

docs/src/components/ThemeIcon.tsx

src/components/ActivityIndicator.tsx

src/components/Appbar/Appbar.tsx

src/components/Appbar/AppbarAction.tsx

src/components/Appbar/AppbarBackAction.tsx

src/components/Appbar/AppbarBackIcon.tsx

src/components/Appbar/AppbarContent.tsx

src/components/Appbar/AppbarHeader.tsx

src/components/Avatar/AvatarIcon.tsx

src/components/Avatar/AvatarImage.tsx

src/components/Avatar/AvatarText.tsx

src/components/Badge.tsx

src/components/Banner.tsx

src/components/BottomNavigation/BottomNavigationRouteScreen.tsx

src/components/Button/Button.tsx

src/components/Button/utils.tsx

src/components/Card/Card.tsx

src/components/Card/CardActions.tsx

src/components/Card/CardContent.tsx

96/100

Accessibility

2 serious
AccessibilitySerious

docs/src/components/IconsList.tsx:24

Icon search input has no accessible name for screen readers

The search input in IconsList, placeholder "Find icon by name…", has no <label> or aria-label. Placeholder text disappears once a value is typed and is not reliably exposed as an accessible name across screen readers.

Why it matters

Screen reader users hear only "edit text, blank" when focusing the field, so they can't tell what the input is for without sighted help.

Fix

Add an aria-label (or visually hidden <label>) that persists independent of the placeholder.

<input
  className="icons-list-searchbar"
  type="search"
  value={query}
  onChange={(event) => {
    setQuery(event.target.value);
  }}
  placeholder="Find icon by name…"
/>
<input
  className="icons-list-searchbar"
  type="search"
  aria-label="Find icon by name"
  value={query}
  onChange={(event) => {
    setQuery(event.target.value);
  }}
  placeholder="Find icon by name…"
/>
AccessibilitySerious

docs/src/components/PaperHomeShowcase.tsx:31

Component gallery screenshots ship with empty alt text

renderGallery renders every image (button.png, card.png, typography.png, and their dark variants) with alt="". These are the actual content of the section, illustrating what each Paper component looks like, not decoration.

Why it matters

A screen reader user browsing this section hears nothing about what each component looks like, losing the entire visual proof point the section exists to make.

Fix

Give each gallery image a descriptive alt derived from its filename instead of an empty string.

const renderGallery = (images: string[]) =>
  images.map((imageName) => (
    <img
      alt=""
      className="paper-home-showcase__gallery-image"
      key={imageName}
      src={`/react-native-paper/gallery/${imageName}`}
    />
  ));
const renderGallery = (images: string[]) =>
  images.map((imageName) => (
    <img
      alt={`${imageName.replace(/-dark|\.png/g, '').replace(/-/g, ' ')} component example`}
      className="paper-home-showcase__gallery-image"
      key={imageName}
      src={`/react-native-paper/gallery/${imageName}`}
    />
  ));
98/100

Craft

1 serious
CraftSerious

docs/src/components/PaperHomeShowcase.tsx:73

Both light and dark galleries render for every visitor at once

The section renders a div.gallery-light with renderGallery(lightImages) and a div.gallery-dark with renderGallery(darkImages) back to back, with no conditional based on the active theme. That's 24 images loaded and painted for a gallery meant to show one theme at a time.

Why it matters

Every visitor downloads and lays out double the images this section needs, and unless CSS elsewhere hides one variant, users see both a light and dark screenshot of the same component stacked, which reads as a bug rather than a feature.

Fix

Toggle visibility with the site's theme state (or CSS prefers-color-scheme) instead of shipping both variants unconditionally.

<div className="paper-home-showcase__gallery gallery-light">
  {renderGallery(lightImages)}
</div>

<div className="paper-home-showcase__gallery gallery-dark">
  {renderGallery(darkImages)}
</div>
<div className="paper-home-showcase__gallery gallery-light" data-theme="light">
  {renderGallery(lightImages)}
</div>

<div className="paper-home-showcase__gallery gallery-dark" data-theme="dark">
  {renderGallery(darkImages)}
</div>
{/* toggle visibility via the site theme context, hiding the inactive variant with CSS rather than rendering both */}

Typography

No issues found

Color

No issues found

Spacing

No issues found

Components

No issues found

Motion

No issues found

UX

No issues found

Working well

  • Filtering on both hyphenated and de-hyphenated query forms in IconsList (item.includes(query.replace(/\s/g, '-')) and item.replace(/-/g, '').includes(query)) is a thoughtful touch that makes search forgiving of how users actually type icon names like 'account circle' vs 'account-circle'.
  • Splitting the intro into a separate eyebrow ("In practice"), title ("Material components, typography, and controls"), and copy paragraph in PaperHomeShowcase keeps the reading order and hierarchy clear instead of collapsing them into one dense block.
  • Using native <details>/<summary> for the version dropdown elsewhere in these docs gets keyboard toggling and disclosure semantics for free, which is the right call over a hand-rolled popover.

Scored July 29, 2026 with Rams Engine v0.0.3 · Engine changelog

This page is an automated design review of callstack/react-native-paper’s UI code: 30 files read against 258 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; any confirmed critical issue caps it at 59.

More design scores

Score your own repo.

Free on public repos, no account. The same engine that scored this page reads your UI code and mints a score page like this one.

Public repos only. The full engine reviews the UI code and mints a public score page — we email you the link too. Already-scored repos open instantly.

Or get a design review on every pull requestInstall Rams