Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/responsive-interaction-readiness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@astryxdesign/cli': patch
---

[docs] Add a reusable Responsive and Interaction Readiness rubric covering adaptive presentation choice, transient and queued UI, viewport obstruction and placement, viewport space, input capability, gestures, mobile viewport constraints, and WCAG 2.2 AA evidence.

@rubycheung
41 changes: 37 additions & 4 deletions internal/lab-readiness/audit.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import os from 'node:os';
import path from 'node:path';
import {describe, it, expect, beforeAll, afterAll} from 'vitest';

import {CHECK_KEYS, HUMAN_REVIEW_KEYS} from './catalog.mjs';
import {CHECK_KEYS, HUMAN_REVIEW_KEYS, getCheck} from './catalog.mjs';
import {deriveChecks, _internal} from './automated.mjs';
import {auditCandidate, buildRegistry, buildReport} from './audit.mjs';

Expand Down Expand Up @@ -99,7 +99,9 @@ describe('automated derivation', () => {
});
const derived = deriveChecks(root, candidate);
expect(derived.accessibilityContracts.state).not.toBe('passed');
expect(derived.accessibilityContracts.note).toMatch(/excludes packages\/lab/);
expect(derived.accessibilityContracts.note).toMatch(
/excludes packages\/lab/,
);
});

it('fails the keyboard check when the RTL sweep stops covering lab', () => {
Expand All @@ -119,7 +121,9 @@ describe('automated derivation', () => {
});
const derived = deriveChecks(root, candidate);
expect(derived.accessibilityContracts.state).not.toBe('passed');
expect(derived.accessibilityContracts.note).toMatch(/resolves to the analyzer/);
expect(derived.accessibilityContracts.note).toMatch(
/resolves to the analyzer/,
);
});

it('requires an advertised state to appear in both a story and a test', () => {
Expand Down Expand Up @@ -215,7 +219,9 @@ describe('automated derivation', () => {
"import {scaleLinear} from 'd3-scale';\n" +
'export function Widget() { return <Text>{String(scaleLinear)}</Text>; }\n',
});
expect(deriveChecks(root, candidate).systemIntegration.state).toBe('passed');
expect(deriveChecks(root, candidate).systemIntegration.state).toBe(
'passed',
);
});

it('accepts inline type modifiers in the barrel', () => {
Expand Down Expand Up @@ -284,6 +290,33 @@ describe('manifest reconciliation', () => {
expect(derived[key]).toBeUndefined();
}
});

it('treats responsive and interaction readiness as an evidenced human-review check', () => {
expect(HUMAN_REVIEW_KEYS).toContain('responsiveInteractionReadiness');
expect(getCheck('responsiveInteractionReadiness')).toMatchObject({
stageKey: 'hardenReview',
sectionKey: 'humanReview',
protocolUrl:
'https://github.com/facebook/astryx/wiki/Component-Hardening-Protocol',
humanReview: true,
});

scaffold();
const result = auditCandidate(root, {
...candidate,
declared: {
responsiveInteractionReadiness: {
state: 'passed',
note: 'Checklist completed with Pass and N/A rows.',
},
},
});
const check = result.checks.find(
c => c.key === 'responsiveInteractionReadiness',
);
expect(check.state).toBe('in_progress');
expect(check.note).toMatch(/requires linked evidence/);
});
});

