GodUIGodUI
129Follow on X

Anatomy of the GodUI Toggle Group

A single-select toggle group is a segmented control, so it gets the same sliding indicator as Tabs from one shared hook.

01/03A segmented control
tsx
const single = props.type === "single" && !props.asChild;useActiveIndicator(rootRef, indicatorRef, {active: '[data-slot="toggle-group-item"][data-state="on"]',items: '[data-slot="toggle-group-item"]',enabled: single,});
01

A segmented control

When only one item can be on, the group reads as a single control with a moving selection, so GodUI gives it one indicator. It slides from the old item to the new one: its box snaps to the new item, then a FLIP animates translate and scale back from the old box.

With type="multiple", several items can be on at once and there's no single target, so the hook is disabled and each item paints its own on background.

02/03Shared with Tabs
tsx
// hooks/use-active-indicator.ts (ships in godui-motion)export function useActiveIndicator(containerRef: React.RefObject<HTMLElement | null>,indicatorRef: React.RefObject<HTMLElement | null>,options: ActiveIndicatorOptions,): void
02

Shared with Tabs

The indicator logic is the same hook that drives Tabs and Command's selection. It watches the active item's attributes, so clicks, arrow keys and controlled value changes all move it. Inserted or resized items snap it into place. Until it has measured once, it leaves the container without data-indicator="ready", and the pressed item keeps shadcn's own background.

03/03Result
03

The result

Click between alignments, or focus the group and use the arrow keys plus Space.

What's animated

InteractionKeyframe / mechanismPropertiesEasingDuration
Select (single)FLIP (WAAPI) on the indicatortranslate, scaleease-spring-snappy260ms
Toggle (multiple)on background snapsnonenonenone
Presstransition on active:scale-[0.96]scaleease-spring-bouncy260ms

Before JavaScript runs, the pressed item paints its own background, exactly as in shadcn.

Why GPU-only

The indicator animates translate and scale; presses animate scale. shadcn's items transition color and box-shadow; GodUI's don't.

Reduced motion

The indicator jumps to the new item without sliding, and presses are instant.

Replacing shadcn

npx shadcn add @godui/toggle-group overwrites components/ui/toggle-group.tsx and installs the GodUI Toggle it styles items with. Exports, props and data-slot attributes match shadcn/ui new-york-v4, so existing imports keep working. A single-select group renders one extra element, an aria-hidden <span data-slot="toggle-group-indicator">.