soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
# DropdownMenu
A menu of actions triggered by a button. Supports submenus, checkbox items, radio groups, keyboard navigation, and typeahead.
## Anatomy
```svelte
< DropdownMenu.Provider bind:open >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< DropdownMenu.Trigger > Actions< / DropdownMenu.Trigger >
< DropdownMenu.Content >
< DropdownMenu.Item > Cut< / DropdownMenu.Item >
< DropdownMenu.Item > Copy< / DropdownMenu.Item >
< DropdownMenu.Separator / >
< DropdownMenu.CheckboxItem bind:checked > Show Toolbar< / DropdownMenu.CheckboxItem >
< DropdownMenu.RadioGroup bind:value >
< DropdownMenu.RadioItem value = "light" > Light< / DropdownMenu.RadioItem >
< DropdownMenu.RadioItem value = "dark" > Dark< / DropdownMenu.RadioItem >
< / DropdownMenu.RadioGroup >
< DropdownMenu.Sub bind:open = {subOpen} >
< DropdownMenu.SubTrigger > More< / DropdownMenu.SubTrigger >
< DropdownMenu.SubContent >
< DropdownMenu.Item > Submenu Item< / DropdownMenu.Item >
< / DropdownMenu.SubContent >
< / DropdownMenu.Sub >
< / DropdownMenu.Content >
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / DropdownMenu.Provider >
```
## Parts
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Part | Element | Description |
| -------------- | ---------- | ------------------------------------------------------------ |
| `Provider` | none | Root context. Manages open state. |
| `Trigger` | `<button>` | Opens the menu on click or keyboard. |
| `Content` | `<div>` | Menu container. Focus scope, dismissal, floating integrated. |
| `Arrow` | `<div>` | Floating arrow pointing toward the trigger. |
| `Item` | `<div>` | Action item. Selectable via click or keyboard. |
| `Group` | `<div>` | Groups related items with an optional heading. |
| `GroupHeading` | `<div>` | Label for a group, linked via `aria-labelledby` . |
| `Separator` | `<div>` | Visual separator between items or groups. |
| `CheckboxItem` | `<div>` | Toggleable item with checked/unchecked state. |
soma: tier 1/2 components, Field/NumberField integration, codex_audit fixes
New components: context-menu, field, file-upload, link-preview, menubar.
Codex audit fixes (2026-04-17):
- Wrappers thinned: table, scroll-area scrollbar, calendar, range-calendar
- Toast Root → Item refactor (data-toast-item, resolves part collision)
- TreeView tab-stop fallback, Table right-pinned offset, Toolbar O(N) registry
- Combobox label registry, Pagination count=0, Splitter feasible-range clamp
- TagsInput relatedTarget, Toast compound hotkey, RadioGroup closest filter
- Accessible-name props (aria-label/-labelledby) tipados en RadioGroup/Slider/
Switch/Toolbar; Slider thumbLabels per-index
- NumberField startValue saneado, Table getIsSomeSelected filtra visibles
- Docs: DropdownMenu CheckboxGroup, NumberField terra-free, Pagination
First/Last snippet
Supporting changes:
- App layer + ling/logr/glob/util consolidation, tests updates
- Terra/scripts mechanical reformat (quotes, imports)
- Test pages updated to match new APIs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 months ago
| `CheckboxGroup` | none | Optional parent. Binds `value: string[]` and flips checked state of child `CheckboxItem` s by their `value` . |
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| `RadioGroup` | `<div>` | Group of mutually exclusive radio items. |
| `RadioItem` | `<div>` | Radio option within a RadioGroup. |
| `Sub` | none | Submenu context. Manages submenu open state. |
| `SubTrigger` | `<div>` | Opens a submenu on hover or keyboard. |
| `SubContent` | `<div>` | Submenu container. Positioned relative to SubTrigger. |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
## ARIA
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Part | Attribute | Value |
| ------------ | ------------------ | ------------------ |
| Trigger | `aria-haspopup` | `menu` |
| Trigger | `aria-expanded` | `true` \| `false` |
| Trigger | `aria-controls` | ID of Content |
| Content | `role` | `menu` |
| Content | `aria-orientation` | `vertical` |
| Item | `role` | `menuitem` |
| CheckboxItem | `role` | `menuitemcheckbox` |
| CheckboxItem | `aria-checked` | `true` \| `false` |
| RadioGroup | `role` | `group` |
| RadioItem | `role` | `menuitemradio` |
| RadioItem | `aria-checked` | `true` \| `false` |
| Group | `role` | `group` |
| Group | `aria-labelledby` | ID of GroupHeading |
| Separator | `role` | `separator` |
| Separator | `aria-orientation` | `horizontal` |
| SubTrigger | `role` | `menuitem` |
| SubTrigger | `aria-haspopup` | `menu` |
| SubTrigger | `aria-expanded` | `true` \| `false` |
| SubTrigger | `aria-controls` | ID of SubContent |
| SubContent | `role` | `menu` |
| SubContent | `aria-orientation` | `vertical` |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
## Data Attributes
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Part | Attribute | Values |
| ------------ | ---------------------------------- | -------------------------------------- |
| Trigger | `data-dropdown-menu-trigger` | Always present |
| Trigger | `data-state` | `open` \| `closed` |
| Content | `data-dropdown-menu-content` | Always present |
| Content | `data-state` | `open` \| `closed` |
| Content | `data-side` | `top` \| `right` \| `bottom` \| `left` |
| Content | `data-align` | `start` \| `center` \| `end` |
| Content | `data-starting-style` | Present during open animation |
| Content | `data-ending-style` | Present during close animation |
| Item | `data-dropdown-menu-item` | Always present |
| Item | `data-disabled` | Present when disabled |
| Item | `data-text-value` | Text content for typeahead |
| CheckboxItem | `data-dropdown-menu-checkbox-item` | Always present |
| CheckboxItem | `data-state` | `checked` \| `unchecked` |
| CheckboxItem | `data-disabled` | Present when disabled |
| RadioItem | `data-dropdown-menu-radio-item` | Always present |
| RadioItem | `data-state` | `checked` \| `unchecked` |
| RadioItem | `data-disabled` | Present when disabled |
| SubTrigger | `data-dropdown-menu-sub-trigger` | Always present |
| SubTrigger | `data-state` | `open` \| `closed` |
| SubTrigger | `data-disabled` | Present when disabled |
| SubContent | `data-dropdown-menu-sub-content` | Always present |
| SubContent | `data-state` | `open` \| `closed` |
| Separator | `data-dropdown-menu-separator` | Always present |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
## Keyboard
### On Trigger
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Key | Action |
| ------------------------------- | --------------------------- |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| `ArrowDown` / `Enter` / `Space` | Open menu, focus first item |
### On Content
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Key | Action |
| ----------------- | --------------------------------- |
| `ArrowDown` | Move to next item |
| `ArrowUp` | Move to previous item |
| `Home` | Move to first item |
| `End` | Move to last item |
| `Enter` / `Space` | Activate focused item |
| `Escape` | Close menu |
| Character keys | Typeahead — jump to matching item |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
### On SubTrigger
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Key | Action |
| ------------------ | ------------ |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| `ArrowRight` (LTR) | Open submenu |
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| `Enter` / `Space` | Open submenu |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
### On SubContent
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| Key | Action |
| ---------------------------- | ------------------------------- |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| `ArrowLeft` (LTR) / `Escape` | Close submenu, focus SubTrigger |
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
| `ArrowDown` / `ArrowUp` | Navigate items within submenu |
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
## Motion — item cascade (opt-in)
`<DropdownMenu.Provider animation="cascade-slide">` (a `CoordinatedPresetName` — `cascade-slide` /
`-fade` / `-scale` ) staggers the menu **rows** in on open and out on close. Omitted ⇒ the menu uses
its plain panel chrome, unchanged.
This is the motion service's **children-DOM coordination mode** (RFC §M9 / Apéndice C). The Content
is the owner `Presence` ; its rows are static DOM, so there is no per-row `Presence` to coordinate.
Instead a `DomCascade` (`soma/layers/dom-cascade.svelte.ts`) propagates the owner's lifecycle onto
each row — it writes `data-animation-style` + the mirrored `data-starting/ending-style` +
`--motion-stagger-index` /`-count` over `getCascadeRows()` (every visible row incl. disabled), so the
generated `cascade-*` preset just works. On close the owner holds the panel until the exit cascade
settles (`pending`). The morfo declares it: the `content` part carries
`animation: { surface: true, staggerChildren: 'item' }` .
When `animation` is set the provider also stamps `data-cascade` on the content so eidos can suppress
the panel's OWN signature (`dismiss-fade`) — otherwise the panel fades whole, taking the rows
cascading inside it, before the stagger finishes. Full design + the coexistence fixes (transition
collision, disabled opacity, dismiss-fade, the trigger/dismissal toggle) are in
[RFC Apéndice C ](../../../eidos/MOTION_SERVICE_RFC.md#apéndice-c--m9-el-modo-children-dom-la-segunda-coordinación ).
docs(soma): add Sema events section to 23 component READMEs
Documenta los cambios doctrinales del sprint Lectura C + cabling
soma. Cada README añade una sección `## Sema events` con tabla
(event / family / verb / target / intent / when) + referencia al
pack si existe + notas doctrinales de las correcciones aplicadas.
Componentes:
- Packs creados este sprint (11): switch, toggle, toggle-group,
menubar, navigation-menu, dropdown-menu, context-menu, tree-view,
tree-grid, tooltip, collapsible.
- Componentes con emisión cableada sin pack (8): listbox, grid-list,
table, feed, command, carousel, announce, clipboard.
- Componentes gestuales con notas sobre handle-scroll no-emitido
(3): drag-drop, virtual-list, virtual-grid.
- Checkbox: documenta la doctrina de dos eventos direccionales
(commit-toggle-check/uncheck con intent affirm/neutral).
Correcciones doctrinales documentadas:
- announce: commit-announce-* → signal.announce / signal.alert
- tree-view: target item → branch para emerge-expand/collapse
- table: shift.sort → commit.set; shift.expand-row → emerge.expand
- drag-drop: commit.drag-start/drop → handle.pick/drop
- clipboard: commit.copy → commit.save; commit.copy-error +
threat → commit.fail + risk
- virtual-list/grid: handle-scroll declarado pero NO emitido
(decisión consciente — buzz nonstop con family.handle haptic-only).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 months ago
## Sema events
| Event | Family | Verb | Target | Intent | Sequence | When |
| --------------- | -------- | -------- | --------- | -------- | -------- | ------------------------------------------------- |
| `open` | `emerge` | `open` | `content` | — | `pre` | Menu opens (`handleOpen` central state mutator). |
| `close` | `emerge` | `close` | `content` | — | `pre` | Menu closes (`handleClose`). |
| `commit-select` | `commit` | `select` | `item` | `affirm` | `post` | User activates an item (mouse click or keyboard). |
`open` / `close` use sequence `pre` so the perceptual signal lands at the gesture moment, before the structural flip (the content is still in DOM, the cascade matches `[data-dropdown-menu-content]` ). `commit-select` fires from MenuItem `onclick` and `onkeydown` with `e.currentTarget` as fallback target.
**Pack**: [`src/uix/sema/components/dropdown-menu.ts` ](../../../sema/components/dropdown-menu.ts ):
- `open` → `emerge.soft` (soft chime, gain 0.08).
- `close` → `emerge.exit.soft` (descending pitch + gain 0.05).
- `commit-select` → `form.commit.subtle` + light `tap` haptic. Softer than radio-group because close-emerge + select-commit + downstream-surface fire in quick succession; spreading intensity avoids double-tap fatigue.
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
## Usage
### Basic
```svelte
< script >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
import { DropdownMenu } from '$soma/components';
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
let open = $state(false);
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / script >
< DropdownMenu.Provider bind:open >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< DropdownMenu.Trigger > Options< / DropdownMenu.Trigger >
< DropdownMenu.Content >
< DropdownMenu.Item > Edit< / DropdownMenu.Item >
< DropdownMenu.Item > Duplicate< / DropdownMenu.Item >
< DropdownMenu.Separator / >
< DropdownMenu.Item > Delete< / DropdownMenu.Item >
< / DropdownMenu.Content >
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / DropdownMenu.Provider >
```
### Checkbox item
```svelte
< script >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
let showToolbar = $state(true);
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / script >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< DropdownMenu.CheckboxItem bind:checked = {showToolbar} > Show Toolbar< / DropdownMenu.CheckboxItem >
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
```
### Radio group
```svelte
< script >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
let theme = $state('light');
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / script >
< DropdownMenu.RadioGroup bind:value = {theme} >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< DropdownMenu.RadioItem value = "light" > Light< / DropdownMenu.RadioItem >
< DropdownMenu.RadioItem value = "dark" > Dark< / DropdownMenu.RadioItem >
< DropdownMenu.RadioItem value = "system" > System< / DropdownMenu.RadioItem >
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / DropdownMenu.RadioGroup >
```
### Submenu
```svelte
< DropdownMenu.Sub >
soma: gesture layer, drawer component, full audit fixes across 26 components
Gesture Layer:
- Gesture.base(), Gesture.drag(), Gesture.resize() — shared pointer tracking
- VelocityTracker with ring buffer, staleness check, projection
- 52 tests (velocity + gesture integration)
- setPointerCapture deferred until moveBuffer exceeded (prevents click stealing)
Drawer Component:
- 8 parts: Provider, Trigger, Content, Overlay, Handle, Title, Description, Close
- Gesture.drag() integration for swipe dismiss
- Snap points (fractional + px), fadeFromIndex, handle tap-to-cycle
- Modal/non-modal/non-dismissible modes
- Logical directions (start/end) RTL-aware via soma presentation
- CSS custom properties (--drawer-progress, --drawer-offset-x/y)
Architecture:
- T1: 219 files migrated from $soma/ alias to relative paths
- T2: 35 wrappers — noop replaced with () => {} inline
- Translation system: componentLangs + common.buttons.* + idlangref constants
- COMPONENT_GUIDE.md + README.md fully updated to reflect current patterns
- contracts.ts: case-normalized registerContract/assertContract
Audit Fixes (P0 critical):
- DI1/PO1/TO1: 'provider' → 'root' in parts/contract/super
- TB1: data-table attr on wrapper
- CH1/SW1/NF4: hidden input rendering fixes
- SP2: panel cleanup on unmount
- RG1: roving tabindex fallback to first item
- CO1: aria-labelledby on collapsible content
Audit Fixes (P1 high):
- SafePolygon integrated in dropdown-menu SubProvider + tooltip
- 9 langs.ts files with idlangref constants
- Dialog: aria-label removed (WCAG 2.5.3), handleOpen/Close guards
- Stepper: count decrement + private, aria-label on List
- ToggleGroup: roving tabindex in multiple mode
- Select: pure aria-activedescendant (no mixed focus), label registry
- NumberField: startValue respects min, scrubber commit on pointerup only
- Toolbar: element-based focus tracking (not index)
Audit Fixes (P2 medium):
- A6: timer/listener cleanup in 6 components
- A12: getDirectionalKeys in 4 components
- A10: DOM queries scoped to root in 3 components
- Dropdown-menu: typeahead + Home/End in SubContent, activate() pattern
- Checkbox: PrimitiveLabelAttributes, getAriaChecked helper, stale value cleanup
- Pagination: reactive page clamping, Set-based computePageRange
- Scroll-area: thumbSize zero-guard, mount flash prevention
- Splitter: collapse/expand respects adjacent constraints, immediate pointer capture
5 issues remain (design decisions): stepper registry, table sub-row IDs,
tags-input ARIA model, tags-input paste, toast exit animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< DropdownMenu.SubTrigger > Share< / DropdownMenu.SubTrigger >
< DropdownMenu.SubContent >
< DropdownMenu.Item > Email< / DropdownMenu.Item >
< DropdownMenu.Item > Slack< / DropdownMenu.Item >
< / DropdownMenu.SubContent >
soma: 10 new components, README docs for all 22, PrimitiveAnchorAttributes
New components (10):
- Tabs: roving tabindex, automatic/manual activation, onFocusChange
- ToggleGroup: single/multiple, roving tabindex, deselectable
- Toast: imperative API (createToaster), swipe-to-dismiss, hotkey, promise()
- ScrollArea: custom scrollbars, visibility modes, thumb drag, position tracking
- Splitter: resizable panels, collapsible, flex-grow sizing, double-click toggle
- Stepper: multi-step wizard, linear mode, step state, PrevTrigger/NextTrigger
- TreeView: WAI-ARIA tree pattern, expand/collapse, typeahead, * expand siblings
- Pagination: page range algorithm, siblingCount/boundaryCount, slice() utility
- Toolbar: WAI-ARIA toolbar, roving tabindex, integrated ToggleGroup, Separator
- Editable: inline edit, activation/submit modes, draft tracking, auto-resize
Documentation:
- README.md for all 22 components with anatomy, ARIA, data-*, keyboard, usage
- Comparison tables vs ark-ui, bits-ui, radix-ui for every component
Infrastructure:
- Added PrimitiveAnchorAttributes to $soma/types/html.ts
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
6 months ago
< / DropdownMenu.Sub >
```