@jmruthers/pace-core 0.6.6 → 0.6.7
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +291 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +241 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-7PMH7XN7.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
- package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
- package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
- package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
- package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
- package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
- package/dist/components.d.ts +5 -4
- package/dist/components.js +27 -32
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -17
- package/dist/rbac/index.js +6 -6
- package/dist/theming/runtime.d.ts +14 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +47 -31
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +21 -10
- package/package.json +6 -5
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +284 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +137 -153
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +10 -9
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +5 -5
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +1 -4
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/storage/README.md +1 -1
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -1,604 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
lastUpdated: 2025-11-18T17:00:00+11:00
|
|
3
|
-
version: 0.5.181
|
|
4
|
-
reviewedBy: documentation-standards-audit
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Best Practices: Accessibility
|
|
8
|
-
|
|
9
|
-
> **📚 Best Practices**: Accessibility & WCAG Compliance | [← Back](./README.md) | [Implementation Guides](../implementation-guides/README.md)
|
|
10
|
-
|
|
11
|
-
Accessibility best practices for creating inclusive PACE Core applications that work for all users.
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
**Last Updated**: 2025-02-08 | **Version**: v0.5.65+
|
|
16
|
-
|
|
17
|
-
## Overview
|
|
18
|
-
|
|
19
|
-
PACE Core components are designed with accessibility in mind, following WCAG 2.1 AA standards. This guide helps you build accessible applications using PACE Core components.
|
|
20
|
-
|
|
21
|
-
## Core Principles
|
|
22
|
-
|
|
23
|
-
### Principle 1: Semantic HTML
|
|
24
|
-
|
|
25
|
-
**Why**: Screen readers rely on semantic HTML to understand page structure and content meaning.
|
|
26
|
-
|
|
27
|
-
**Implementation**:
|
|
28
|
-
```tsx
|
|
29
|
-
// ✅ Good - Use semantic HTML
|
|
30
|
-
import { Button } from '@jmruthers/pace-core';
|
|
31
|
-
|
|
32
|
-
function MyComponent() {
|
|
33
|
-
return (
|
|
34
|
-
<main>
|
|
35
|
-
<h1>Page Title</h1>
|
|
36
|
-
<section>
|
|
37
|
-
<h2>Section Title</h2>
|
|
38
|
-
<p>Content here</p>
|
|
39
|
-
</section>
|
|
40
|
-
<Button aria-label="Submit form">Submit</Button>
|
|
41
|
-
</main>
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
**Avoid**:
|
|
47
|
-
```tsx
|
|
48
|
-
// ❌ Bad - Overuse of divs
|
|
49
|
-
<div>
|
|
50
|
-
<div className="title">Page Title</div>
|
|
51
|
-
<div>
|
|
52
|
-
<div className="section">Content</div>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### Principle 2: Keyboard Navigation
|
|
58
|
-
|
|
59
|
-
**Why**: Users who cannot use a mouse or prefer keyboard navigation must be able to access all interactive elements.
|
|
60
|
-
|
|
61
|
-
**Implementation**:
|
|
62
|
-
```tsx
|
|
63
|
-
import { Button, DataTable } from '@jmruthers/pace-core';
|
|
64
|
-
|
|
65
|
-
// PACE Core components handle keyboard navigation automatically
|
|
66
|
-
function AccessibleTable() {
|
|
67
|
-
return (
|
|
68
|
-
<DataTable
|
|
69
|
-
data={data}
|
|
70
|
-
columns={columns}
|
|
71
|
-
features={{
|
|
72
|
-
// Keyboard navigation enabled by default
|
|
73
|
-
pagination: true,
|
|
74
|
-
sorting: true,
|
|
75
|
-
}}
|
|
76
|
-
/>
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### Principle 3: ARIA Labels and Roles
|
|
82
|
-
|
|
83
|
-
**Why**: Provide clear context for screen readers when visible text isn't sufficient.
|
|
84
|
-
|
|
85
|
-
**Implementation**:
|
|
86
|
-
```tsx
|
|
87
|
-
import { Button, Icon } from '@jmruthers/pace-core';
|
|
88
|
-
|
|
89
|
-
function ActionButton({ onDelete }) {
|
|
90
|
-
return (
|
|
91
|
-
<Button
|
|
92
|
-
onClick={onDelete}
|
|
93
|
-
aria-label="Delete user"
|
|
94
|
-
aria-describedby="delete-help-text"
|
|
95
|
-
>
|
|
96
|
-
<Icon name="trash" aria-hidden="true" />
|
|
97
|
-
Delete
|
|
98
|
-
</Button>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
**Avoid**:
|
|
104
|
-
```tsx
|
|
105
|
-
// ❌ Bad - Icon without label
|
|
106
|
-
<Button onClick={onDelete}>
|
|
107
|
-
<Icon name="trash" />
|
|
108
|
-
</Button>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## PACE Core Component Accessibility Features
|
|
112
|
-
|
|
113
|
-
### DataTable Component
|
|
114
|
-
|
|
115
|
-
**Built-in accessibility**:
|
|
116
|
-
- ✅ Keyboard navigation (Tab, Enter, Arrow keys)
|
|
117
|
-
- ✅ ARIA roles and labels
|
|
118
|
-
- ✅ Screen reader announcements
|
|
119
|
-
- ✅ Focus management
|
|
120
|
-
|
|
121
|
-
**Example**:
|
|
122
|
-
```tsx
|
|
123
|
-
import { DataTable } from '@jmruthers/pace-core';
|
|
124
|
-
|
|
125
|
-
function AccessibleDataTable() {
|
|
126
|
-
return (
|
|
127
|
-
<DataTable
|
|
128
|
-
data={data}
|
|
129
|
-
columns={columns}
|
|
130
|
-
aria-label="User data table"
|
|
131
|
-
features={{
|
|
132
|
-
search: true,
|
|
133
|
-
pagination: true,
|
|
134
|
-
}}
|
|
135
|
-
/>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### Button Component
|
|
141
|
-
|
|
142
|
-
**Built-in accessibility**:
|
|
143
|
-
- ✅ Keyboard focusable via native HTML `<button>` element
|
|
144
|
-
- ✅ Native keyboard support: `Enter` and `Space` keys automatically activate buttons (standard browser behavior)
|
|
145
|
-
- ✅ Proper focus indicators via `focus-visible` styles
|
|
146
|
-
- ✅ ARIA attributes support via `React.ButtonHTMLAttributes`
|
|
147
|
-
|
|
148
|
-
**Keyboard Navigation**: The Button component uses native HTML `<button>` elements, which provide automatic keyboard accessibility. When a button is focused, pressing `Enter` or `Space` will trigger the button's `onClick` handler without requiring any custom keyboard event handlers. This is standard browser behavior and works out of the box.
|
|
149
|
-
|
|
150
|
-
**Example**:
|
|
151
|
-
```tsx
|
|
152
|
-
import { Button } from '@jmruthers/pace-core';
|
|
153
|
-
|
|
154
|
-
function AccessibleButton() {
|
|
155
|
-
return (
|
|
156
|
-
<Button
|
|
157
|
-
aria-label="Close dialog"
|
|
158
|
-
aria-describedby="close-help"
|
|
159
|
-
>
|
|
160
|
-
Close
|
|
161
|
-
<span id="close-help" className="sr-only">
|
|
162
|
-
Closes the current dialog
|
|
163
|
-
</span>
|
|
164
|
-
</Button>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Form Components
|
|
170
|
-
|
|
171
|
-
**Built-in accessibility**:
|
|
172
|
-
- ✅ Label associations
|
|
173
|
-
- ✅ Error announcements
|
|
174
|
-
- ✅ Required field indicators
|
|
175
|
-
- ✅ Validation feedback
|
|
176
|
-
|
|
177
|
-
**Example**:
|
|
178
|
-
```tsx
|
|
179
|
-
import { Input, Label, FormError } from '@jmruthers/pace-core';
|
|
180
|
-
|
|
181
|
-
function AccessibleForm() {
|
|
182
|
-
return (
|
|
183
|
-
<form aria-labelledby="form-title">
|
|
184
|
-
<h2 id="form-title">User Information</h2>
|
|
185
|
-
|
|
186
|
-
<div>
|
|
187
|
-
<Label htmlFor="email">Email Address</Label>
|
|
188
|
-
<Input
|
|
189
|
-
id="email"
|
|
190
|
-
type="email"
|
|
191
|
-
required
|
|
192
|
-
aria-required="true"
|
|
193
|
-
aria-describedby="email-error"
|
|
194
|
-
/>
|
|
195
|
-
<FormError id="email-error" role="alert">
|
|
196
|
-
Please enter a valid email
|
|
197
|
-
</FormError>
|
|
198
|
-
</div>
|
|
199
|
-
</form>
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
### Dialog/Modal Components
|
|
205
|
-
|
|
206
|
-
**Built-in accessibility**:
|
|
207
|
-
- ✅ Focus trap management
|
|
208
|
-
- ✅ ESC key support
|
|
209
|
-
- ✅ ARIA roles and properties
|
|
210
|
-
- ✅ Screen reader announcements
|
|
211
|
-
|
|
212
|
-
**Example**:
|
|
213
|
-
```tsx
|
|
214
|
-
import { Dialog, DialogTrigger, DialogContent } from '@jmruthers/pace-core';
|
|
215
|
-
|
|
216
|
-
function AccessibleDialog() {
|
|
217
|
-
return (
|
|
218
|
-
<Dialog>
|
|
219
|
-
<DialogTrigger aria-label="Open user settings">
|
|
220
|
-
Settings
|
|
221
|
-
</DialogTrigger>
|
|
222
|
-
<DialogContent
|
|
223
|
-
aria-labelledby="dialog-title"
|
|
224
|
-
aria-describedby="dialog-description"
|
|
225
|
-
>
|
|
226
|
-
<h2 id="dialog-title">User Settings</h2>
|
|
227
|
-
<p id="dialog-description">
|
|
228
|
-
Configure your account preferences
|
|
229
|
-
</p>
|
|
230
|
-
{/* Dialog content */}
|
|
231
|
-
</DialogContent>
|
|
232
|
-
</Dialog>
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## Common Patterns
|
|
238
|
-
|
|
239
|
-
### Pattern 1: Loading States with Announcements
|
|
240
|
-
|
|
241
|
-
**Use when**: Data is loading asynchronously
|
|
242
|
-
|
|
243
|
-
**Example**:
|
|
244
|
-
```tsx
|
|
245
|
-
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
246
|
-
|
|
247
|
-
function AccessibleUserProfile() {
|
|
248
|
-
const { user, loading, error } = useUnifiedAuth();
|
|
249
|
-
|
|
250
|
-
return (
|
|
251
|
-
<div role="status" aria-live="polite">
|
|
252
|
-
{loading && (
|
|
253
|
-
<div aria-busy="true">
|
|
254
|
-
<span className="sr-only">Loading user data</span>
|
|
255
|
-
Loading...
|
|
256
|
-
</div>
|
|
257
|
-
)}
|
|
258
|
-
{error && (
|
|
259
|
-
<div role="alert">
|
|
260
|
-
<span className="sr-only">Error loading user data</span>
|
|
261
|
-
Error: {error.message}
|
|
262
|
-
</div>
|
|
263
|
-
)}
|
|
264
|
-
{user && (
|
|
265
|
-
<div>
|
|
266
|
-
<h1>Welcome, {user.email}</h1>
|
|
267
|
-
</div>
|
|
268
|
-
)}
|
|
269
|
-
</div>
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### Pattern 2: Skip Links
|
|
275
|
-
|
|
276
|
-
**Use when**: Creating long pages with repetitive navigation
|
|
277
|
-
|
|
278
|
-
**Example**:
|
|
279
|
-
```tsx
|
|
280
|
-
function AccessibleLayout() {
|
|
281
|
-
return (
|
|
282
|
-
<div>
|
|
283
|
-
{/* Skip link */}
|
|
284
|
-
<a href="#main-content" className="skip-link">
|
|
285
|
-
Skip to main content
|
|
286
|
-
</a>
|
|
287
|
-
|
|
288
|
-
<Navigation />
|
|
289
|
-
|
|
290
|
-
<main id="main-content" tabIndex="-1">
|
|
291
|
-
<h1>Main Content</h1>
|
|
292
|
-
</main>
|
|
293
|
-
|
|
294
|
-
<Footer />
|
|
295
|
-
</div>
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### Pattern 3: Focus Management
|
|
301
|
-
|
|
302
|
-
**Use when**: Opening modals or changing page context
|
|
303
|
-
|
|
304
|
-
**Example**:
|
|
305
|
-
```tsx
|
|
306
|
-
import { useEffect, useRef } from 'react';
|
|
307
|
-
import { Dialog, DialogContent } from '@jmruthers/pace-core';
|
|
308
|
-
|
|
309
|
-
function AccessibleDialog({ isOpen, onClose }) {
|
|
310
|
-
const titleRef = useRef<HTMLHeadingElement>(null);
|
|
311
|
-
|
|
312
|
-
useEffect(() => {
|
|
313
|
-
if (isOpen && titleRef.current) {
|
|
314
|
-
// Focus the dialog title when it opens
|
|
315
|
-
titleRef.current.focus();
|
|
316
|
-
}
|
|
317
|
-
}, [isOpen]);
|
|
318
|
-
|
|
319
|
-
return (
|
|
320
|
-
<Dialog isOpen={isOpen} onClose={onClose}>
|
|
321
|
-
<DialogContent
|
|
322
|
-
aria-labelledby="dialog-title"
|
|
323
|
-
role="dialog"
|
|
324
|
-
aria-modal="true"
|
|
325
|
-
>
|
|
326
|
-
<h2 id="dialog-title" ref={titleRef} tabIndex={-1}>
|
|
327
|
-
Important Information
|
|
328
|
-
</h2>
|
|
329
|
-
{/* Dialog content */}
|
|
330
|
-
</DialogContent>
|
|
331
|
-
</Dialog>
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### Pattern 4: Error Messages
|
|
337
|
-
|
|
338
|
-
**Use when**: Form validation errors or error states
|
|
339
|
-
|
|
340
|
-
**Example**:
|
|
341
|
-
```tsx
|
|
342
|
-
import { Input, FormError } from '@jmruthers/pace-core';
|
|
343
|
-
|
|
344
|
-
function AccessibleForm() {
|
|
345
|
-
const [email, setEmail] = useState('');
|
|
346
|
-
const [error, setError] = useState('');
|
|
347
|
-
|
|
348
|
-
return (
|
|
349
|
-
<div>
|
|
350
|
-
<Label htmlFor="email">Email</Label>
|
|
351
|
-
<Input
|
|
352
|
-
id="email"
|
|
353
|
-
type="email"
|
|
354
|
-
value={email}
|
|
355
|
-
onChange={(e) => setEmail(e.target.value)}
|
|
356
|
-
aria-invalid={!!error}
|
|
357
|
-
aria-describedby={error ? "email-error" : undefined}
|
|
358
|
-
/>
|
|
359
|
-
{error && (
|
|
360
|
-
<FormError id="email-error" role="alert">
|
|
361
|
-
{error}
|
|
362
|
-
</FormError>
|
|
363
|
-
)}
|
|
364
|
-
</div>
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
## Advanced Usage
|
|
370
|
-
|
|
371
|
-
### Custom Accessibility Attributes
|
|
372
|
-
|
|
373
|
-
When PACE Core components need additional accessibility attributes:
|
|
374
|
-
|
|
375
|
-
```tsx
|
|
376
|
-
import { Button, DataTable } from '@jmruthers/pace-core';
|
|
377
|
-
|
|
378
|
-
function AdvancedAccessibility() {
|
|
379
|
-
return (
|
|
380
|
-
<>
|
|
381
|
-
{/* Custom ARIA attributes */}
|
|
382
|
-
<Button
|
|
383
|
-
aria-label="Save changes"
|
|
384
|
-
aria-describedby="save-status"
|
|
385
|
-
aria-busy={isSaving}
|
|
386
|
-
>
|
|
387
|
-
Save
|
|
388
|
-
</Button>
|
|
389
|
-
<span id="save-status" className="sr-only">
|
|
390
|
-
{isSaving ? 'Saving' : 'Save'}
|
|
391
|
-
</span>
|
|
392
|
-
|
|
393
|
-
{/* DataTable with custom accessibility */}
|
|
394
|
-
<DataTable
|
|
395
|
-
data={data}
|
|
396
|
-
columns={columns}
|
|
397
|
-
aria-label="User management table"
|
|
398
|
-
aria-describedby="table-description"
|
|
399
|
-
/>
|
|
400
|
-
<p id="table-description" className="sr-only">
|
|
401
|
-
Interactive table for managing users with sorting and filtering
|
|
402
|
-
</p>
|
|
403
|
-
</>
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
### Screen Reader Only Content
|
|
409
|
-
|
|
410
|
-
Use the `.sr-only` class for content that should only be visible to screen readers:
|
|
411
|
-
|
|
412
|
-
```tsx
|
|
413
|
-
function ScreenReaderExample() {
|
|
414
|
-
return (
|
|
415
|
-
<Button aria-label="Download file">
|
|
416
|
-
<Icon name="download" aria-hidden="true" />
|
|
417
|
-
Download
|
|
418
|
-
<span className="sr-only">PDF document</span>
|
|
419
|
-
</Button>
|
|
420
|
-
);
|
|
421
|
-
}
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
### Live Regions for Dynamic Content
|
|
425
|
-
|
|
426
|
-
Use live regions for dynamic content updates:
|
|
427
|
-
|
|
428
|
-
```tsx
|
|
429
|
-
import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
430
|
-
|
|
431
|
-
function LiveRegionExample() {
|
|
432
|
-
const { user } = useUnifiedAuth();
|
|
433
|
-
|
|
434
|
-
return (
|
|
435
|
-
<div role="region" aria-live="polite" aria-label="User status">
|
|
436
|
-
{user && (
|
|
437
|
-
<p>
|
|
438
|
-
Logged in as {user.email}
|
|
439
|
-
</p>
|
|
440
|
-
)}
|
|
441
|
-
</div>
|
|
442
|
-
);
|
|
443
|
-
}
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
## Testing Accessibility
|
|
447
|
-
|
|
448
|
-
### Manual Testing Checklist
|
|
449
|
-
|
|
450
|
-
- [ ] **Keyboard Navigation**: All interactive elements accessible via keyboard
|
|
451
|
-
- [ ] **Focus Indicators**: Visible focus indicators on all interactive elements
|
|
452
|
-
- [ ] **Screen Reader**: Test with screen reader (NVDA, JAWS, VoiceOver)
|
|
453
|
-
- [ ] **Color Contrast**: Meet WCAG AA contrast ratios (4.5:1 for text, 3:1 for UI)
|
|
454
|
-
- [ ] **ARIA Labels**: All icons and images have appropriate labels
|
|
455
|
-
- [ ] **Semantic HTML**: Using proper HTML elements
|
|
456
|
-
- [ ] **Error Messages**: Properly associated with form fields
|
|
457
|
-
|
|
458
|
-
### Automated Testing Tools
|
|
459
|
-
|
|
460
|
-
**Recommended tools**:
|
|
461
|
-
- **axe DevTools**: Browser extension for accessibility testing
|
|
462
|
-
- **WAVE**: Web accessibility evaluation tool
|
|
463
|
-
- **Lighthouse**: Accessibility auditing
|
|
464
|
-
- **Pa11y**: Command-line accessibility testing
|
|
465
|
-
|
|
466
|
-
**Example setup**:
|
|
467
|
-
```bash
|
|
468
|
-
# Install Pa11y
|
|
469
|
-
npm install -g pa11y
|
|
470
|
-
|
|
471
|
-
# Run accessibility tests
|
|
472
|
-
pa11y http://localhost:3000
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
### Color Contrast
|
|
476
|
-
|
|
477
|
-
Ensure text meets contrast requirements:
|
|
478
|
-
|
|
479
|
-
```tsx
|
|
480
|
-
// ✅ Good contrast
|
|
481
|
-
<p className="text-sec-800 bg-sec-50">
|
|
482
|
-
High contrast text
|
|
483
|
-
</p>
|
|
484
|
-
|
|
485
|
-
// ❌ Poor contrast
|
|
486
|
-
<p className="text-sec-300 bg-sec-400">
|
|
487
|
-
Low contrast text (hard to read)
|
|
488
|
-
</p>
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
## Common Issues and Solutions
|
|
492
|
-
|
|
493
|
-
### Issue 1: Missing Focus Indicators
|
|
494
|
-
|
|
495
|
-
**Problem**: Interactive elements don't show visible focus state
|
|
496
|
-
|
|
497
|
-
**Solution**: Use PACE Core components which include focus styles, or add custom focus styles
|
|
498
|
-
|
|
499
|
-
```css
|
|
500
|
-
/* Custom focus styles */
|
|
501
|
-
button:focus-visible {
|
|
502
|
-
outline: 2px solid var(--color-main-600);
|
|
503
|
-
outline-offset: 2px;
|
|
504
|
-
}
|
|
505
|
-
```
|
|
506
|
-
|
|
507
|
-
### Issue 2: Missing Alt Text
|
|
508
|
-
|
|
509
|
-
**Problem**: Images without alt text
|
|
510
|
-
|
|
511
|
-
**Solution**: Always provide meaningful alt text
|
|
512
|
-
|
|
513
|
-
```tsx
|
|
514
|
-
// ✅ Good
|
|
515
|
-
<img src="user-avatar.jpg" alt="User profile picture" />
|
|
516
|
-
|
|
517
|
-
// ❌ Bad
|
|
518
|
-
<img src="user-avatar.jpg" />
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
### Issue 3: Form Labels Not Associated
|
|
522
|
-
|
|
523
|
-
**Problem**: Input fields without associated labels
|
|
524
|
-
|
|
525
|
-
**Solution**: Use proper label associations
|
|
526
|
-
|
|
527
|
-
```tsx
|
|
528
|
-
// ✅ Good
|
|
529
|
-
<Label htmlFor="email">Email</Label>
|
|
530
|
-
<Input id="email" type="email" />
|
|
531
|
-
|
|
532
|
-
// ❌ Bad
|
|
533
|
-
<div>Email</div>
|
|
534
|
-
<Input type="email" />
|
|
535
|
-
```
|
|
536
|
-
|
|
537
|
-
## WCAG Compliance
|
|
538
|
-
|
|
539
|
-
### Level AA Compliance
|
|
540
|
-
|
|
541
|
-
PACE Core components are designed to meet WCAG 2.1 Level AA standards:
|
|
542
|
-
|
|
543
|
-
- ✅ **Perceivable**: All information must be perceivable to users
|
|
544
|
-
- ✅ **Operable**: Interface components must be operable
|
|
545
|
-
- ✅ **Understandable**: Information and UI operation must be understandable
|
|
546
|
-
- ✅ **Robust**: Content must be robust enough to work with assistive technologies
|
|
547
|
-
|
|
548
|
-
### Compliance Checklist
|
|
549
|
-
|
|
550
|
-
- [ ] **Color Contrast**: All text meets 4.5:1 contrast ratio
|
|
551
|
-
- [ ] **Keyboard Access**: All functionality available via keyboard
|
|
552
|
-
- [ ] **Focus Indicators**: Visible focus on all interactive elements
|
|
553
|
-
- [ ] **ARIA Labels**: Proper labels for all icons and images
|
|
554
|
-
- [ ] **Semantic HTML**: Using appropriate HTML elements
|
|
555
|
-
- [ ] **Error Messages**: Properly announced to screen readers
|
|
556
|
-
- [ ] **Live Regions**: Dynamic content properly announced
|
|
557
|
-
|
|
558
|
-
## Related Documentation
|
|
559
|
-
|
|
560
|
-
- [Component API Reference](../api-reference/components.md)
|
|
561
|
-
- [Form Implementation Guide](../implementation-guides/forms.md)
|
|
562
|
-
- [DataTable Guide](../implementation-guides/data-tables.md)
|
|
563
|
-
- [Security Best Practices](./security.md)
|
|
564
|
-
- [Testing Best Practices](./testing.md)
|
|
565
|
-
|
|
566
|
-
## Additional Resources
|
|
567
|
-
|
|
568
|
-
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
|
|
569
|
-
- [ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
|
|
570
|
-
- [WebAIM Resources](https://webaim.org/)
|
|
571
|
-
- [MDN Accessibility Guide](https://developer.mozilla.org/en-US/docs/Web/Accessibility)
|
|
572
|
-
|
|
573
|
-
---
|
|
574
|
-
|
|
575
|
-
**Next Steps**: Review your application's accessibility, implement missing ARIA attributes, and test with screen readers.
|
|
576
|
-
|
|
577
|
-
## ⚠️ Edge Cases
|
|
578
|
-
|
|
579
|
-
### Accessibility vs Performance
|
|
580
|
-
|
|
581
|
-
When accessibility features impact performance:
|
|
582
|
-
- Optimize ARIA live regions to reduce re-renders
|
|
583
|
-
- Use efficient focus management techniques
|
|
584
|
-
- Balance screen reader announcements with performance
|
|
585
|
-
- Test performance with assistive technologies enabled
|
|
586
|
-
- Profile accessibility features for bottlenecks
|
|
587
|
-
|
|
588
|
-
### Complex Accessibility Scenarios
|
|
589
|
-
|
|
590
|
-
When dealing with complex accessibility requirements:
|
|
591
|
-
- Test with multiple screen reader combinations
|
|
592
|
-
- Verify keyboard navigation in complex UIs
|
|
593
|
-
- Ensure focus management in dynamic content
|
|
594
|
-
- Test with different assistive technology configurations
|
|
595
|
-
- Document accessibility patterns for complex components
|
|
596
|
-
|
|
597
|
-
### Third-Party Component Accessibility
|
|
598
|
-
|
|
599
|
-
When using third-party components:
|
|
600
|
-
- Verify third-party components meet accessibility standards
|
|
601
|
-
- Add wrapper components for accessibility improvements
|
|
602
|
-
- Test third-party integrations with assistive technologies
|
|
603
|
-
- Document accessibility limitations
|
|
604
|
-
- Provide alternatives when components aren't accessible
|