GodUIGodUI
129Follow on X

Anatomy of the Magic Tab

How a segmented control borrows Magic Button's three-layer stack, but only the selected tab ever pays for it.

01/04Three layers, one tab

unselected

three spans

selected

Front
label face, lifts −4px when selected
Edge
gradient wall, fakes the 3D side
Shadow
blurred, grounds the raised tab
tsx
const shadowOpacity = selected ? (rainbow ? "opacity-70" : "opacity-100") : "opacity-0";const edgeFill = selected ? `opacity-100 ${...}` : "opacity-0";const frontState = selected? `-translate-y-[4px] ${frontVariantSelected[variant]} ...`: `bg-transparent text-muted-foreground ${frontVariantPreview[variant]}`;
01

Three layers, one tab

Magic Tab is Magic Button's sibling: the same three-layer illusion of a pushed-up surface and the same springy bezier, on a role="tablist" instead of a lone button. The difference is selection. A button is either pressed or not; a tab has to hold a rest state for every item it isn't, and spend the 3D budget only on the one it is.

Every tab is a <button> with the same absolutely-stacked shadow, edge, and front-face spans as Magic Button. The difference: on an unselected tab the shadow and edge sit at opacity-0 and the front is flat (bg-transparent, no lift). Only the selected tab's stack materializes. The scene goes flat → the three spans → assembled lift:

Unselected tabs still preview the selected color flat on hover/focus (frontVariantPreview) as a hint of what clicking does, but never lift. Only the selected tab lifts.

02/04Three lift stops
rest
selected
focus
none
600ms
250ms
0px
-4px · …,1
-6px · …,1.5
tsx
// front face"-translate-y-[4px] group-focus-visible:-translate-y-[6px][transition:translate_600ms_cubic-bezier(0.3,0.7,0.4,1)]group-focus-visible:[transition:translate_250ms_cubic-bezier(0.3,0.7,0.4,1.5)]"
02

Three lift stops

A selected tab sits at -4px and goes one step further on focus-visible, to -6px, the same way Magic Button's hover lift previews what a press would feel like. Rest → selected uses the slower settle bezier; selected → focus overshoots on the snappier one:

600ms at rest→selected is deliberately unhurried; 250ms with a 1.5 overshoot control point on selected→focus is the snap that marks the tab as interactive. Both offsets animate translate, never top. Magic Button follows the same compositor-only rule for the same reason: moving a layer is free, re-laying it out is not.

03/04Rainbow, paused offscreen
in view
128px past edge

animationPlayState flips to “paused” once the tablist clears the 128px margin, and resumes where it left off on the way back in

tsx
const io = new IntersectionObserver(([entry]) => {  for (const layer of root.querySelectorAll<HTMLElement>(".animate-magic-rainbow"))    layer.style.animationPlayState = entry.isIntersecting ? "" : "paused";},{ rootMargin: "128px" },);
03

Rainbow, paused offscreen

The selected tab's edge and shadow can run the same sliding rainbow gradient as Magic Button: background-size: 200% 100% with a background-position keyframe. That keyframe costs main-thread work, so an IntersectionObserver on the tablist root pauses every .animate-magic-rainbow layer the instant it scrolls out of view:

rootMargin: "128px" resumes the sweep just before the tablist re-enters the viewport, so scrolling back to it never catches a frozen mid-cycle frame snapping back to life.

04/04Result
04

The result

Magic Tab uses the same three spans and bezier as Magic Button. On each render it decides which single tab may spend them.

Accessibility

The container is role="tablist" with aria-orientation="horizontal"; each button is role="tab" with aria-selected. Focus and selection are separate: arrow keys move a roving tabIndex between tabs without selecting them, and Enter/Space commits whichever tab currently holds focus:

tsx
 
case "ArrowRight":
  moveFocus(enabled[(currentIndex + 1) % enabled.length].value);
  break;
case "Enter":
case " ":
  if (rovingValue !== undefined) select(rovingValue);
  break;

This is the WAI-ARIA "manual activation" tab pattern: you can arrow through every tab to read its label before committing, instead of every keypress switching panels. Tabbing out of the list resets the roving stop back to the selected tab.

Motion Score

Magic TabCC: Paint-triggering
StranslateSelected tab face / indicator motion
Cbackground-positionSelected tab rainbow keyframe loop
Each property is graded by how the browser runs it, from S (composited off the main thread) down to F (layout thrashing); the component takes the worst. MotionScore methodology →