rcf-lite 0.19.0 → 0.21.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/CHANGELOG.md +38 -0
- package/bin/rcf.js +5 -0
- package/blueprints/application-admin-console/CHANGELOG.md +11 -0
- package/blueprints/application-admin-console/README.md +98 -0
- package/blueprints/application-admin-console/blueprint.json +226 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2202-application-admin-console-baseline-roles.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2203-application-admin-console-invite-transport.json +20 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2204-application-admin-console-audit-retention.json +20 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-001.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-002.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-003.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-004.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-005.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-006.json +18 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2201-application-admin-console-shell.json +40 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2202-application-admin-console-capability-discovery.json +44 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2203-application-admin-console-permission-matrix.json +34 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2204-application-admin-console-audit-view.json +40 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21101.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21102.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21103.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21104.json +28 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21105.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21106.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21107.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21108.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21109.json +33 -0
- package/blueprints/application-admin-console/docs/topics.md +35 -0
- package/blueprints/application-admin-console/guide/application-admin-console.md +29 -0
- package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +182 -0
- package/blueprints/application-api-rest/docs/topics.md +5 -0
- package/blueprints/application-charts/CHANGELOG.md +12 -0
- package/blueprints/application-charts/README.md +73 -0
- package/blueprints/application-charts/blueprint.json +26 -0
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1902-application-charts-accessible-palette.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1903-application-charts-motion.json +25 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-003.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-004.json +15 -0
- package/blueprints/application-charts/contributions/tacs/tac-1901-application-charts-render-shell.json +42 -0
- package/blueprints/application-charts/contributions/tacs/tac-1902-application-charts-keyboard-traversal.json +40 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18102.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18103.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18104.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +35 -0
- package/blueprints/application-charts/docs/topics.md +37 -0
- package/blueprints/application-charts/guide/application-charts.md +44 -0
- package/blueprints/application-charts/probe-packs/application-charts.pack.mjs +191 -0
- package/blueprints/application-dashboard/CHANGELOG.md +10 -0
- package/blueprints/application-dashboard/README.md +102 -0
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +124 -0
- package/blueprints/application-dashboard/blueprint.json +29 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2003-application-dashboard-export-formats.json +25 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-001.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-004.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-005.json +15 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2001-application-dashboard-tile-grid.json +47 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +41 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +35 -0
- package/blueprints/application-dashboard/docs/topics.md +43 -0
- package/blueprints/application-dashboard/guide/application-dashboard.md +48 -0
- package/blueprints/application-dashboard/probe-packs/application-dashboard.pack.mjs +231 -0
- package/blueprints/application-datatable/CHANGELOG.md +8 -0
- package/blueprints/application-datatable/README.md +43 -0
- package/blueprints/application-datatable/blueprint.json +33 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1801-application-datatable-pattern-choice.json +25 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1802-application-datatable-url-state.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1803-application-datatable-page-size.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1804-application-datatable-selection-persistence.json +20 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-001.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-002.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-003.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-004.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-005.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +15 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1801-application-datatable-shell.json +50 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1802-application-datatable-query-adapter.json +39 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1803-application-datatable-selection-model.json +28 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17101.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17102.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17103.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17104.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17105.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17106.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17107.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17108.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17109.json +44 -0
- package/blueprints/application-datatable/docs/topics.md +35 -0
- package/blueprints/application-datatable/guide/application-datatable.md +38 -0
- package/blueprints/application-datatable/probe-packs/application-datatable.pack.mjs +240 -0
- package/blueprints/application-error-handling/docs/topics.md +5 -0
- package/blueprints/application-notifications-in-app/CHANGELOG.md +9 -0
- package/blueprints/application-notifications-in-app/README.md +80 -0
- package/blueprints/application-notifications-in-app/blueprint.json +30 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2102-application-notifications-in-app-toast-timeout-floor.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2103-application-notifications-in-app-retention-window.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-001.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-002.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-003.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-004.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-005.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +46 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +52 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2103-application-notifications-in-app-preferences.json +40 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20104.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20106.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20107.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20108.json +26 -0
- package/blueprints/application-notifications-in-app/docs/topics.md +39 -0
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +47 -0
- package/blueprints/application-notifications-in-app/probe-packs/application-notifications-in-app.pack.mjs +328 -0
- package/blueprints/application-spa/docs/topics.md +5 -0
- package/blueprints/delivery-ci-workflows/docs/topics.md +5 -0
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +5 -0
- package/blueprints/email-smtp-resend/docs/topics.md +5 -0
- package/blueprints/observability-essentials/docs/topics.md +5 -0
- package/blueprints/observability-logging/CHANGELOG.md +5 -0
- package/blueprints/observability-logging/README.md +1 -1
- package/blueprints/observability-logging/blueprint.json +113 -21
- package/blueprints/observability-logging/docs/topics.md +5 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +5 -0
- package/blueprints/persistence-data-d1/docs/topics.md +5 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +5 -0
- package/blueprints/security-auth-clerk/CHANGELOG.md +5 -0
- package/blueprints/security-auth-clerk/blueprint.json +2 -1
- package/blueprints/security-auth-clerk/docs/topics.md +5 -0
- package/blueprints/security-auth-keycloak/CHANGELOG.md +5 -0
- package/blueprints/security-auth-keycloak/blueprint.json +2 -1
- package/blueprints/security-auth-keycloak/docs/topics.md +5 -0
- package/blueprints/security-auth-magic-link/CHANGELOG.md +5 -0
- package/blueprints/security-auth-magic-link/blueprint.json +2 -1
- package/blueprints/security-auth-magic-link/docs/topics.md +5 -0
- package/blueprints/security-auth-oauth2/CHANGELOG.md +5 -0
- package/blueprints/security-auth-oauth2/blueprint.json +2 -1
- package/blueprints/security-auth-oauth2/docs/topics.md +5 -0
- package/blueprints/security-secrets-management/docs/topics.md +5 -0
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +2 -2
- package/rcf/code-nodes/cn-098.json +13 -0
- package/rcf/code-nodes/cn-099.json +13 -0
- package/rcf/code-nodes/cn-100.json +13 -0
- package/rcf/code-nodes/cn-101.json +13 -0
- package/rcf/code-nodes/cn-102.json +13 -0
- package/rcf/code-nodes/cn-103.json +13 -0
- package/rcf/code-nodes/cn-104.json +13 -0
- package/rcf/code-nodes/cn-105.json +13 -0
- package/rcf/code-nodes/cn-106.json +13 -0
- package/rcf/code-nodes/cn-107.json +14 -0
- package/rcf/code-nodes/cn-108.json +13 -0
- package/rcf/code-nodes/cn-109.json +12 -0
- package/rcf/code-nodes/cn-110.json +12 -0
- package/rcf/code-nodes/cn-111.json +14 -0
- package/rcf/code-nodes/cn-112.json +14 -0
- package/rcf/code-nodes/cn-113.json +12 -0
- package/rcf/code-nodes/cn-114.json +13 -0
- package/rcf/code-nodes/cn-115.json +13 -0
- package/rcf/code-nodes/cn-116.json +12 -0
- package/rcf/code-nodes/cn-117.json +13 -0
- package/rcf/code-nodes/cn-118.json +13 -0
- package/rcf/code-nodes/cn-119.json +13 -0
- package/rcf/code-nodes/cn-120.json +13 -0
- package/rcf/code-nodes/cn-121.json +12 -0
- package/rcf/code-nodes/cn-122.json +12 -0
- package/rcf/code-nodes/cn-123.json +13 -0
- package/rcf/code-nodes/cn-124.json +13 -0
- package/rcf/code-nodes/cn-125.json +13 -0
- package/rcf/code-nodes/cn-126.json +13 -0
- package/rcf/code-nodes/cn-127.json +12 -0
- package/rcf/code-nodes/cn-128.json +14 -0
- package/rcf/code-nodes/cn-129.json +14 -0
- package/rcf/code-nodes/cn-130.json +14 -0
- package/rcf/code-nodes/cn-131.json +15 -0
- package/rcf/code-nodes/cn-132.json +12 -0
- package/rcf/code-nodes/cn-133.json +13 -0
- package/rcf/evals/eval-001.json +55 -0
- package/rcf/fbs/fbs-035.json +18 -0
- package/rcf/fbs/fbs-036.json +22 -0
- package/rcf/fbs/fbs-037.json +19 -0
- package/rcf/fbs/fbs-038.json +19 -0
- package/rcf/fbs/fbs-039.json +21 -0
- package/rcf/fbs/fbs-040.json +20 -0
- package/rcf/fbs/fbs-041.json +13 -0
- package/rcf/fbs/fbs-042.json +13 -0
- package/rcf/requirements/req-016.json +37 -0
- package/rcf/requirements/req-017.json +18 -0
- package/rcf/requirements/req-018.json +18 -0
- package/rcf/requirements/req-019.json +38 -0
- package/rcf/requirements/req-020.json +13 -0
- package/rcf/requirements/req-021.json +13 -0
- package/rcf/requirements/req-022.json +13 -0
- package/rcf/requirements/req-023.json +14 -0
- package/rcf/test-suites/ts-045.json +46 -0
- package/rcf/test-suites/ts-046.json +78 -0
- package/rcf/test-suites/ts-047.json +54 -0
- package/rcf/test-suites/ts-048.json +54 -0
- package/rcf/test-suites/ts-049.json +70 -0
- package/rcf/test-suites/ts-050.json +69 -0
- package/rcf/test-suites/ts-051.json +22 -0
- package/rcf/test-suites/ts-052.json +20 -0
- package/rcf/user-stories/us-1601.json +37 -0
- package/rcf/user-stories/us-1701.json +56 -0
- package/rcf/user-stories/us-1801.json +40 -0
- package/rcf/user-stories/us-1901.json +40 -0
- package/rcf/user-stories/us-2001.json +50 -0
- package/rcf/user-stories/us-2101.json +45 -0
- package/rcf/user-stories/us-2201.json +60 -0
- package/rcf/user-stories/us-2301.json +51 -0
- package/releases/releases.yaml +20 -1
- package/src/blueprint/apply.js +98 -1
- package/src/blueprint/capabilities.js +318 -0
- package/src/blueprint/loader.js +247 -0
- package/src/browser-verify/boot.js +180 -0
- package/src/browser-verify/index.js +13 -0
- package/src/browser-verify/manifest-writer.js +31 -6
- package/src/browser-verify/pack-browser.js +294 -0
- package/src/browser-verify/pack-loader.js +176 -0
- package/src/browser-verify/pack-runner.js +193 -0
- package/src/browser-verify/pack-schema.js +155 -0
- package/src/browser-verify/runner.js +24 -1
- package/src/cli/blueprint.js +92 -0
- package/src/cli/browser-verify.js +147 -7
- package/src/cli/create.js +14 -0
- package/src/cli/eval-coverage.js +221 -0
- package/src/cli/eval.js +43 -0
- package/src/cli/finalise.js +64 -0
- package/src/cli/help.js +4 -0
- package/src/core/errors/index.js +7 -0
- package/src/core/store/ids.js +5 -1
- package/src/core/store/init.js +4 -0
- package/src/core/store/loader.js +4 -0
- package/src/core/store/validator.js +8 -1
- package/src/core/store/walker.js +71 -2
- package/src/core/store/writer.js +4 -0
- package/src/eval/judge.js +338 -0
- package/src/finalise/index.js +8 -0
- package/src/finalise/ingest.js +27 -0
- package/src/finalise/ship-without-eval.js +123 -0
- package/src/query/eval-coverage.js +162 -0
- package/src/verify/chain/index.js +67 -0
- package/src/verify/cli/run.js +15 -0
- package/src/verify/engine/index.js +10 -0
- package/src/verify/verdict/index.js +46 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Dashboard design guidance
|
|
2
|
+
|
|
3
|
+
A packaged asset shipped with the `application-dashboard` blueprint. Read at apply, referenced at project-side review, and cited from every REQ, ADR and pack check that anchors on a design rule. The applying agent honours the eight sections below. Where a section names an AC id, the rule is a runtime-observable AC on this blueprint (the ship gate refuses on failure). Where a section stays operator guidance, the applying agent honours it and the shipping surface is reviewed by hand.
|
|
4
|
+
|
|
5
|
+
Sources are cited by URL at each section. Five bodies of work anchor this guidance:
|
|
6
|
+
|
|
7
|
+
- Nielsen Norman Group research on how people read on the web: https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/
|
|
8
|
+
- Stephen Few's dashboard-design library at Perceptual Edge: https://www.perceptualedge.com/library.php
|
|
9
|
+
- Edward Tufte, The Visual Display of Quantitative Information (Wikipedia reference): https://en.wikipedia.org/wiki/The_Visual_Display_of_Quantitative_Information
|
|
10
|
+
- GOV.UK Design System patterns index: https://design-system.service.gov.uk/patterns/
|
|
11
|
+
- WCAG 2.2 Understanding docs: https://www.w3.org/WAI/WCAG22/Understanding/
|
|
12
|
+
|
|
13
|
+
## 1. Primary KPI placement
|
|
14
|
+
|
|
15
|
+
The primary KPI is the reader's anchor. Place it top-left on every ratified breakpoint (1440, 1024, 360). NN/g's F-shaped-pattern reading research reports that the top-left region of a text-heavy layout is where a reader's eye lands first; that is the spot the anchor tile has to occupy. On a 360 phone layout the tile row reflows to one column and the primary KPI stays first in DOM order and top of the stack.
|
|
16
|
+
|
|
17
|
+
The primary KPI kind is one of five values (ADR-2001): `revenue`, `active-users`, `error-rate`, `throughput`, `custom`. A `custom` value carries a short operator name in `data-kpi-name`. A dashboard with no primary KPI fails project-side review.
|
|
18
|
+
|
|
19
|
+
Sources:
|
|
20
|
+
- NN/g F-shaped pattern of reading: https://www.nngroup.com/articles/f-shaped-pattern-reading-web-content/
|
|
21
|
+
- Stephen Few, Dashboard Design for Rich and Rapid Monitoring (Perceptual Edge): https://www.perceptualedge.com/articles/visual_business_intelligence/dd_for_rapid_monitoring.pdf
|
|
22
|
+
|
|
23
|
+
Hardens into AC-19102-1.
|
|
24
|
+
|
|
25
|
+
## 2. Tile density and count limits
|
|
26
|
+
|
|
27
|
+
Keep the tile row to at most eight tiles. Beyond eight the glance value drops sharply; a reader scanning a nine-tile row misses the middle tiles on the first fixation and either scrolls or gives up. If the dashboard needs more metrics, break them into a second view (a drilldown), not a longer row.
|
|
28
|
+
|
|
29
|
+
A stat tile carries one number. A stat tile that tries to carry a mini-chart and three numbers is a small dashboard inside a dashboard; move it to its own dashboard slot instead.
|
|
30
|
+
|
|
31
|
+
The primary tile can be visually heavier than the supporting tiles (a larger value, an accent border) but the shape stays a stat tile: one metric, one context line, one state.
|
|
32
|
+
|
|
33
|
+
Sources:
|
|
34
|
+
- Stephen Few, Dashboard Confusion Revisited (Perceptual Edge): https://www.perceptualedge.com/articles/visual_business_intelligence/dboard_confusion_revisited.pdf
|
|
35
|
+
- Tufte on chartjunk (Wikipedia summary of the concept): https://en.wikipedia.org/wiki/Chartjunk
|
|
36
|
+
|
|
37
|
+
Stays operator guidance.
|
|
38
|
+
|
|
39
|
+
## 3. Timeframe and filter chrome
|
|
40
|
+
|
|
41
|
+
The timeframe picker is one of the most-touched controls on the surface. Ship three presets by recommendedDefault (ADR-2002): `last-7-days`, `last-30-days`, `quarter-to-date`. `last-7-days` is the ship default unless the operator elicits an override. Operators may supply their own preset set (a fiscal-year window, a shift window) at apply; missing presets are ignored, extra presets append.
|
|
42
|
+
|
|
43
|
+
Filter chrome exposes each operator-configured filter as a labelled interactive control (a `<button>`, a `<select>`, or an `<input>`), keyboard-reachable in reading order before the tile row. A hover-only filter is refused; a dropdown that opens on hover fails the accessibility contract.
|
|
44
|
+
|
|
45
|
+
Sources:
|
|
46
|
+
- GOV.UK Design System patterns index (the standalone filter pattern page has been retired; the index is the current landing): https://design-system.service.gov.uk/patterns/
|
|
47
|
+
- WCAG 2.2 Understanding SC 2.1.1 Keyboard: https://www.w3.org/WAI/WCAG22/Understanding/keyboard.html
|
|
48
|
+
- WCAG 2.2 Understanding SC 1.4.13 Content on Hover or Focus: https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html
|
|
49
|
+
|
|
50
|
+
Hardens into AC-19105-1 and the fan-out rule under AC-19104-1.
|
|
51
|
+
|
|
52
|
+
## 4. Loading, empty and error states
|
|
53
|
+
|
|
54
|
+
Every tile carries the same four-state contract: `loading`, `empty`, `error`, `populated`. Each state has a distinct visual cue and a distinct accessible name; the state's cue is not colour-only (WCAG 1.4.1). A loading tile renders a skeleton or a spinner; an empty tile renders a labelled empty-state block; an error tile renders a labelled error block with the recorded reason; a populated tile renders the metric.
|
|
55
|
+
|
|
56
|
+
Every tile wraps its content in a `role="region"` element with `aria-live="polite"` so a state change is announced to assistive tech.
|
|
57
|
+
|
|
58
|
+
Sources:
|
|
59
|
+
- NN/g on empty states: https://www.nngroup.com/articles/empty-state-interface-design/
|
|
60
|
+
- WCAG 2.2 Understanding SC 1.4.1 Use of Colour: https://www.w3.org/WAI/WCAG22/Understanding/use-of-color.html
|
|
61
|
+
- WCAG 2.2 Understanding SC 4.1.3 Status Messages: https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html
|
|
62
|
+
|
|
63
|
+
Hardens into AC-19103-1 and AC-19103-2.
|
|
64
|
+
|
|
65
|
+
## 5. Colour and contrast
|
|
66
|
+
|
|
67
|
+
Dashboard tiles read at a glance; low contrast punishes the reader. Text on a tile carries at least 4.5:1 contrast against its background (WCAG 1.4.3); state-cue graphics carry 3:1 non-text contrast (WCAG 1.4.11). If the shipped chart region reuses the application-charts render shell, the palette contract comes from ADR-1902 on that blueprint; the shipped light and dark categorical palettes are contrast-safe by default.
|
|
68
|
+
|
|
69
|
+
Colour alone never carries state or series distinction: pair colour with a shape, a pattern or a label. Traffic-light state cues (red, orange, green) recur as a defect on shipped dashboards; pair the colour with an icon, a label or a text state.
|
|
70
|
+
|
|
71
|
+
Sources:
|
|
72
|
+
- WCAG 2.2 Understanding SC 1.4.3 Contrast Minimum: https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html
|
|
73
|
+
- WCAG 2.2 Understanding SC 1.4.11 Non-text Contrast: https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html
|
|
74
|
+
|
|
75
|
+
Stays operator guidance for the tile row; hardens for the chart region through application-charts AC-18102-1 and AC-18105-1.
|
|
76
|
+
|
|
77
|
+
## 6. When a table beats a chart
|
|
78
|
+
|
|
79
|
+
If the reader's question is what the value is, ship a stat tile. If the reader's question is how the values compare across a small set, ship a stat tile row and a table. If the reader's question is how the values move over time, ship a chart. If the reader wants to sort, filter, page, select, or export a table of records, ship the `application-datatable` blueprint's table; the dashboard's tile row is not a replacement.
|
|
80
|
+
|
|
81
|
+
A chart with three data points is a table. A pie chart with more than four slices is a table. A dashboard that overuses charts to fill space produces the chartjunk Tufte warned against; a table is often the honest shape.
|
|
82
|
+
|
|
83
|
+
The dashboard's chart region delegates rendering to the application-charts render shell (TAC-1901); the accessibility, palette, text-alternative and keyboard-traversal ACs on that blueprint apply. The paired text-alternative table is one of those ACs (application-charts AC-18103-1), so the reader always has the table view for the chart.
|
|
84
|
+
|
|
85
|
+
Sources:
|
|
86
|
+
- The Visual Display of Quantitative Information (Wikipedia reference): https://en.wikipedia.org/wiki/The_Visual_Display_of_Quantitative_Information
|
|
87
|
+
- NN/g Choosing Chart Types (video): https://www.nngroup.com/videos/choosing-chart-types/
|
|
88
|
+
- NN/g Comparison Tables, 5 scenarios (video): https://www.nngroup.com/videos/comparison-tables/
|
|
89
|
+
|
|
90
|
+
Stays operator guidance; the shell contract enforces the chart-region mount through the render shell (AC-19101-2).
|
|
91
|
+
|
|
92
|
+
## 7. Refresh cadence and staleness
|
|
93
|
+
|
|
94
|
+
Every dashboard reader wants to know how fresh the data is. The shell renders one `as of <ISO-8601>` stamp on the shell root and every tile carries the same stamp. On a timeframe or filter change the shell refetches every tile with the same boundary, waits for the batch, and updates the stamp. A tile whose stamp drifts from the shell root is a defect.
|
|
95
|
+
|
|
96
|
+
Auto-refresh is off by default. An operator elicits a refresh interval at apply if the surface genuinely needs unattended refresh (an ops screen, an event-day dashboard); the elicited interval sets `data-auto-refresh` on the shell root to the elicited seconds. A dashboard that refreshes every 30 seconds without an operator opt-in wastes budget and produces distracting motion; a dashboard that refreshes on a hidden tab drops keystrokes in the operator's active tab.
|
|
97
|
+
|
|
98
|
+
Sources:
|
|
99
|
+
- Nielsen, Response Times: The 3 Important Limits (NN/g): https://www.nngroup.com/articles/response-times-3-important-limits/
|
|
100
|
+
- Stephen Few, Dashboard Design for Real-Time Situation Awareness (Perceptual Edge): https://www.perceptualedge.com/articles/Whitepapers/Dashboard_Design.pdf
|
|
101
|
+
|
|
102
|
+
Hardens into AC-19104-1 (fan-out and stamp) and AC-19104-2 (auto-refresh default).
|
|
103
|
+
|
|
104
|
+
## 8. Anti-patterns
|
|
105
|
+
|
|
106
|
+
Read this list against the shipped surface; if any of the following applies, fix it before ship.
|
|
107
|
+
|
|
108
|
+
- The primary KPI is anywhere other than top-left.
|
|
109
|
+
- A tile carries the same number as another tile at a different boundary and the reader compares them.
|
|
110
|
+
- The tile row has more than eight tiles.
|
|
111
|
+
- A state (loading, empty, error) is signalled by colour alone.
|
|
112
|
+
- The dashboard auto-refreshes without an operator opt-in.
|
|
113
|
+
- The export handle is a hover-only dropdown.
|
|
114
|
+
- A canvas-only chart with no text-alternative surface (this is caught by application-charts AC-18103-1 on the chart region).
|
|
115
|
+
- The dashboard renders a chartjunk grid (three overlapping bar charts, a rainbow-gradient donut) to fill space.
|
|
116
|
+
- The dashboard mixes stale tiles and fresh tiles under one `as of` stamp.
|
|
117
|
+
- The dashboard names a "primary KPI" that is not the reader's actual anchor question.
|
|
118
|
+
|
|
119
|
+
Sources:
|
|
120
|
+
- Stephen Few, Common Pitfalls in Dashboard Design (Perceptual Edge whitepaper): https://www.perceptualedge.com/articles/Whitepapers/Common_Pitfalls.pdf
|
|
121
|
+
- Stephen Few, Why Most Dashboards Fail (Perceptual Edge): https://www.perceptualedge.com/articles/misc/WhyMostDashboardsFail.pdf
|
|
122
|
+
- NN/g Data Visualizations for Dashboards (video): https://www.nngroup.com/videos/data-visualizations-dashboards/
|
|
123
|
+
|
|
124
|
+
Stays operator guidance; individual patterns harden through the ACs the guidance names above.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "application-dashboard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"category": "application",
|
|
5
|
+
"suggestedCompanions": [
|
|
6
|
+
{ "role": "logging", "reason": "Dashboard tile refresh, timeframe change and export activation are the surface's most-touched instrumentation points; a logging companion supplies the factory the tiles and the chart region write records against." },
|
|
7
|
+
{ "role": "errorHandling", "reason": "A tile whose fetch fails renders the error-state visual per REQ-003; the error-state contract needs a project-side error-record factory the application-error-handling companion provides." }
|
|
8
|
+
],
|
|
9
|
+
"contributions": [
|
|
10
|
+
{ "id": "application-dashboard-REQ-001", "kind": "req", "path": "requirements/application-dashboard-req-001.json" },
|
|
11
|
+
{ "id": "application-dashboard-REQ-002", "kind": "req", "path": "requirements/application-dashboard-req-002.json" },
|
|
12
|
+
{ "id": "application-dashboard-REQ-003", "kind": "req", "path": "requirements/application-dashboard-req-003.json" },
|
|
13
|
+
{ "id": "application-dashboard-REQ-004", "kind": "req", "path": "requirements/application-dashboard-req-004.json" },
|
|
14
|
+
{ "id": "application-dashboard-REQ-005", "kind": "req", "path": "requirements/application-dashboard-req-005.json" },
|
|
15
|
+
{ "id": "application-dashboard-US-19101", "kind": "us", "path": "user-stories/application-dashboard-us-19101.json" },
|
|
16
|
+
{ "id": "application-dashboard-US-19102", "kind": "us", "path": "user-stories/application-dashboard-us-19102.json" },
|
|
17
|
+
{ "id": "application-dashboard-US-19103", "kind": "us", "path": "user-stories/application-dashboard-us-19103.json" },
|
|
18
|
+
{ "id": "application-dashboard-US-19104", "kind": "us", "path": "user-stories/application-dashboard-us-19104.json" },
|
|
19
|
+
{ "id": "application-dashboard-US-19105", "kind": "us", "path": "user-stories/application-dashboard-us-19105.json" },
|
|
20
|
+
{ "id": "application-dashboard-US-19106", "kind": "us", "path": "user-stories/application-dashboard-us-19106.json" },
|
|
21
|
+
{ "id": "application-dashboard-US-19107", "kind": "us", "path": "user-stories/application-dashboard-us-19107.json" },
|
|
22
|
+
{ "id": "TAC-2001-application-dashboard-tile-grid", "kind": "tac", "path": "tacs/tac-2001-application-dashboard-tile-grid.json" },
|
|
23
|
+
{ "id": "TAC-2002-application-dashboard-filter-chrome", "kind": "tac", "path": "tacs/tac-2002-application-dashboard-filter-chrome.json" },
|
|
24
|
+
{ "id": "TAC-2003-application-dashboard-export-handle", "kind": "tac", "path": "tacs/tac-2003-application-dashboard-export-handle.json" },
|
|
25
|
+
{ "id": "ADR-2001-application-dashboard-primary-kpi-enum", "kind": "adr", "path": "adrs/adr-2001-application-dashboard-primary-kpi-enum.json", "recommendedDefault": false, "elicited": true, "standardsTraceClause": "NN/g F-scan; Gestalt proximity" },
|
|
26
|
+
{ "id": "ADR-2002-application-dashboard-timeframe-presets", "kind": "adr", "path": "adrs/adr-2002-application-dashboard-timeframe-presets.json", "recommendedDefault": true, "elicited": true, "standardsTraceClause": "NN/g dashboard design (timeframe defaults)" },
|
|
27
|
+
{ "id": "ADR-2003-application-dashboard-export-formats", "kind": "adr", "path": "adrs/adr-2003-application-dashboard-export-formats.json", "recommendedDefault": true, "elicited": true, "standardsTraceClause": "GOV.UK Design System (download patterns); WCAG 1.3.1 (info and relationships)" }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-2001-application-dashboard-primary-kpi-enum",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Elicit the primary KPI kind from a fixed enum (revenue, active-users, error-rate, throughput, custom)",
|
|
8
|
+
"context": "The primary KPI is the reader's anchor on the dashboard's first fixation. Every applying project already has a primary KPI in the business sense; the problem is that the surface's `data-kpi-kind` attribute either stays free-form (any string) and cross-project comparisons drift, or hard-picks one KPI at the shelf and forces every applying project to relabel. Neither option lands the runtime discipline the pack needs to prove the primary-KPI-top-left rule.",
|
|
9
|
+
"decision": "The primary-KPI kind is elicited at apply from a fixed enum: `revenue`, `active-users`, `error-rate`, `throughput`, or `custom`. The elicited value lands on the primary tile as `data-kpi-kind`; a `custom` choice carries a `data-kpi-name` attribute with the operator's own short name. The pack asserts the attribute value is one of the enum values (or `custom` with a `data-kpi-name`), the tile is top-left in DOM order and CSS Grid position at every ratified breakpoint. The five enum values cover the shipped shelf's known cases (SaaS revenue dashboards, product-analytics active-users dashboards, SRE error-rate dashboards, throughput-focused ops dashboards, and the custom escape hatch); a new enum value moves the ADR to v1.1.0 with a shelf-wide review.",
|
|
10
|
+
"consequences": "Applying projects pick from a small, review-worthy set; the pack has a runtime-observable attribute to check; cross-project comparisons on a shelf-wide dashboard registry are trivial. The `custom` value keeps the escape hatch honest: a project with a KPI outside the five stays within the ADR while documenting its own name on `data-kpi-name`.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Free-form primary-KPI kind",
|
|
14
|
+
"summary": "The attribute accepts any string.",
|
|
15
|
+
"reasonNotChosen": "Every applying project would ship its own label and cross-project reasoning would drift; the pack could not usefully assert a value shape."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Hard-pick revenue as the primary KPI",
|
|
19
|
+
"summary": "Every dashboard on the shelf carries `revenue` as its primary KPI.",
|
|
20
|
+
"reasonNotChosen": "Product-analytics and SRE dashboards would have to relabel their real primary KPI; the shelf would ship a dishonest attribute."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-2002-application-dashboard-timeframe-presets",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Ship three timeframe presets by recommendedDefault with elicited overrides and auto-refresh off unless elicited",
|
|
8
|
+
"context": "Timeframe presets on a dashboard are the single most-touched control; the wrong default (a rolling 24-hour window on a monthly-cycle business) produces a dashboard that is silently wrong at every open. Operators often want their own presets (a fiscal-year window, a shift window). Auto-refresh is one of the most common accessibility and cost defects on shipped dashboards: an unattended refresh runs the fan-out on a hidden tab all day.",
|
|
9
|
+
"decision": "The blueprint ships three timeframe presets by recommendedDefault: `last-7-days`, `last-30-days`, and `quarter-to-date`. `last-7-days` is the ship default unless the operator elicits an override at apply. Operators supply their own preset set through the elicited override; missing presets are ignored, extra presets append to the shipped set. Auto-refresh is OFF by default: `data-auto-refresh` on the shell root reads `off`; an operator-elicited refresh interval sets it to the elicited seconds and the shell refetches on the same fan-out contract at that interval. A shell that ships auto-refresh on by default fails project-side review.",
|
|
10
|
+
"consequences": "The applying project gets a safe timeframe default that matches the most common dashboard-glance case; operators with an unusual cycle (a fiscal-year business) elicit their own set. Auto-refresh stays off unless the operator explicitly turns it on with an interval, and the pack asserts the default state through `data-auto-refresh`.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Ship five timeframe presets",
|
|
14
|
+
"summary": "Add `today` and `this-week` to the shipped set.",
|
|
15
|
+
"reasonNotChosen": "`today` produces an early-morning dashboard that is mostly empty; `this-week` overlaps with `last-7-days` without adding a clear read. The three-preset set is what the shipped surfaces need."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Auto-refresh on by default",
|
|
19
|
+
"summary": "Every dashboard refreshes on a 60-second interval.",
|
|
20
|
+
"reasonNotChosen": "Unattended refresh is a cost and accessibility defect; the elicited-opt-in path keeps the shell honest."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"adrId": "ADR-2003-application-dashboard-export-formats",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "accepted",
|
|
7
|
+
"title": "Ship three export formats by recommendedDefault (CSV, PDF, PNG-of-chart) with elicited overrides and PNG delegation to the charts render shell",
|
|
8
|
+
"context": "Export is a legal-and-audit necessity on most shipped dashboards, and the accessibility posture of an export handle is often the last thing anyone reviews. The three most-requested formats are CSV (data extract), PDF (whole-dashboard snapshot), and PNG (one-chart download). SVG, XLSX and a Slack-share button are common project-side additions. A dashboard shell that carries its own PNG generator is a common defect because it produces a chart image that drifts from the shipped chart.",
|
|
9
|
+
"decision": "The blueprint ships three export formats by recommendedDefault: `csv`, `pdf`, and `png-chart`. Operators supply their own format set through the elicited override; missing formats are ignored, extra formats append to the shipped set with an operator-supplied `label` and `data-export-format` value. PNG-of-chart delegates to the application-charts render shell (TAC-1901): the export handle carries no PNG generator of its own; the charts shell owns the PNG output for every rendered chart on the surface. Applying projects that ship a chart engine outside the render shell either supersede this ADR with a project-authored delegation or lose the PNG-of-chart affordance.",
|
|
10
|
+
"consequences": "The applying project gets the three most-requested formats out of the box and an elicited override for the rest. The delegation to the charts shell keeps the PNG output consistent with the rendered chart; a project that supersedes the delegation names the residual and owns the chart-drift risk.",
|
|
11
|
+
"alternativesConsidered": [
|
|
12
|
+
{
|
|
13
|
+
"name": "Ship the format list open-ended (no defaults)",
|
|
14
|
+
"summary": "Every project elicits its own format set at apply.",
|
|
15
|
+
"reasonNotChosen": "Every project would ship the first-pass format set the operator asked for and the accessibility posture of the format list would move with the operator's brief. The three-format default carries the shelf's discipline."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "Bake a PNG generator into the dashboard shell",
|
|
19
|
+
"summary": "The shell owns the PNG output for its rendered charts.",
|
|
20
|
+
"reasonNotChosen": "The charts shell already renders every chart on the surface; a second PNG path drifts from the rendered chart and duplicates the accessibility contract."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
24
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
25
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-dashboard-REQ-001",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The dashboard shell composes a tile row, a chart region, filter chrome, a timeframe picker and an export handle",
|
|
5
|
+
"description": "A rendered dashboard on the shipped surface composes five regions on one page: a tile row carrying the primary KPI and up to seven supporting stat tiles; a chart region reusing the application-charts render shell for every rendered chart; filter chrome exposing operator-configured filters as accessible controls; a timeframe picker exposing the presets ADR-2002 elicits; and an export handle whose formats ADR-2003 elicits. The five regions are the shell contract; a dashboard that ships fewer regions (a page with no export handle, or no filter chrome) either supersedes this REQ with a project-authored REQ documenting the omitted region or renders the region as empty with a labelled `role=\"region\"` element the pack can inspect.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "A dashboard is a compound surface: the tile row, the chart region and the filter chrome each need their own AC coverage. Naming the five regions on the shell is what lets every subsequent REQ, TAC and pack check anchor onto a stable, inspectable structure rather than a floating layout convention.",
|
|
10
|
+
"tags": ["blueprint:application-dashboard", "category:01-shell-composition"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-dashboard-REQ-002",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The primary KPI tile sits top-left in DOM order and in CSS Grid position across the ratified breakpoints",
|
|
5
|
+
"description": "The tile row's primary KPI carries a top-left placement the reader reaches first, on the NN/g F-scan of the surface, at every ratified breakpoint (1440, 1024, 360). At 1440 and 1024 the primary KPI is the first tile in DOM order and its computed CSS Grid column-start is 1 and row-start is 1; at 360 the tile row reflows to one column and the primary KPI is the first tile in DOM order and its row-start is 1. The tile carries a `data-tile-role=\"primary-kpi\"` attribute and a `data-kpi-kind` attribute whose value is one of the ADR-2001 enum values (revenue, active-users, error-rate, throughput, custom). A dashboard that ships no primary KPI tile fails this REQ at project-side review; a dashboard whose primary KPI is not top-left at any of the three breakpoints fails the pack check AC-19102-1.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "The primary KPI is the reader's anchor on a dashboard glance; the F-scan reading pattern (NN/g dashboard design research) puts the top-left tile at the reader's first fixation. Codifying the placement as a runtime-observable CSS Grid position at the three ratified breakpoints turns a design convention into a check a Playwright probe can drive.",
|
|
10
|
+
"tags": ["blueprint:application-dashboard", "category:02-primary-kpi-hierarchy"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-dashboard-REQ-003",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "Every tile honours a four-state contract with distinct visuals, role region, aria-live polite, and non-colour distinction",
|
|
5
|
+
"description": "Every tile on the shell renders one of four states at any moment: loading, empty, error, populated. Each state carries a distinct visual (a skeleton stripe or spinner for loading, a labelled empty-state block for empty, a labelled error block with the recorded reason for error, and the actual metric for populated). Each tile wraps its content in `role=\"region\"` with an `aria-live=\"polite\"` announcer that reads the state transition on change. The state distinction combines a visual cue and a text label (non-colour distinction, WCAG 1.4.1): the state's visual is not colour-only, and the state's accessible name reads `<tile title>, <state>` on entry. A tile that renders no visible state (a blank tile) fails REQ-003 at project-side review; a tile that carries state-only through colour fails the pack check AC-19103-1.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "The four-state contract is the shelf's most-repeated data-region pattern (see application-datatable REQ-005 for the same shape on the table shell); giving the dashboard tile its own explicit ACs is what stops the state contract from silently drifting between the two surfaces. The aria-live announcer is what makes a tile's state change reachable to a screen-reader user; the non-colour distinction is what makes the state legible to a colour-blind reader.",
|
|
10
|
+
"tags": ["blueprint:application-dashboard", "category:03-tile-four-state"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-dashboard-REQ-004",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The timeframe picker and the filter chrome refetch every tile and chart with the same boundary and update the as-of stamp",
|
|
5
|
+
"description": "A timeframe preset change (from the operator-elicited set: last-7-days, last-30-days, quarter-to-date or an elicited override) issues one refetch per tile and one refetch per rendered chart, and every fetch carries the same `from` and `to` boundary and the same `preset` name. A filter chrome change (operator toggles a filter chip, types into a filter input) issues the same refetch fan-out with the same boundary. Once every fetch has returned (or the timeout has elapsed) the shell updates one `as of <ISO-8601>` stamp on the shell, and every rendered tile carries the same stamp. A shell whose fetches drift boundaries (one tile refetches with the new boundary, another with the old) fails the pack check AC-19104-1; a shell whose as-of stamp does not match every tile's rendered stamp fails the same check.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "The fan-out contract is what stops a dashboard from lying to the reader: two tiles at different boundaries render numbers the reader compares as if they were the same period, and the comparison is silently wrong. Codifying the same-boundary rule and pinning it to a single as-of stamp is the runtime check that makes the fan-out contract inspectable.",
|
|
10
|
+
"tags": ["blueprint:application-dashboard", "category:04-fanout-contract"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"reqId": "application-dashboard-REQ-005",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"title": "The export handle exposes an accessible format list and delegates PNG-of-chart to the application-charts render shell",
|
|
5
|
+
"description": "The export handle is a labelled `<button>` on the shell that opens an operator-navigable list of export formats: CSV of the currently rendered data, PDF of the shipped dashboard surface, and PNG of a specific rendered chart. The list is keyboard-reachable in reading order and closes on Escape without losing focus. PNG-of-chart delegates to the application-charts render shell (TAC-1901): the export handle names the chart the operator picked from the chart region and the charts shell owns the PNG generation. Formats outside the shipped set (SVG, XLSX) are the elicited-override path (ADR-2003) and follow the same accessible-list contract.",
|
|
6
|
+
"category": "functional",
|
|
7
|
+
"domain": "application",
|
|
8
|
+
"priority": "must",
|
|
9
|
+
"rationale": "Export is one of the shelf's most-requested affordances and one of the most under-reviewed for accessibility: a hover-only dropdown or a mouse-only download button is common. Naming the accessible-list contract explicitly and delegating PNG-of-chart to the charts blueprint is what keeps the export handle honest and prevents a duplicate PNG generator inside the dashboard shell.",
|
|
10
|
+
"tags": ["blueprint:application-dashboard", "category:05-export-handle"],
|
|
11
|
+
"version": "1.0.0",
|
|
12
|
+
"status": "approved",
|
|
13
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
14
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
15
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-2001-application-dashboard-tile-grid",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Dashboard tile grid, primary KPI placement, and breakpoint reflow",
|
|
8
|
+
"purpose": "Owns the dashboard shell's tile row and tile grid: the CSS Grid definition every tile lives on, the primary KPI placement top-left, the four-state region contract on every tile, and the breakpoint reflow to one column at 360. The shell mounts the chart region through the application-charts render shell (TAC-1901's dependency here) and delegates chart rendering to that shell; the tile grid is the substitutable interface the pack asserts on.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Mount the tile row region as a CSS Grid container whose primary tile carries `data-tile-role=\"primary-kpi\"` and lives at grid-column-start 1, grid-row-start 1 at 1440 and 1024, and grid-row-start 1 with a one-column reflow at 360 (AC-19102-1).",
|
|
11
|
+
"Render every tile with a `role=\"region\"` wrapper, an `aria-live=\"polite\"` announcer, a `data-tile-state` attribute naming the current state, and a non-colour visual cue for each state (skeleton or spinner for loading, labelled block for empty, labelled block with recorded reason for error, metric value for populated) (AC-19103-1).",
|
|
12
|
+
"Announce state transitions on the aria-live region as `<tile title>, <new state>` (AC-19103-2).",
|
|
13
|
+
"Mount the chart region through the application-charts render shell (TAC-1901): the chart region contains at least one `section.chartRegion[role=\"region\"]` element carrying the shape the application-charts pack asserts on (AC-19101-2).",
|
|
14
|
+
"Expose a `data-kpi-kind` attribute on the primary tile whose value is one of ADR-2001's enum (revenue, active-users, error-rate, throughput, custom); a custom value carries a `data-kpi-name` attribute with the operator-elicited name (AC-19102-1)."
|
|
15
|
+
],
|
|
16
|
+
"internalStructure": "One shell module that renders the five labelled regions on the surface, plus small internal helpers per state (loading, empty, error, populated) that render the state's DOM shape into the same region wrapper. The tile grid is a CSS Grid definition with breakpoint-scoped `grid-template-columns` rules; the primary tile carries an explicit `grid-column-start: 1; grid-row-start: 1` at every breakpoint.",
|
|
17
|
+
"interfaces": [
|
|
18
|
+
{
|
|
19
|
+
"name": "renderDashboardShell",
|
|
20
|
+
"kind": "factory",
|
|
21
|
+
"description": "renderDashboardShell({ tiles, chartRegion, filters, timeframe, exportHandle, refreshInterval, asOf }) -> { mount(rootElement), unmount() }. The project supplies the tile inventory (elicited at apply per ADR-2001), the chart region declarations, the filter chrome, the timeframe picker (elicited from ADR-2002's presets), the export handle (elicited from ADR-2003's formats), and the optional refresh interval; the shell owns the CSS Grid DOM plumbing, the region wrapping, the aria-live announcers and the state routing."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "tileStateContract",
|
|
25
|
+
"kind": "shape",
|
|
26
|
+
"description": "A tile in each of four states carries `data-tile-state=\"loading|empty|error|populated\"` on its wrapping `role=\"region\"` element; the accessible name reads `<tile title>, <state>`; the state's visual cue is not colour-only."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"dependencies": [
|
|
30
|
+
{
|
|
31
|
+
"name": "Chart render shell",
|
|
32
|
+
"kind": "tac",
|
|
33
|
+
"tacId": "TAC-1901-application-charts-render-shell",
|
|
34
|
+
"description": "The dashboard's chart region mounts every chart through the application-charts render shell. The dashboard blueprint does not duplicate the chart accessibility ACs; the charts pack fires on the dashboard's chart route through its own applicability predicate."
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "Timeframe and filter fan-out",
|
|
38
|
+
"kind": "tac",
|
|
39
|
+
"tacId": "TAC-2002-application-dashboard-filter-chrome",
|
|
40
|
+
"description": "The tile grid delegates refetch fan-out to TAC-2002 on timeframe change and filter change; every tile re-renders through the shell factory on refetch."
|
|
41
|
+
}
|
|
42
|
+
],
|
|
43
|
+
"tradeoffs": "The primary KPI top-left placement is opinionated on a 360 phone layout: the F-scan does not directly apply to a single-column stack, and a project with a very different information hierarchy at mobile may want the primary KPI second (below a sticky header). The reflow rule here favours consistency with the desktop reading position; a project that supersedes it authors its own REQ and names the residual. The shell is framework-agnostic; a project applying it picks React, Vue, Svelte or hand-authored DOM and writes the mount function against the same DOM contract.",
|
|
44
|
+
"notes": "Known mechanism-reach gap: the shell contract cannot itself prove the applying project's tile factory emits the DOM markers the pack asserts on (`data-tile-role`, `data-kpi-kind`, `data-tile-state`). A build-scan supplement in a v1.1 minor bump would close the class.",
|
|
45
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
46
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-2002-application-dashboard-filter-chrome",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Timeframe picker and filter chrome with refetch fan-out contract",
|
|
8
|
+
"purpose": "Owns the shell's timeframe picker and filter chrome, and the refetch fan-out contract: a preset change or a filter change issues one refetch per tile and one per rendered chart, every fetch carrying the same boundary and the same preset name, and once the batch has returned the shell updates one `data-as-of` attribute the tiles inherit. The fan-out contract is the substitutable interface the pack asserts on (AC-19104-1).",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Render the timeframe picker as an accessible list of presets (labelled `<button>` elements or a `<select>`) with a keyboard-reachable default from ADR-2002 (`last-7-days` unless elicited) (AC-19104-1).",
|
|
11
|
+
"Render filter chrome as labelled interactive elements (chips, dropdowns, text inputs) keyboard-reachable in reading order before the tile row; a hover-only control is refused at project-side review (AC-19105-1).",
|
|
12
|
+
"On a preset change or a filter change, issue one refetch per tile and one per rendered chart; every fetch carries the same `from` and `to` boundary, the same `preset` name and the same active-filters set (AC-19104-1, AC-19105-2).",
|
|
13
|
+
"Update one `data-as-of` attribute on the shell root once every fetch has returned (or the timeout has elapsed) and propagate the same value to every tile's `data-as-of` attribute (AC-19104-1).",
|
|
14
|
+
"Expose a request log on `window.__dashboardFetches` (an append-only array of `{ from, to, preset, filters, tileId, chartId, at }` records) so the pack can read every fetch after each preset change (AC-19104-1)."
|
|
15
|
+
],
|
|
16
|
+
"internalStructure": "One preset-picker module and one filter-chrome module composed on the shell factory. The fan-out contract is implemented as a fetch dispatcher that receives the boundary and the active-filters set, invokes a per-tile fetcher and a per-chart fetcher, and awaits the batch before updating the shell's `data-as-of` attribute.",
|
|
17
|
+
"interfaces": [
|
|
18
|
+
{
|
|
19
|
+
"name": "onTimeframeChange",
|
|
20
|
+
"kind": "function",
|
|
21
|
+
"description": "onTimeframeChange({ preset, from, to }) -> Promise<void>. Called by the preset picker on activation; issues the fan-out and updates the shell's data-as-of."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "onFilterChange",
|
|
25
|
+
"kind": "function",
|
|
26
|
+
"description": "onFilterChange({ filters }) -> Promise<void>. Called by the filter chrome on activation; issues the fan-out with the current boundary and updates the shell's data-active-filters and data-as-of."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
"dependencies": [
|
|
30
|
+
{
|
|
31
|
+
"name": "Tile grid",
|
|
32
|
+
"kind": "tac",
|
|
33
|
+
"tacId": "TAC-2001-application-dashboard-tile-grid",
|
|
34
|
+
"description": "The fan-out dispatcher calls back into TAC-2001 to re-render each tile through the shell factory on refetch."
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"tradeoffs": "The single as-of stamp on the shell root is opinionated: a project whose per-tile freshness differs (a slow-cached tile at 5 minutes, a live tile at 15 seconds) may want a per-tile stamp instead. This TAC insists on the shell-level stamp because it is the reader's mental model of the dashboard's coherence; a per-tile stamp is a project-authored override that supersedes REQ-004 and names the residual. Auto-refresh is off by default (AC-19104-2) because unattended refresh is the most common defect on shipped dashboards.",
|
|
38
|
+
"notes": "Known mechanism-reach gap: filter fan-out (AC-19105-2) is a runtime-observable clause the shipped pack does not itself check today (the pack asserts the timeframe fan-out on AC-19104-1). A v1.1 minor bump would add a filter-fan-out check on the pack; the README names it individually.",
|
|
39
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
40
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
41
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tacId": "TAC-2003-application-dashboard-export-handle",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"tadId": "TAD-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"name": "Export handle with format list and delegation to the charts render shell",
|
|
8
|
+
"purpose": "Owns the shell's export handle: a labelled `<button>` that on activation opens an accessible list of formats (CSV, PDF, PNG-of-chart by default; ADR-2003 elicits overrides), and delegates PNG-of-chart generation to the application-charts render shell (TAC-1901). The handle is the substitutable interface the shell exposes to export tooling; the PNG-of-chart delegation stops the dashboard shell from carrying its own PNG generator.",
|
|
9
|
+
"responsibilities": [
|
|
10
|
+
"Render the export handle region as a labelled `<button>` element with accessible name reading `Export` or an operator-configured equivalent (AC-19106-1).",
|
|
11
|
+
"On activation, open an accessible format list (a menu, a listbox or a set of `<button>` elements) that is keyboard-reachable in reading order and closes on Escape without losing focus on the export button (AC-19106-1).",
|
|
12
|
+
"Render each format entry with a `data-export-format` attribute whose value is one of `csv`, `pdf`, `png-chart` or ADR-2003's elicited override; the shipped default set is CSV, PDF and PNG-of-chart (AC-19106-1).",
|
|
13
|
+
"Delegate PNG-of-chart generation to the application-charts render shell (TAC-1901): the export handle references the chosen chart through a `data-chart-id` attribute (or a runtime prompt) and the charts shell owns the PNG output (AC-19106-2)."
|
|
14
|
+
],
|
|
15
|
+
"internalStructure": "One export-handle button plus one format-list component (a menu or listbox pattern per the WAI-ARIA APG). The button owns the open and close semantics and the focus contract; the format list owns the reading-order navigation and the delegation to the charts shell.",
|
|
16
|
+
"interfaces": [
|
|
17
|
+
{
|
|
18
|
+
"name": "onExportRequest",
|
|
19
|
+
"kind": "function",
|
|
20
|
+
"description": "onExportRequest({ format, chartId? }) -> Promise<{ blobRef, filename }>. Called by the format list on activation; for `png-chart` the shell resolves through the application-charts render shell."
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"dependencies": [
|
|
24
|
+
{
|
|
25
|
+
"name": "Chart render shell",
|
|
26
|
+
"kind": "tac",
|
|
27
|
+
"tacId": "TAC-1901-application-charts-render-shell",
|
|
28
|
+
"description": "PNG-of-chart export generation delegates to the charts shell; the dashboard export handle carries no PNG generator of its own."
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tradeoffs": "The three shipped formats (CSV, PDF, PNG-of-chart) cover the common dashboard export cases; ADR-2003's elicited override handles SVG, XLSX and any operator-specific format. The delegation to the charts shell means a project that ships a bespoke chart engine outside the render shell needs a PNG output path of its own; the export handle names the residual under project-side review.",
|
|
32
|
+
"notes": "Known mechanism-reach gap: the pack browser has no download-capture seam today, so AC-19106-2 (PNG delegation) is proven at project-side review, not through the shipped pack. The README names it individually.",
|
|
33
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-dashboard-US-19101",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-dashboard-REQ-001",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The dashboard shell renders the five required regions on every shipped surface",
|
|
8
|
+
"asA": "product owner responsible for the shipped dashboard surface",
|
|
9
|
+
"iWant": "the shell to render a tile row, a chart region, filter chrome, a timeframe picker and an export handle on every dashboard surface",
|
|
10
|
+
"soThat": "every REQ, TAC and pack check on this blueprint anchors onto a stable, inspectable shell structure rather than a floating layout convention",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-19101-1",
|
|
14
|
+
"description": "Given a rendered dashboard surface, the DOM carries five labelled `role=\"region\"` elements naming (via `aria-label` or an in-region `<h2>` header) the tile row, the chart region, the filter chrome, the timeframe picker and the export handle. A surface that omits one of the five regions either renders the region as an empty labelled `role=\"region\"` element the pack can inspect or supersedes REQ-001 with a project-authored REQ documenting the omission.",
|
|
15
|
+
"given": "a rendered dashboard surface",
|
|
16
|
+
"when": "the accessibility tree is read",
|
|
17
|
+
"then": "five labelled regions cover the tile row, the chart region, the filter chrome, the timeframe picker and the export handle",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-19101-2",
|
|
23
|
+
"description": "Given the shell's chart region, the rendered chart mounts through the application-charts render shell (TAC-1901): the chart region contains at least one `section.chartRegion[role=\"region\"]` element carrying the shape the application-charts pack asserts on (an `svg.chartSvg` and a paired `<table>` element in the same landmark). A chart region that renders a chart outside the render shell fails project-side review.",
|
|
24
|
+
"given": "the rendered chart region",
|
|
25
|
+
"when": "the mount seam is inspected",
|
|
26
|
+
"then": "the chart mounts through the application-charts render shell",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "library"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-2001-application-dashboard-tile-grid"],
|
|
32
|
+
"tags": ["blueprint:application-dashboard"],
|
|
33
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-dashboard-US-19102",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-dashboard-REQ-002",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The primary KPI tile sits top-left in DOM order and in CSS Grid position across the ratified breakpoints",
|
|
8
|
+
"asA": "reader glancing at the shipped dashboard on a laptop, a tablet and a phone",
|
|
9
|
+
"iWant": "the primary KPI to land at the top-left first-fixation position on every ratified breakpoint",
|
|
10
|
+
"soThat": "the F-scan reading pattern lands on the primary KPI first, without a per-surface layout negotiation",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-19102-1",
|
|
14
|
+
"description": "Given a rendered dashboard surface at each of the three ratified viewports (1440, 1024, 360), the primary KPI tile (`data-tile-role=\"primary-kpi\"`) is the first tile in DOM order within the tile row region; at 1440 and 1024 the tile's computed CSS Grid `grid-column-start` is 1 and `grid-row-start` is 1; at 360 the tile row reflows to one column and the primary KPI's `grid-row-start` is 1 (the top row). The tile carries a `data-kpi-kind` attribute whose value is one of the ADR-2001 enum (revenue, active-users, error-rate, throughput, custom). Probed by the application-dashboard pack check AC-19102-1 (Playwright drives the browser to the dashboard route, resizes the viewport to each of the three widths, reads the DOM order and the computed CSS Grid position, and asserts every breakpoint places the primary KPI top-left).",
|
|
15
|
+
"given": "a rendered dashboard surface at 1440, 1024 and 360",
|
|
16
|
+
"when": "the DOM order and the computed CSS Grid position are read",
|
|
17
|
+
"then": "the primary KPI tile is first in DOM order and top-left in CSS Grid at each of the three widths",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-19102-2",
|
|
23
|
+
"description": "Given a rendered dashboard surface with no primary KPI tile, the surface either supersedes REQ-002 with a project-authored REQ documenting the omission or fails project-side review. This case is a documentation-and-review contract; the pack asserts the primary KPI tile exists (AC-19102-1) but does not itself enforce the fallback path.",
|
|
24
|
+
"given": "a rendered dashboard with no primary KPI tile",
|
|
25
|
+
"when": "the surface is reviewed",
|
|
26
|
+
"then": "the surface supersedes REQ-002 with a project-authored REQ or fails review",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "library"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-2001-application-dashboard-tile-grid"],
|
|
32
|
+
"tags": ["blueprint:application-dashboard"],
|
|
33
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
35
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-dashboard-US-19103",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-dashboard-REQ-003",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Every tile honours the four-state contract with distinct visuals, role region, aria-live polite and non-colour distinction",
|
|
8
|
+
"asA": "screen-reader user and colour-blind reader on the shipped dashboard",
|
|
9
|
+
"iWant": "every tile state (loading, empty, error, populated) to carry a distinct visual, a labelled region, an aria-live polite announcer and a non-colour distinction",
|
|
10
|
+
"soThat": "the tile's current state is reachable regardless of assistive tech and legible regardless of colour perception",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-19103-1",
|
|
14
|
+
"description": "Given a rendered tile in each of the four states (loading, empty, error, populated), the tile wraps its content in a `role=\"region\"` element carrying `aria-live=\"polite\"` and a labelled state descriptor (`data-tile-state=\"<state>\"`). The state's visual cue is not colour-only: loading carries a skeleton stripe or spinner element, empty carries a labelled empty-state block, error carries a labelled error block with the recorded reason, populated carries the metric value. Every state exposes its accessible name as `<tile title>, <state>` on the wrapping region. Probed by the application-dashboard pack check AC-19103-1 (Playwright drives to `?tile=<id>&state=<state>` for each of the four states on each of two tiles, reads the accessibility tree and the DOM, and asserts every state carries the role region, the aria-live polite, the data-tile-state attribute, and a non-colour visual cue).",
|
|
15
|
+
"given": "a tile switched into each of the four states",
|
|
16
|
+
"when": "the DOM and the accessibility tree are read",
|
|
17
|
+
"then": "each state carries role region, aria-live polite, data-tile-state, a non-colour visual cue and the announced name",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-19103-2",
|
|
23
|
+
"description": "Given a tile transitioning between states (loading to populated, populated to error) at runtime, the tile's `aria-live=\"polite\"` region announces the new state's accessible name to the assistive tech; the announcement text reads `<tile title>, <new state>` and the visual cue changes in the same paint. This AC is a runtime-observable behaviour on state transition; the pack does not simulate the transition today (the runner has no synthetic-event seam beyond click/type/press), so the AC is proven at project-side review and the README names the transition-observation gap under known mechanism-reach gaps.",
|
|
24
|
+
"given": "a tile transitioning between states",
|
|
25
|
+
"when": "the transition renders",
|
|
26
|
+
"then": "the aria-live polite region announces the new state's accessible name and the visual cue changes",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "runtime"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-2001-application-dashboard-tile-grid"],
|
|
32
|
+
"tags": ["blueprint:application-dashboard"],
|
|
33
|
+
"createdAt": "2026-09-04T22:10:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T22:10:00Z"
|
|
35
|
+
}
|