@softspark/ai-toolkit 2.4.1 → 2.5.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.
Files changed (37) hide show
  1. package/AGENTS.md +32 -19
  2. package/CHANGELOG.md +23 -0
  3. package/README.md +11 -11
  4. package/app/.claude-plugin/plugin.json +1 -1
  5. package/app/agents/code-reviewer.md +6 -7
  6. package/app/agents/frontend-specialist.md +33 -2
  7. package/app/agents/seo-specialist.md +1 -1
  8. package/app/personas/frontend-lead.md +48 -5
  9. package/app/skills/a11y-validate/SKILL.md +377 -0
  10. package/app/skills/a11y-validate/reference/aria-patterns.md +259 -0
  11. package/app/skills/a11y-validate/reference/eaa-compliance.md +252 -0
  12. package/app/skills/a11y-validate/reference/mobile-eaa.md +329 -0
  13. package/app/skills/a11y-validate/reference/wcag-2-1-aa.md +285 -0
  14. package/app/skills/a11y-validate/reference/wcag-2-2-aa.md +221 -0
  15. package/app/skills/a11y-validate/scripts/a11y-scanner.py +639 -0
  16. package/app/skills/clean-code/reference/python.md +3 -3
  17. package/app/skills/design-engineering/SKILL.md +2 -5
  18. package/app/skills/review/SKILL.md +30 -6
  19. package/app/skills/seo-validate/SKILL.md +460 -0
  20. package/app/skills/seo-validate/reference/core-web-vitals.md +445 -0
  21. package/app/skills/seo-validate/reference/geo-aeo-patterns.md +259 -0
  22. package/app/skills/seo-validate/reference/geo-guidelines.md +248 -0
  23. package/app/skills/seo-validate/reference/schema-types.md +465 -0
  24. package/app/skills/seo-validate/reference/spa-ssg-patterns.md +351 -0
  25. package/app/skills/seo-validate/reference/w3c-guidelines.md +289 -0
  26. package/app/skills/seo-validate/scripts/seo-scanner.py +549 -0
  27. package/bin/ai-toolkit.js +4 -4
  28. package/kb/reference/architecture-overview.md +1 -1
  29. package/kb/reference/comparison.md +1 -1
  30. package/kb/reference/skills-catalog.md +3 -1
  31. package/llms-full.txt +10 -6
  32. package/manifest.json +3 -3
  33. package/package.json +2 -2
  34. package/scripts/config_cli.py +4 -10
  35. package/scripts/doctor.py +3 -3
  36. package/scripts/install_steps/ai_tools.py +1 -1
  37. package/scripts/plugin.py +1 -1
