1 min lesson
Pick a spec with real surface area
For each case in "Pick a spec with real surface area", name the signal and the response you would use.
Step 1 of 3
Pick a spec with real surface areaSprint options
An imperative toast() API plus a <Toaster /> host.
Surface area: queueing, max-visible, auto-dismiss with hover-pause, swipe-or-click to dismiss.
Motion: stack reflow with FLIP so toasts slide as the queue changes.
A right-edge drawer with a backdrop and a controlled open prop.
Surface area: focus trap, scroll lock on the body, Escape to close, restore focus on close.
Motion: transform-based slide plus a backdrop fade, never animating width or right.
Learn more
Advanced table
Self-review against the DE rubric
Self-review against the DE rubricGrade your own output
- Axis
- API design
- What strong looks like
- Controlled where it matters, sensible defaults, composable children over config props
- Common miss
- A dozen boolean props that should have been one
variantor slot
- Axis
- Polish
- What strong looks like
- Easing, focus ring, spacing all feel deliberate at 100%, not 90%
- Common miss
- Default browser focus outline and a linear 200ms-everything transition
- Axis
- Accessibility
- What strong looks like
- Roles, focus trap and restore, keyboard parity with mouse
- Common miss
- Mouse-only; Tab leaks behind the open panel
- Axis
- Performance
- What strong looks like
- Animations on transform/opacity; no layout thrash on the hot path
- Common miss
- Animating layout properties, re-rendering the whole list on every keystroke
| Axis | What strong looks like | Common miss |
|---|---|---|
| API design | Controlled where it matters, sensible defaults, composable children over config props | A dozen boolean props that should have been one variant or slot |
| Polish | Easing, focus ring, spacing all feel deliberate at 100%, not 90% | Default browser focus outline and a linear 200ms-everything transition |
| Accessibility | Roles, focus trap and restore, keyboard parity with mouse | Mouse-only; Tab leaks behind the open panel |
| Performance | Animations on transform/opacity; no layout thrash on the hot path | Animating layout properties, re-rendering the whole list on every keystroke |
Score each 1–5. Anything under 4 is the thing you fix before the next sprint.
/* Good: transform + opacity stay on the compositor */
.panel {
transform: translateX(100%);
transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
.panel[data-open='true'] { transform: translateX(0); }
/* Bad: animating 'right' or 'width' forces layout every frame */
.panel--janky { right: -400px; transition: right 280ms ease; }When the clock stops, open Cursor's own UI, Linear or Vercel and find their equivalent component. Compare timing, easing, focus behavior and dark mode side by side with yours. The gap you see is your real score - and naming that gap out loud is itself a strong signal.
“It works and it's accessible. With another hour I'd add a reduced-motion variant and tune the exit easing - right now the enter feels right but the exit is a touch fast.” Naming exactly what's still at 90% shows the 90→100 instinct without pretending you hit 100 under a timer.
QYou have 90 minutes for a slide-over panel build round. What should you do in the first 15 minutes?