Overview
CardPicker provides an intuitive single-choice selection interface with options displayed as horizontal icon cards. Users can search, filter by category, and toggle between compact and full views. Ideal for selecting project types, templates, or element types.
Key Features
- Search across labels, descriptions, and hidden metadata
- Category filtering with dropdown selector
- Compact/Full view toggle (auto-hidden without descriptions)
- Customizable colors per option via Tailwind classes
- Badge support for labels like New, Popular, Beta
- Keyboard navigation with arrow keys and Enter to select
Interactive Examples
Basic Usage
Simple card selection with search
With Categories
Filter options by category using the dropdown
Multi-Select
Enable multiple selections with the multiple prop
Set multiple=true to allow selecting multiple options. A checkbox indicator appears on each card.
Multi-Select Required
With required, at least one option must remain selected
When multiple=true and required=true, users cannot deselect the last remaining item.
Scrolling
With many options, the picker scrolls within a fixed height
This example has 22 options with a maxHeight of 350px, forcing the content to scroll.
Full View Mode
Full view shows descriptions with 2 columns on desktop
Set defaultViewMode="full" to show descriptions by default. Users can toggle between compact and full views.
Structured questionnaire with multiple question types
Quick single-question vote
Open-ended forum thread for detailed feedback
Structured issue reporting with severity levels
Capture and prioritize user suggestions
Net Promoter Score measurement
Optional Selection
Click the selected item again to deselect it
When required=false, clicking the selected item again will deselect it.
In Dialog
CardPicker works seamlessly inside dialogs
Custom Colors
Items can have unique colors via colorClass prop
Each option can have a colorClassprop with Tailwind classes to style the icon and selection border.
Empty State
What users see when no options match their search
Try searching for something that doesn't exist to see the empty state.
No element types match your search
Interfaces
CardPickerOption
| Prop | Type | Description |
|---|---|---|
id | string | Unique identifier for the option |
label | string | Display label for the option |
description | string? | Optional description shown in Full view mode |
meta | string? | Hidden searchable text for synonyms and keywords |
icon | IconDefinition | Font Awesome icon to display |
categories | string[]? | Category IDs this option belongs to |
badge | string? | Optional badge text (e.g., New, Popular) |
colorClass | string? | Tailwind classes for icon and border colors |
CardPickerCategory
| Prop | Type | Description |
|---|---|---|
id | string | Unique identifier for the category |
label | string | Display label for the category dropdown |
Props Reference
| Prop | Type | Default | Description |
|---|---|---|---|
options | CardPickerOption[] | required | Array of options to display |
value | string | null | - | Currently selected option ID (controlled) |
onChange | (value: string | null) => void | - | Callback when selection changes |
categories | CardPickerCategory[] | [] | Categories for dropdown filter |
required | boolean | true | When false, clicking selected item deselects it |
size | 'sm' | 'default' | 'lg' | 'default' | Card size variant |
defaultViewMode | 'compact' | 'full' | 'compact' | Initial view mode (compact hides descriptions) |
showViewToggle | boolean | true | Show view mode toggle button (auto-hidden without descriptions) |
maxHeight | number | 500 | Maximum height in pixels before scrolling |
inDialog | boolean | false | Enable dialog mode (fixed height behavior) |
searchPlaceholder | string | 'Search...' | Placeholder text for search input |
emptyMessage | string | 'No options...' | Message shown when no options match search |
disabled | boolean | false | Disable all interactions |
Usage
import { CardPicker, type CardPickerOption, type CardPickerCategory } from '@/ui/components';
import { faClipboardList, faSquarePollVertical } from '@fortawesome/sharp-duotone-light-svg-icons';
// Define your options
const options: CardPickerOption[] = [
{
id: 'survey',
label: 'Survey',
description: 'Structured questionnaire',
meta: 'questionnaire form', // Hidden searchable text
icon: faClipboardList,
categories: ['feedback'],
badge: 'Popular',
colorClass: 'text-blue-500 border-blue-500',
},
{
id: 'poll',
label: 'Poll',
description: 'Quick single-question vote',
icon: faSquarePollVertical,
categories: ['feedback'],
colorClass: 'text-purple-500 border-purple-500',
},
];
// Optional categories for filtering
const categories: CardPickerCategory[] = [
{ id: 'feedback', label: 'Feedback' },
{ id: 'research', label: 'Research' },
];
// Basic usage
const [selected, setSelected] = useState<string | null>(null);
<CardPicker
options={options}
value={selected}
onChange={setSelected}
/>
// With all options
<CardPicker
options={options}
value={selected}
onChange={setSelected}
categories={categories}
required={false}
size="default"
defaultViewMode="full"
showViewToggle={true}
maxHeight={500}
searchPlaceholder="Search elements..."
emptyMessage="No elements match your search"
/>