@astryxdesign/core 0.7.3-canary.fba04ed → 0.7.3
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/CHANGELOG.md +88 -0
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +15 -2
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +25 -2
- package/dist/Chat/ChatSystemMessage.d.ts +4 -0
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +4 -2
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +9 -5
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +2 -0
- package/package.json +4 -4
- package/src/Button/Button.test.tsx +13 -2
- package/src/Button/Button.tsx +23 -2
- package/src/Button/__tests__/Button.a11y.states.ts +4 -3
- package/src/Carousel/Carousel.spec.md +146 -0
- package/src/Chat/ChatComposer.spec.md +26 -26
- package/src/Chat/ChatComposer.test.tsx +58 -2
- package/src/Chat/ChatComposer.tsx +25 -1
- package/src/Chat/ChatSystemMessage.doc.mjs +1 -1
- package/src/Chat/ChatSystemMessage.test.tsx +25 -3
- package/src/Chat/ChatSystemMessage.tsx +6 -4
- package/src/Chat/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +8 -9
- package/src/CheckboxList/__tests__/CheckboxList.a11y.chromium.spec.ts +7 -6
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +62 -7
- package/src/DropdownMenu/DropdownMenuRadioGroup.spec.md +190 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +10 -4
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +93 -0
- package/src/DropdownMenu/__tests__/DropdownMenuRadioGroupAudit.a11y.chromium.spec.ts +327 -0
- package/src/FieldStatus/FieldStatus.spec.md +4 -4
- package/src/FieldStatus/__tests__/StatusMessage.a11y.renders.tsx +0 -18
- package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +3 -18
- package/src/FieldStatus/__tests__/StatusMessage.a11y.test.tsx +1 -2
- package/src/Markdown/Markdown.helpers.perf.test.ts +25 -19
- package/src/Table/plugins/columnResize/useTableColumnResize.spec.md +11 -11
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +4 -3
|
@@ -130,9 +130,9 @@ intentional decision.
|
|
|
130
130
|
region, including on first mount and when message or type changes, without
|
|
131
131
|
moving focus. Inside a mounted live container, `spec:AST-086` FR4 applies.
|
|
132
132
|
- **AR5 — Assistive-technology output.** Claims about whether, when, or how the
|
|
133
|
-
message is spoken or presented in braille
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
message is spoken or presented in braille are recommended real-AT follow-up
|
|
134
|
+
under `spec:AST-009`, not a merge or release requirement; DOM and
|
|
135
|
+
accessibility-tree checks prove programmatic exposure and routing.
|
|
136
136
|
- **AR2 — Visible description.** The rendered message box MUST remain available
|
|
137
137
|
to assistive technology for `aria-describedby` association and MUST NOT become
|
|
138
138
|
its own newly mounted live region.
|
|
@@ -182,7 +182,7 @@ change either presentation.
|
|
|
182
182
|
| FR5, FR6 | `FieldStatus.test.tsx` forwarding and update suites | Initial render and rerender | Breaking the released root or update behavior fails compatibility assertions. | `audit:FieldStatus/behavior` |
|
|
183
183
|
| AR1 | `StatusMessage.a11y.test.tsx` and `StatusMessage.a11y.chromium.spec.ts` | Error, warning, and success; post-mount message replacement | Removing the persistent channel, changing its role/urgency, or dropping a post-mount update fails the shared status-message contract. | `audit:FieldStatus/accessibility` |
|
|
184
184
|
| AR1 | `FieldStatus.test.tsx` channel-routing suite | First non-empty mount; same-instance message and type changes | Breaking FieldStatus's first-use hook call or severity rerouting fails component-specific assertions. | `audit:FieldStatus/accessibility` |
|
|
185
|
-
| AR5 |
|
|
185
|
+
| AR5 | Recommended real-AT follow-up under `spec:AST-009` | First mount; message replacement; type/urgency change | Spoken and braille output stay unverified until a real-AT receipt exists; this does not block merge or release. | `audit:FieldStatus/accessibility` |
|
|
186
186
|
| AR2 | `FieldStatus.test.tsx` | Attached/detached visible message and empty message | The visible description becomes a second live region or is hidden from assistive technology. | `audit:FieldStatus/accessibility` |
|
|
187
187
|
| Theming anatomy map | `scripts/check-knowledge.mjs` | Consumer anatomy and current targets | Missing, extra, duplicated, prefixed, or stale mappings fail repository validation. | `audit:FieldStatus/theming` |
|
|
188
188
|
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import {useEffect, useState, type ReactElement, type ReactNode} from 'react';
|
|
13
|
-
import {ChatSystemMessage} from '../../Chat/ChatSystemMessage';
|
|
14
13
|
import {ProgressBar} from '../../ProgressBar/ProgressBar';
|
|
15
14
|
import {Spinner} from '../../Spinner/Spinner';
|
|
16
15
|
import {Toast} from '../../Toast/Toast';
|
|
@@ -198,22 +197,6 @@ function SpinnerHarness({visibleLabel}: {visibleLabel: boolean}) {
|
|
|
198
197
|
);
|
|
199
198
|
}
|
|
200
199
|
|
|
201
|
-
function ChatSystemMessageHarness() {
|
|
202
|
-
const initial = 'Conversation started';
|
|
203
|
-
const [message, setMessage] = useState(initial);
|
|
204
|
-
return (
|
|
205
|
-
<Frame>
|
|
206
|
-
<TransitionButton name="show" onClick={() => setMessage(initial)} />
|
|
207
|
-
<TransitionButton
|
|
208
|
-
name="replace"
|
|
209
|
-
onClick={() => setMessage('A file was shared')}
|
|
210
|
-
/>
|
|
211
|
-
<TransitionButton name="clear" onClick={() => setMessage('')} />
|
|
212
|
-
<ChatSystemMessage>{message}</ChatSystemMessage>
|
|
213
|
-
</Frame>
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
200
|
function ProgressHarness({
|
|
218
201
|
initial,
|
|
219
202
|
progressValue = 40,
|
|
@@ -289,7 +272,6 @@ export const CORE_STATUS_MESSAGE_STATE_RENDERS: Record<
|
|
|
289
272
|
<SpinnerHarness visibleLabel={false} />
|
|
290
273
|
),
|
|
291
274
|
'spinner-visible-label-mounted': () => <SpinnerHarness visibleLabel />,
|
|
292
|
-
'chat-system-status-mounted': () => <ChatSystemMessageHarness />,
|
|
293
275
|
'progress-loading-to-complete': () => <ProgressHarness />,
|
|
294
276
|
'progress-custom-range': () => (
|
|
295
277
|
<ProgressHarness
|
|
@@ -14,7 +14,6 @@ export type CoreStatusMessageBinding =
|
|
|
14
14
|
| 'Toast card'
|
|
15
15
|
| 'FieldStatus announcement channel'
|
|
16
16
|
| 'Spinner'
|
|
17
|
-
| 'ChatSystemMessage'
|
|
18
17
|
| 'ProgressBar';
|
|
19
18
|
|
|
20
19
|
export interface CoreStatusMessageBindingDefinition {
|
|
@@ -188,20 +187,6 @@ export const CORE_STATUS_MESSAGE_BINDING_STATES = [
|
|
|
188
187
|
}),
|
|
189
188
|
storyId: 'a11y-status-message-pattern--spinner-visible-label-mounted',
|
|
190
189
|
},
|
|
191
|
-
{
|
|
192
|
-
id: 'chat-system-status-mounted',
|
|
193
|
-
binding: 'ChatSystemMessage',
|
|
194
|
-
summary: 'a chat status notice is mounted with its live-region content',
|
|
195
|
-
facts: liveFacts({
|
|
196
|
-
role: 'status',
|
|
197
|
-
politeness: 'polite',
|
|
198
|
-
initialMessage: 'Conversation started',
|
|
199
|
-
message: 'Conversation started',
|
|
200
|
-
replacement: 'A file was shared',
|
|
201
|
-
semanticTransitions: ['replace', 'clear'],
|
|
202
|
-
}),
|
|
203
|
-
storyId: 'a11y-status-message-pattern--chat-system-status-mounted',
|
|
204
|
-
},
|
|
205
190
|
{
|
|
206
191
|
id: 'progress-loading-to-complete',
|
|
207
192
|
binding: 'ProgressBar',
|
|
@@ -279,10 +264,10 @@ export const CORE_STATUS_MESSAGE_EXCLUSIONS = [
|
|
|
279
264
|
'A composing control that marks Spinner aria-hidden owns the surrounding busy semantics; the decorative ring is not another status message.',
|
|
280
265
|
},
|
|
281
266
|
{
|
|
282
|
-
owner: 'ChatSystemMessage
|
|
283
|
-
part: '
|
|
267
|
+
owner: 'ChatSystemMessage',
|
|
268
|
+
part: 'chat notice or date separator',
|
|
284
269
|
reason:
|
|
285
|
-
'
|
|
270
|
+
'spec:AST-086 FR4: a notice added to a chat log is delivered by the log, so neither the notice row nor the divider carries its own live role; a date or section separator is ordinary transcript content.',
|
|
286
271
|
},
|
|
287
272
|
{
|
|
288
273
|
owner: 'ChatMessageList and streaming logs',
|
|
@@ -128,7 +128,6 @@ describe('Core status-message binding inventory', () => {
|
|
|
128
128
|
),
|
|
129
129
|
].sort(),
|
|
130
130
|
).toEqual([
|
|
131
|
-
'ChatSystemMessage',
|
|
132
131
|
'FieldStatus announcement channel',
|
|
133
132
|
'ProgressBar',
|
|
134
133
|
'Spinner',
|
|
@@ -141,7 +140,7 @@ describe('Core status-message binding inventory', () => {
|
|
|
141
140
|
expect(CORE_STATUS_MESSAGE_EXCLUSIONS.map(entry => entry.part)).toEqual([
|
|
142
141
|
'visible validation text',
|
|
143
142
|
'aria-hidden decorative spinner',
|
|
144
|
-
'
|
|
143
|
+
'chat notice or date separator',
|
|
145
144
|
'role=log transcript updates',
|
|
146
145
|
'composer errors and tool-run states',
|
|
147
146
|
'busy announcement',
|
|
@@ -357,17 +357,17 @@ describe('Markdown helper performance', () => {
|
|
|
357
357
|
}),
|
|
358
358
|
];
|
|
359
359
|
|
|
360
|
-
// Timed on the transform stage alone
|
|
361
|
-
//
|
|
362
|
-
// parse
|
|
363
|
-
//
|
|
360
|
+
// Timed on the transform stage alone: this is a few hundred
|
|
361
|
+
// microseconds against a parse of milliseconds, so measuring the whole
|
|
362
|
+
// parse buries it. Each side is compared at its FASTEST sample, the
|
|
363
|
+
// least-disturbed run it achieved, and the two sides alternate sample by
|
|
364
|
+
// sample so a slow stretch of the machine reaches both instead of one.
|
|
364
365
|
const root = parseMarkdownAst(source);
|
|
365
|
-
const
|
|
366
|
+
const transformOnly = (
|
|
366
367
|
plugins: ReadonlyArray<ReturnType<typeof createMarkdownPlugin>>,
|
|
367
|
-
)
|
|
368
|
+
) => {
|
|
368
369
|
const prepared = prepareMarkdownPlugins(plugins);
|
|
369
|
-
|
|
370
|
-
for (let sample = 0; sample < 60; sample++) {
|
|
370
|
+
return () => {
|
|
371
371
|
const start = performance.now();
|
|
372
372
|
benchmarkSink ^= applyMarkdownTransforms(
|
|
373
373
|
root,
|
|
@@ -376,18 +376,24 @@ describe('Markdown helper performance', () => {
|
|
|
376
376
|
true,
|
|
377
377
|
'block',
|
|
378
378
|
).children.length;
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
void benchmarkSink;
|
|
382
|
-
return fastest;
|
|
379
|
+
return performance.now() - start;
|
|
380
|
+
};
|
|
383
381
|
};
|
|
384
|
-
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
382
|
+
const single = transformOnly(plugin('scale-single', gaps));
|
|
383
|
+
const double = transformOnly(plugin('scale-double', doubled));
|
|
384
|
+
let fastestSingle = Number.POSITIVE_INFINITY;
|
|
385
|
+
let fastestDouble = Number.POSITIVE_INFINITY;
|
|
386
|
+
for (let sample = 0; sample < 80; sample++) {
|
|
387
|
+
// The first rounds only warm both sides.
|
|
388
|
+
const singleTime = single();
|
|
389
|
+
const doubleTime = double();
|
|
390
|
+
if (sample >= 20) {
|
|
391
|
+
fastestSingle = Math.min(fastestSingle, singleTime);
|
|
392
|
+
fastestDouble = Math.min(fastestDouble, doubleTime);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
void benchmarkSink;
|
|
396
|
+
const ratio = fastestDouble / fastestSingle;
|
|
391
397
|
console.log(
|
|
392
398
|
` ${sections} sections, ${doubled.length} ranges over ${gaps.length}: ${ratio.toFixed(3)}`,
|
|
393
399
|
);
|
|
@@ -227,17 +227,17 @@ without a target of its own.
|
|
|
227
227
|
|
|
228
228
|
## Verification map
|
|
229
229
|
|
|
230
|
-
| Contract | Verification
|
|
231
|
-
| ------------------ |
|
|
232
|
-
| FR1, FR6 | `useTableColumnResize.test.tsx` boundary-presence cases plus hover-capability and coarse-primary cases
|
|
233
|
-
| FR2 | Browser measurement of scroll-region vertical overflow with the plugin enabled
|
|
234
|
-
| FR3-FR5, FR9, ORD1 | New focused tests for resting, header-hovered, pointer-on-boundary, focused, and dragging states
|
|
235
|
-
| FR10, ORD0 | Scroll-gate test driving the scroll region with a stationary pointer over the header
|
|
236
|
-
| FR7 | Snapshot or assertion that header hover changes no other header or row treatment
|
|
237
|
-
| FR8, AR1-AR3, AR6 | Existing keyboard and ARIA suites
|
|
238
|
-
| PR1, PR2 | Render-count assertion around header pointer enter/leave and during a scroll; listener and observer inspection
|
|
239
|
-
| Plugin composition | Test mounting the resize and sticky-columns plugins together in both insertion orders
|
|
240
|
-
| Record shape | `scripts/check-knowledge.mjs`
|
|
230
|
+
| Contract | Verification | Representative states | Mutation or failure expectation |
|
|
231
|
+
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
232
|
+
| FR1, FR6 | `useTableColumnResize.test.tsx` boundary-presence cases plus hover-capability and coarse-primary cases | Resizable, opted-out, and generated columns; hover-capable, coarse-primary with keyboard, and coarse-only inputs | A boundary appears on a non-resizable column, disappears from a resizable one, the hover reveal fires where no pointer can hover, or the control is absent where an input can operate it. |
|
|
233
|
+
| FR2 | Browser measurement of scroll-region vertical overflow with the plugin enabled | Short and tall tables, wrapped and single-line headers, dense and default | The indicator ends below the last row or the scroll region gains vertical scroll that the same table lacks without resize. |
|
|
234
|
+
| FR3-FR5, FR9, ORD1 | New focused tests for resting, header-hovered, pointer-on-boundary, focused, and dragging states | Rest, header hover, hover plus pointer on one boundary, keyboard focus with no pointer in the row, drag | A resting header draws boundaries, header hover misses a boundary, the pointed/focused boundary fails to outrank the hint, or focus alone draws a neighbor. |
|
|
235
|
+
| FR10, ORD0 | Scroll-gate test driving the scroll region with a stationary pointer over the header | Pointer resting over a header while the region scrolls and after it settles | Boundaries reveal mid-scroll, an existing hint survives the scroll, or disclosure fails to resume once scrolling stops. |
|
|
236
|
+
| FR7 | Snapshot or assertion that header hover changes no other header or row treatment | Header hover over a sortable and a selectable header | Header hover changes background, label, cursor, width, or another control's state. |
|
|
237
|
+
| FR8, AR1-AR3, AR6 | Existing keyboard and ARIA suites and a coarse-primary keyboard case; an assistive-technology spot check is recommended follow-up | Tab to boundary, arrow resize, screen-reader navigation of the header, coarse-primary device with a keyboard | The boundary leaves tab order on any input that can operate it, loses its name or values, or the hint reaches the accessibility tree. |
|
|
238
|
+
| PR1, PR2 | Render-count assertion around header pointer enter/leave and during a scroll; listener and observer inspection | Pointer enters and leaves the header repeatedly; the region scrolls under a resting pointer | Disclosure rerenders the Table, the scroll gate sets React state, more than one scroll listener or any timer is added, or the extent measurement observes what it resizes. |
|
|
239
|
+
| Plugin composition | Test mounting the resize and sticky-columns plugins together in both insertion orders | Pinned start column with resize enabled, before and after a drag | A pinned column loses `position: sticky` in either order, or the composition depends on caller insertion order. |
|
|
240
|
+
| Record shape | `scripts/check-knowledge.mjs` | Colocated module record, canonical id and filename, parent backlink | A missing, misnamed, mis-parented, or unlinked record passes validation. |
|
|
241
241
|
|
|
242
242
|
Browser, render-count, and assistive-technology evidence are pending. Passing this
|
|
243
243
|
specification pull request proves record integrity only.
|
|
@@ -214,8 +214,9 @@ add semantic/custom cases to representative Table render and no-op update budget
|
|
|
214
214
|
- **AR5 — Supplemental tooltip.** Tooltip may repeat `label` as pointer help, but
|
|
215
215
|
the indicator's accessible name MUST remain sufficient without opening it. The
|
|
216
216
|
current indicator is not focusable, so tooltip presence is not keyboard evidence.
|
|
217
|
-
- **AR6 — Row context.**
|
|
218
|
-
|
|
217
|
+
- **AR6 — Row context.** The named status is exposed in its row context without a
|
|
218
|
+
duplicate name, proved at the accessibility tree. Assistive-technology
|
|
219
|
+
observation of the announcement is recommended follow-up under `spec:AST-009`.
|
|
219
220
|
|
|
220
221
|
## Design relationships
|
|
221
222
|
|
|
@@ -259,7 +260,7 @@ own AST-002 review and synchronized consumer anatomy.
|
|
|
259
260
|
| FR3, FR4, FR6 | Add public-subpath compile fixtures for the unchanged interface, declaration merging and extension, semantic interface, callback union, missing labels, unknown statuses, and forbidden mixtures. | Stable custom annotations/extensions; all semantic statuses. | `TableRowStatus` changes or stops merging, semantic usage is inaccessible, or supported status mixes with custom fields. |
|
|
260
261
|
| FR3-FR5 | Extend row-status runtime tests with semantic-looking custom colors, raw/palette dots, explicit custom icons, all semantic statuses, and active-theme substitution. | Custom dot, custom icon, and three semantic outcomes. | Custom color selects an implicit glyph, semantic status bypasses shared resolution, or variant becomes caller/theme input. |
|
|
261
262
|
| FR7, ORD2-ORD4, PR4 | Runtime tests under development and production modes with repeated mixed objects, rows, and renders. | `status + color`, `status + icon`, and all three fields. | Custom input overrides supported status, forbidden fields affect output, production warns, or development warns more than once per loaded module instance. |
|
|
262
|
-
| AR1-AR6 | Existing role/name tests plus browser axe, forced-colors, tooltip modality, and VoiceOver table
|
|
263
|
+
| AR1-AR6 | Existing role/name tests plus browser axe, forced-colors, tooltip modality, and accessibility-tree row-context evidence; VoiceOver table navigation is recommended follow-up. | Semantic glyphs, custom icon, custom dot, `null`, light/dark, and every shipped theme. | Header or indicator loses its name, nested glyph is announced twice, glyph distinctions disappear, tooltip becomes sole meaning, or row context duplicates status. |
|
|
263
264
|
| PR1-PR3 | Extend `Table.perf.test.tsx` with semantic/custom initial render and no-op update cases. | Stable rerender, mixed rows, and theme substitution. | Resolution adds measurement/resources, creates a parallel registry, or exceeds existing representative Table budgets. |
|
|
264
265
|
| Structural ownership | `scripts/check-knowledge.mjs`. | Colocated module, canonical filename/id, and parent backlink. | A missing, duplicate, orphaned, mis-parented, misnamed, or undiscovered record passes validation. |
|
|
265
266
|
| Public hygiene and scope | Prettier, `check:knowledge`, checker tests, `check:repo`, changed-file scan, and public-content scan. | Parent backlink plus one module specification; no Changeset. | Runtime/docs files, private context, invalid record shape, or unrelated changes enter this contract proposal. |
|