callstack/react-native-paper
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
30 files reviewed·July 29, 2026
Low
Design risk in this codebase.
More findings
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
Accessibility
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…"
/>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}`}
/>
));Craft
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
Color
Spacing
Components
Motion
UX
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.