@chromvoid/headless-ui 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +207 -67
- package/dist/copy-button/index.d.ts +2 -0
- package/dist/copy-button/index.js +6 -2
- package/dist/menu/index.js +1 -1
- package/package.json +2 -2
- package/specs/ADR-001-headless-architecture.md +6 -6
- package/specs/ADR-002-repo-release-model.md +2 -2
- package/specs/ISSUE-BACKLOG.md +2 -2
- package/specs/components/accordion.md +1 -1
- package/specs/components/alert-dialog.md +1 -1
- package/specs/components/alert.md +1 -1
- package/specs/components/badge.md +1 -1
- package/specs/components/breadcrumb.md +1 -1
- package/specs/components/button.md +1 -1
- package/specs/components/callout.md +1 -1
- package/specs/components/card.md +1 -1
- package/specs/components/carousel.md +1 -1
- package/specs/components/checkbox.md +2 -2
- package/specs/components/combobox.md +1 -1
- package/specs/components/command-palette.md +1 -1
- package/specs/components/context-menu.md +1 -1
- package/specs/components/copy-button.md +7 -3
- package/specs/components/dialog.md +1 -1
- package/specs/components/disclosure.md +1 -1
- package/specs/components/drawer.md +1 -1
- package/specs/components/feed.md +1 -1
- package/specs/components/grid.md +1 -1
- package/specs/components/input.md +1 -1
- package/specs/components/landmarks.md +1 -1
- package/specs/components/link.md +1 -1
- package/specs/components/listbox.md +1 -1
- package/specs/components/menu-button.md +1 -1
- package/specs/components/menu.md +1 -1
- package/specs/components/meter.md +1 -1
- package/specs/components/number.md +1 -1
- package/specs/components/popover.md +1 -1
- package/specs/components/progress.md +1 -1
- package/specs/components/radio-group.md +1 -1
- package/specs/components/select.md +1 -1
- package/specs/components/sidebar.md +1 -1
- package/specs/components/slider-multi-thumb.md +1 -1
- package/specs/components/slider.md +1 -1
- package/specs/components/spinbutton.md +1 -1
- package/specs/components/spinner.md +1 -1
- package/specs/components/switch.md +1 -1
- package/specs/components/table.md +1 -1
- package/specs/components/tabs.md +1 -1
- package/specs/components/textarea.md +1 -1
- package/specs/components/toast.md +1 -1
- package/specs/components/toolbar.md +1 -1
- package/specs/components/tooltip.md +1 -1
- package/specs/components/treegrid.md +1 -1
- package/specs/components/treeview.md +1 -1
- package/specs/components/window-splitter.md +1 -1
- package/specs/ops/git-shard-sync.md +4 -4
- package/specs/release/GAP-TO-GREEN-ISSUES.md +6 -6
- package/specs/release/mvp-changelog.md +2 -2
- package/specs/release/release-rehearsal.md +1 -1
- package/specs/signals.md +1 -1
package/README.md
CHANGED
|
@@ -1,9 +1,140 @@
|
|
|
1
|
-
|
|
2
|
-
built on Reatom v1000 and WAI-ARIA APG behavior contracts.
|
|
1
|
+
# @chromvoid/headless-ui
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
`@chromvoid/headless-ui` is a standalone headless package for building accessible UI behavior
|
|
4
|
+
without coupling that behavior to a visual layer.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
It is the behavioral foundation for future ChromVoid UI kits and product interfaces:
|
|
7
|
+
|
|
8
|
+
- reactive component models built on Reatom v1001
|
|
9
|
+
- WAI-ARIA APG-aligned keyboard and accessibility contracts
|
|
10
|
+
- explicit state transitions and event handling
|
|
11
|
+
- framework-agnostic rendering ownership
|
|
12
|
+
|
|
13
|
+
This package does **not** ship styled components, templates, CSS, icons, or product-specific
|
|
14
|
+
layout decisions. It owns behavior and accessibility semantics. Your UI layer owns markup,
|
|
15
|
+
styling, motion, and composition.
|
|
16
|
+
|
|
17
|
+
## What This Package Is For
|
|
18
|
+
|
|
19
|
+
Use this package when you want to build:
|
|
20
|
+
|
|
21
|
+
- a design system or UI kit on top of stable headless behavior contracts
|
|
22
|
+
- product-specific components without rewriting keyboard, focus, and ARIA logic
|
|
23
|
+
- framework bindings that stay thin because the behavior already lives in the model
|
|
24
|
+
- accessible widgets that remain portable outside the ChromVoid monorepo
|
|
25
|
+
|
|
26
|
+
Use something else if you want:
|
|
27
|
+
|
|
28
|
+
- ready-made visual components
|
|
29
|
+
- a DOM renderer
|
|
30
|
+
- a framework-specific component library
|
|
31
|
+
- a package that hides Reatom from the public model shape
|
|
32
|
+
|
|
33
|
+
## Mental Model
|
|
34
|
+
|
|
35
|
+
Each component is a small behavior engine.
|
|
36
|
+
|
|
37
|
+
1. Create a model with `createX(options)`.
|
|
38
|
+
2. Read reactive `state` from Reatom atoms and computed values.
|
|
39
|
+
3. Call `actions` in response to user intent.
|
|
40
|
+
4. Apply `contracts.get*Props()` to your DOM or framework layer.
|
|
41
|
+
|
|
42
|
+
In other words:
|
|
43
|
+
|
|
44
|
+
- the package decides how a widget behaves
|
|
45
|
+
- the package exposes what ARIA attributes and handlers are required
|
|
46
|
+
- your app decides how the widget looks and where it is rendered
|
|
47
|
+
|
|
48
|
+
That split is the core idea behind the repository.
|
|
49
|
+
|
|
50
|
+
## How It Works
|
|
51
|
+
|
|
52
|
+
The public API is intentionally repetitive across components:
|
|
53
|
+
|
|
54
|
+
- `state`: reactive sources of truth
|
|
55
|
+
- `actions`: the only supported mutation path
|
|
56
|
+
- `contracts`: grouped prop getters for ARIA, ids, and event handlers
|
|
57
|
+
|
|
58
|
+
Typical shape:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
const model = createX(options)
|
|
62
|
+
|
|
63
|
+
model.state
|
|
64
|
+
model.actions
|
|
65
|
+
model.contracts.getRootProps()
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Example with a real component:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import {createButton} from '@chromvoid/headless-ui/button'
|
|
72
|
+
|
|
73
|
+
const button = createButton({
|
|
74
|
+
idBase: 'save',
|
|
75
|
+
onPress: () => {
|
|
76
|
+
console.log('save')
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
const buttonProps = button.contracts.getButtonProps()
|
|
81
|
+
|
|
82
|
+
button.state.isDisabled()
|
|
83
|
+
button.actions.setLoading(true)
|
|
84
|
+
|
|
85
|
+
buttonProps.role
|
|
86
|
+
buttonProps.tabindex
|
|
87
|
+
buttonProps.onClick
|
|
88
|
+
buttonProps.onKeyDown
|
|
89
|
+
buttonProps.onKeyUp
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The same pattern scales from simple controls such as `button` and `checkbox` to larger widgets
|
|
93
|
+
such as `listbox`, `combobox`, `treeview`, `grid`, or `treegrid`.
|
|
94
|
+
|
|
95
|
+
## Design Philosophy
|
|
96
|
+
|
|
97
|
+
This package is opinionated in a very specific way.
|
|
98
|
+
|
|
99
|
+
- **Headless, not vague**: it avoids visual output, but it is strict about behavior, focus, and
|
|
100
|
+
accessibility semantics.
|
|
101
|
+
- **Signal-first state**: public state stays reactive so UI layers can read it directly instead of
|
|
102
|
+
synchronizing snapshots by hand.
|
|
103
|
+
- **Intent-first actions**: keyboard and pointer flows map to model actions, not scattered UI glue.
|
|
104
|
+
- **Contract-first accessibility**: ARIA attributes, roles, ids, and linkage are part of the
|
|
105
|
+
public contract, not an afterthought.
|
|
106
|
+
- **Thin adapters**: adapters exist to map models into renderers, not to contain business logic.
|
|
107
|
+
- **Standalone by default**: the package must work outside this monorepo, with no hidden internal
|
|
108
|
+
imports or release-time coupling.
|
|
109
|
+
- **DX over inertia in pre-v1**: while the package is still `<1.0`, ergonomics and API consistency
|
|
110
|
+
take priority over preserving temporary shapes.
|
|
111
|
+
|
|
112
|
+
## Why The Repository Looks Like This
|
|
113
|
+
|
|
114
|
+
This package is developed inside a monorepo for local integration speed, but it is treated as an
|
|
115
|
+
independent public library.
|
|
116
|
+
|
|
117
|
+
That leads to a few hard rules:
|
|
118
|
+
|
|
119
|
+
- no imports from `@project/*`, `apps/*`, or other monorepo-only modules
|
|
120
|
+
- package-local scripts, tests, specs, and release checks
|
|
121
|
+
- explicit architecture docs and component specs
|
|
122
|
+
- stable lean-import support through subpath exports
|
|
123
|
+
|
|
124
|
+
This directory is a **development mirror**. The canonical release history and publishing flow live
|
|
125
|
+
in a separate public git-shard repository.
|
|
126
|
+
|
|
127
|
+
## Getting Started
|
|
128
|
+
|
|
129
|
+
Install the package in a Node 20+ ESM environment:
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
npm install @chromvoid/headless-ui
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Then pick the import style that matches your use case.
|
|
136
|
+
|
|
137
|
+
## Import Contract
|
|
7
138
|
|
|
8
139
|
The package ships from `dist/` and supports both a convenience root barrel and lean leaf imports.
|
|
9
140
|
|
|
@@ -13,7 +144,7 @@ Use the root barrel when convenience matters more than bundle shape:
|
|
|
13
144
|
import {createButton, createTabs} from '@chromvoid/headless-ui'
|
|
14
145
|
```
|
|
15
146
|
|
|
16
|
-
Use leaf subpaths
|
|
147
|
+
Use leaf subpaths when you want a deliberately narrow dependency graph:
|
|
17
148
|
|
|
18
149
|
```ts
|
|
19
150
|
import {createButton} from '@chromvoid/headless-ui/button'
|
|
@@ -21,17 +152,70 @@ import {CompositeNavigationOrientation} from '@chromvoid/headless-ui/interaction
|
|
|
21
152
|
import {toggleSelection} from '@chromvoid/headless-ui/core/selection'
|
|
22
153
|
```
|
|
23
154
|
|
|
24
|
-
The root barrel
|
|
155
|
+
The root barrel is supported, but leaf subpaths are the stable lean-import contract for
|
|
156
|
+
applications and higher-level packages such as `@chromvoid/uikit`.
|
|
157
|
+
|
|
158
|
+
## What Ships In The Package
|
|
159
|
+
|
|
160
|
+
The package currently includes headless models for:
|
|
161
|
+
|
|
162
|
+
- **Inputs and selection**: `button`, `checkbox`, `combobox`, `date-picker`, `input`, `listbox`,
|
|
163
|
+
`number`, `radio-group`, `select`, `slider`, `slider-multi-thumb`, `spinbutton`, `switch`,
|
|
164
|
+
`textarea`
|
|
165
|
+
- **Feedback and content**: `alert`, `badge`, `callout`, `card`, `copy-button`, `meter`,
|
|
166
|
+
`progress`, `spinner`, `toast`
|
|
167
|
+
- **Disclosure and overlays**: `accordion`, `alert-dialog`, `command-palette`, `context-menu`,
|
|
168
|
+
`dialog`, `disclosure`, `drawer`, `menu`, `menu-button`, `popover`, `tooltip`
|
|
169
|
+
- **Navigation and structure**: `breadcrumb`, `landmarks`, `link`, `sidebar`, `tabs`, `toolbar`,
|
|
170
|
+
`treeview`, `window-splitter`
|
|
171
|
+
- **Data and composite widgets**: `carousel`, `feed`, `grid`, `table`, `treegrid`
|
|
172
|
+
|
|
173
|
+
Shared layers:
|
|
174
|
+
|
|
175
|
+
- [`src/core/`](./src/core/): low-level state primitives such as selection and value-range logic
|
|
176
|
+
- [`src/interactions/`](./src/interactions/): keyboard intents, typeahead, composite navigation,
|
|
177
|
+
overlay focus
|
|
178
|
+
- [`src/a11y-contracts/`](./src/a11y-contracts/): typed ARIA and role contracts
|
|
179
|
+
- [`src/adapters/`](./src/adapters/): thin adapter contracts for presentation-layer bindings
|
|
180
|
+
|
|
181
|
+
## Repository Map
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
src/
|
|
185
|
+
core/
|
|
186
|
+
interactions/
|
|
187
|
+
a11y-contracts/
|
|
188
|
+
adapters/
|
|
189
|
+
<component>/
|
|
190
|
+
|
|
191
|
+
specs/
|
|
192
|
+
ADR-*.md
|
|
193
|
+
components/<component>.md
|
|
194
|
+
release/*
|
|
195
|
+
ops/*
|
|
196
|
+
```
|
|
25
197
|
|
|
26
|
-
|
|
198
|
+
Repository conventions:
|
|
27
199
|
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- `./specs/release/mvp-changelog.md`
|
|
200
|
+
- every component lives in [`src/<component>/`](./src/)
|
|
201
|
+
- every component has a colocated test file in `src/<component>/<component>.test.ts`
|
|
202
|
+
- every component has a dedicated behavior spec in [`specs/components/<component>.md`](./specs/components/)
|
|
203
|
+
- package boundaries are enforced so the code remains portable outside this monorepo
|
|
33
204
|
|
|
34
|
-
##
|
|
205
|
+
## Quality And Release Discipline
|
|
206
|
+
|
|
207
|
+
The repository treats behavior and accessibility as release contracts, not informal implementation
|
|
208
|
+
details.
|
|
209
|
+
|
|
210
|
+
That discipline is enforced through:
|
|
211
|
+
|
|
212
|
+
- unit tests for transitions and invariants
|
|
213
|
+
- shared APG regression coverage for cross-component accessibility guarantees
|
|
214
|
+
- package export checks and bundle shape checks
|
|
215
|
+
- standalone boundary checks to prevent accidental monorepo coupling
|
|
216
|
+
- explicit SemVer and deprecation policy for public API evolution
|
|
217
|
+
|
|
218
|
+
## Package-Local Workflow
|
|
35
219
|
|
|
36
220
|
Run all package checks from the package root:
|
|
37
221
|
|
|
@@ -43,57 +227,13 @@ npm run build
|
|
|
43
227
|
npm pack --dry-run
|
|
44
228
|
```
|
|
45
229
|
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- `
|
|
51
|
-
- `
|
|
52
|
-
- `
|
|
53
|
-
- `
|
|
54
|
-
- `
|
|
55
|
-
- `
|
|
56
|
-
- `meter` (`src/meter/`, `specs/components/meter.md`)
|
|
57
|
-
- `link` (`src/link/`, `specs/components/link.md`)
|
|
58
|
-
- `table` (`src/table/`, `specs/components/table.md`)
|
|
59
|
-
- `button` (`src/button/`, `specs/components/button.md`)
|
|
60
|
-
- `checkbox` (`src/checkbox/`, `specs/components/checkbox.md`)
|
|
61
|
-
- `switch` (`src/switch/`, `specs/components/switch.md`)
|
|
62
|
-
- `radio-group` (`src/radio-group/`, `specs/components/radio-group.md`)
|
|
63
|
-
- `slider` (`src/slider/`, `specs/components/slider.md`)
|
|
64
|
-
- `spinbutton` (`src/spinbutton/`, `specs/components/spinbutton.md`)
|
|
65
|
-
- `slider-multi-thumb` (`src/slider-multi-thumb/`, `specs/components/slider-multi-thumb.md`)
|
|
66
|
-
- `disclosure` (`src/disclosure/`, `specs/components/disclosure.md`)
|
|
67
|
-
- `accordion` (`src/accordion/`, `specs/components/accordion.md`)
|
|
68
|
-
- `dialog` (`src/dialog/`, `specs/components/dialog.md`)
|
|
69
|
-
- `alert-dialog` (`src/alert-dialog/`, `specs/components/alert-dialog.md`)
|
|
70
|
-
- `tooltip` (`src/tooltip/`, `specs/components/tooltip.md`)
|
|
71
|
-
- `menu-button` (`src/menu-button/`, `specs/components/menu-button.md`)
|
|
72
|
-
- `toolbar` (`src/toolbar/`, `specs/components/toolbar.md`)
|
|
73
|
-
- `grid` (`src/grid/`, `specs/components/grid.md`)
|
|
74
|
-
- `treegrid` (`src/treegrid/`, `specs/components/treegrid.md`)
|
|
75
|
-
- `feed` (`src/feed/`, `specs/components/feed.md`)
|
|
76
|
-
- `carousel` (`src/carousel/`, `specs/components/carousel.md`)
|
|
77
|
-
- `window-splitter` (`src/window-splitter/`, `specs/components/window-splitter.md`)
|
|
78
|
-
|
|
79
|
-
## MVP-next scaffolds (not finalized)
|
|
80
|
-
|
|
81
|
-
- `popover` (`src/popover/`, `specs/components/popover.md`)
|
|
82
|
-
- `select` (`src/select/`, `specs/components/select.md`)
|
|
83
|
-
- `context-menu` (`src/context-menu/`, `specs/components/context-menu.md`)
|
|
84
|
-
- `command-palette` (`src/command-palette/`, `specs/components/command-palette.md`)
|
|
85
|
-
- `toast` (`src/toast/`, `specs/components/toast.md`)
|
|
86
|
-
- `progress` (`src/progress/`, `specs/components/progress.md`)
|
|
87
|
-
|
|
88
|
-
## Shared layers
|
|
89
|
-
|
|
90
|
-
- `src/core/` - selection and value-range state primitives
|
|
91
|
-
- `src/interactions/` - keyboard intents, typeahead, composite navigation, overlay focus
|
|
92
|
-
- `src/a11y-contracts/` - typed aria/role contracts
|
|
93
|
-
- `src/adapters/` - adapter contracts and integration coverage
|
|
94
|
-
|
|
95
|
-
## Conventions
|
|
96
|
-
|
|
97
|
-
- each component lives in a dedicated directory: `src/<component>/`
|
|
98
|
-
- each component has a dedicated contract spec: `specs/components/<component>.md`
|
|
99
|
-
- package must remain independent from monorepo-only imports (`@project/*`, `apps/*`)
|
|
230
|
+
## Read Next
|
|
231
|
+
|
|
232
|
+
If you are new to the repository, these documents explain the bigger picture:
|
|
233
|
+
|
|
234
|
+
- [`./specs/ADR-001-headless-architecture.md`](./specs/ADR-001-headless-architecture.md)
|
|
235
|
+
- [`./specs/ADR-003-public-api-versioning.md`](./specs/ADR-003-public-api-versioning.md)
|
|
236
|
+
- [`./specs/ADR-004-focus-selection-policy.md`](./specs/ADR-004-focus-selection-policy.md)
|
|
237
|
+
- [`./specs/IMPLEMENTATION-ROADMAP.md`](./specs/IMPLEMENTATION-ROADMAP.md)
|
|
238
|
+
- [`./specs/ISSUE-BACKLOG.md`](./specs/ISSUE-BACKLOG.md)
|
|
239
|
+
- [`./specs/RELEASE-CANDIDATE.md`](./specs/RELEASE-CANDIDATE.md)
|
|
@@ -9,6 +9,8 @@ export interface CreateCopyButtonOptions {
|
|
|
9
9
|
feedbackDuration?: number;
|
|
10
10
|
isDisabled?: boolean;
|
|
11
11
|
ariaLabel?: string;
|
|
12
|
+
successLabel?: string;
|
|
13
|
+
errorLabel?: string;
|
|
12
14
|
onCopy?: (value: string) => void;
|
|
13
15
|
onError?: (error: unknown) => void;
|
|
14
16
|
clipboard?: ClipboardAdapter;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { action, atom, computed } from '@reatom/core';
|
|
2
2
|
const clampDuration = (v) => Math.max(0, v);
|
|
3
3
|
const isSpaceKey = (key) => key === ' ' || key === 'Spacebar';
|
|
4
|
+
const DEFAULT_SUCCESS_LABEL = 'Copied';
|
|
5
|
+
const DEFAULT_ERROR_LABEL = 'Copy failed';
|
|
4
6
|
const STATUS_TO_ICON = {
|
|
5
7
|
idle: 'copy',
|
|
6
8
|
success: 'success',
|
|
@@ -8,6 +10,8 @@ const STATUS_TO_ICON = {
|
|
|
8
10
|
};
|
|
9
11
|
export function createCopyButton(options = {}) {
|
|
10
12
|
const clipboard = options.clipboard ?? navigator.clipboard;
|
|
13
|
+
const successLabel = options.successLabel ?? DEFAULT_SUCCESS_LABEL;
|
|
14
|
+
const errorLabel = options.errorLabel ?? DEFAULT_ERROR_LABEL;
|
|
11
15
|
const statusAtom = atom('idle', 'copyButton.status');
|
|
12
16
|
const isDisabledAtom = atom(options.isDisabled ?? false, 'copyButton.isDisabled');
|
|
13
17
|
const isCopyingAtom = atom(false, 'copyButton.isCopying');
|
|
@@ -103,10 +107,10 @@ export function createCopyButton(options = {}) {
|
|
|
103
107
|
ariaLabel = options.ariaLabel;
|
|
104
108
|
}
|
|
105
109
|
else if (status === 'success') {
|
|
106
|
-
ariaLabel =
|
|
110
|
+
ariaLabel = successLabel;
|
|
107
111
|
}
|
|
108
112
|
else {
|
|
109
|
-
ariaLabel =
|
|
113
|
+
ariaLabel = errorLabel;
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
116
|
const props = {
|
package/dist/menu/index.js
CHANGED
|
@@ -471,7 +471,7 @@ export function createMenu(options) {
|
|
|
471
471
|
'aria-label': parentItem?.label,
|
|
472
472
|
};
|
|
473
473
|
},
|
|
474
|
-
getSubmenuItemProps(
|
|
474
|
+
getSubmenuItemProps(_parentItemId, childId) {
|
|
475
475
|
const item = submenuItemById.get(childId);
|
|
476
476
|
if (!item) {
|
|
477
477
|
throw new Error(`Unknown submenu item id: ${childId}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chromvoid/headless-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Headless interaction and accessibility contracts for future UI kit",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"a11y",
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
"test:watch": "vitest --config ./vitest.config.ts --watch"
|
|
77
77
|
},
|
|
78
78
|
"dependencies": {
|
|
79
|
-
"@reatom/core": "^
|
|
79
|
+
"@reatom/core": "^1001.0.0"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@types/node": "^24.11.0",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
> **Authors**: Team ChromVoid
|
|
7
7
|
> **Related Documents**:
|
|
8
8
|
>
|
|
9
|
-
> - [packages/headless/README.md](../README.md) - package goal
|
|
9
|
+
> - [packages/headless-ui/README.md](../README.md) - package goal
|
|
10
10
|
> - [WAI-ARIA APG patterns](https://www.w3.org/WAI/ARIA/apg/patterns/) - accessibility behavior patterns
|
|
11
11
|
> - [WAI-ARIA APG keyboard interface](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/) - keyboard and focus rules
|
|
12
12
|
> - [Reatom docs](https://www.reatom.dev/) - state management model
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
> - [ADR-003-public-api-versioning](./ADR-003-public-api-versioning.md) - SemVer and deprecation policy
|
|
15
15
|
> - [ADR-004-focus-selection-policy](./ADR-004-focus-selection-policy.md) - shared focus/selection policy
|
|
16
16
|
>
|
|
17
|
-
> **Note**: `packages/headless` in this monorepo is a development mirror.
|
|
17
|
+
> **Note**: `packages/headless-ui` in this monorepo is a development mirror.
|
|
18
18
|
> The canonical source, versioning, and publishing flow live in a separate public git-shard repository.
|
|
19
19
|
|
|
20
20
|
## Context
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
We need a highly independent headless package for a future UI kit:
|
|
23
23
|
|
|
24
24
|
- no visual layer;
|
|
25
|
-
- Reatom
|
|
25
|
+
- Reatom v1001 as the state runtime;
|
|
26
26
|
- behavior contracts aligned with WAI-ARIA APG.
|
|
27
27
|
|
|
28
28
|
The package is developed in this monorepo for local integration speed,
|
|
@@ -56,7 +56,7 @@ If this package is treated as a regular internal monorepo module, we get:
|
|
|
56
56
|
|
|
57
57
|
### 1. Repository Model and Ownership
|
|
58
58
|
|
|
59
|
-
1. `packages/headless` in this monorepo is a development mirror.
|
|
59
|
+
1. `packages/headless-ui` in this monorepo is a development mirror.
|
|
60
60
|
2. Canonical code history, tags, and releases are managed in a separate public git-shard repository.
|
|
61
61
|
3. Publishing to package registries is done only from git-shard.
|
|
62
62
|
|
|
@@ -134,8 +134,8 @@ Example:
|
|
|
134
134
|
|
|
135
135
|
### 5. State Runtime Policy
|
|
136
136
|
|
|
137
|
-
- **MUST**: Reatom
|
|
138
|
-
- **MUST NOT**:
|
|
137
|
+
- **MUST**: Reatom v1001.
|
|
138
|
+
- **MUST NOT**: legacy state runtime in headless core.
|
|
139
139
|
|
|
140
140
|
### 6. Testing and Verification
|
|
141
141
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
## Context
|
|
12
12
|
|
|
13
|
-
`packages/headless` is developed in the monorepo for local integration convenience.
|
|
13
|
+
`packages/headless-ui` is developed in the monorepo for local integration convenience.
|
|
14
14
|
The package must still be published as an independent public package from a separate git-shard repository.
|
|
15
15
|
|
|
16
16
|
Without a clear model, mirror and shard will drift, and releases will become hard to reproduce.
|
|
@@ -42,7 +42,7 @@ We need a formal source-of-truth and release flow that answers:
|
|
|
42
42
|
### 1. Source of Truth
|
|
43
43
|
|
|
44
44
|
1. Public git-shard repository is the single canonical source for `headless`.
|
|
45
|
-
2. `packages/headless` in monorepo is mirror-only development workspace.
|
|
45
|
+
2. `packages/headless-ui` in monorepo is mirror-only development workspace.
|
|
46
46
|
|
|
47
47
|
### 2. Release Ownership
|
|
48
48
|
|
package/specs/ISSUE-BACKLOG.md
CHANGED
|
@@ -18,11 +18,11 @@ Common labels:
|
|
|
18
18
|
|
|
19
19
|
Applies to all issues unless overridden:
|
|
20
20
|
|
|
21
|
-
1. Code/docs changed in `packages/headless` only.
|
|
21
|
+
1. Code/docs changed in `packages/headless-ui` only.
|
|
22
22
|
2. No forbidden imports (boundary check remains green).
|
|
23
23
|
3. `npm run lint` passes.
|
|
24
24
|
4. `npm run test` passes.
|
|
25
|
-
5. Public exports are wired in `packages/headless/src/index.ts`.
|
|
25
|
+
5. Public exports are wired in `packages/headless-ui/src/index.ts`.
|
|
26
26
|
6. Component behavior stays aligned with corresponding `specs/components/<component>.md`.
|
|
27
27
|
|
|
28
28
|
## Backlog Baseline
|
|
@@ -118,7 +118,7 @@ When config atoms change at runtime, the model enforces invariants:
|
|
|
118
118
|
|
|
119
119
|
## ADR-001 Compliance
|
|
120
120
|
|
|
121
|
-
- **Runtime Policy**: Reatom
|
|
121
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
122
122
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
123
123
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
124
124
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
|
|
61
61
|
## ADR-001 Compliance
|
|
62
62
|
|
|
63
|
-
- **Runtime Policy**: Reatom
|
|
63
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
64
64
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
65
65
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
66
66
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
|
|
54
54
|
## ADR-001 Compliance
|
|
55
55
|
|
|
56
|
-
- **Runtime Policy**: Reatom
|
|
56
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
57
57
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
58
58
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
59
59
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -206,7 +206,7 @@ This section defines what UIKit (`cv-badge`) binds to from the headless model.
|
|
|
206
206
|
|
|
207
207
|
## ADR-001 Compliance
|
|
208
208
|
|
|
209
|
-
- **Runtime Policy**: Reatom
|
|
209
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
210
210
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
211
211
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
212
212
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
|
|
63
63
|
## ADR-001 Compliance
|
|
64
64
|
|
|
65
|
-
- **Runtime Policy**: Reatom
|
|
65
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
66
66
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
67
67
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
68
68
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -103,7 +103,7 @@ UIKit (`cv-button`) binds to the headless contract as follows:
|
|
|
103
103
|
|
|
104
104
|
## ADR-001 Compliance
|
|
105
105
|
|
|
106
|
-
- **Runtime Policy**: Reatom
|
|
106
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
107
107
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
108
108
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
109
109
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -180,7 +180,7 @@ This section defines what UIKit (`cv-callout`) binds to from the headless model.
|
|
|
180
180
|
|
|
181
181
|
## ADR-001 Compliance
|
|
182
182
|
|
|
183
|
-
- **Runtime Policy**: Reatom
|
|
183
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
184
184
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
185
185
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
186
186
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
package/specs/components/card.md
CHANGED
|
@@ -264,7 +264,7 @@ This section defines what UIKit (`cv-card`) binds to from the headless model.
|
|
|
264
264
|
|
|
265
265
|
## ADR-001 Compliance
|
|
266
266
|
|
|
267
|
-
- **Runtime Policy**: Reatom
|
|
267
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
268
268
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
269
269
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
270
270
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -127,7 +127,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
127
127
|
|
|
128
128
|
## ADR-001 Compliance
|
|
129
129
|
|
|
130
|
-
- **Runtime Policy**: Reatom
|
|
130
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
131
131
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
132
132
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
133
133
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -147,7 +147,7 @@ When this contract changes in a breaking way, the change MUST be documented in t
|
|
|
147
147
|
|
|
148
148
|
### Parity matrix (Headless vs UIKit)
|
|
149
149
|
|
|
150
|
-
This matrix is intentionally short and exists to prevent drift between `packages/headless/specs/components/checkbox.md` and `packages/uikit/specs/components/checkbox.md`.
|
|
150
|
+
This matrix is intentionally short and exists to prevent drift between `packages/headless-ui/specs/components/checkbox.md` and `packages/uikit/specs/components/checkbox.md`.
|
|
151
151
|
|
|
152
152
|
| Surface | Headless | UIKit |
|
|
153
153
|
| ---------------------------- | ------------------------------------------ | ---------------------------------------- |
|
|
@@ -161,7 +161,7 @@ This matrix is intentionally short and exists to prevent drift between `packages
|
|
|
161
161
|
|
|
162
162
|
## ADR-001 Compliance
|
|
163
163
|
|
|
164
|
-
- **Runtime Policy**: Reatom
|
|
164
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
165
165
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
166
166
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
167
167
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -405,7 +405,7 @@ UIKit adapter will:
|
|
|
405
405
|
|
|
406
406
|
## ADR-001 Compliance
|
|
407
407
|
|
|
408
|
-
- **Runtime Policy**: Reatom
|
|
408
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
409
409
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
410
410
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
411
411
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
|
|
80
80
|
## ADR-001 Compliance
|
|
81
81
|
|
|
82
|
-
- **Runtime Policy**: Reatom
|
|
82
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
83
83
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
84
84
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
85
85
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -544,7 +544,7 @@ All menu keyboard handling is no-op when the menu is closed.
|
|
|
544
544
|
|
|
545
545
|
## ADR-001 Compliance
|
|
546
546
|
|
|
547
|
-
- **Runtime Policy**: Reatom
|
|
547
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
548
548
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
549
549
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
550
550
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
| `feedbackDuration` | `number` | `1500` | Milliseconds to show success/error before reverting to idle (clamped >= 0) |
|
|
18
18
|
| `isDisabled` | `boolean` | `false` | Whether the button starts in a disabled state |
|
|
19
19
|
| `ariaLabel` | `string \| undefined` | `undefined` | Accessible label for the button (e.g., `'Copy password'`) |
|
|
20
|
+
| `successLabel` | `string \| undefined` | `'Copied'` | Accessible/status label used after successful copy |
|
|
21
|
+
| `errorLabel` | `string \| undefined` | `'Copy failed'` | Accessible/status label used after copy failure |
|
|
20
22
|
| `onCopy` | `(value: string) => void \| undefined` | `undefined` | Called on successful copy with the resolved value |
|
|
21
23
|
| `onError` | `(error: unknown) => void \| undefined` | `undefined` | Called when copy fails with the error |
|
|
22
24
|
| `clipboard` | `{ writeText(text: string): Promise<void> } \| undefined` | `navigator.clipboard` | Injectable clipboard adapter for testing and environments without native clipboard API |
|
|
@@ -80,8 +82,8 @@ type CopyButtonStatus = 'idle' | 'success' | 'error'
|
|
|
80
82
|
**`aria-label` resolution:**
|
|
81
83
|
|
|
82
84
|
- If `options.ariaLabel` is set and status is `'idle'`: returns `ariaLabel` as-is
|
|
83
|
-
- If `options.ariaLabel` is set and status is `'success'`: returns `'Copied'`
|
|
84
|
-
- If `options.ariaLabel` is set and status is `'error'`: returns `'Copy failed'`
|
|
85
|
+
- If `options.ariaLabel` is set and status is `'success'`: returns `successLabel` or `'Copied'`
|
|
86
|
+
- If `options.ariaLabel` is set and status is `'error'`: returns `errorLabel` or `'Copy failed'`
|
|
85
87
|
- If `options.ariaLabel` is not set: `aria-label` is omitted (consumer provides labeling externally)
|
|
86
88
|
|
|
87
89
|
#### `CopyStatusProps` shape
|
|
@@ -240,6 +242,8 @@ This section defines what UIKit (`cv-copy-button`) binds to from the headless mo
|
|
|
240
242
|
| `feedback-duration` | `feedbackDuration` | Numeric attribute, defaults to `1500` |
|
|
241
243
|
| `disabled` | `isDisabled` | Boolean attribute |
|
|
242
244
|
| `aria-label` | `ariaLabel` | Labeling |
|
|
245
|
+
| `success-label` | `successLabel` | Localized success feedback label supplied by adapters |
|
|
246
|
+
| `error-label` | `errorLabel` | Localized error feedback label supplied by adapters |
|
|
243
247
|
|
|
244
248
|
### UIKit-only concerns (NOT in headless)
|
|
245
249
|
|
|
@@ -278,7 +282,7 @@ This section defines what UIKit (`cv-copy-button`) binds to from the headless mo
|
|
|
278
282
|
|
|
279
283
|
## ADR-001 Compliance
|
|
280
284
|
|
|
281
|
-
- **Runtime Policy**: Reatom
|
|
285
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
282
286
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
283
287
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
284
288
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -287,7 +287,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
287
287
|
|
|
288
288
|
## ADR-001 Compliance
|
|
289
289
|
|
|
290
|
-
- **Runtime Policy**: Reatom
|
|
290
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
291
291
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
292
292
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
293
293
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -244,7 +244,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
244
244
|
|
|
245
245
|
## ADR-001 Compliance
|
|
246
246
|
|
|
247
|
-
- **Runtime Policy**: Reatom
|
|
247
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
248
248
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
249
249
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
250
250
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -339,7 +339,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
339
339
|
|
|
340
340
|
## ADR-001 Compliance
|
|
341
341
|
|
|
342
|
-
- **Runtime Policy**: Reatom
|
|
342
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
343
343
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
344
344
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
345
345
|
- **Composition**: `createDrawer` wraps `createDialog`; no duplication of dialog internals.
|
package/specs/components/feed.md
CHANGED
|
@@ -251,7 +251,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
251
251
|
|
|
252
252
|
## ADR-001 Compliance
|
|
253
253
|
|
|
254
|
-
- **Runtime Policy**: Reatom
|
|
254
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
255
255
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
256
256
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
257
257
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
package/specs/components/grid.md
CHANGED
|
@@ -173,7 +173,7 @@ UIKit (or any rendering adapter) must:
|
|
|
173
173
|
|
|
174
174
|
## ADR-001 Compliance
|
|
175
175
|
|
|
176
|
-
- **Runtime Policy**: Reatom only; no
|
|
176
|
+
- **Runtime Policy**: Reatom only; no legacy state runtime in headless core.
|
|
177
177
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
178
178
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
179
179
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -238,7 +238,7 @@ UIKit (`cv-input`) binds to the headless contract as follows:
|
|
|
238
238
|
|
|
239
239
|
## ADR-001 Compliance
|
|
240
240
|
|
|
241
|
-
- **Runtime Policy**: Reatom
|
|
241
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
242
242
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
243
243
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
244
244
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -125,7 +125,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
125
125
|
|
|
126
126
|
## ADR-001 Compliance
|
|
127
127
|
|
|
128
|
-
- **Runtime Policy**: Reatom
|
|
128
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
129
129
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
130
130
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
131
131
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
package/specs/components/link.md
CHANGED
|
@@ -121,7 +121,7 @@ UIKit (`cv-link`) binds to the headless contract as follows:
|
|
|
121
121
|
|
|
122
122
|
## ADR-001 Compliance
|
|
123
123
|
|
|
124
|
-
- **Runtime Policy**: Reatom
|
|
124
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
125
125
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
126
126
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
127
127
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -340,7 +340,7 @@ UIKit adapter will:
|
|
|
340
340
|
|
|
341
341
|
## ADR-001 Compliance
|
|
342
342
|
|
|
343
|
-
- **Runtime Policy**: Reatom
|
|
343
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
344
344
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
345
345
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
346
346
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
|
|
65
65
|
## ADR-001 Compliance
|
|
66
66
|
|
|
67
|
-
- **Runtime Policy**: Reatom
|
|
67
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
68
68
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
69
69
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
70
70
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
package/specs/components/menu.md
CHANGED
|
@@ -609,7 +609,7 @@ UIKit adapter (`cv-menu`) will:
|
|
|
609
609
|
|
|
610
610
|
## ADR-001 Compliance
|
|
611
611
|
|
|
612
|
-
- **Runtime Policy**: Reatom
|
|
612
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
613
613
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
614
614
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
615
615
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -137,7 +137,7 @@ A default slot is supported in the UIKit layer for custom label content inside t
|
|
|
137
137
|
|
|
138
138
|
## ADR-001 Compliance
|
|
139
139
|
|
|
140
|
-
- **Runtime Policy**: Reatom
|
|
140
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
141
141
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
142
142
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
143
143
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -375,7 +375,7 @@ UIKit reads `state.draftText()` and `state.value()` to determine what to display
|
|
|
375
375
|
|
|
376
376
|
## ADR-001 Compliance
|
|
377
377
|
|
|
378
|
-
- **Runtime Policy**: Reatom
|
|
378
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
379
379
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings. The number module sits in the interactions layer, composing the spinbutton core.
|
|
380
380
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules. Only imports from `../spinbutton` (intra-package) and `@reatom/core`.
|
|
381
381
|
- **Composition**: `createNumber` internally creates a `createSpinbutton` instance. It does NOT duplicate spinbutton logic.
|
|
@@ -238,7 +238,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
238
238
|
|
|
239
239
|
## ADR-001 Compliance
|
|
240
240
|
|
|
241
|
-
- **Runtime Policy**: Reatom
|
|
241
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
242
242
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
243
243
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
244
244
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -175,7 +175,7 @@ Note: `increment()` and `decrement()` are available for programmatic use but hav
|
|
|
175
175
|
|
|
176
176
|
## ADR-001 Compliance
|
|
177
177
|
|
|
178
|
-
- **Runtime Policy**: Reatom
|
|
178
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
179
179
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
180
180
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
181
181
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -139,7 +139,7 @@ UIKit adapter (`cv-radio-group` + `cv-radio`) will:
|
|
|
139
139
|
|
|
140
140
|
## ADR-001 Compliance
|
|
141
141
|
|
|
142
|
-
- **Runtime Policy**: Reatom
|
|
142
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
143
143
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
144
144
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
145
145
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -132,7 +132,7 @@ UIKit adapter will:
|
|
|
132
132
|
|
|
133
133
|
## ADR-001 Compliance
|
|
134
134
|
|
|
135
|
-
- **Runtime Policy**: Reatom
|
|
135
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
136
136
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
137
137
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
138
138
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -306,7 +306,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
306
306
|
|
|
307
307
|
## ADR-001 Compliance
|
|
308
308
|
|
|
309
|
-
- **Runtime Policy**: Reatom
|
|
309
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
310
310
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
311
311
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
312
312
|
- **Composition**: `createSidebar` composes `createDialog` for mobile overlay mode; no duplication of dialog internals.
|
|
@@ -66,7 +66,7 @@ It handles multi-value state, thumb collision/crossing prevention, and independe
|
|
|
66
66
|
|
|
67
67
|
## ADR-001 Compliance
|
|
68
68
|
|
|
69
|
-
- **Runtime Policy**: Reatom
|
|
69
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
70
70
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
71
71
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
72
72
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -72,7 +72,7 @@ It handles range constraints, step increments, and standard keyboard navigation
|
|
|
72
72
|
|
|
73
73
|
## ADR-001 Compliance
|
|
74
74
|
|
|
75
|
-
- **Runtime Policy**: Reatom
|
|
75
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
76
76
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
77
77
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
78
78
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -128,7 +128,7 @@ Range semantics:
|
|
|
128
128
|
|
|
129
129
|
## ADR-001 Compliance
|
|
130
130
|
|
|
131
|
-
- **Runtime Policy**: Reatom
|
|
131
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
132
132
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
133
133
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
134
134
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -118,7 +118,7 @@ This section defines what UIKit (`cv-spinner`) binds to from the headless model.
|
|
|
118
118
|
|
|
119
119
|
## ADR-001 Compliance
|
|
120
120
|
|
|
121
|
-
- **Runtime Policy**: Reatom
|
|
121
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
122
122
|
- **Layering**: `core -> interactions -> a11y-contracts -> adapters`; adapters remain thin mappings.
|
|
123
123
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
124
124
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -162,7 +162,7 @@ UIKit adapter (`cv-switch`) will:
|
|
|
162
162
|
|
|
163
163
|
## ADR-001 Compliance
|
|
164
164
|
|
|
165
|
-
- **Runtime Policy**: Reatom
|
|
165
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
166
166
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
167
167
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
168
168
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -388,7 +388,7 @@ UIKit adapter will:
|
|
|
388
388
|
|
|
389
389
|
## ADR-001 Compliance
|
|
390
390
|
|
|
391
|
-
- **Runtime Policy**: Reatom
|
|
391
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
392
392
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
393
393
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
394
394
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
package/specs/components/tabs.md
CHANGED
|
@@ -252,7 +252,7 @@ This section lists exactly what the UIKit adapter layer binds to.
|
|
|
252
252
|
|
|
253
253
|
## ADR-001 Compliance
|
|
254
254
|
|
|
255
|
-
- **Runtime Policy**: Reatom
|
|
255
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
256
256
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
257
257
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
258
258
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -172,7 +172,7 @@ UIKit (`cv-textarea`) binds to the headless contract as follows:
|
|
|
172
172
|
|
|
173
173
|
## ADR-001 Compliance
|
|
174
174
|
|
|
175
|
-
- **Runtime Policy**: Reatom
|
|
175
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
176
176
|
- **Layering**: core/interactions/a11y-contracts/adapters boundaries preserved.
|
|
177
177
|
- **Independence**: no monorepo app imports.
|
|
178
178
|
- **Verification**: standalone headless tests via package command.
|
|
@@ -183,7 +183,7 @@ UIKit adapters MUST bind to the headless model as follows:
|
|
|
183
183
|
|
|
184
184
|
## ADR-001 Compliance
|
|
185
185
|
|
|
186
|
-
- **Runtime Policy**: Reatom
|
|
186
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
187
187
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
188
188
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
189
189
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -264,7 +264,7 @@ This section lists exactly what the UIKit adapter layer binds to.
|
|
|
264
264
|
|
|
265
265
|
## ADR-001 Compliance
|
|
266
266
|
|
|
267
|
-
- **Runtime Policy**: Reatom
|
|
267
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
268
268
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
269
269
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
270
270
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -240,7 +240,7 @@ Headless adapters (e.g., the UIKit `cv-tooltip` web component, React wrappers) M
|
|
|
240
240
|
|
|
241
241
|
## ADR-001 Compliance
|
|
242
242
|
|
|
243
|
-
- **Runtime Policy**: Reatom
|
|
243
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
244
244
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
245
245
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
246
246
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -266,7 +266,7 @@ Note: `getCellProps` includes an `onFocus` handler that must be wired to the cel
|
|
|
266
266
|
|
|
267
267
|
## ADR-001 Compliance
|
|
268
268
|
|
|
269
|
-
- **Runtime Policy**: Reatom
|
|
269
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
270
270
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
271
271
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
272
272
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -78,7 +78,7 @@ In multiple-select mode (`selectionMode: 'multiple'`), focus and selection remai
|
|
|
78
78
|
|
|
79
79
|
## ADR-001 Compliance
|
|
80
80
|
|
|
81
|
-
- **Runtime Policy**: Reatom
|
|
81
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
82
82
|
- **Layering**: core -> interactions -> a11y-contracts -> adapters; adapters remain thin mappings.
|
|
83
83
|
- **Independence**: No imports from @project/_, apps/_, or other out-of-package modules.
|
|
84
84
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -282,7 +282,7 @@ The UIKit adapter reads `snap` and `snapThreshold` from element attributes (or c
|
|
|
282
282
|
|
|
283
283
|
## ADR-001 Compliance
|
|
284
284
|
|
|
285
|
-
- **Runtime Policy**: Reatom
|
|
285
|
+
- **Runtime Policy**: Reatom v1001 only; no legacy state runtime in headless core.
|
|
286
286
|
- **Layering**: core → interactions → a11y-contracts → adapters; adapters remain thin mappings.
|
|
287
287
|
- **Independence**: No imports from `@project/*`, `apps/*`, or other out-of-package modules.
|
|
288
288
|
- **Verification**: Mandatory adapter integration tests and standalone package test execution.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
This document defines the operational sync flow between:
|
|
6
6
|
|
|
7
|
-
- monorepo mirror: `packages/headless`
|
|
7
|
+
- monorepo mirror: `packages/headless-ui`
|
|
8
8
|
- canonical public repository: git-shard
|
|
9
9
|
|
|
10
10
|
It implements `HLS-001` and supports ADR-001/ADR-002.
|
|
@@ -22,7 +22,7 @@ Use this when changes were developed inside monorepo and must be promoted to can
|
|
|
22
22
|
|
|
23
23
|
### Preconditions
|
|
24
24
|
|
|
25
|
-
1. changes are limited to `packages/headless/**`
|
|
25
|
+
1. changes are limited to `packages/headless-ui/**`
|
|
26
26
|
2. local checks pass:
|
|
27
27
|
- `npm run lint`
|
|
28
28
|
- `npm run test`
|
|
@@ -58,7 +58,7 @@ Use this after shard releases or direct shard-first development.
|
|
|
58
58
|
|
|
59
59
|
1. create monorepo branch:
|
|
60
60
|
- naming: `sync/shard-YYYYMMDD-<tag-or-topic>`
|
|
61
|
-
2. copy/sync shard files into `packages/headless`
|
|
61
|
+
2. copy/sync shard files into `packages/headless-ui`
|
|
62
62
|
3. run mirror checks:
|
|
63
63
|
- `npm run lint`
|
|
64
64
|
- `npm run test`
|
|
@@ -100,7 +100,7 @@ If a critical bugfix is required:
|
|
|
100
100
|
|
|
101
101
|
Before any sync merge:
|
|
102
102
|
|
|
103
|
-
- [ ] scope limited to `packages/headless/**`
|
|
103
|
+
- [ ] scope limited to `packages/headless-ui/**`
|
|
104
104
|
- [ ] lint/test checks are green
|
|
105
105
|
- [ ] no forbidden imports
|
|
106
106
|
- [ ] source and destination references documented
|
|
@@ -7,7 +7,7 @@ This file provides issue-ready tickets for the remaining work before stable rele
|
|
|
7
7
|
## How to Use
|
|
8
8
|
|
|
9
9
|
- copy each issue into tracker as a standalone task
|
|
10
|
-
- keep scope limited to `packages/headless/**` unless issue says otherwise
|
|
10
|
+
- keep scope limited to `packages/headless-ui/**` unless issue says otherwise
|
|
11
11
|
- require evidence links for CI runs and docs updates
|
|
12
12
|
|
|
13
13
|
Common labels:
|
|
@@ -26,7 +26,7 @@ Common labels:
|
|
|
26
26
|
- **Labels**: `headless`, `release`, `governance`, `ci`
|
|
27
27
|
- **Scope**: add an automated gate that validates SemVer classification in release PR metadata
|
|
28
28
|
- **Deliverables**:
|
|
29
|
-
- release-governance check script in `packages/headless/scripts/`
|
|
29
|
+
- release-governance check script in `packages/headless-ui/scripts/`
|
|
30
30
|
- CI workflow job that runs the check for release PR context
|
|
31
31
|
- **Acceptance Criteria**:
|
|
32
32
|
- release PR without explicit SemVer classification fails CI
|
|
@@ -54,7 +54,7 @@ Common labels:
|
|
|
54
54
|
- **Labels**: `headless`, `tests`, `a11y`
|
|
55
55
|
- **Scope**: add component-level integration tests validating adapter-style bindings for keyboard/pointer flows
|
|
56
56
|
- **Deliverables**:
|
|
57
|
-
- adapter integration tests under `packages/headless/src/adapters/`
|
|
57
|
+
- adapter integration tests under `packages/headless-ui/src/adapters/`
|
|
58
58
|
- **Acceptance Criteria**:
|
|
59
59
|
- tests validate `model -> bindings -> events -> state` flow
|
|
60
60
|
- tests cover keyboard and pointer paths
|
|
@@ -67,8 +67,8 @@ Common labels:
|
|
|
67
67
|
- **Labels**: `headless`, `docs`
|
|
68
68
|
- **Scope**: align README and ADR-001 metadata with implemented state of package
|
|
69
69
|
- **Deliverables**:
|
|
70
|
-
- `packages/headless/README.md` updated with all implemented components and structure
|
|
71
|
-
- `packages/headless/specs/ADR-001-headless-architecture.md` status/version update
|
|
70
|
+
- `packages/headless-ui/README.md` updated with all implemented components and structure
|
|
71
|
+
- `packages/headless-ui/specs/ADR-001-headless-architecture.md` status/version update
|
|
72
72
|
- **Acceptance Criteria**:
|
|
73
73
|
- README no longer describes listbox as the only current example
|
|
74
74
|
- ADR-001 status reflects accepted architecture baseline
|
|
@@ -79,7 +79,7 @@ Common labels:
|
|
|
79
79
|
- **Status**: Open
|
|
80
80
|
- **Priority**: High
|
|
81
81
|
- **Labels**: `headless`, `ci`, `release`
|
|
82
|
-
- **Scope**: add root CI job that runs package-specific lint and tests for `packages/headless`
|
|
82
|
+
- **Scope**: add root CI job that runs package-specific lint and tests for `packages/headless-ui`
|
|
83
83
|
- **Deliverables**:
|
|
84
84
|
- root workflow update with headless package job
|
|
85
85
|
- **Acceptance Criteria**:
|
|
@@ -26,8 +26,8 @@ Data and composite widgets (latest tranche):
|
|
|
26
26
|
|
|
27
27
|
Full implemented surface at this point (30 patterns) is reflected in:
|
|
28
28
|
|
|
29
|
-
- `packages/headless/src/index.ts`
|
|
30
|
-
- `packages/headless/README.md`
|
|
29
|
+
- `packages/headless-ui/src/index.ts`
|
|
30
|
+
- `packages/headless-ui/README.md`
|
|
31
31
|
|
|
32
32
|
## Testing and APG Hardening
|
|
33
33
|
|
package/specs/signals.md
CHANGED
|
@@ -136,7 +136,7 @@ If you use a signal-aware base element (for example an XLit-style base),
|
|
|
136
136
|
this gives automatic dependency tracking.
|
|
137
137
|
|
|
138
138
|
```ts
|
|
139
|
-
class ListboxView extends
|
|
139
|
+
class ListboxView extends ReatomLitElement {
|
|
140
140
|
model = createListbox()
|
|
141
141
|
|
|
142
142
|
render() {
|