Data Entry Molecules
Available via @stackmates/ui-interactive/molecules
EditableText
Inline editable text that toggles between a clickable display span and an input field. Uses useOptimistic for instant feedback and useTransition for async action props.
Click the text below to edit:
Current value: Project Alpha
EditableTextProps
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | — | The current text value |
| action* | (newValue: string) => void | Promise<void> | — | Async action prop called with the new value on commit |
| displayValue | (value: string) => ReactNode | — | Custom display renderer receiving the optimistic value |
| placeholder | string | 'Click to edit' | Placeholder text when value is empty |
| className | string | — | Additional CSS classes |
Installation
import { EditableText } from '@stackmates/ui-interactive/molecules';Usage
Inline label edit with server action
<EditableText
value={deal.name}
action={async (newName) => {
await updateDealName(deal.id, newName);
}}
placeholder="Untitled deal"
/>Accessibility
- Display span has role="button" and tabIndex={0} for keyboard activation
- Enter key commits; Escape key cancels editing
- data-pending attribute set during async transition for CSS styling
InputOTP
One-time password input with individual digit slots. Supports paste, arrow-key navigation, and numeric-only mode.
Entered: (empty)
InputOTPProps
| Prop | Type | Default | Description |
|---|---|---|---|
| length | number | 6 | Number of OTP digit slots |
| value | string | — | Controlled OTP value |
| onChange | (value: string) => void | — | Callback when value changes |
| mask | boolean | false | Replace digits with dots |
| type | 'text' | 'number' | 'text' | Use "number" to restrict to digits |
Installation
import { InputOTP } from '@stackmates/ui-interactive/molecules';Accessibility
- role="group" with aria-label "One-time password input"
- Each slot has aria-label "Digit N of M"
- Paste support for full code entry
- Arrow keys navigate between slots
SelectRx
Radix select dropdown with groups, labels, and separators. Rx suffix avoids conflict with atoms/Select.
Selected: (none)
SelectRx compound
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | Controlled selected value |
| onValueChange | (value: string) => void | — | Callback when selection changes |
| defaultValue | string | — | Default value (uncontrolled) |
| disabled | boolean | false | Disable the trigger |
Installation
import { SelectRx, SelectTriggerRx, SelectContentRx, SelectItemRx, SelectValueRx, SelectGroupRx, SelectLabelRx, SelectSeparatorRx } from '@stackmates/ui-interactive/molecules';Accessibility
- Full keyboard navigation (Arrow, Enter, Escape)
- Check icon indicates current selection
- Scroll buttons for overflowing content
RadioGroupRx
Radix radio group for mutually exclusive selection. Rx suffix avoids conflict with atoms/Radio.
Selected: comfortable
RadioGroupRx / RadioGroupItemRx
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | Controlled selected value |
| onValueChange | (value: string) => void | — | Callback when selection changes |
| orientation | 'horizontal' | 'vertical' | 'vertical' | Layout direction |
| disabled | boolean | false | Disable all items |
Installation
import { RadioGroupRx, RadioGroupItemRx } from '@stackmates/ui-interactive/molecules';Accessibility
- Proper role="radiogroup" via Radix
- Arrow keys navigate, Space selects
- loop (default true) wraps navigation
ToggleGroup
Grouped toggle buttons with single or multiple selection. Inherits Toggle atom variants via context.
Default variant
Outline variant
Active: center
ToggleGroup / ToggleGroupItem
| Prop | Type | Default | Description |
|---|---|---|---|
| type* | 'single' | 'multiple' | — | Single or multiple selection mode |
| value | string | string[] | — | Controlled active value(s) |
| variant | 'default' | 'outline' | 'default' | Visual variant from Toggle atom |
| size | 'default' | 'sm' | 'lg' | 'default' | Size variant from Toggle atom |
Installation
import { ToggleGroup, ToggleGroupItem } from '@stackmates/ui-interactive/molecules';Accessibility
- type="single" enforces mutual exclusion
- type="multiple" allows any combination
- Use aria-label for icon-only items
Resizable
Split-panel layout with draggable handles. Built on react-resizable-panels.
ResizablePanelGroup / ResizablePanel / ResizableHandle
| Prop | Type | Default | Description |
|---|---|---|---|
| direction | 'horizontal' | 'vertical' | 'horizontal' | Split direction |
| defaultSize | number | — | Panel default size as percentage (ResizablePanel) |
| minSize | number | — | Panel minimum size as percentage (ResizablePanel) |
| withHandle | boolean | false | Show grip icon (ResizableHandle) |
Installation
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@stackmates/ui-interactive/molecules';Accessibility
- Handle is focusable and keyboard-operable
- withHandle adds visible grip for discoverability
Carousel
Content carousel powered by Embla Carousel. Supports looping, orientation, and keyboard navigation.
CarouselProps
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | 'horizontal' | 'vertical' | 'horizontal' | Scroll direction |
| opts | CarouselOptions | — | Embla options (loop, align, etc.) |
| plugins | CarouselPlugin | — | Embla plugins (autoplay, etc.) |
| setApi | (api: CarouselApi) => void | — | Receive Embla API for programmatic control |
Installation
import { Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext } from '@stackmates/ui-interactive/molecules';Accessibility
- role="region" with aria-roledescription="carousel"
- Slides have role="group" + aria-roledescription="slide"
- Arrow keys scroll, nav buttons have sr-only labels
Listbox
Headless UI listbox for selecting from a dropdown list. Shows selected value inline.
Selected: (none)
Listbox / ListboxOption / ListboxLabel
| Prop | Type | Default | Description |
|---|---|---|---|
| value | T | — | Controlled selected value |
| onChange | (value: T) => void | — | Callback when selection changes |
| placeholder | ReactNode | — | Placeholder when nothing selected |
| aria-label | string | — | Accessible label for the trigger |
Installation
import { Listbox, ListboxOption, ListboxLabel, ListboxDescription } from '@stackmates/ui-interactive/molecules';Accessibility
- Headless UI Listbox with proper ARIA roles
- Arrow keys + Enter for selection
- Check mark on selected option
Combobox
Searchable dropdown built on Headless UI Combobox. Type to filter options with custom filtering, virtual scrolling, and render-prop children for option rendering.
Selected: (none)
ComboboxProps<T>
| Prop | Type | Default | Description |
|---|---|---|---|
| options* | T[] | — | Array of options to display |
| displayValue* | (value: T | null) => string | undefined | — | Extract display string from an option |
| filter | (value: T, query: string) => boolean | — | Custom filter. Falls back to displayValue includes check. |
| placeholder | string | — | Placeholder text for the input |
| children* | (value: T) => ReactElement | — | Render function for each option row |
Installation
import { Combobox, ComboboxOption, ComboboxLabel, ComboboxDescription } from '@stackmates/ui-interactive/molecules';Accessibility
- Headless UI ARIA combobox pattern with aria-label support
- Arrow keys + Enter for keyboard navigation and selection
- Selected option shows check icon indicator
Command
Command palette built on cmdk. Compound component with search input, grouped items, empty state, and keyboard shortcuts. Use CommandDialog for modal overlay variant.
Command
| Prop | Type | Default | Description |
|---|---|---|---|
| children* | ReactNode | — | CommandInput, CommandList, CommandGroup, CommandItem composition |
| className | string | — | Additional CSS classes on the Command root |
Installation
import { Command, CommandDialog, CommandInput, CommandList, CommandGroup, CommandItem, CommandEmpty, CommandSeparator, CommandShortcut } from '@stackmates/ui-interactive/molecules';Accessibility
- Built on cmdk with full keyboard navigation and auto-filtering
- Search input auto-focused inside CommandDialog
- Items support aria-selected state