steven-tey/precedent
Reviewed against Rams quality heuristics: accessibility, color, typography, spacing, components, motion, UX, and craft.
25 files reviewed·July 25, 2026
More findings
Verdict
Surface polish outruns interaction discipline: nice type and CTA hierarchy sit next to focus rings stripped with nothing to replace them. The biggest risk is a tooltip trigger that keyboard users can't reach at all.
Files Rams reviewed
app/layout.tsx
app/page.tsx
app/opengraph-image.tsx
components/home/card.tsx
components/home/component-grid.tsx
components/home/demo-modal.tsx
components/home/web-vitals.tsx
components/layout/navbar.tsx
components/shared/counting-numbers.tsx
components/shared/icons/buymeacoffee.tsx
components/shared/icons/expanding-arrow.tsx
components/shared/icons/github.tsx
components/shared/icons/google.tsx
components/shared/icons/loading-circle.tsx
components/shared/icons/loading-spinner.module.css
components/shared/modal.tsx
components/shared/popover.tsx
components/shared/tooltip.tsx
app/globals.css
components/shared/icons/index.tsx
components/layout/footer.tsx
components/shared/icons/loading-dots.module.css
components/shared/icons/loading-dots.tsx
components/shared/icons/loading-spinner.tsx
components/shared/icons/twitter.tsx
Accessibility
components/home/component-grid.tsx:50
Tooltip trigger div can never receive keyboard focus
The "Tooltip" trigger in components/home/component-grid.tsx is a plain `<div>` with `cursor-default` and no `tabIndex`, `role`, or keyboard handler, wrapped by the `Tooltip` component. A mouse user can hover it to see the tooltip content, but there is no way to Tab to it.
Why it matters
Keyboard-only and screen-reader users can never trigger this element at all, so the tooltip content is permanently unreachable for them, which is a full lockout rather than a degraded experience.
Fix
Make any element that reveals content on hover also focusable and revealed on focus, using a native button or an explicit tabIndex with keyboard handling.
<Tooltip content="Precedent is an opinionated collection of components, hooks, and utilities for your Next.js project.">
<div className="flex w-36 cursor-default items-center justify-center rounded-md border border-gray-300 px-3 py-2 transition-all duration-75 hover:border-gray-800 focus:outline-none active:bg-gray-100">
<p className="text-gray-600">Tooltip</p>
</div>
</Tooltip><Tooltip content="Precedent is an opinionated collection of components, hooks, and utilities for your Next.js project.">
<button
type="button"
className="flex w-36 cursor-default items-center justify-center rounded-md border border-gray-300 px-3 py-2 transition-all duration-75 hover:border-gray-800 focus-visible:ring-2 focus-visible:ring-gray-400 active:bg-gray-100"
>
<p className="text-gray-600">Tooltip</p>
</button>
</Tooltip>components/home/component-grid.tsx:17
Modal and Popover buttons strip focus rings with no replacement
Both the "Modal" trigger button and the "Popover" trigger button in components/home/component-grid.tsx apply `focus:outline-none` with no `focus-visible` ring or alternate focus style to replace it. Only `hover:` and `active:` states are styled.
Why it matters
Keyboard users tabbing through the grid get no visual indication of which control currently has focus, so they lose track of position on the page and can't confirm what pressing Enter will activate.
Fix
Never remove the default focus outline without adding a visible focus-visible style as a replacement.
<button
onClick={() => setShowDemoModal(true)}
className="flex w-36 items-center justify-center rounded-md border border-gray-300 px-3 py-2 transition-all duration-75 hover:border-gray-800 focus:outline-none active:bg-gray-100"
>
<p className="text-gray-600">Modal</p>
</button><button
onClick={() => setShowDemoModal(true)}
className="flex w-36 items-center justify-center rounded-md border border-gray-300 px-3 py-2 transition-all duration-75 hover:border-gray-800 focus-visible:ring-2 focus-visible:ring-gray-400 active:bg-gray-100"
>
<p className="text-gray-600">Modal</p>
</button>Craft
components/home/card.tsx:23
Card heading title text is transparent, relying on a gradient clip
In components/home/card.tsx, the h2 rendering `{title}` uses `bg-gradient-to-br from-black to-stone-500 bg-clip-text text-transparent` instead of a solid text color. Every card title on the homepage grid inherits this same decorative fill, so the effect repeats across the whole section rather than being an intentional one-off accent.
Why it matters
Gradient-clipped text depends on the browser correctly compositing background-clip across every viewport and zoom level; any fallback failure (older browsers, high-contrast mode, print) drops the title to invisible transparent text, and it also caps the heading's contrast below what a solid dark color would give against the white card background.
Fix
Use a solid ink color for heading text and reserve gradients for non-text decorative surfaces.
<h2 className="bg-gradient-to-br from-black to-stone-500 bg-clip-text font-display text-xl font-bold text-transparent [text-wrap:balance] md:text-3xl md:font-normal">
{title}
</h2><h2 className="font-display text-xl font-bold text-gray-900 [text-wrap:balance] md:text-3xl md:font-normal">
{title}
</h2>app/opengraph-image.tsx:33
OG image headline uses gradient-clipped text instead of solid ink
The h1 "Precedent" in app/opengraph-image.tsx fills its glyphs with a black-to-stone-500 gradient via backgroundClip: 'text' and color: 'transparent' instead of a solid color. This is the generated-image equivalent of gradient-text templates, and it renders inconsistently across social platforms that strip or flatten CSS backgrounds in OG image scrapers.
Why it matters
OG images are rendered once and cached by link-unfurling crawlers (Twitter, Slack, iMessage); if the gradient clip fails to rasterize correctly in the satori/resvg pipeline, the brand name can render faint or invisible in shared links, which is the first impression for anyone clicking a shared URL.
Fix
Use a solid, high-contrast fill color for headline text in generated share images so it renders reliably across all unfurl renderers.
<h1
style={{
fontSize: "100px",
fontFamily: "SF Pro",
background:
"linear-gradient(to bottom right, #000000 21.66%, #78716c 86.47%)",
backgroundClip: "text",
color: "transparent",
lineHeight: "5rem",
letterSpacing: "-0.02em",
}}
>
Precedent
</h1><h1
style={{
fontSize: "100px",
fontFamily: "SF Pro",
color: "#000000",
lineHeight: "5rem",
letterSpacing: "-0.02em",
}}
>
Precedent
</h1>Typography
Color
Spacing
Components
Motion
UX
Working well
- The two footer CTAs are clearly differentiated: 'Deploy to Vercel' is a solid black-filled button while 'Star on GitHub' is an outlined white button with a shadow, so the primary action reads instantly without relying on color alone.
- Setting lang="en" on the <html> element is correct and easy to miss: it lets screen readers and browsers pick the right pronunciation and hyphenation rules from the very first paint.
- The popover menu items ('Item 1', 'Item 2', 'Item 3') use consistent hover/active states across all three buttons, giving predictable feedback for that one interaction pattern.
Scored July 25, 2026 with Rams Engine v0.0.3 · Engine changelog
First scored July 9, 2026: 59/100. This rescore on v0.0.3: 59/100.
This page is an automated design review of steven-tey/precedent’s UI code: 25 files read against 309 versioned rules covering accessibility, color, typography, spacing, components, UX, motion, and craft. The score is out of 100; confirmed criticals cap it — one at 59, two at 49, three or more at 39.
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.