Option cards
Radio group rendered as option cards; the selection outline is made of pixels that fly to the newly selected card, then keep circling.
Playground
Change a prop and the component re-renders. Props marked remounts set an initial value, so the component starts over.
<PxChoice
label="Plan"
options={[
{
value: "free",
label: "Free",
description: "For trying things out",
price: "€0"
},
{
value: "pro",
label: "Pro",
description: "For daily work",
price: "€20/mo"
},
{
value: "team",
label: "Team",
description: "Shared projects",
price: "€30/user"
}
]}
defaultValue="pro"
/>Installation
pnpm dlx shadcn@latest add @lumesec/px-choiceFirst timeRegister the @lumesec registry once, or install by URL+
Adds @lumesec to your components.json:
pnpm dlx shadcn@latest registry add @lumesec=https://elements.lumesec.ai/r/{name}.jsonOr skip the setup and install by URL:
npx shadcn@latest add https://elements.lumesec.ai/r/px-choice.jsonUsage
import { PxChoice } from "@/components/lumesec/px-choice";
export function Example() {
return (
<PxChoice
name="plan"
label="Plan"
defaultValue="pro"
options={[
{ value: "free", label: "Free", description: "For trying things out", price: "€0" },
{ value: "pro", label: "Pro", description: "For daily work", price: "€20/mo" },
{ value: "team", label: "Team", description: "Shared projects", price: "€30/user" },
]}
/>
);
}Behaviour
A radio group as cards. The selection outline is made of pixels that fly from the old card to the new one, then keep circling slowly.
API reference
Props
Also accepts every prop of <div> (React.ComponentProps<"div">), spread onto the root element.
optionsTypereadonly PxChoiceOption[]The cards: { value?: string; label: string; description?: string; price?: string }. value defaults to label; price is shown in monospace.
valueTypestringControlled selected value. Use with onValueChange.
defaultValueTypestringDefaultfirst optionInitially selected value when uncontrolled. A form reset restores it.
labelTypeReact.ReactNodeLabel above the cards; names the radio group.
nameTypestringForm field name; the selected value submits under it.
disabledTypebooleanDefaultfalseDims the group and disables the cards.
onValueChangeType(value: string) => voidCalled when a different card is selected.
Ref
ref points at the root HTMLDivElement.
Keyboard
| Keys | Action |
|---|---|
| ArrowRight / ArrowDown | Select and focus the next card, wrapping at the end. |
| ArrowLeft / ArrowUp | Select and focus the previous card, wrapping at the start. |
Accessibility
- Cards are native buttons with
role="radio"andaria-checkedinside arole="radiogroup"labelled bylabel. - Roving tabindex: only the selected card is in the tab order.
- The pixel outline and check are drawn on an
aria-hiddencanvas; the selection is exposed througharia-checked. - With
name, a hidden input submits the selected card's value. There is no validation. Form reset restoresdefaultValue(or the first option) and callsonValueChangewhen that changes the value. - Reduced motion: the outline jumps to the selected card and stops circling.
Theming
Styled with Tailwind classes on your shadcn theme tokens, so light and dark follow your theme. The accent comes from --lumesec. See Theming.
This component reads --foreground, --muted-foreground, --card, --border, --lumesec and --lumesec-shine.
Notes
- Without reduced motion the outline animates continuously while the component is on screen.
- Cards are laid out in an auto-fit grid with a 120 px minimum width.
Related
Was this page helpful?