@adobe/design-data-spec 0.8.0 → 0.10.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/components/accordion.json +18 -1
- package/components/action-bar.json +12 -1
- package/components/action-button.json +19 -1
- package/components/action-group.json +12 -1
- package/components/alert-banner.json +11 -1
- package/components/alert-dialog.json +19 -1
- package/components/avatar-group.json +4 -1
- package/components/avatar.json +4 -1
- package/components/badge.json +4 -1
- package/components/body.json +3 -0
- package/components/bottom-navigation-android.json +17 -0
- package/components/breadcrumbs.json +19 -2
- package/components/button-group.json +12 -1
- package/components/button.json +21 -3
- package/components/calendar.json +22 -0
- package/components/cards.json +18 -1
- package/components/checkbox-group.json +17 -1
- package/components/checkbox.json +24 -1
- package/components/close-button.json +19 -1
- package/components/coach-indicator.json +4 -1
- package/components/coach-mark.json +13 -1
- package/components/code.json +3 -0
- package/components/color-area.json +24 -1
- package/components/color-handle.json +13 -1
- package/components/color-loupe.json +4 -1
- package/components/color-slider.json +24 -1
- package/components/color-wheel.json +24 -1
- package/components/combo-box.json +24 -1
- package/components/contextual-help.json +18 -1
- package/components/date-picker.json +23 -1
- package/components/detail.json +3 -0
- package/components/divider.json +4 -1
- package/components/drop-zone.json +18 -1
- package/components/field-label.json +4 -1
- package/components/heading.json +3 -0
- package/components/help-text.json +5 -2
- package/components/illustrated-message.json +4 -1
- package/components/in-field-progress-button.json +18 -0
- package/components/in-field-progress-circle.json +4 -1
- package/components/in-line-alert.json +11 -1
- package/components/link.json +19 -1
- package/components/list-view.json +18 -1
- package/components/menu.json +19 -1
- package/components/meter.json +4 -1
- package/components/number-field.json +24 -1
- package/components/opacity-checkerboard.json +4 -1
- package/components/picker.json +24 -1
- package/components/popover.json +12 -1
- package/components/progress-bar.json +4 -1
- package/components/progress-circle.json +4 -1
- package/components/radio-button.json +24 -1
- package/components/radio-group.json +17 -1
- package/components/rating.json +24 -1
- package/components/scroll-zoom-bar.json +12 -0
- package/components/search-field.json +28 -1
- package/components/segmented-control.json +18 -1
- package/components/select-box.json +18 -1
- package/components/side-navigation.json +18 -1
- package/components/slider.json +24 -1
- package/components/standard-dialog.json +19 -1
- package/components/standard-panel.json +3 -0
- package/components/status-light.json +4 -1
- package/components/steplist.json +18 -1
- package/components/swatch-group.json +12 -1
- package/components/swatch.json +18 -1
- package/components/switch.json +19 -1
- package/components/tab-bar-ios.json +17 -0
- package/components/table.json +23 -1
- package/components/tabs.json +18 -1
- package/components/tag-field.json +18 -1
- package/components/tag-group.json +18 -1
- package/components/tag.json +18 -1
- package/components/takeover-dialog.json +19 -1
- package/components/text-area.json +28 -1
- package/components/text-field.json +28 -1
- package/components/thumbnail.json +4 -1
- package/components/title.json +40 -10
- package/components/toast.json +13 -1
- package/components/tooltip.json +17 -1
- package/components/tray.json +11 -0
- package/components/tree-view.json +19 -1
- package/conformance/README.md +7 -7
- package/conformance/invalid/SPEC-001/dataset.json +10 -0
- package/conformance/invalid/SPEC-001/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-002/dataset.json +16 -0
- package/conformance/invalid/SPEC-002/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-003/dataset.json +15 -0
- package/conformance/invalid/SPEC-003/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-004/dataset.json +15 -0
- package/conformance/invalid/SPEC-004/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-005/dataset.json +11 -0
- package/conformance/invalid/SPEC-005/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-006/dataset.json +15 -0
- package/conformance/invalid/SPEC-006/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-007/dataset.json +9 -0
- package/conformance/invalid/SPEC-007/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-008/dataset.json +25 -0
- package/conformance/invalid/SPEC-008/expected-errors.json +2 -1
- package/conformance/invalid/SPEC-009/dataset.json +12 -0
- package/conformance/invalid/SPEC-009/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-010/dataset.json +12 -0
- package/conformance/invalid/SPEC-011/dataset.json +25 -0
- package/conformance/invalid/SPEC-012/dataset.json +16 -0
- package/conformance/invalid/SPEC-013/dataset.json +11 -0
- package/conformance/invalid/SPEC-014/dataset.json +12 -0
- package/conformance/invalid/SPEC-014/expected-errors.json +1 -1
- package/conformance/invalid/SPEC-015/dataset.json +22 -0
- package/conformance/invalid/SPEC-015/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-015/tokens.tokens.json +19 -0
- package/conformance/invalid/SPEC-016/dataset.json +11 -0
- package/conformance/invalid/SPEC-016/expected-errors.json +2 -2
- package/conformance/invalid/SPEC-017/dataset.json +10 -0
- package/conformance/invalid/SPEC-024/dataset.json +4 -3
- package/conformance/invalid/SPEC-024/expected-errors.json +2 -2
- package/conformance/invalid/SPEC-025/dataset.json +12 -0
- package/conformance/invalid/SPEC-025/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-026/dataset.json +18 -0
- package/conformance/invalid/SPEC-026/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-028/dataset.json +21 -0
- package/conformance/invalid/SPEC-028/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-029/dataset.json +20 -0
- package/conformance/invalid/SPEC-029/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-030/dataset.json +15 -0
- package/conformance/invalid/SPEC-030/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-031/dataset.json +17 -0
- package/conformance/invalid/SPEC-031/expected-errors.json +10 -0
- package/conformance/invalid/SPEC-032/dataset.json +27 -0
- package/conformance/invalid/SPEC-032/expected-errors.json +15 -0
- package/conformance/resolution/base-fallback/expected.json +1 -1
- package/conformance/resolution/product-layer-wins/expected.json +5 -0
- package/conformance/resolution/product-layer-wins/input/tokens.tokens.json +7 -0
- package/conformance/resolution/product-layer-wins/product-context.json +11 -0
- package/conformance/resolution/product-layer-wins/query.json +4 -0
- package/conformance/resolution/specificity-wins/expected.json +1 -1
- package/conformance/valid/SPEC-014/dataset.json +12 -0
- package/conformance/valid/SPEC-016/dataset.json +16 -0
- package/conformance/valid/SPEC-025/dataset.json +24 -0
- package/conformance/valid/SPEC-026/dataset.json +15 -0
- package/conformance/valid/SPEC-028/dataset.json +21 -0
- package/conformance/valid/SPEC-029/dataset.json +24 -0
- package/conformance/valid/SPEC-030/dataset.json +17 -0
- package/conformance/valid/SPEC-031/dataset.json +24 -0
- package/conformance/valid/SPEC-032/dataset.json +16 -0
- package/conformance/valid/component-refs/README.md +5 -0
- package/conformance/valid/component-with-accessibility.json +32 -0
- package/fields/color-scheme.json +2 -2
- package/fields/contrast.json +2 -2
- package/fields/density.json +1 -1
- package/fields/scale.json +2 -2
- package/fields/size.json +1 -1
- package/package.json +4 -13
- package/rules/rules.yaml +40 -4
- package/schemas/accessibility.schema.json +60 -0
- package/schemas/component.schema.json +19 -0
- package/schemas/field.schema.json +2 -2
- package/schemas/manifest.schema.json +1 -1
- package/schemas/{dimension.schema.json → mode-set.schema.json} +3 -3
- package/schemas/token.schema.json +5 -5
- package/schemas/value-types/README.md +20 -0
- package/schemas/value-types/drop-shadow.schema.json +5 -5
- package/schemas/value-types/typography-scale.schema.json +2 -2
- package/schemas/value-types/typography.schema.json +5 -5
- package/spec/accessibility-adapters.md +219 -0
- package/spec/accessibility.md +219 -0
- package/spec/agent-surface.md +4 -4
- package/spec/cascade.md +7 -7
- package/spec/component-format.md +32 -0
- package/spec/document-blocks.md +1 -1
- package/spec/index.md +28 -20
- package/spec/manifest.md +2 -2
- package/spec/mode-sets.md +64 -0
- package/spec/query.md +18 -18
- package/spec/taxonomy.md +5 -5
- package/spec/token-format.md +12 -12
- package/spec/dimensions.md +0 -64
- package/src/canonical.js +0 -61
- package/src/validate.js +0 -190
- /package/conformance/resolution/alias-resolved-after-cascade/{dimensions → mode-sets}/color-scheme.json +0 -0
- /package/conformance/resolution/base-fallback/{dimensions → mode-sets}/color-scheme.json +0 -0
- /package/conformance/resolution/specificity-wins/{dimensions → mode-sets}/color-scheme.json +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Accessibility adapters
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
> **This chapter is informative.** It provides guidance for platform adapter repos; it does not add normative constraints to the foundation spec.
|
|
6
|
+
|
|
7
|
+
This chapter shows how the semantic accessibility vocabulary defined in [Accessibility](accessibility.md) maps to real platform APIs across web (ARIA), iOS (UIAccessibility), Android (AccessibilityNodeInfo), and voice/multimodal surfaces. Platform adapter repos use this as a translation contract when implementing accessibility support for Spectrum components. The foundation layer ships intent; adapters ship the platform binding.
|
|
8
|
+
|
|
9
|
+
Scoped under planned RFC-B. See [rfc-coordination.md](../docs/rfc-coordination.md).
|
|
10
|
+
|
|
11
|
+
## Adapter overview
|
|
12
|
+
|
|
13
|
+
A platform adapter repo declares which foundation components it supports and implements a mapping layer that translates each component's `accessibility` declaration to the platform's native accessibility API. When a field is absent from a component's `accessibility` declaration, the adapter falls back to its own defaults or omits the attribute.
|
|
14
|
+
|
|
15
|
+
Adapters are not required to implement every field — a minimal adapter might only handle `role` and `focusable`. The fields documented below describe what each foundation field means at the platform layer when the adapter chooses to implement it.
|
|
16
|
+
|
|
17
|
+
## Web / ARIA
|
|
18
|
+
|
|
19
|
+
ARIA (Accessible Rich Internet Applications) is the primary web accessibility API. Adapters set HTML `role` attributes and `aria-*` state properties on the root element or on relevant sub-elements.
|
|
20
|
+
|
|
21
|
+
### `role`
|
|
22
|
+
|
|
23
|
+
| Foundation `role` | ARIA / HTML equivalent |
|
|
24
|
+
| ----------------- | ---------------------------------------------- |
|
|
25
|
+
| `button` | `<button>` or `role="button"` |
|
|
26
|
+
| `checkbox` | `<input type="checkbox">` or `role="checkbox"` |
|
|
27
|
+
| `combobox` | `role="combobox"` |
|
|
28
|
+
| `dialog` | `role="dialog"` |
|
|
29
|
+
| `link` | `<a href>` or `role="link"` |
|
|
30
|
+
| `listbox` | `role="listbox"` |
|
|
31
|
+
| `menu` | `role="menu"` |
|
|
32
|
+
| `menuitem` | `role="menuitem"` |
|
|
33
|
+
| `radio` | `<input type="radio">` or `role="radio"` |
|
|
34
|
+
| `slider` | `role="slider"` |
|
|
35
|
+
| `spinbutton` | `role="spinbutton"` |
|
|
36
|
+
| `switch` | `role="switch"` |
|
|
37
|
+
| `tab` | `role="tab"` |
|
|
38
|
+
| `textbox` | `<input type="text">` or `role="textbox"` |
|
|
39
|
+
| `tooltip` | `role="tooltip"` |
|
|
40
|
+
| `tree` | `role="tree"` |
|
|
41
|
+
|
|
42
|
+
### `intents`
|
|
43
|
+
|
|
44
|
+
| Foundation intent | Web guidance |
|
|
45
|
+
| ----------------- | ------------------------------------------------------------------------------------------------- |
|
|
46
|
+
| `trigger` | Ensure the element has an accessible name via `aria-label`, `aria-labelledby`, or a visible label |
|
|
47
|
+
| `select` | Set `aria-selected` on child options; the container gets `role="listbox"` or `role="combobox"` |
|
|
48
|
+
| `navigate` | Use `<a href>` or `role="link"`; ensure the destination is announced |
|
|
49
|
+
| `expand` | Set `aria-expanded="true"` / `"false"` on the trigger element |
|
|
50
|
+
| `collapse` | Toggle `aria-expanded` to `"false"` |
|
|
51
|
+
| `input` | Associate a visible `<label>` or `aria-label`; use `aria-describedby` for hints |
|
|
52
|
+
| `choose` | Use `aria-valuenow`, `aria-valuemin`, `aria-valuemax` for range inputs |
|
|
53
|
+
| `dismiss` | Return focus to the trigger element on close; announce the closure if needed |
|
|
54
|
+
|
|
55
|
+
### `focusable`
|
|
56
|
+
|
|
57
|
+
* `true` → set `tabindex="0"` on the root element, or use a natively focusable HTML element.
|
|
58
|
+
* `false` → set `tabindex="-1"` for elements that receive programmatic focus; use `aria-hidden="true"` for purely decorative elements. For roving-tabindex composites (radio groups, toolbars, tree views), the adapter manages which child holds `tabindex="0"`.
|
|
59
|
+
|
|
60
|
+
### `keyboardIntents`
|
|
61
|
+
|
|
62
|
+
| Foundation intent | Conventional key binding |
|
|
63
|
+
| ------------------ | ------------------------------------- |
|
|
64
|
+
| `activate` | Enter, Space |
|
|
65
|
+
| `expand` | ArrowDown, Enter, Space |
|
|
66
|
+
| `collapse` | Escape, ArrowUp |
|
|
67
|
+
| `navigate-options` | ArrowUp, ArrowDown |
|
|
68
|
+
| `navigate-items` | ArrowLeft, ArrowRight |
|
|
69
|
+
| `increment` | ArrowUp, ArrowRight |
|
|
70
|
+
| `decrement` | ArrowDown, ArrowLeft |
|
|
71
|
+
| `dismiss` | Escape |
|
|
72
|
+
| `select-all` | Ctrl+A (Windows/Linux), Cmd+A (macOS) |
|
|
73
|
+
|
|
74
|
+
Key bindings shown are conventional. Web adapters should follow the ARIA Authoring Practices Guide patterns for the component's `role`.
|
|
75
|
+
|
|
76
|
+
### `wcag`
|
|
77
|
+
|
|
78
|
+
The `wcag` array is developer guidance at the web layer, not an automated attribute. Web adapter implementations should:
|
|
79
|
+
|
|
80
|
+
* Include listed criteria in component documentation.
|
|
81
|
+
* Add automated accessibility tests (e.g., axe-core) that target listed criteria.
|
|
82
|
+
* Flag in PR checklists when changes may affect listed criteria.
|
|
83
|
+
|
|
84
|
+
### State fields
|
|
85
|
+
|
|
86
|
+
* `announce` → set `aria-live="polite"` (or `"assertive"` for urgent transitions) on a live region element and inject the `announce` text on state entry.
|
|
87
|
+
* `communicates` → map to the corresponding `aria-*` state attribute (e.g., `"expanded"` → `aria-expanded="true"`). See the `communicates` vocabulary table in [Accessibility](accessibility.md#communicates).
|
|
88
|
+
* `blocksInteraction` → set `aria-disabled="true"` and `tabindex="-1"` on the root element; suppress pointer and keyboard events.
|
|
89
|
+
|
|
90
|
+
## iOS / UIAccessibility
|
|
91
|
+
|
|
92
|
+
iOS exposes accessibility semantics through `UIAccessibility` protocol properties on `UIView` (UIKit) and through accessibility modifiers in SwiftUI.
|
|
93
|
+
|
|
94
|
+
### `role`
|
|
95
|
+
|
|
96
|
+
| Foundation `role` | UIAccessibilityTraits / SwiftUI |
|
|
97
|
+
| ----------------- | -------------------------------------------------------------- |
|
|
98
|
+
| `button` | `.button` |
|
|
99
|
+
| `checkbox` | `.button` with toggled state, or SwiftUI `Toggle` |
|
|
100
|
+
| `combobox` | `.button` (picker-like behavior) |
|
|
101
|
+
| `dialog` | Presented as modal sheet; VoiceOver reads the accessible label |
|
|
102
|
+
| `link` | `.link` |
|
|
103
|
+
| `listbox` | Container view; children use `.button` or `.selected` |
|
|
104
|
+
| `menu` | `.button` on trigger; menu items as `.button` |
|
|
105
|
+
| `menuitem` | `.button` |
|
|
106
|
+
| `radio` | `.button` with `.selected` when active |
|
|
107
|
+
| `slider` | `.adjustable` |
|
|
108
|
+
| `spinbutton` | `.adjustable` |
|
|
109
|
+
| `switch` | `.button` with `.selected` / SwiftUI `Toggle` |
|
|
110
|
+
| `tab` | `.button` with `.selected` |
|
|
111
|
+
| `textbox` | `.keyboard` traits; `UITextField` or `UITextView` |
|
|
112
|
+
| `tooltip` | `.staticText` on an overlay element |
|
|
113
|
+
| `tree` | Hierarchical cells with `accessibilityContainerType` |
|
|
114
|
+
|
|
115
|
+
### `intents`
|
|
116
|
+
|
|
117
|
+
* `trigger` → provide `accessibilityLabel` describing the action the user will invoke.
|
|
118
|
+
* `select` → set `accessibilityTraits` to include `.selected` when the item is in a selected state.
|
|
119
|
+
* `expand` / `collapse` → update `accessibilityHint` or `accessibilityValue` to describe the current expanded/collapsed state.
|
|
120
|
+
* `choose` → implement `accessibilityIncrement()` / `accessibilityDecrement()` with the `.adjustable` trait.
|
|
121
|
+
* `dismiss` → handle `accessibilityPerformEscape()` to close the view and return focus.
|
|
122
|
+
|
|
123
|
+
### `focusable`
|
|
124
|
+
|
|
125
|
+
* `true` → `isAccessibilityElement = true`.
|
|
126
|
+
* `false` → `isAccessibilityElement = false`. For composite views that manage focus internally (e.g., a radio group), set `accessibilityContainerType` and manage the focused child programmatically.
|
|
127
|
+
|
|
128
|
+
### `keyboardIntents`
|
|
129
|
+
|
|
130
|
+
Relevant for external keyboard support (iPad with Magic Keyboard, Bluetooth keyboard):
|
|
131
|
+
|
|
132
|
+
* `activate` → register a `UIKeyCommand` for Return and Space.
|
|
133
|
+
* `navigate-options` / `navigate-items` → register `UIKeyCommand` entries for arrow keys.
|
|
134
|
+
* `dismiss` → register a `UIKeyCommand` for Escape.
|
|
135
|
+
|
|
136
|
+
### `wcag`
|
|
137
|
+
|
|
138
|
+
Include WCAG criteria in component documentation and Accessibility Inspector audits. The `wcag` array has no automatic mapping at the iOS layer.
|
|
139
|
+
|
|
140
|
+
### State fields
|
|
141
|
+
|
|
142
|
+
* `announce` → call `UIAccessibility.post(notification: .announcement, argument: announceText)` on state entry. In SwiftUI, use `AccessibilityNotification.Announcement`.
|
|
143
|
+
* `communicates` → set the corresponding trait or value (e.g., `"expanded"` → set `accessibilityValue = "expanded"` / `"collapsed"`; `"disabled"` → add `.notEnabled`; `"busy"` → add `.causesPageTurn` or a custom announcement).
|
|
144
|
+
* `blocksInteraction` → add `.notEnabled` trait; set `isAccessibilityElement = false` on interactive children.
|
|
145
|
+
|
|
146
|
+
## Android / AccessibilityNodeInfo
|
|
147
|
+
|
|
148
|
+
Android exposes accessibility semantics via `AccessibilityNodeInfo` populated through `ViewCompat.setAccessibilityDelegate()` or Jetpack Compose `Modifier.semantics {}`.
|
|
149
|
+
|
|
150
|
+
### `role`
|
|
151
|
+
|
|
152
|
+
| Foundation `role` | Android mapping |
|
|
153
|
+
| ----------------- | ----------------------------------------------------------- |
|
|
154
|
+
| `button` | `Button` widget or `setRoleDescription("button")` |
|
|
155
|
+
| `checkbox` | `CheckBox` widget or `setCheckable(true)` |
|
|
156
|
+
| `combobox` | `Spinner` widget or `setRoleDescription("combobox")` |
|
|
157
|
+
| `dialog` | Dialog window; `setDismissable(true)` |
|
|
158
|
+
| `link` | `setRoleDescription("link")`; add `ACTION_CLICK` |
|
|
159
|
+
| `listbox` | `RecyclerView` with `setCollectionInfo` |
|
|
160
|
+
| `menu` | `setRoleDescription("menu")` on the container |
|
|
161
|
+
| `menuitem` | `setRoleDescription("menu item")` |
|
|
162
|
+
| `radio` | `RadioButton` widget or `setCheckable(true)` + `setChecked` |
|
|
163
|
+
| `slider` | `SeekBar` widget or `RangeSemantics` in Compose |
|
|
164
|
+
| `spinbutton` | `setRoleDescription("spin button")` |
|
|
165
|
+
| `switch` | `Switch` widget or `setRoleDescription("switch")` |
|
|
166
|
+
| `tab` | `TabLayout` tab item; `setSelected(true)` when active |
|
|
167
|
+
| `textbox` | `EditText` widget or `TextField` in Compose |
|
|
168
|
+
| `tooltip` | `setTooltipText(text)` |
|
|
169
|
+
| `tree` | `setCollectionInfo` with hierarchical structure |
|
|
170
|
+
|
|
171
|
+
### `intents`
|
|
172
|
+
|
|
173
|
+
* `trigger` → set `setContentDescription()` describing the action.
|
|
174
|
+
* `select` → call `setSelected(true)` on selection.
|
|
175
|
+
* `expand` / `collapse` → call `setExpandable(true)` and `setExpanded(true/false)`.
|
|
176
|
+
* `choose` → add `ACTION_SCROLL_FORWARD` / `ACTION_SCROLL_BACKWARD` actions.
|
|
177
|
+
* `dismiss` → call `setDismissable(true)`; handle `ACTION_DISMISS`.
|
|
178
|
+
|
|
179
|
+
### `focusable`
|
|
180
|
+
|
|
181
|
+
* `true` → `setFocusable(true)` and `setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES)`.
|
|
182
|
+
* `false` → `setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)` for decorative views. For composite views, manage focus via `performAccessibilityAction(ACTION_ACCESSIBILITY_FOCUS, ...)`.
|
|
183
|
+
|
|
184
|
+
### `keyboardIntents`
|
|
185
|
+
|
|
186
|
+
Relevant for physical keyboard input (Chromebook, external keyboard):
|
|
187
|
+
|
|
188
|
+
* `activate` → handle `KeyEvent.KEYCODE_ENTER` / `KEYCODE_SPACE`.
|
|
189
|
+
* `navigate-options` / `navigate-items` → handle arrow key `KeyEvent`s.
|
|
190
|
+
* `dismiss` → handle `KeyEvent.KEYCODE_ESCAPE` or `KEYCODE_BACK`.
|
|
191
|
+
|
|
192
|
+
### `wcag`
|
|
193
|
+
|
|
194
|
+
Include criteria in component documentation and Accessibility Scanner audits. No automatic mapping.
|
|
195
|
+
|
|
196
|
+
### State fields
|
|
197
|
+
|
|
198
|
+
* `announce` → call `ViewCompat.announceForAccessibility(view, announceText)` or send `AccessibilityEvent.TYPE_ANNOUNCEMENT`. In Compose, use `LocalAccessibilityManager.current?.announce(...)`.
|
|
199
|
+
* `communicates` → set the corresponding node property (e.g., `"expanded"` → call `setExpandable(true)` then `setExpanded(true)`; `"checked"` → `setChecked(true)`; `"disabled"` → `setEnabled(false)`).
|
|
200
|
+
* `blocksInteraction` → call `setEnabled(false)` on the root view. Use `IMPORTANT_FOR_ACCESSIBILITY_YES` to keep the element discoverable by AT as disabled; use `IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS` to hide the element and its subtree from AT entirely.
|
|
201
|
+
|
|
202
|
+
## Voice and multimodal
|
|
203
|
+
|
|
204
|
+
> **Informative sketch.** The following mapping is exploratory. Platform-specific voice adapter specs are deferred.
|
|
205
|
+
|
|
206
|
+
For voice interfaces (Alexa, Google Assistant, Siri Shortcuts) and future multimodal surfaces, the foundation vocabulary maps conceptually as follows:
|
|
207
|
+
|
|
208
|
+
| Foundation field | Voice / multimodal mapping |
|
|
209
|
+
| ----------------- | --------------------------------------------------------------------- |
|
|
210
|
+
| `role` | Utterance type in a voice schema (e.g., `button` → invocable command) |
|
|
211
|
+
| `intents` | Action category exposed in a voice intent catalog |
|
|
212
|
+
| `announce` | Spoken response on state transition |
|
|
213
|
+
| `communicates` | State value spoken when the user queries component status |
|
|
214
|
+
| `focusable` | Not applicable for purely voice surfaces |
|
|
215
|
+
| `keyboardIntents` | Not applicable for purely voice surfaces |
|
|
216
|
+
|
|
217
|
+
### `wcag`
|
|
218
|
+
|
|
219
|
+
WCAG 2.x success criteria apply at the web layer. For voice and multimodal surfaces, WCAG is not directly applicable; accessibility requirements for these surfaces are deferred to platform-specific adapter specs.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Accessibility
|
|
2
|
+
|
|
3
|
+
**Spec version:** `1.0.0-draft` (see [Overview](index.md))
|
|
4
|
+
|
|
5
|
+
This chapter defines the **semantic accessibility vocabulary** that component declarations carry at the foundation layer. A component's accessibility declaration expresses intent — its semantic role, interaction purposes, focus behavior, and applicable WCAG criteria — without encoding platform-specific APIs. Platform adapter repos translate this vocabulary to ARIA attributes, iOS UIAccessibility traits, Android AccessibilityNodeInfo properties, and other platform contracts.
|
|
6
|
+
|
|
7
|
+
This mirrors how the cascade defines foundation→platform layering for tokens: the spec ships the vocabulary; platform repos ship the mapping.
|
|
8
|
+
|
|
9
|
+
Scoped under planned RFC-B. See [rfc-coordination.md](../docs/rfc-coordination.md).
|
|
10
|
+
|
|
11
|
+
## Accessibility declaration
|
|
12
|
+
|
|
13
|
+
The `accessibility` object is an optional top-level field on a [component declaration](component-format.md). When present, it MUST conform to [`accessibility.schema.json`](../schemas/accessibility.schema.json) (schema added in Phase 7.3).
|
|
14
|
+
|
|
15
|
+
### Fields
|
|
16
|
+
|
|
17
|
+
| Field | Type | Required | Description |
|
|
18
|
+
| ----------------- | --------- | -------- | -------------------------------------------------------- |
|
|
19
|
+
| `role` | string | No | Semantic role from the canonical role vocabulary |
|
|
20
|
+
| `intents` | string\[] | No | Semantic interaction intents |
|
|
21
|
+
| `focusable` | boolean | No | Whether the component receives keyboard focus by default |
|
|
22
|
+
| `keyboardIntents` | string\[] | No | Keyboard interaction intents when focused |
|
|
23
|
+
| `wcag` | object\[] | No | Applicable WCAG 2.x success criteria |
|
|
24
|
+
|
|
25
|
+
**NORMATIVE:** An `accessibility` object SHOULD contain at least one field. An empty `accessibility` object provides no semantic value.
|
|
26
|
+
|
|
27
|
+
> **Note:** Anatomy parts (see [Anatomy format](anatomy-format.md)) do not carry an
|
|
28
|
+
> `accessibility` field at this spec version. Component-level accessibility applies to the
|
|
29
|
+
> component as a whole. Per-part accessibility semantics are deferred to Phase 7.3.
|
|
30
|
+
|
|
31
|
+
### `role`
|
|
32
|
+
|
|
33
|
+
The `role` field names the semantic role of the component. It maps conceptually to ARIA widget and landmark roles, iOS `UIAccessibilityTraits`, Android role descriptions, and equivalent constructs on other platforms — but it is **not** a direct ARIA attribute. Platform adapters perform the translation.
|
|
34
|
+
|
|
35
|
+
**NORMATIVE:** Custom values (outside the canonical vocabulary below) are permitted. When using a custom value, the component SHOULD include a `description` field that documents the role's semantics.
|
|
36
|
+
|
|
37
|
+
**Canonical role vocabulary:**
|
|
38
|
+
|
|
39
|
+
| Value | Semantic meaning |
|
|
40
|
+
| ------------ | --------------------------------------------------- |
|
|
41
|
+
| `button` | Triggers a discrete action |
|
|
42
|
+
| `checkbox` | Binary on/off selection |
|
|
43
|
+
| `combobox` | Combined text input with a selectable option list |
|
|
44
|
+
| `dialog` | Modal overlay requiring a user response |
|
|
45
|
+
| `link` | Navigates the user to another context |
|
|
46
|
+
| `listbox` | Selectable list of options |
|
|
47
|
+
| `menu` | List of commands or options |
|
|
48
|
+
| `menuitem` | Individual item within a menu |
|
|
49
|
+
| `radio` | Single-select option within a group |
|
|
50
|
+
| `slider` | Range input with a continuous value |
|
|
51
|
+
| `spinbutton` | Numeric input with increment and decrement controls |
|
|
52
|
+
| `switch` | Toggles between two states (on/off) |
|
|
53
|
+
| `tab` | Selects a panel within a tabbed interface |
|
|
54
|
+
| `textbox` | Accepts free-form text input |
|
|
55
|
+
| `tooltip` | Contextual information overlay; not interactive |
|
|
56
|
+
| `tree` | Hierarchical navigable list |
|
|
57
|
+
|
|
58
|
+
### `intents`
|
|
59
|
+
|
|
60
|
+
The `intents` array lists the semantic interaction purposes the component supports. Multiple intents are permitted — a combobox, for example, both accepts text input and selects from a list.
|
|
61
|
+
|
|
62
|
+
Platform adapters use `intents` to determine which ARIA properties, traits, or accessibility attributes to apply.
|
|
63
|
+
|
|
64
|
+
**Canonical intent vocabulary:**
|
|
65
|
+
|
|
66
|
+
| Value | Meaning |
|
|
67
|
+
| ---------- | ------------------------------------------ |
|
|
68
|
+
| `trigger` | Activates or invokes an action |
|
|
69
|
+
| `select` | Selects from a set of options |
|
|
70
|
+
| `navigate` | Moves the user to another context |
|
|
71
|
+
| `expand` | Reveals additional content |
|
|
72
|
+
| `collapse` | Conceals content |
|
|
73
|
+
| `input` | Accepts user-typed text |
|
|
74
|
+
| `choose` | Picks a value from a range or discrete set |
|
|
75
|
+
| `dismiss` | Closes or removes an element |
|
|
76
|
+
|
|
77
|
+
### `focusable`
|
|
78
|
+
|
|
79
|
+
The `focusable` boolean declares whether the component receives keyboard focus via the Tab key by default.
|
|
80
|
+
|
|
81
|
+
* `true` — the component is in the tab order; platform adapters set `tabindex="0"` or the platform equivalent.
|
|
82
|
+
* `false` — the component is not in the tab order; child elements may still be individually
|
|
83
|
+
focusable. Components that manage focus internally (radio groups, toolbars, tree views)
|
|
84
|
+
use the roving `tabindex` pattern — one child is focusable at a time. For these, set
|
|
85
|
+
`focusable: false`; the platform adapter manages which child holds `tabindex="0"`.
|
|
86
|
+
* When absent, focus behavior is unspecified at the foundation layer.
|
|
87
|
+
|
|
88
|
+
### `keyboardIntents`
|
|
89
|
+
|
|
90
|
+
The `keyboardIntents` array lists the keyboard interaction intents the component responds to when focused. Platform adapters use this to bind keyboard event handlers.
|
|
91
|
+
|
|
92
|
+
**RECOMMENDED:** Where a `keyboardIntents` value has a direct semantic equivalent in `intents`,
|
|
93
|
+
both SHOULD be declared. For example, a component with `expand` in `intents` SHOULD also include
|
|
94
|
+
`expand` in `keyboardIntents`. Keyboard-specific intents such as `activate`, `navigate-options`,
|
|
95
|
+
and `navigate-items` have no `intents` counterpart and are keyboard-only.
|
|
96
|
+
|
|
97
|
+
**Canonical keyboard intent vocabulary:**
|
|
98
|
+
|
|
99
|
+
| Value | Default key(s) | Meaning |
|
|
100
|
+
| ------------------ | ----------------------- | ------------------------------------------------------- |
|
|
101
|
+
| `activate` | Enter, Space | Triggers the component's primary action |
|
|
102
|
+
| `expand` | Space, Enter, ArrowDown | Reveals associated content |
|
|
103
|
+
| `collapse` | Escape, ArrowUp | Conceals associated content |
|
|
104
|
+
| `navigate-options` | ArrowUp, ArrowDown | Moves focus through a list of options |
|
|
105
|
+
| `navigate-items` | ArrowLeft, ArrowRight | Moves focus between peer elements (tabs, toolbar items) |
|
|
106
|
+
| `increment` | ArrowUp, ArrowRight | Increases a numeric or ranged value |
|
|
107
|
+
| `decrement` | ArrowDown, ArrowLeft | Decreases a numeric or ranged value |
|
|
108
|
+
| `dismiss` | Escape | Closes or cancels |
|
|
109
|
+
| `select-all` | Ctrl+A | Selects all items in a collection |
|
|
110
|
+
|
|
111
|
+
The "Default key(s)" column is informative. Platform adapters determine actual key bindings; the foundation layer declares intent only.
|
|
112
|
+
|
|
113
|
+
### `wcag`
|
|
114
|
+
|
|
115
|
+
The `wcag` array lists the WCAG 2.x success criteria applicable to this component. Entries are objects with the following fields:
|
|
116
|
+
|
|
117
|
+
| Field | Type | Required | Description |
|
|
118
|
+
| ----------- | ------ | -------- | -------------------------------------------- |
|
|
119
|
+
| `criterion` | string | Yes | WCAG criterion number, e.g. `"1.3.1"` |
|
|
120
|
+
| `level` | string | Yes | Conformance level: `"A"`, `"AA"`, or `"AAA"` |
|
|
121
|
+
| `title` | string | No | Human-readable criterion title |
|
|
122
|
+
|
|
123
|
+
**NORMATIVE:** `criterion` MUST be a valid WCAG 2.x criterion number in
|
|
124
|
+
`"<principle>.<guideline>.<criterion>"` format, where `<principle>` is 1–4 (matching WCAG 2.x
|
|
125
|
+
principles: Perceivable, Operable, Understandable, Robust). `level` MUST be one of `"A"`,
|
|
126
|
+
`"AA"`, or `"AAA"`.
|
|
127
|
+
|
|
128
|
+
Example `wcag` entry:
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{ "criterion": "4.1.2", "level": "A", "title": "Name, Role, Value" }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## State-level accessibility fields
|
|
135
|
+
|
|
136
|
+
State declarations (see [State model](state-model.md)) MAY carry the following additional fields that describe how assistive technology responds to state transitions. These fields extend the base state declaration object defined in `spec/state-model.md`.
|
|
137
|
+
|
|
138
|
+
| Field | Type | Required | Description |
|
|
139
|
+
| ------------------- | ------- | -------- | --------------------------------------------------------- |
|
|
140
|
+
| `announce` | string | No | Screen-reader announcement hint for this state transition |
|
|
141
|
+
| `communicates` | string | No | Semantic meaning conveyed to AT when this state is active |
|
|
142
|
+
| `blocksInteraction` | boolean | No | Whether this state prevents all user interaction |
|
|
143
|
+
|
|
144
|
+
### `announce`
|
|
145
|
+
|
|
146
|
+
A hint string used by platform adapters to populate ARIA live regions or post accessibility notifications when the state is entered. The text is a template hint, not a final user-facing string — platform implementations localize and adapt it.
|
|
147
|
+
|
|
148
|
+
**RECOMMENDED:** Phrasing SHOULD be concise (under 10 words) and describe the transition, not the resulting state. Prefer `"Dialog opened"` over `"The dialog is now open"`.
|
|
149
|
+
|
|
150
|
+
### `communicates`
|
|
151
|
+
|
|
152
|
+
A string describing the semantic state the component is in after the transition. Platform adapters use this to set `aria-*` state attributes or equivalent:
|
|
153
|
+
|
|
154
|
+
| Example value | ARIA equivalent |
|
|
155
|
+
| ------------- | ---------------------- |
|
|
156
|
+
| `"selected"` | `aria-selected="true"` |
|
|
157
|
+
| `"expanded"` | `aria-expanded="true"` |
|
|
158
|
+
| `"checked"` | `aria-checked="true"` |
|
|
159
|
+
| `"invalid"` | `aria-invalid="true"` |
|
|
160
|
+
| `"required"` | `aria-required="true"` |
|
|
161
|
+
| `"busy"` | `aria-busy="true"` |
|
|
162
|
+
| `"pressed"` | `aria-pressed="true"` |
|
|
163
|
+
| `"disabled"` | `aria-disabled="true"` |
|
|
164
|
+
|
|
165
|
+
The ARIA mapping column is informative; the foundation layer declares semantic meaning only.
|
|
166
|
+
|
|
167
|
+
### `blocksInteraction`
|
|
168
|
+
|
|
169
|
+
A boolean declaring whether this state prevents all user interaction with the component.
|
|
170
|
+
|
|
171
|
+
* `true` — the component cannot be interacted with while in this state (e.g., `disabled`, `loading`); platform adapters SHOULD set `aria-disabled` or equivalent.
|
|
172
|
+
* `false` or absent — user interaction is not blocked by this state.
|
|
173
|
+
|
|
174
|
+
## Example
|
|
175
|
+
|
|
176
|
+
A `button` component with a complete accessibility declaration and two states carrying state-level accessibility fields:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"name": "button",
|
|
181
|
+
"displayName": "Button",
|
|
182
|
+
"meta": { "category": "actions", "documentationUrl": "https://spectrum.adobe.com/page/button/" },
|
|
183
|
+
"accessibility": {
|
|
184
|
+
"role": "button",
|
|
185
|
+
"intents": ["trigger"],
|
|
186
|
+
"focusable": true,
|
|
187
|
+
"keyboardIntents": ["activate"],
|
|
188
|
+
"wcag": [
|
|
189
|
+
{ "criterion": "4.1.2", "level": "A", "title": "Name, Role, Value" },
|
|
190
|
+
{ "criterion": "1.4.3", "level": "AA", "title": "Contrast (Minimum)" }
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
"states": [
|
|
194
|
+
{
|
|
195
|
+
"name": "disabled",
|
|
196
|
+
"trigger": { "type": "prop", "prop": "disabled" },
|
|
197
|
+
"announce": "Button disabled",
|
|
198
|
+
"communicates": "disabled",
|
|
199
|
+
"blocksInteraction": true
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
"name": "loading",
|
|
203
|
+
"trigger": { "type": "prop", "prop": "pending" },
|
|
204
|
+
"announce": "Loading",
|
|
205
|
+
"communicates": "busy",
|
|
206
|
+
"blocksInteraction": true
|
|
207
|
+
}
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## SPEC rules
|
|
213
|
+
|
|
214
|
+
| Rule ID | Severity | Name | Assert |
|
|
215
|
+
| -------- | -------- | -------------------------- | -------------------------------------------------------------------------------------- |
|
|
216
|
+
| SPEC-030 | warning | accessibility-empty | When `accessibility` is declared with no fields, the object provides no semantic value |
|
|
217
|
+
| SPEC-031 | warning | accessibility-wcag-missing | When `accessibility` is declared, `wcag` SHOULD list at least one criterion |
|
|
218
|
+
|
|
219
|
+
Both rules are `warning` severity — they do not block validation. Rules are defined in `rules/rules.yaml` and implemented in the SDK in Phase 7.4.
|
package/spec/agent-surface.md
CHANGED
|
@@ -9,7 +9,7 @@ This document defines the **agent-readable surface**: the contract an external A
|
|
|
9
9
|
|
|
10
10
|
The surface targets three consumer shapes:
|
|
11
11
|
|
|
12
|
-
1. **Authoring an external system.** A non-Spectrum design system being constructed inside an AI tool (e.g. a finance-dashboard prototype tool) wants to produce spec-conformant tokens,
|
|
12
|
+
1. **Authoring an external system.** A non-Spectrum design system being constructed inside an AI tool (e.g. a finance-dashboard prototype tool) wants to produce spec-conformant tokens, mode sets, and components without re-deriving the format from prose.
|
|
13
13
|
2. **Extending Spectrum.** A product or platform team adds tokens, components, or overrides on top of the published Spectrum foundation and needs to validate that the additions cascade and resolve correctly.
|
|
14
14
|
3. **Adhering to Spectrum.** A prototyping tool generates UI that should match Spectrum even where no bound component exists (e.g. CSS for a custom card). The agent needs to look up tokens by intent, validate proposed property values against the foundation, and report drift.
|
|
15
15
|
|
|
@@ -27,7 +27,7 @@ The surface targets three consumer shapes:
|
|
|
27
27
|
|
|
28
28
|
| Operation | Reads | Returns | Backed by |
|
|
29
29
|
| -------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
|
|
30
|
-
| `resolve_token` | property +
|
|
30
|
+
| `resolve_token` | property + mode set context | winning token (literal or resolved alias) with file/UUID/specificity | `cascade::resolve` |
|
|
31
31
|
| `query_tokens` | filter expression (see [Query](query.md)) | matching token list | `query::filter` |
|
|
32
32
|
| `validate_usage` | candidate token document or fragment | `ValidationReport` (Layer 1 + Layer 2 diagnostics) | `validate::validate_*` |
|
|
33
33
|
| `describe_component` | component identifier | component contract (anatomy, options, states, tokenBindings); see [#832](https://github.com/adobe/spectrum-design-data/discussions/832) and [Phase 6.7](#describe_component-return-shape) | (Phase 6 contract) |
|
|
@@ -51,7 +51,7 @@ An agent loop benefits from a small, structural overview at session start so tha
|
|
|
51
51
|
| ---------------- | -------------- | ----------------------------------------------------------------- |
|
|
52
52
|
| `specVersion` | string | The spec version the dataset declares (see [Overview](index.md)). |
|
|
53
53
|
| `manifest` | object \| null | Resolved platform manifest, if any (see [Manifest](manifest.md)). |
|
|
54
|
-
| `
|
|
54
|
+
| `modeSets` | array | Declared mode sets with modes and defaults. |
|
|
55
55
|
| `components` | array | Component identifiers exposed by the dataset (post Phase 6). |
|
|
56
56
|
| `taxonomyFields` | array | Active name-object fields and their declared vocabulary. |
|
|
57
57
|
| `tokenCount` | integer | Total tokens in the merged cascade. |
|
|
@@ -130,7 +130,7 @@ The `describe_component` tool returns the component declaration object as stored
|
|
|
130
130
|
|
|
131
131
|
The following sketch shows an agent loop that adheres-to-Spectrum while authoring a non-bound component.
|
|
132
132
|
|
|
133
|
-
1. Agent calls `primer ./spectrum-data` and learns that `colorScheme` and `scale` are the active
|
|
133
|
+
1. Agent calls `primer ./spectrum-data` and learns that `colorScheme` and `scale` are the active mode sets and that `button`, `picker`, and `card` are exposed components.
|
|
134
134
|
2. User asks for a "subtle hover background for a card on dark mode".
|
|
135
135
|
3. Agent calls `suggest_token "subtle hover background for card" --property background-color`.
|
|
136
136
|
4. Surface returns a ranked list including `background-color-hover` from Spectrum foundation and `background-color-card-hover` from a card component group.
|
package/spec/cascade.md
CHANGED
|
@@ -20,9 +20,9 @@ Design data is organized in three layers, ordered from lowest to highest precede
|
|
|
20
20
|
|
|
21
21
|
## Semantic specificity
|
|
22
22
|
|
|
23
|
-
**Specificity** counts how many **non-default**
|
|
23
|
+
**Specificity** counts how many **non-default** mode set fields in the token’s **name object** are set for the mode sets declared in the dataset.
|
|
24
24
|
|
|
25
|
-
**NORMATIVE:** Default
|
|
25
|
+
**NORMATIVE:** Default mode set values (see [Mode Sets](mode-sets.md)) **MUST NOT** contribute to specificity.
|
|
26
26
|
|
|
27
27
|
**NORMATIVE:** When two candidates from the **same layer** match the context, the candidate with **higher** specificity **MUST** win.
|
|
28
28
|
|
|
@@ -35,20 +35,20 @@ Design data is organized in three layers, ordered from lowest to highest precede
|
|
|
35
35
|
|
|
36
36
|
## Context
|
|
37
37
|
|
|
38
|
-
A **resolution context** is a set of
|
|
38
|
+
A **resolution context** is a set of mode set key/value pairs (e.g. `colorScheme: dark`, `scale: medium`, `contrast: regular`) plus the **target layer** being resolved (usually product → platform → foundation).
|
|
39
39
|
|
|
40
40
|
## Resolution algorithm (informative outline)
|
|
41
41
|
|
|
42
42
|
The following outline is **RECOMMENDED** for conforming resolvers:
|
|
43
43
|
|
|
44
|
-
1. Collect all token candidates whose name object **matches** the context (every specified
|
|
44
|
+
1. Collect all token candidates whose name object **matches** the context (every specified mode set in the context equals the name object’s mode set field, or the name object omits that mode set where omission means “matches any” per mode set rules).
|
|
45
45
|
2. Filter to candidates at or below the requested layer.
|
|
46
46
|
3. Select the maximum **layer** precedence.
|
|
47
47
|
4. Within that layer, select the maximum **specificity**.
|
|
48
48
|
5. Break remaining ties by document order (earlier in file wins; lexicographically earlier file path wins across files). Emit SPEC-006 warning.
|
|
49
49
|
6. If the winning candidate is an alias (`$ref`), **resolve the alias chain** to a literal value (see [Alias resolution](#alias-resolution)).
|
|
50
50
|
|
|
51
|
-
Exact matching rules for omitted
|
|
51
|
+
Exact matching rules for omitted mode sets are defined alongside mode set declarations in [Mode Sets](mode-sets.md).
|
|
52
52
|
|
|
53
53
|
## Alias resolution
|
|
54
54
|
|
|
@@ -58,9 +58,9 @@ Exact matching rules for omitted dimensions are defined alongside dimension decl
|
|
|
58
58
|
|
|
59
59
|
**RATIONALE:** Aliases participate in cascade as opaque references — their target values are not examined during specificity calculation or layer comparison. This keeps resolution deterministic and allows aliases to be valid candidates at any specificity level.
|
|
60
60
|
|
|
61
|
-
## Cross-
|
|
61
|
+
## Cross-mode-set overrides
|
|
62
62
|
|
|
63
|
-
**NORMATIVE:** Overrides that combine multiple
|
|
63
|
+
**NORMATIVE:** Overrides that combine multiple mode sets in a way not expressible by a single name object alone **MUST** use **explicit combination tokens** (tokens whose name object sets multiple non-default mode sets) as defined in the dataset; magic merging of unrelated tokens is **NOT** allowed.
|
|
64
64
|
|
|
65
65
|
## References
|
|
66
66
|
|
package/spec/component-format.md
CHANGED
|
@@ -40,6 +40,7 @@ A component declaration **MUST** contain:
|
|
|
40
40
|
| `lifecycle` | object | Version lifecycle metadata — see [Lifecycle](#lifecycle). |
|
|
41
41
|
| `tokenBindings` | array | Tokens this component uses — see [Token bindings](#token-bindings) (Phase 6.7). |
|
|
42
42
|
| `documentBlocks` | array | Typed prose blocks for this component — see [Document blocks](#document-blocks) (Phase 9). |
|
|
43
|
+
| `accessibility` | object | Semantic accessibility vocabulary — see [Accessibility](accessibility.md) (Phase 7). |
|
|
43
44
|
|
|
44
45
|
**NORMATIVE:** No properties beyond those listed above are permitted at the top level of a component declaration. Additional fields **MUST** cause a Layer 1 schema error.
|
|
45
46
|
|
|
@@ -351,6 +352,37 @@ A complete button component declaration:
|
|
|
351
352
|
}
|
|
352
353
|
```
|
|
353
354
|
|
|
355
|
+
## Accessibility
|
|
356
|
+
|
|
357
|
+
**Phase 7.** Component declarations MAY carry an `accessibility` object at the top level. State declarations MAY carry `announce`, `communicates`, and `blocksInteraction` fields. See [spec/accessibility.md](accessibility.md) for the full vocabulary, SPEC rules, and examples.
|
|
358
|
+
|
|
359
|
+
```json
|
|
360
|
+
{
|
|
361
|
+
"name": "button",
|
|
362
|
+
"displayName": "Button",
|
|
363
|
+
"meta": { "category": "actions", "documentationUrl": "https://spectrum.adobe.com/page/button/" },
|
|
364
|
+
"accessibility": {
|
|
365
|
+
"role": "button",
|
|
366
|
+
"intents": ["trigger"],
|
|
367
|
+
"focusable": true,
|
|
368
|
+
"keyboardIntents": ["activate"],
|
|
369
|
+
"wcag": [
|
|
370
|
+
{ "criterion": "4.1.2", "level": "A", "title": "Name, Role, Value" }
|
|
371
|
+
]
|
|
372
|
+
},
|
|
373
|
+
"states": [
|
|
374
|
+
{
|
|
375
|
+
"name": "disabled",
|
|
376
|
+
"trigger": "prop",
|
|
377
|
+
"precedence": 100,
|
|
378
|
+
"announce": "Button disabled",
|
|
379
|
+
"communicates": "disabled",
|
|
380
|
+
"blocksInteraction": true
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
354
386
|
## Document blocks
|
|
355
387
|
|
|
356
388
|
**Phase 9.** Component declarations MAY carry a `documentBlocks` array at the top level, and individual anatomy parts MAY carry their own `documentBlocks` arrays. See [spec/document-blocks.md](document-blocks.md) for the full block schema, type vocabulary, and SPEC rules.
|
package/spec/document-blocks.md
CHANGED
|
@@ -67,7 +67,7 @@ Accessibility notes specific to this entity — contrast behavior, screen reader
|
|
|
67
67
|
```json
|
|
68
68
|
{
|
|
69
69
|
"type": "accessibility",
|
|
70
|
-
"content": "Accent background tokens must maintain a minimum 3:1 contrast ratio against the surface they sit on in both light and dark schemes. The high-contrast
|
|
70
|
+
"content": "Accent background tokens must maintain a minimum 3:1 contrast ratio against the surface they sit on in both light and dark schemes. The high-contrast mode-set variant provides an alternative that meets 4.5:1."
|
|
71
71
|
}
|
|
72
72
|
```
|
|
73
73
|
|