describe('report shape', () => {
Expand Down
289 changes: 222 additions & 67 deletions internal/lab-readiness/catalog.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

/**
* @file catalog.mjs
* @description The lab graduation rubric: the five lifecycle stages and the 30
* @description The lab graduation rubric: the five lifecycle stages and the 31
* checks a lab component must pass before it can be promoted into
* `@astryxdesign/core`. This is the schema the Storybook readiness panel and
* `apps/storybook/.lab-readiness/latest.json` are built against.
Expand All @@ -22,7 +22,7 @@
* Storybook readiness panel that reads the emitted report.
*/

export const SCHEMA_VERSION = 1;
export const SCHEMA_VERSION = 2;
export const REPORT_KIND = 'astryx-lab-readiness-report';

const SPEC_PROTOCOL =
Expand Down Expand Up @@ -82,73 +82,228 @@ const STAGE_META = {
* readiness panel renders them in, and it is also lifecycle order.
*/
const CHECKS = [
['research', 'research', 'triage', 'Triage',
'A named owner has confirmed the problem and scope.'],
['research', 'research', 'internalResearch', 'Internal research',
'Existing Astryx and internal patterns have been audited.'],
['research', 'research', 'externalResearch', 'External research',
'Relevant design-system and web precedents have been compared.'],
['research', 'research', 'useCases', 'Use cases',
'Primary use cases, non-goals, and constraints are documented.'],

['spec', 'spec', 'draftSpec', 'Draft spec',
'An RFC describes the component contract and intended behavior.'],
['spec', 'spec', 'surfaceAudit', 'Surface audit',
'Composition, naming, variants, states, and tokens are enumerated.'],
['spec', 'spec', 'specReview', 'Spec review',
'Design and engineering reviewers have resolved blocking feedback.'],
['spec', 'spec', 'apiArbitration', 'API arbitration',
'Competing APIs were evaluated when the choice was non-obvious.'],
['spec', 'spec', 'finalizedSpec', 'Finalized spec',
'The accepted contract is recorded as the build baseline.'],

['build', 'build', 'implementation', 'Implementation',
'The component implements the agreed public contract.'],
['build', 'build', 'systemIntegration', 'System integration',
'Tokens, themes, composition, and shared primitives are integrated.'],
['build', 'build', 'stories', 'Stories',
'Storybook demonstrates representative states and composition.'],
['build', 'build', 'tests', 'Tests',
'Focused behavioral and contract tests cover the implementation.'],
['build', 'build', 'documentation', 'Documentation',
'The public API, usage, and important constraints are documented.'],
['build', 'build', 'reviewAndCI', 'Review and CI',
'Code review and required automated checks are complete.'],
['build', 'build', 'mergedPR', 'Merged PR',
'The build is merged into the lab package.'],

['hardenChecks', 'automatedAudit', 'tokensTheming', 'Tokens and theming',
'Token usage and theme integration pass the automated audit.'],
['hardenChecks', 'automatedAudit', 'reuseNaming', 'Reuse and naming',
'Existing primitives are reused and public names follow conventions.'],
['hardenChecks', 'automatedAudit', 'structureTypes', 'Structure and types',
'File structure, exports, and TypeScript contracts pass inspection.'],
['hardenChecks', 'automatedAudit', 'accessibilityContracts',
[
'research',
'research',
'triage',
'Triage',
'A named owner has confirmed the problem and scope.',
],
[
'research',
'research',
'internalResearch',
'Internal research',
'Existing Astryx and internal patterns have been audited.',
],
[
'research',
'research',
'externalResearch',
'External research',
'Relevant design-system and web precedents have been compared.',
],
[
'research',
'research',
'useCases',
'Use cases',
'Primary use cases, non-goals, and constraints are documented.',
],

[
'spec',
'spec',
'draftSpec',
'Draft spec',
'An RFC describes the component contract and intended behavior.',
],
[
'spec',
'spec',
'surfaceAudit',
'Surface audit',
'Composition, naming, variants, states, and tokens are enumerated.',
],
[
'spec',
'spec',
'specReview',
'Spec review',
'Design and engineering reviewers have resolved blocking feedback.',
],
[
'spec',
'spec',
'apiArbitration',
'API arbitration',
'Competing APIs were evaluated when the choice was non-obvious.',
],
[
'spec',
'spec',
'finalizedSpec',
'Finalized spec',
'The accepted contract is recorded as the build baseline.',
],

[
'build',
'build',
'implementation',
'Implementation',
'The component implements the agreed public contract.',
],
[
'build',
'build',
'systemIntegration',
'System integration',
'Tokens, themes, composition, and shared primitives are integrated.',
],
[
'build',
'build',
'stories',
'Stories',
'Storybook demonstrates representative states and composition.',
],
[
'build',
'build',
'tests',
'Tests',
'Focused behavioral and contract tests cover the implementation.',
],
[
'build',
'build',
'documentation',
'Documentation',
'The public API, usage, and important constraints are documented.',
],
[
'build',
'build',
'reviewAndCI',
'Review and CI',
'Code review and required automated checks are complete.',
],
[
'build',
'build',
'mergedPR',
'Merged PR',
'The build is merged into the lab package.',
],

[
'hardenChecks',
'automatedAudit',
'tokensTheming',
'Tokens and theming',
'Token usage and theme integration pass the automated audit.',
],
[
'hardenChecks',
'automatedAudit',
'reuseNaming',
'Reuse and naming',
'Existing primitives are reused and public names follow conventions.',
],
[
'hardenChecks',
'automatedAudit',
'structureTypes',
'Structure and types',
'File structure, exports, and TypeScript contracts pass inspection.',
],
[
'hardenChecks',
'automatedAudit',
'accessibilityContracts',
'Accessibility contracts',
'Static and automated accessibility requirements pass.'],
['hardenChecks', 'automatedAudit', 'exportsAuditCI', 'Exports and CI',
'Public exports, builds, tests, and required CI checks are green.'],

['hardenChecks', 'objectiveFixes', 'stateCoverage', 'State coverage',
'All supported interaction and semantic states are covered.'],
['hardenChecks', 'objectiveFixes', 'visualThemes', 'Visual themes',
'Light, dark, and nested-theme rendering is verified.'],
['hardenChecks', 'objectiveFixes', 'keyboardAccessibility',
'Static and automated accessibility requirements pass.',
],
[
'hardenChecks',
'automatedAudit',
'exportsAuditCI',
'Exports and CI',
'Public exports, builds, tests, and required CI checks are green.',
],

[
'hardenChecks',
'objectiveFixes',
'stateCoverage',
'State coverage',
'All supported interaction and semantic states are covered.',
],
[
'hardenChecks',
'objectiveFixes',
'visualThemes',
'Visual themes',
'Light, dark, and nested-theme rendering is verified.',
],
[
'hardenChecks',
'objectiveFixes',
'keyboardAccessibility',
'Keyboard and accessibility',
'Keyboard, focus, semantics, naming, and contrast are verified.'],
['hardenChecks', 'objectiveFixes', 'edgeCases', 'Edge cases',
'Empty, overflow, loading, disabled, and stress cases are resolved.'],
['hardenChecks', 'objectiveFixes', 'storyCompleteness', 'Story completeness',
'Stories make the completed state and edge-case matrix reviewable.'],

['hardenReview', 'humanReview', 'visualQuality', 'Visual quality',
'A human reviewer has approved polish and visual consistency.'],
['hardenReview', 'humanReview', 'compositionQuality', 'Composition quality',
'Real compositions confirm the API works beyond isolated demos.'],
['hardenReview', 'humanReview', 'scopeBoundary', 'Scope boundary',
'The component\u2019s responsibilities and non-goals remain coherent.'],
['hardenReview', 'humanReview', 'archivedReview', 'Archived review',
'The final checklist, decision, and follow-ups are linked.'],
'Keyboard, focus, semantics, naming, and contrast are verified.',
],
[
'hardenChecks',
'objectiveFixes',
'edgeCases',
'Edge cases',
'Empty, overflow, loading, disabled, and stress cases are resolved.',
],
[
'hardenChecks',
'objectiveFixes',
'storyCompleteness',
'Story completeness',
'Stories make the completed state and edge-case matrix reviewable.',
],

[
'hardenReview',
'humanReview',
'visualQuality',
'Visual quality',
'A human reviewer has approved polish and visual consistency.',
],
[
'hardenReview',
'humanReview',
'compositionQuality',
'Composition quality',
'Real compositions confirm the API works beyond isolated demos.',
],
[
'hardenReview',
'humanReview',
'scopeBoundary',
'Scope boundary',
'The component\u2019s responsibilities and non-goals remain coherent.',
],
[
'hardenReview',
'humanReview',
'responsiveInteractionReadiness',
'Responsive and Interaction Readiness',
'The reusable Responsive and Interaction Readiness rubric records Pass, Fail, or N/A with evidence for adaptive presentation choice, transient and queued UI, viewport obstruction and placement, input, gesture, mobile viewport, and WCAG 2.2 AA contracts.',
],
[
'hardenReview',
'humanReview',
'archivedReview',
'Archived review',
'The final checklist, decision, and follow-ups are linked.',
],
];

export const CHECK_CATALOG = CHECKS.map(
Expand Down
Loading
Loading