Quiz - shadcn-ui and the accessibility baseline
Your product’s primary button needs a brand-coloured variant="brand" you’ll reuse on dozens of screens, and your Select needs a custom anchor-positioning behaviour its current API can’t express at all. Where does each change belong?
The brand button is a new cva variant added to the existing button.tsx; the Select is the one that justifies a fork — edit select.tsx in components/ui/ directly and comment why.
Both are forks — once you’re editing shadcn output at all, you’ve left the upgrade path, so fork both files in components/ui/ and move on.
Both are className overrides at the call site — cn() puts your classes last, so you never need to touch the component files for either one.
cva variant on the existing file — you extend, you stay upgradeable. A fork is reserved for the case where the primitive’s API itself can’t express the state you need, which is exactly the custom-positioned Select. Forking the button too would needlessly cut it off from upstream accessibility fixes, and a className override can’t add a reusable named variant or restructure a component’s anchoring.A touch-primary size="icon" button on a mobile screen holds a 16px Lucide glyph and fails the WCAG 2.2 target-size floor. What’s the correct fix?
Grow the hit area with padding to at least 44×44 (min-h-11 min-w-11) and leave the 16px glyph as-is — visual size and tappable area are different things.
Scale the icon itself up to 44px so the whole target reaches the size floor.
Add aria-label to the button — the target-size rule is satisfied once a screen reader can announce the control.
aria-label fixes naming, a different commitment entirely.You write {error && <div role="alert">{error}</div>}. Sighted users see the error appear, but screen-reader users hear nothing. Why, and what’s the fix?
The region only enters the DOM with its text already inside, so assistive tech never registered it to watch. Render <div role="alert">{error}</div> unconditionally and toggle only its contents.
role="alert" is polite by default and waits for the user to be idle; switch it to aria-live="assertive" so it announces immediately.
A role="alert" region must also carry aria-atomic="true" to announce; add that attribute and the existing conditional render will announce correctly.
role="alert" is already assertive-and-atomic, so neither swapping the attribute nor adding aria-atomic addresses the timing problem.A RouteFocus component focuses the new page’s <h1> on every navigation, because Next.js moves focus nowhere on a soft navigation. Which details are load-bearing for it to actually work? Select all that apply.
The heading carries tabindex="-1" so a non-interactive <h1> is a legal focus target without entering anyone’s Tab order.
The focus call uses { preventScroll: true } so moving focus doesn’t fight the framework’s scroll restoration.
The heading is given a positive tabindex so it sits first in the page’s focus order.
The component focuses a ref captured from the previous route, reused across navigations.
<h1> isn’t focusable, so tabindex="-1" makes it a script-only target, and preventScroll: true keeps the focus move from yanking the viewport away from the framework’s scroll position. A positive tabindex is the global-order anti-pattern, and you must query the heading fresh after the new route paints — a ref to the previous route’s node points at something already unmounted.Why is modelling a data panel with three booleans (isLoading, error, data) considered the canonical bug, versus a single status discriminated union?
Three booleans can express eight combinations for four real states — the extra four (like loading and errored and full) are impossible states the booleans permit; the union makes only the four valid shapes writable.
Booleans render more slowly than a switch over a union, so the union is the performance fix.
The union is only a style preference — both express the same set of states, so the choice doesn’t change which states are reachable.
case. It’s not about render speed, and it’s not a wash — the reachable state space genuinely differs.Quiz complete
Score by topic