All Case Studies

vercel/next.js

130k+

The React framework — DevTools overlay components.

DevTools overlay components — tooltip, indicator, copy button, toast — internal UI that ships with every Next.js app.

packages/next/src/next-devtools/dev-overlay/components/tooltip/tooltip.tsx

packages/next/src/next-devtools/dev-overlay/components/devtools-indicator/devtools-indicator.tsx

packages/next/src/next-devtools/dev-overlay/components/copy-button/index.tsx

packages/next/src/next-devtools/dev-overlay/components/toast/index.tsx

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

Issues

A11Y-004·components/devtools-indicator/devtools-indicator.tsx:58Serious

The panel toggle logic has no aria-expanded state communicated to assistive technology. A screen reader user activating the trigger has no way to know whether it opened or closed the panel.

- <NextLogo
- onTriggerClick={() => { ... }}
- >
+ <NextLogo
+ aria-expanded={panel === "panel-selector"}
+ onTriggerClick={() => { ... }}
+ >
A11Y-004·components/copy-button/index.tsx:120Serious

The button uses aria-disabled instead of the native disabled attribute, but the click guard is a manual if (!isDisabled) check inside onClick. The button is still focusable and still receives keyboard events.

- aria-disabled={isDisabled}
+ disabled={isDisabled}
+ aria-disabled={isDisabled}
SLOP-001·components/devtools-indicator/devtools-indicator.tsx:37Serious

The Toast uses dynamic computed property keys with a magic number 20 (via INDICATOR_PADDING) for positioning. This value lives in a constant but has no relationship to any spacing token.

- [vertical]: 20
+ [vertical]: "var(--indicator-padding, 1.25rem)"
UX-010·components/copy-button/index.tsx:196Moderate

The disabled copy button style only sets a background and cursor — there is no opacity reduction or other standard disabled signal. Users scanning visually may not register it as inactive.

- background-color: var(--color-gray-100);
- cursor: not-allowed;
+ background-color: var(--color-gray-100);
+ cursor: not-allowed;
+ opacity: 0.6;

Working well

Using @base-ui-components/react/tooltip as the primitive is the right call — you get focus management, ARIA roles, and portal handling for free.

The disableDrag={panel !== null} guard on Draggable prevents the indicator from being repositioned while a panel is open, avoiding a desync between indicator position and panel anchor.

The if (!title) return children early return is clean defensive design — rather than rendering a broken tooltip with an empty label.

Get this on every pull request.

Get Started