GodUIGodUI
129Follow on X

Anatomy of the GodUI Combobox

A Base UI popup animated with the same keyframe as every Radix popover, and chips that make room for each other with FLIP.

01/03Base UI, not Radix
opacity
0 → 1
scale
0.96 → 1
translate
0 -4px → 0 0
tsx
<ComboboxPrimitive.Popupdata-slot="combobox-content"className={cn(  "… origin-(--transform-origin) …   data-[side=bottom]:[--godui-enter-y:-0.25rem] …   data-open:animate-godui-popover-in data-closed:animate-godui-popover-out",  className,)}/>
01

Base UI, not Radix

shadcn/ui builds its combobox on Base UI, so GodUI does too: replacing the file mustn't change which library your call sites talk to.

Base UI names things differently from Radix. The popup gets data-open and data-closed instead of data-state, and publishes its transform origin as --transform-origin. The motion is the same godui-popover-in keyframe every Radix popover uses, though. Base UI waits for running CSS animations before it unmounts the popup, so the exit keyframe plays out.

02/03Chips that make room
tsx
function ComboboxChips({ className, ref, ...props }) {const chipsRef = React.useRef<HTMLDivElement | null>(null);const [version, bump] = React.useReducer((n: number) => n + 1, 0);useFlipGroup(chipsRef, version, {  selector: '[data-slot="combobox-chip"], [data-slot="combobox-chip-input"]',});// … <ComboboxChip> bumps on mount and unmount}
02

Chips that make room

Removing a chip changes the flex-wrap layout: every chip after it moves left, and some may jump up a line. GodUI lets that layout happen in one step, then plays each moved chip's old position back to its new one with translate, using the same useFlipGroup hook as Accordion.

Each chip renders a tiny signal that bumps a counter on mount and unmount, the exact commit where the layout changed. Chips added after the container mounted pop in with godui-fade-scale-in; the chips of the initial value are part of the first paint and don't. If you remove chips quickly, a chip that's still sliding starts its next slide from where it's drawn.

03/03Result
03

The result

Remove a chip with its ×, then type in the input and add one back.

What's animated

The check pops in on the item you select, and only then: checks and chips already there when the combobox or popup mounts stay still.

InteractionKeyframe / mechanismPropertiesEasingDuration
Opengodui-popover-inopacity, scale 0.96 → 1 from the anchor, translate 4px → 0ease-spring-snappy260ms
Closegodui-popover-outthe same, reversedease-out-expo150ms
Selected checkgodui-fade-scale-in from 50%scale, opacityease-spring-snappy260ms
Chip addedgodui-fade-scale-inscale, opacityease-spring-snappy260ms
Chip removedthe chips after it FLIPtranslateease-out-expo260ms
Item highlightsnapsnonenonenone

Why GPU-only

The popup animates opacity, scale and translate; chips animate scale, opacity and translate. shadcn's chips container transitions color and box-shadow; GodUI's doesn't.

Reduced motion

--godui-motion: 0 turns the popup, check and chip entrances into fades, and useFlipGroup moves chips into place without sliding.

Replacing shadcn

npx shadcn add @godui/combobox overwrites components/ui/combobox.tsx and installs the GodUI button and input-group it uses. Exports, props and data-slot attributes match shadcn/ui new-york-v4, so existing imports keep working.