@@ -0,0 +1,252 @@
1
+ # European Accessibility Act (EAA) — Compliance Reference
2
+
3
+ Reference for `a11y-validate` Category 8e (EAA documentation). Legal framework, enforcement dates, member-state transposition deltas, and accessibility-statement templates.
4
+
5
+ **Not legal advice.** Consult counsel in your target jurisdiction.
6
+
7
+ ## Directive (EU) 2019/882
8
+
9
+ **Full title**: Directive (EU) 2019/882 of the European Parliament and of the Council of 17 April 2019 on the accessibility requirements for products and services.
10
+
11
+ **Common name**: European Accessibility Act (EAA).
12
+
13
+ **Published**: Official Journal of the European Union, 7 June 2019.
14
+
15
+ **Adopted**: 17 April 2019.
16
+
17
+ **Deadline for member-state transposition into national law**: 28 June 2022.
18
+
19
+ **Deadline for business compliance**: **28 June 2025** (products placed on the market after this date; existing contracts up to 28 June 2030; self-service terminals already in use may have until 2045).
20
+
21
+ ## Scope
22
+
23
+ ### Products in scope (Article 2(1))
24
+
25
+ - Consumer general-purpose computer hardware and OS (desktops, laptops, tablets, smartphones).
26
+ - Self-service terminals: ATMs, ticket machines, check-in kiosks, interactive info points.
27
+ - Consumer terminal equipment with interactive computing capability (e.g., smart TVs, set-top boxes).
28
+ - E-readers.
29
+
30
+ ### Services in scope (Article 2(2))
31
+
32
+ - Electronic communications (telephony, VoIP, text messaging).
33
+ - Services providing access to audiovisual media (streaming, VOD).
34
+ - **Elements of passenger transport services** (websites, mobile apps, ticketing, information services, e-tickets).
35
+ - Consumer banking services (online banking, mobile banking apps).
36
+ - E-books and dedicated e-book software.
37
+ - **E-commerce services** (online stores, marketplaces — consumer-facing).
38
+
39
+ ### Out of scope
40
+
41
+ - Microenterprises (<10 employees AND <€2 million annual turnover) providing services. Still apply if selling products.
42
+ - Private websites/apps not providing covered services.
43
+ - B2B-only services.
44
+ - Pre-recorded AV media published before 28 June 2025.
45
+ - Content from third parties not controlled by the service provider.
46
+
47
+ ## Legal Requirements (Chapter III)
48
+
49
+ ### Article 4 — Accessibility requirements
50
+
51
+ Products and services must meet the accessibility requirements in **Annex I** of the directive. Annex I is intentionally functional/outcome-based (e.g., "information must be presentable in more than one sensory modality"). Technical implementation is defined by **harmonized standards** — primarily **EN 301 549 v3.2.1**, which aligns with WCAG 2.1 Level AA.
52
+
53
+ ### Article 13 — Obligations of service providers
54
+
55
+ Service providers must:
56
+ 1. Design and provide services in accordance with accessibility requirements.
57
+ 2. Prepare the necessary information in the form of an **accessibility statement** in the general terms and conditions.
58
+ 3. Preserve this information for as long as the service is in operation.
59
+
60
+ ### Article 14 — Accessibility statement
61
+
62
+ The core documentary obligation. Statements must include:
63
+
64
+ 1. A description of how the service meets the accessibility requirements.
65
+ 2. If the service does not fully comply, the reasons for disproportionate burden or fundamental alteration claims.
66
+ 3. Contact information for accessibility feedback.
67
+ 4. Reference to the enforcement procedure in the user's member state.
68
+
69
+ Statements are typically published at a URL like `/accessibility` or `/accessibility-statement` and linked from the footer of every public page.
70
+
71
+ ### Article 23 — Penalties
72
+
73
+ Member states define penalties. Typical ranges:
74
+
75
+ - **Germany (BFSG)**: up to €100,000 fine per violation; market surveillance authority: Bundesanstalt für Arbeitsschutz und Arbeitsmedizin (BAuA).
76
+ - **France (Loi 2023-171)**: up to €250,000 fine per violation; enforcement: Arcom + DGCCRF.
77
+ - **Italy (Legislative Decree 82/2022)**: fines between €5,000 and 5% of annual turnover; enforcement: AgID.
78
+ - **Spain (Royal Decree 193/2023)**: up to €1,000,000 fine; enforcement: Autoridad Independiente de Control Administrativo.
79
+ - **Netherlands (Uitvoeringswet)**: fines up to €103,000; enforcement: Agentschap Telecom.
80
+ - **Poland (Ustawa o zapewnianiu spełniania wymagań dostępności)**: fines up to 10× monthly average wage (~PLN 75,000); enforcement: Prezes Zarządu PFRON + UOKiK.
81
+
82
+ Beyond fines, regulators can order service withdrawal from the EU market.
83
+
84
+ ## Harmonized Standard: EN 301 549 v3.2.1
85
+
86
+ Full title: "Accessibility requirements for ICT products and services."
87
+
88
+ Published by ETSI (European Telecommunications Standards Institute), CEN, and CENELEC. Current version: **v3.2.1**, March 2021.
89
+
90
+ **Compliance with EN 301 549 is presumed to satisfy the EAA.** Deviations require individual justification.
91
+
92
+ Structure:
93
+
94
+ | Chapter | Scope |
95
+ |---------|-------|
96
+ | 4 | General / generic requirements |
97
+ | 5 | Generic requirements on all ICT |
98
+ | 6 | ICT with two-way voice communication |
99
+ | 7 | ICT with video capabilities |
100
+ | 8 | Hardware |
101
+ | 9 | Web (full WCAG 2.1 AA) |
102
+ | 10 | Non-web documents (PDF, etc.) |
103
+ | 11 | Software (native apps — mobile, desktop) |
104
+ | 12 | Documentation and support services |
105
+ | 13 | ICT providing relay / emergency services |
106
+
107
+ For websites and mobile apps, chapters 9 and 11 are most relevant.
108
+
109
+ ## Timeline
110
+
111
+ | Date | Event |
112
+ |------|-------|
113
+ | 17 April 2019 | Directive adopted |
114
+ | 7 June 2019 | Published in Official Journal |
115
+ | 28 June 2022 | Member-state transposition deadline |
116
+ | **28 June 2025** | **Business compliance deadline — products/services placed on market** |
117
+ | 28 June 2030 | End of transition for existing contracts |
118
+ | 28 June 2045 | Outer limit for self-service terminals in service before 2025 |
119
+
120
+ **If you are selling to EU consumers and reading this after 28 June 2025: you are already required to comply.**
121
+
122
+ ## Accessibility Statement Template
123
+
124
+ Most member states publish an official template. Common structural elements (minimum):
125
+
126
+ ```markdown
127
+ # Accessibility Statement
128
+
129
+ [Organization name] is committed to making [service name / website URL] accessible in accordance with [Directive (EU) 2019/882 / national transposing law, e.g., Loi 2023-171 for France].
130
+
131
+ ## Conformance Status
132
+
133
+ This [website / mobile application] is **[fully | partially | non-]compliant** with [EN 301 549 v3.2.1 / WCAG 2.1 Level AA].
134
+
135
+ [If partially / non-compliant:] The following content is not accessible:
136
+
137
+ - [Non-conformant element 1 — e.g., "PDF invoices from before 2023 lack tagged structure"]
138
+ - [Non-conformant element 2]
139
+
140
+ These non-conformances are due to [disproportionate burden reasoning / third-party content / technology limitations].
141
+
142
+ ## Preparation of This Statement
143
+
144
+ This statement was prepared on [ISO date, e.g., 2025-06-15] and last reviewed on [date].
145
+
146
+ The assessment method was:
147
+ - [self-assessment / third-party audit by <firm>]
148
+ - [manual testing / automated tooling: axe-core, Lighthouse, Pa11y]
149
+ - [assistive technology testing: NVDA, JAWS, VoiceOver, TalkBack]
150
+
151
+ ## Feedback and Contact Information
152
+
153
+ If you encounter any accessibility barriers on [service name], please contact us:
154
+
155
+ - Email: [accessibility@example.com]
156
+ - Phone: [+XX ...]
157
+ - Postal: [address]
158
+
159
+ We aim to respond within [14 days / as per national requirement].
160
+
161
+ ## Enforcement Procedure
162
+
163
+ If you are not satisfied with our response, you may contact the national enforcement body:
164
+
165
+ - [Member state enforcement body name]
166
+ - [URL / phone / email]
167
+
168
+ ## Technical Specifications
169
+
170
+ Accessibility of [service] relies on the following technologies:
171
+
172
+ - HTML5
173
+ - CSS
174
+ - JavaScript
175
+ - [WAI-ARIA 1.2]
176
+ - [PDF/UA for document accessibility]
177
+ ```
178
+
179
+ ## Member-State Enforcement URLs (to cite in statements)
180
+
181
+ Replace placeholders in statement templates with these URLs:
182
+
183
+ | Member state | Enforcement body | URL |
184
+ |---|---|---|
185
+ | Austria | Sozialministeriumservice (BSB) | https://www.sozialministeriumservice.at/ |
186
+ | Belgium | BOSA DG for Digital Transformation | https://bosa.belgium.be/ |
187
+ | Bulgaria | Ministry of Transport and Comms | https://www.mtc.government.bg/ |
188
+ | Croatia | Ministry of Physical Planning | https://mpgi.gov.hr/ |
189
+ | Cyprus | Department for Social Inclusion | http://www.mlsi.gov.cy/ |
190
+ | Czechia | Ministry of Industry and Trade | https://www.mpo.gov.cz/ |
191
+ | Denmark | Digitaliseringsstyrelsen | https://digst.dk/ |
192
+ | Estonia | Riigi Infosüsteemi Amet (RIA) | https://www.ria.ee/ |
193
+ | Finland | Regional State Administrative Agency | https://www.saavutettavuusvaatimukset.fi/ |
194
+ | France | Arcom + DGCCRF | https://www.arcom.fr/ |
195
+ | Germany | BFIT-Bund | https://www.bfit-bund.de/ |
196
+ | Greece | General Secretariat for Digital Governance | https://gov.gr/ |
197
+ | Hungary | Nemzeti Média- és Hírközlési Hatóság (NMHH) | https://nmhh.hu/ |
198
+ | Ireland | National Disability Authority (NDA) | https://nda.ie/ |
199
+ | Italy | AgID | https://www.agid.gov.it/ |
200
+ | Latvia | Ministry of Welfare | https://www.lm.gov.lv/ |
201
+ | Lithuania | Ministry of Social Security | https://socmin.lrv.lt/ |
202
+ | Luxembourg | SIP (Service information et presse) | https://sip.gouvernement.lu/ |
203
+ | Malta | Commission for the Rights of Persons with Disabilities (CRPD) | https://www.crpd.org.mt/ |
204
+ | Netherlands | Agentschap Telecom | https://www.agentschaptelecom.nl/ |
205
+ | Poland | PFRON + UOKiK | https://www.pfron.org.pl/ |
206
+ | Portugal | AMA (Agência para a Modernização Administrativa) | https://www.ama.gov.pt/ |
207
+ | Romania | Autoritatea Națională pentru Drepturile Persoanelor cu Dizabilități | https://andpdca.gov.ro/ |
208
+ | Slovakia | Ministry of Investments, Regional Development and Informatization | https://www.mirri.gov.sk/ |
209
+ | Slovenia | Ministry of Public Administration | https://www.gov.si/ |
210
+ | Spain | Autoridad Independiente de Control Administrativo | https://administracionelectronica.gob.es/ |
211
+ | Sweden | Myndigheten för digital förvaltning (DIGG) | https://www.digg.se/ |
212
+
213
+ ## Common Member-State Route Conventions
214
+
215
+ The skill detects accessibility statements at any of these URL patterns:
216
+
217
+ - `/accessibility` — English (generic)
218
+ - `/accessibility-statement` — English (explicit)
219
+ - `/a11y` — English (shortform)
220
+ - `/dostepnosc` — Polish
221
+ - `/deklaracja-dostepnosci` — Polish (fuller)
222
+ - `/barrierefreiheit` — German
223
+ - `/barrierefreiheitserklaerung` — German (fuller)
224
+ - `/declaration-accessibilite` — French
225
+ - `/declaración-accesibilidad` — Spanish
226
+ - `/dichiarazione-accessibilita` — Italian
227
+ - `/dichiarazione-di-accessibilita` — Italian (fuller)
228
+ - `/toegankelijkheidsverklaring` — Dutch
229
+ - `/tilgangelighetserklaering` — Norwegian (non-EU but adjacent)
230
+ - `/tillganglighetsutlatande` — Swedish
231
+ - `/saavutettavuusseloste` — Finnish
232
+ - `/prohlaseni-o-pristupnosti` — Czech
233
+ - `/vyhlasenie-o-pristupnosti` — Slovak
234
+ - `/nyilatkozat-az-akadalymentesitesrol` — Hungarian
235
+
236
+ ## Accessibility Conformance Report (ACR) / VPAT
237
+
238
+ Beyond the public accessibility statement, many organizations produce a machine-readable or structured **Accessibility Conformance Report** — often using the **VPAT® 2.5 Rev** template (Voluntary Product Accessibility Template) from the Information Technology Industry Council (ITI).
239
+
240
+ VPAT sections for EU markets use the "INT" or "EU" variant, which maps to EN 301 549.
241
+
242
+ VPAT is not legally required under EAA but is common in B2B / procurement contexts.
243
+
244
+ Template: https://www.itic.org/policy/accessibility/vpat
245
+
246
+ ## References
247
+
248
+ - EAA directive (full text): https://eur-lex.europa.eu/eli/dir/2019/882/oj
249
+ - EN 301 549 v3.2.1 (PDF): https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf
250
+ - European Commission EAA page: https://ec.europa.eu/social/main.jsp?catId=1202
251
+ - W3C WAI EAA overview: https://www.w3.org/WAI/policies/european-union/#eaa
252
+ - W3C accessibility statement generator: https://www.w3.org/WAI/planning/statements/generator/
@@ -0,0 +1,329 @@
1
+ # Mobile Accessibility — EN 301 549 & EAA
2
+
3
+ Reference for `a11y-validate` Category 8d. Platform a11y APIs and cross-platform framework patterns (React Native, Flutter).
4
+
5
+ **EAA scope includes consumer mobile apps** (Article 2(2) — electronic communications, banking, e-commerce, transport). EN 301 549 Chapter 11 covers software / native apps.
6
+
7
+ ## Platform APIs
8
+
9
+ ### iOS — UIAccessibility (UIKit/SwiftUI)
10
+
11
+ Core properties on `UIView` / `UIAccessibilityElement`:
12
+
13
+ - `isAccessibilityElement: Bool` — is this an atomic element for VoiceOver?
14
+ - `accessibilityLabel: String?` — concise name.
15
+ - `accessibilityValue: String?` — current value (for sliders, inputs).
16
+ - `accessibilityHint: String?` — what happens on activation.
17
+ - `accessibilityTraits: UIAccessibilityTraits` — button, link, header, selected, adjustable, etc.
18
+ - `accessibilityIdentifier: String?` — for UI testing (not user-facing).
19
+
20
+ SwiftUI modifiers:
21
+ - `.accessibilityLabel(_:)`
22
+ - `.accessibilityValue(_:)`
23
+ - `.accessibilityHint(_:)`
24
+ - `.accessibilityAddTraits(_:)` / `.accessibilityRemoveTraits(_:)`
25
+ - `.accessibilityElement(children:)`
26
+ - `.accessibilityHidden(_:)`
27
+
28
+ ### Android — AccessibilityNodeInfo
29
+
30
+ Core XML attributes:
31
+ - `android:contentDescription` — equivalent to `accessibilityLabel`.
32
+ - `android:labelFor` — for inputs.
33
+ - `android:importantForAccessibility` — yes / no / auto / noHideDescendants.
34
+ - `android:accessibilityHeading` — heading level.
35
+ - `android:screenReaderFocusable` — focusable by TalkBack.
36
+ - `android:accessibilityLiveRegion` — none / polite / assertive.
37
+
38
+ Jetpack Compose modifiers:
39
+ - `Modifier.semantics { contentDescription = "..." }`
40
+ - `Modifier.clearAndSetSemantics { ... }`
41
+ - `Modifier.semantics(mergeDescendants = true) { ... }`
42
+
43
+ ## React Native
44
+
45
+ ```jsx
46
+ import { TouchableOpacity, Pressable, Text, Image, AccessibilityInfo } from 'react-native';
47
+
48
+ // Button equivalent
49
+ <TouchableOpacity
50
+ accessible={true}
51
+ accessibilityRole="button"
52
+ accessibilityLabel="Submit form"
53
+ accessibilityHint="Sends your data for processing"
54
+ accessibilityState={{ disabled: loading, busy: submitting }}
55
+ onPress={handleSubmit}
56
+ >
57
+ <Text>Submit</Text>
58
+ </TouchableOpacity>
59
+
60
+ // Image with a11y
61
+ <Image
62
+ source={require('./photo.jpg')}
63
+ accessible={true}
64
+ accessibilityLabel="Team photo from 2025 conference"
65
+ />
66
+
67
+ // Decorative image — hide from AT
68
+ <Image
69
+ source={require('./decorative-pattern.jpg')}
70
+ accessibilityElementsHidden={true}
71
+ importantForAccessibility="no"
72
+ />
73
+
74
+ // Announce dynamic change
75
+ AccessibilityInfo.announceForAccessibility('Item added to cart');
76
+
77
+ // Check if screen reader is active
78
+ const isEnabled = await AccessibilityInfo.isScreenReaderEnabled();
79
+ ```
80
+
81
+ Common React Native a11y props:
82
+ - `accessible` — whether element is a11y element (default: true for Text, Image, TouchableOpacity).
83
+ - `accessibilityLabel` — required on all interactive elements without visible text.
84
+ - `accessibilityHint` — what happens on activation.
85
+ - `accessibilityRole` — button / link / image / header / adjustable / summary / alert / checkbox / radio / togglebutton / tab / tablist / search / combobox / menu / menuitem / menubar / progressbar / radiogroup / scrollbar / spinbutton / switch / timer / toolbar.
86
+ - `accessibilityState` — `{ disabled, selected, checked, busy, expanded }`.
87
+ - `accessibilityValue` — `{ min, max, now, text }` for sliders/progress.
88
+ - `accessibilityLiveRegion` (Android) / `accessibilityElementsHidden` (iOS) — live updates.
89
+ - `onAccessibilityTap` — alt handler for VoiceOver double-tap.
90
+ - `onMagicTap` — iOS double-tap with two fingers.
91
+
92
+ ### Common RN a11y violations (flagged by Category 8d)
93
+
94
+ ```jsx
95
+ // Bad — no accessibilityLabel
96
+ <TouchableOpacity onPress={close}>
97
+ <Icon name="close" />
98
+ </TouchableOpacity>
99
+
100
+ // Good
101
+ <TouchableOpacity
102
+ onPress={close}
103
+ accessibilityRole="button"
104
+ accessibilityLabel="Close dialog"
105
+ >
106
+ <Icon name="close" accessibilityElementsHidden importantForAccessibility="no" />
107
+ </TouchableOpacity>
108
+ ```
109
+
110
+ ```jsx
111
+ // Bad — decorative image announced by TalkBack
112
+ <Image source={require('./pattern.png')} />
113
+
114
+ // Good
115
+ <Image
116
+ source={require('./pattern.png')}
117
+ accessibilityElementsHidden={true}
118
+ importantForAccessibility="no"
119
+ />
120
+ ```
121
+
122
+ ### Key RN a11y libraries
123
+
124
+ - `@react-native-community/hooks` — `useAccessibilityInfo()`.
125
+ - `react-native-reanimated` — respects `reduceMotion` via `useReducedMotion()`.
126
+ - `@testing-library/react-native` — has `getByRole`, `getByA11yLabel` queries for testing.
127
+
128
+ ### Testing
129
+
130
+ - **iOS**: Xcode Accessibility Inspector (⌥⌘8 in Simulator).
131
+ - **Android**: Accessibility Scanner app + TalkBack.
132
+ - **Automated**: Lighthouse for WebView content; platform-specific tools for native.
133
+
134
+ ## Flutter
135
+
136
+ ```dart
137
+ import 'package:flutter/material.dart';
138
+ import 'package:flutter/semantics.dart';
139
+
140
+ // Button with semantics
141
+ Semantics(
142
+ label: 'Submit form',
143
+ hint: 'Sends your data for processing',
144
+ button: true,
145
+ enabled: !loading,
146
+ child: GestureDetector(
147
+ onTap: handleSubmit,
148
+ child: Container(
149
+ child: Text('Submit'),
150
+ ),
151
+ ),
152
+ )
153
+
154
+ // Simpler for standard widgets — most have built-in semantics
155
+ ElevatedButton(
156
+ onPressed: handleSubmit,
157
+ child: Text('Submit'), // Text becomes accessible name automatically
158
+ )
159
+
160
+ // Icon-only button (needs explicit label)
161
+ IconButton(
162
+ icon: Icon(Icons.close),
163
+ onPressed: close,
164
+ tooltip: 'Close', // Tooltip doubles as accessibility label
165
+ )
166
+
167
+ // Image with a11y
168
+ Image.asset(
169
+ 'assets/team.jpg',
170
+ semanticLabel: 'Team photo from 2025 conference',
171
+ )
172
+
173
+ // Decorative image — exclude from semantics tree
174
+ Image.asset(
175
+ 'assets/pattern.jpg',
176
+ excludeFromSemantics: true,
177
+ )
178
+
179
+ // Announce dynamic change
180
+ SemanticsService.announce('Item added to cart', TextDirection.ltr);
181
+
182
+ // Merge child semantics into one (for grouped interactive elements)
183
+ MergeSemantics(
184
+ child: Row(
185
+ children: [
186
+ Checkbox(value: isChecked, onChanged: setChecked),
187
+ Text('Agree to terms'),
188
+ ],
189
+ ),
190
+ )
191
+
192
+ // Exclude interactive semantics from child
193
+ ExcludeSemantics(
194
+ child: AnimatedIcon(...), // purely decorative
195
+ )
196
+ ```
197
+
198
+ Key Flutter semantic properties:
199
+ - `label` — accessible name.
200
+ - `hint` — action hint.
201
+ - `value` — current value (slider / input).
202
+ - `increasedValue` / `decreasedValue` — for adjustable widgets.
203
+ - `button` / `link` / `header` / `textField` / `checked` / `selected` — role booleans.
204
+ - `enabled` / `focused` / `focusable` — state.
205
+ - `image` — is an image (for decorative vs. informative).
206
+ - `liveRegion` — announce changes.
207
+ - `hidden` — excluded from a11y tree (different from `excludeFromSemantics` which merges up).
208
+
209
+ ### Common Flutter a11y violations (flagged)
210
+
211
+ ```dart
212
+ // Bad — GestureDetector with no semantics
213
+ GestureDetector(
214
+ onTap: close,
215
+ child: Icon(Icons.close),
216
+ )
217
+
218
+ // Good
219
+ Semantics(
220
+ label: 'Close dialog',
221
+ button: true,
222
+ child: GestureDetector(
223
+ onTap: close,
224
+ child: Icon(Icons.close),
225
+ ),
226
+ )
227
+
228
+ // Or use IconButton which has built-in semantics
229
+ IconButton(
230
+ icon: Icon(Icons.close),
231
+ onPressed: close,
232
+ tooltip: 'Close dialog',
233
+ )
234
+ ```
235
+
236
+ ```dart
237
+ // Bad — Image without label
238
+ Image.network('https://example.com/product.jpg')
239
+
240
+ // Good
241
+ Image.network(
242
+ 'https://example.com/product.jpg',
243
+ semanticLabel: 'Red leather handbag, size medium',
244
+ )
245
+ ```
246
+
247
+ ### Flutter a11y testing
248
+
249
+ - `flutter test --tags accessibility` with `SemanticsTester`.
250
+ - `flutter_driver` with `SerializableFinder.bySemanticsLabel(...)`.
251
+ - Accessibility Inspector on iOS simulator / Accessibility Scanner on Android.
252
+
253
+ ## Cross-Platform Patterns
254
+
255
+ ### Reduced motion
256
+
257
+ **React Native**:
258
+ ```jsx
259
+ import { useReducedMotion } from 'react-native-reanimated';
260
+
261
+ const reducedMotion = useReducedMotion();
262
+ const duration = reducedMotion ? 0 : 300;
263
+ ```
264
+
265
+ **Flutter**:
266
+ ```dart
267
+ final reduceMotion = MediaQuery.of(context).disableAnimations;
268
+ final duration = reduceMotion ? Duration.zero : Duration(milliseconds: 300);
269
+ ```
270
+
271
+ ### Font scaling
272
+
273
+ **React Native**: text scales with system font size by default. Set `allowFontScaling={false}` only with explicit reason (often inappropriate — WCAG 1.4.4).
274
+
275
+ **Flutter**: `MediaQuery.of(context).textScaler` (replaces `textScaleFactor` in Flutter 3.16+). Use `Text(..., textScaler: MediaQuery.textScalerOf(context))` explicitly or rely on default inheritance.
276
+
277
+ ### Contrast mode
278
+
279
+ **iOS**: `UIAccessibilityDarkerSystemColorsEnabled` / `accessibilityContrastChanged` notification.
280
+
281
+ **Android**: `AccessibilityManager.isHighTextContrastEnabled()`.
282
+
283
+ **React Native**: `AccessibilityInfo.isHighTextContrastEnabled()` (Android only) / check `useColorScheme()` + manual high-contrast theme.
284
+
285
+ **Flutter**: `MediaQuery.of(context).highContrast`.
286
+
287
+ ### Screen reader detection
288
+
289
+ **React Native**:
290
+ ```jsx
291
+ AccessibilityInfo.isScreenReaderEnabled().then(enabled => { ... });
292
+ AccessibilityInfo.addEventListener('screenReaderChanged', handler);
293
+ ```
294
+
295
+ **Flutter**:
296
+ ```dart
297
+ MediaQuery.of(context).accessibleNavigation // true if TalkBack/VoiceOver active
298
+ ```
299
+
300
+ ## EN 301 549 Mobile Chapter 11 — Key Clauses
301
+
302
+ Maps WCAG criteria to native software context:
303
+
304
+ | Clause | WCAG | Implementation |
305
+ |--------|------|----------------|
306
+ | 11.1.1.1 | 1.1.1 | All non-text content has text alternative |
307
+ | 11.1.2.1 | 1.2.1 | Prerecorded audio/video alternatives |
308
+ | 11.1.2.2 | 1.2.2 | Captions for prerecorded video |
309
+ | 11.1.3.1 | 1.3.1 | Info and relationships via accessibility API |
310
+ | 11.1.3.2 | 1.3.2 | Meaningful sequence exposed to AT |
311
+ | 11.1.4.1 | 1.4.1 | No color-only signalling |
312
+ | 11.1.4.2 | 1.4.2 | Audio control |
313
+ | 11.1.4.3 | 1.4.3 | Contrast minimum (4.5:1) |
314
+ | 11.1.4.4 | 1.4.4 | Text resize to 200% without loss |
315
+ | 11.2.1.1 | 2.1.1 | All functionality keyboard-accessible (external keyboard) |
316
+ | 11.2.1.2 | 2.1.2 | No keyboard trap |
317
+ | 11.2.2.1 | 2.2.1 | Timing adjustable |
318
+ | 11.4.1.1 | 4.1.1 | Parsing (platform UI tree correctness) |
319
+ | 11.4.1.2 | 4.1.2 | Name, role, value exposed to AT |
320
+
321
+ ## References
322
+
323
+ - Apple Accessibility (iOS): https://developer.apple.com/accessibility/ios/
324
+ - Android Accessibility: https://developer.android.com/guide/topics/ui/accessibility
325
+ - React Native A11y API: https://reactnative.dev/docs/accessibility
326
+ - Flutter Semantics: https://api.flutter.dev/flutter/widgets/Semantics-class.html
327
+ - Flutter Accessibility guide: https://docs.flutter.dev/ui/accessibility-and-internationalization/accessibility
328
+ - EN 301 549 v3.2.1: https://www.etsi.org/deliver/etsi_en/301500_301599/301549/03.02.01_60/en_301549v030201p.pdf
329
+ - Mobile a11y best practices (BBC): https://www.bbc.co.uk/accessibility/forproducts/mobile/