ChoiceCards
One of a few options, each a card that says what it means. Use it for a choice that deserves more than a select, where the description is what helps a person decide.
tsx
import { ChoiceCards } from '@basmilius/react-ui';tsx
import { useState } from 'react';
import { Cloud, HardDrive } from 'lucide-react';
import { ChoiceCards } from '@basmilius/react-ui';
type Storage = 'local' | 'cloud';
export default function ChoiceCardsDemo() {
const [storage, setStorage] = useState<Storage>('local');
return (
<ChoiceCards<Storage>
label="Where to keep the project"
className="w-full max-w-xl"
value={storage}
onValueChange={setStorage}
choices={[
{ value: 'local', title: 'On this computer', description: 'Fast, and only here.', icon: HardDrive },
{ value: 'cloud', title: 'In your account', description: 'On every device you sign in on.', icon: Cloud }
]}
/>
);
}Vertical, with a detail
Choices with long descriptions stand one under the other with orientation="vertical". A vertical group can show a detail right under the checked card, for what that choice still asks for, such as a folder or an address. radio="start" moves the dot before the title.
tsx
import { useState } from 'react';
import { ChoiceCards, Field, Input } from '@basmilius/react-ui';
type Source = 'empty' | 'clone';
export default function ChoiceCardsVertical() {
const [source, setSource] = useState<Source>('clone');
return (
<ChoiceCards<Source>
label="How to start"
orientation="vertical"
radio="start"
className="w-full max-w-md"
value={source}
onValueChange={setSource}
choices={[
{ value: 'empty', title: 'An empty folder', description: 'Nothing in it yet.' },
{ value: 'clone', title: 'Clone a repository', description: 'Copy one from a remote.' }
]}
detail={
<Field label="Repository URL" className="px-1 pb-1">
<Input mono placeholder="git@github.com:owner/repo.git" />
</Field>
}
/>
);
}Keyboard
The cards are a Base UI radio group. Tab moves into the group and onto the checked card, and the arrow keys move between cards and check them.
Props
ChoiceCards is generic over the value, a string or a number.
| Prop | Type | Default | |
|---|---|---|---|
value | Value | Required. | |
onValueChange | (value: Value) => void | Required. | |
choices | readonly Choice<Value>[] | Required. | |
label | string | Required. The group has no visible heading of its own. | |
orientation | 'horizontal' | 'vertical' | 'horizontal' | |
radio | 'start' | 'end' | 'end' | |
detail | ReactNode | Vertical groups only. | |
disabled | boolean | ||
className | string | ||
ref | Ref<HTMLDivElement> |
A Choice<Value> is { value, title, description, icon?, disabled? }. ChoiceCardsProps and Choice are exported types.