GodUIGodUI
129Follow on X

Anatomy of the GodUI Select

Two positioning modes share one keyframe, and the check mark pops each time the list reopens on your choice.

01/03Item-aligned vs popper
opacity
0 → 1
scale
0.96 → 1
translate (popper)
0 -4px → 0 0
tsx
<SelectPrimitive.Contentdata-slot="select-content"className={cn(  "relative z-50 … origin-(--radix-select-content-transform-origin) …   data-[side=bottom]:[--godui-enter-y:-0.25rem] …   data-[state=open]:animate-godui-popover-in data-[state=closed]:animate-godui-popover-out",  position === "popper" && "data-[side=bottom]:translate-y-1 …",  className,)}position={position}/>
01

Item-aligned vs popper

By default (position="item-aligned") Radix places the list so the selected option sits right over the trigger, like a native macOS menu. In that mode Radix sets no data-side, so the drift variables stay at 0 and the list only scales and fades into place.

With position="popper" the list opens below or above the trigger like a popover. Radix sets data-side, the drift variables kick in, and the list slides 4px out of the trigger as it grows: the same godui-popover-in keyframe, with the extra drift only in popper mode.

02/03The check
scale
0.5 → 1
opacity
0 → 1
tsx
<span data-slot="select-item-indicator" className="absolute right-2 flex size-3.5 items-center justify-center"><SelectPrimitive.ItemIndicator className="[--godui-enter-scale:0.5] animate-godui-fade-scale-in">  <CheckIcon className="size-4" /></SelectPrimitive.ItemIndicator></span>
02

The check

Radix renders the selected item's indicator only for that item. Every time the list opens, the check next to your current value pops in from half size, a small confirmation of what's selected as the list appears.

03/03Result
03

The result

Open the select, pick a fruit, then reopen it to see the check on your choice.

What's animated

InteractionKeyframe / mechanismPropertiesEasingDuration
Opengodui-popover-inopacity, scale 0.96 → 1; translate toward the trigger in popper modeease-spring-snappy260ms
Closegodui-popover-outthe same, reversedease-out-expo150ms
Selected checkgodui-fade-scale-in from 50%scale, opacityease-spring-snappy260ms
Trigger hover / focussnapsnonenonenone

Why GPU-only

The list animates opacity, scale and translate; the check animates scale and opacity. shadcn's trigger transitions color and box-shadow; GodUI's snaps.

Reduced motion

--godui-motion: 0 removes scale and drift, so the list and the check only fade, in 150ms.

Replacing shadcn

npx shadcn add @godui/select overwrites components/ui/select.tsx. Exports, props and data-slot attributes match shadcn/ui new-york-v4, so existing imports keep working. It also installs godui-motion (easings, keyframes, the FLIP hook) into your project.