All Case Studies

shadcn/ui

80k+

The component library powering most modern Next.js apps.

Landing page, interactive prompt form, radio choice card, and root layout — a mix of page-level and interactive components.

app/(app)/(root)/page.tsx

app/(app)/(root)/components/notion-prompt-form.tsx

app/(app)/(root)/components/field-choice-card.tsx

app/layout.tsx

Rams Score77/100
6 issues·4 files reviewed·April 15, 2026View on GitHub →

Issues

A11Y-001·components/notion-prompt-form.tsx:122Serious

Every AvatarImage in the mention pills, the sub-menu user list, and the sub-menu trigger is rendered without an alt attribute. When the image fails to load, the AvatarFallback handles the visual — but a screen reader announcing an image with no alt text will either skip it entirely or announce the raw URL.

- <AvatarImage src={item.image} />
+ <AvatarImage src={item.image} alt={item.title} />
UX-001·components/notion-prompt-form.tsx:333Serious

The Send button has no disabled state and no loading state. A user can click it on an empty textarea, and there is no visual feedback during any async operation. At minimum, disable it when the textarea is empty and add a spinner or pulse during submission.

- <InputGroupButton
- aria-label="Send"
- className="ml-auto rounded-full"
- variant="default"
- size="icon-sm"
- >
- <IconArrowUp />
+ <InputGroupButton
+ aria-label="Send"
+ className="ml-auto rounded-full"
+ variant="default"
+ size="icon-sm"
+ type="submit"
+ disabled={!value.trim()}
+ >
UX-018·components/notion-prompt-form.tsx:176Moderate

The InputGroupTextarea has no Cmd+Enter / Ctrl+Enter submit handler. Multi-line prompt inputs universally support keyboard submission — users who have typed a prompt and hit Cmd+Enter will find nothing happens.

- <InputGroupTextarea
- id="notion-prompt"
- placeholder="Ask, search, or make anything..."
- />
+ <InputGroupTextarea
+ id="notion-prompt"
+ placeholder="Ask, search, or make anything..."
+ onKeyDown={(e) => {
+ if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') formRef.current?.requestSubmit()
+ }}
+ />
SLOP-014·page.tsx:68Moderate

The mobile section uses w-[160vw] — an arbitrary viewport-width override that overflows the container intentionally but with a magic number. This creates a fragile relationship with the container width.

- <section className="-mx-4 w-[160vw] overflow-hidden rounded-lg border border-border/50 md:hidden md:w-[150vw]">
+ <section className="-mx-4 w-screen overflow-hidden rounded-lg border border-border/50 md:hidden">

Working well

Using onFocusCapture with stopPropagation on the TooltipTrigger wrapping the mention popover trigger is a deliberate fix for the known Radix Tooltip+Popover nesting issue — this kind of subtle fix signals real attention to interaction quality.

The blocking inline script for theme detection runs before paint, reads localStorage.theme and prefers-color-scheme, and sets the meta theme-color before hydration. This is the correct pattern for eliminating flash-of-wrong-theme.

The FieldLabel is correctly present with htmlFor matching the textarea id, then visually hidden with sr-only. Most prompt-style inputs skip the label entirely and rely on placeholder text.

Get this on every pull request.

Get Started