Interactive Molecules
Available via @stackmates/ui-interactive/molecules
Dialog
Modal dialogs built on Radix UI Dialog primitive. Use for focused interactions that require user attention.
DialogProps
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state |
| onOpenChange | (open: boolean) => void | — | Called when open state changes |
| children* | ReactNode | — | DialogTrigger + DialogContent |
Installation
import {
Dialog, DialogContent, DialogHeader, DialogTitle,
DialogDescription, DialogFooter, DialogTrigger,
} from '@stackmates/ui-interactive/molecules';Usage
Controlled dialog
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
<DialogContent>
<DialogHeader><DialogTitle>Title</DialogTitle></DialogHeader>
<DialogFooter><Button onClick={() => setOpen(false)}>Done</Button></DialogFooter>
</DialogContent>
</Dialog>Accessibility
- Focus trapped inside dialog when open
- Escape key closes the dialog
- aria-labelledby linked to DialogTitle automatically
- Background content marked as aria-hidden
Accordion
Expandable content sections. Supports single or multiple open items.
AccordionProps
| Prop | Type | Default | Description |
|---|---|---|---|
| type* | 'single' | 'multiple' | — | Allow one or many items open |
| collapsible | boolean | false | Allow collapsing all items (single mode) |
Installation
import {
Accordion, AccordionContent, AccordionItem, AccordionTrigger,
} from '@stackmates/ui-interactive/molecules';Usage
Single collapsible
<Accordion type="single" collapsible>
<AccordionItem value="item-1">
<AccordionTrigger>Section Title</AccordionTrigger>
<AccordionContent>Content here</AccordionContent>
</AccordionItem>
</Accordion>Accessibility
- Keyboard navigable with arrow keys
- Space/Enter toggles sections
- aria-expanded state managed automatically
AlertDialog
Confirmation dialog that interrupts workflow. Use for destructive actions requiring explicit user consent.
AlertDialogProps
| Prop | Type | Default | Description |
|---|---|---|---|
| open | boolean | — | Controlled open state |
| onOpenChange | (open: boolean) => void | — | Called when open state changes |
Installation
import {
AlertDialog, AlertDialogAction, AlertDialogCancel,
AlertDialogContent, AlertDialogDescription,
AlertDialogFooter, AlertDialogHeader, AlertDialogTitle,
AlertDialogTrigger,
} from '@stackmates/ui-interactive/molecules';Accessibility
- role="alertdialog" for screen readers
- Cannot be dismissed by clicking outside (requires explicit action)
- Focus returns to trigger on close
MessageRow
Single message with avatar. User right-aligned, assistant left-aligned. Supports streaming indicator.
I'll analyze your pipeline using the optimal-stopping algorithm.
Run the sales-rfp workflow for the Acme deal.
Starting the sales-rfp-workflow...
MessageRowProps
| Prop | Type | Default | Description |
|---|---|---|---|
| message* | MessageRowData | — | Message data object with id, role, content, agentName, isStreaming |
| className | string | — | Additional CSS classes |
Installation
import { MessageRow } from '@stackmates/ui-interactive/molecules';Usage
Assistant message
<MessageRow message={{ id: '1', role: 'assistant', content: 'Hello!', agentName: 'Bot' }} />Streaming message
<MessageRow message={{ id: '2', role: 'assistant', content: 'Typing...', isStreaming: true }} />Accessibility
- Messages use semantic list structure
- Role (user/assistant) conveyed via visual alignment and labels
MessageComposer
Textarea + send button. Enter sends, Shift+Enter for newline.
MessageComposerProps
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | — | Current textarea value |
| onChange* | (value: string) => void | — | Value change handler |
| onSubmit* | () => void | — | Send handler (also triggered by Enter key) |
| isLoading | boolean | false | Disable input while sending |
| placeholder | string | 'Type a message...' | Placeholder text |
Installation
import { MessageComposer } from '@stackmates/ui-interactive/molecules';Accessibility
- Textarea auto-resizes to content
- Enter key submits (keyboard shortcut)
- Shift+Enter creates newline
- Send button disabled when loading
EntitySelector
Pick entity from list with avatar initials, description, and badges.
EntitySelectorProps
| Prop | Type | Default | Description |
|---|---|---|---|
| entities* | EntityItem[] | — | List of selectable entities (id, name, description, badges) |
| selectedId | string | — | Currently selected entity ID |
| onSelect* | (id: string) => void | — | Selection handler |
Installation
import { EntitySelector } from '@stackmates/ui-interactive/molecules';Usage
Basic usage
<EntitySelector
entities={[{ id: '1', name: 'Agent', description: 'Desc', badges: ['tag'] }]}
selectedId={selected}
onSelect={setSelected}
/>StageCard
Workflow stage with status badge, agent name, duration, and confidence score.
StageCardProps
| Prop | Type | Default | Description |
|---|---|---|---|
| stage* | StageCardData | — | Stage data (id, name, status, agent, durationMs, confidence) |
| className | string | — | Additional CSS classes |
Installation
import { StageCard } from '@stackmates/ui-interactive/molecules';Usage
Completed stage
<StageCard stage={{
id: '1', name: 'Research', status: 'completed',
agent: 'Architect', durationMs: 8500, confidence: 0.92
}} />