@a11ypros/a11y-ui-components 1.0.1 → 1.0.3
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/README.md +182 -157
- package/dist/components/Button/Button.d.ts +37 -0
- package/dist/components/Button/Button.d.ts.map +1 -0
- package/dist/components/Button/Button.js +52 -0
- package/dist/components/Button/index.d.ts +3 -0
- package/dist/components/Button/index.d.ts.map +1 -0
- package/dist/components/Button/index.js +1 -0
- package/dist/components/DataTable/DataTable.d.ts +71 -0
- package/dist/components/DataTable/DataTable.d.ts.map +1 -0
- package/dist/components/DataTable/DataTable.js +122 -0
- package/dist/components/DataTable/index.d.ts +3 -0
- package/dist/components/DataTable/index.d.ts.map +1 -0
- package/dist/components/DataTable/index.js +1 -0
- package/dist/components/Form/Checkbox.d.ts +36 -0
- package/dist/components/Form/Checkbox.d.ts.map +1 -0
- package/dist/components/Form/Checkbox.js +39 -0
- package/dist/components/Form/Fieldset.d.ts +33 -0
- package/dist/components/Form/Fieldset.d.ts.map +1 -0
- package/dist/components/Form/Fieldset.js +34 -0
- package/dist/components/Form/Input.d.ts +37 -0
- package/dist/components/Form/Input.d.ts.map +1 -0
- package/dist/components/Form/Input.js +41 -0
- package/dist/components/Form/Label.d.ts +30 -0
- package/dist/components/Form/Label.d.ts.map +1 -0
- package/dist/components/Form/Label.js +30 -0
- package/dist/components/Form/Radio.d.ts +53 -0
- package/dist/components/Form/Radio.d.ts.map +1 -0
- package/dist/components/Form/Radio.js +39 -0
- package/dist/components/Form/Select.d.ts +51 -0
- package/dist/components/Form/Select.d.ts.map +1 -0
- package/dist/components/Form/Select.js +49 -0
- package/dist/components/Form/Textarea.d.ts +44 -0
- package/dist/components/Form/Textarea.d.ts.map +1 -0
- package/dist/components/Form/Textarea.js +43 -0
- package/dist/components/Form/index.d.ts +8 -0
- package/dist/components/Form/index.d.ts.map +1 -0
- package/dist/components/Form/index.js +7 -0
- package/dist/components/Link/Link.d.ts +34 -0
- package/dist/components/Link/Link.d.ts.map +1 -0
- package/dist/components/Link/Link.js +48 -0
- package/dist/components/Link/index.d.ts +3 -0
- package/dist/components/Link/index.d.ts.map +1 -0
- package/dist/components/Link/index.js +1 -0
- package/dist/components/Modal/Modal.d.ts +64 -0
- package/dist/components/Modal/Modal.d.ts.map +1 -0
- package/dist/components/Modal/Modal.js +108 -0
- package/dist/components/Modal/index.d.ts +3 -0
- package/dist/components/Modal/index.d.ts.map +1 -0
- package/dist/components/Modal/index.js +1 -0
- package/dist/components/Tabs/Tabs.d.ts +63 -0
- package/dist/components/Tabs/Tabs.d.ts.map +1 -0
- package/dist/components/Tabs/Tabs.js +134 -0
- package/dist/components/Tabs/index.d.ts +3 -0
- package/dist/components/Tabs/index.d.ts.map +1 -0
- package/dist/components/Tabs/index.js +1 -0
- package/dist/components/Toast/Toast.d.ts +59 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -0
- package/dist/components/Toast/Toast.js +91 -0
- package/dist/components/Toast/ToastProvider.d.ts +22 -0
- package/dist/components/Toast/ToastProvider.d.ts.map +1 -0
- package/dist/components/Toast/ToastProvider.js +33 -0
- package/dist/components/Toast/index.d.ts +5 -0
- package/dist/components/Toast/index.d.ts.map +1 -0
- package/dist/components/Toast/index.js +2 -0
- package/dist/hooks/useAriaLive.d.ts +9 -0
- package/dist/hooks/useAriaLive.d.ts.map +1 -0
- package/dist/hooks/useAriaLive.js +39 -0
- package/dist/hooks/useFocusReturn.d.ts +9 -0
- package/dist/hooks/useFocusReturn.d.ts.map +1 -0
- package/dist/hooks/useFocusReturn.js +33 -0
- package/dist/hooks/useFocusTrap.d.ts +9 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/hooks/useFocusTrap.js +68 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/{packages/design-system/src/index.ts → dist/index.js} +0 -4
- package/dist/styles/index.d.ts +3 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/styles/index.js +1 -0
- package/dist/tokens/breakpoints.d.ts +25 -0
- package/dist/tokens/breakpoints.d.ts.map +1 -0
- package/dist/tokens/breakpoints.js +23 -0
- package/dist/tokens/colors.d.ts +81 -0
- package/dist/tokens/colors.d.ts.map +1 -0
- package/dist/tokens/colors.js +86 -0
- package/dist/tokens/index.d.ts +6 -0
- package/dist/tokens/index.d.ts.map +1 -0
- package/dist/tokens/index.js +5 -0
- package/dist/tokens/motion.d.ts +30 -0
- package/dist/tokens/motion.d.ts.map +1 -0
- package/dist/tokens/motion.js +34 -0
- package/dist/tokens/spacing.d.ts +22 -0
- package/dist/tokens/spacing.d.ts.map +1 -0
- package/dist/tokens/spacing.js +20 -0
- package/dist/tokens/theme.d.ts +159 -0
- package/dist/tokens/theme.d.ts.map +1 -0
- package/dist/tokens/theme.js +15 -0
- package/dist/tokens/typography.d.ts +45 -0
- package/dist/tokens/typography.d.ts.map +1 -0
- package/dist/tokens/typography.js +56 -0
- package/dist/utils/aria.d.ts +60 -0
- package/dist/utils/aria.d.ts.map +1 -0
- package/dist/utils/aria.js +86 -0
- package/dist/utils/focus.d.ts +30 -0
- package/dist/utils/focus.d.ts.map +1 -0
- package/dist/utils/focus.js +80 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/keyboard.d.ts +38 -0
- package/dist/utils/keyboard.d.ts.map +1 -0
- package/dist/utils/keyboard.js +59 -0
- package/package.json +49 -31
- package/.storybook/custom.css +0 -69
- package/.storybook/main.ts +0 -46
- package/.storybook/manager.ts +0 -26
- package/.storybook/package.json +0 -6
- package/.storybook/preview.tsx +0 -31
- package/.storybook/public/logo.png +0 -0
- package/.storybook/vite.config.ts +0 -24
- package/.storybook/welcome.mdx +0 -97
- package/DEPLOYMENT.md +0 -154
- package/apps/web/app/(docs)/audit/audit.css +0 -269
- package/apps/web/app/(docs)/audit/page.tsx +0 -271
- package/apps/web/app/(docs)/components/button/page.tsx +0 -49
- package/apps/web/app/(docs)/components/form/page.tsx +0 -92
- package/apps/web/app/(docs)/components/link/page.tsx +0 -31
- package/apps/web/app/(docs)/components/modal/page.tsx +0 -41
- package/apps/web/app/(docs)/components/page.tsx +0 -37
- package/apps/web/app/(docs)/components/table/page.tsx +0 -54
- package/apps/web/app/(docs)/components/tabs/page.tsx +0 -61
- package/apps/web/app/(docs)/components/toast/page.tsx +0 -51
- package/apps/web/app/api/audit/route.ts +0 -128
- package/apps/web/app/favicon.ico +0 -0
- package/apps/web/app/layout.tsx +0 -20
- package/apps/web/app/page.tsx +0 -17
- package/apps/web/app/styles/globals.css +0 -5
- package/apps/web/next-env.d.ts +0 -5
- package/apps/web/next.config.js +0 -21
- package/apps/web/package.json +0 -28
- package/apps/web/public/_headers +0 -17
- package/apps/web/public/_redirects +0 -31
- package/apps/web/public/logo.png +0 -0
- package/apps/web/tsconfig.json +0 -29
- package/netlify/functions/audit.ts +0 -163
- package/netlify.toml +0 -37
- package/packages/design-system/README.md +0 -252
- package/packages/design-system/package.json +0 -68
- package/packages/design-system/scripts/copy-css.js +0 -63
- package/packages/design-system/src/components/Button/Button.stories.tsx +0 -228
- package/packages/design-system/src/components/Button/Button.tsx +0 -137
- package/packages/design-system/src/components/Button/index.ts +0 -3
- package/packages/design-system/src/components/DataTable/DataTable.stories.tsx +0 -211
- package/packages/design-system/src/components/DataTable/DataTable.tsx +0 -293
- package/packages/design-system/src/components/DataTable/index.ts +0 -3
- package/packages/design-system/src/components/Form/Checkbox.stories.tsx +0 -252
- package/packages/design-system/src/components/Form/Checkbox.tsx +0 -114
- package/packages/design-system/src/components/Form/Fieldset.stories.tsx +0 -210
- package/packages/design-system/src/components/Form/Fieldset.tsx +0 -71
- package/packages/design-system/src/components/Form/Input.stories.tsx +0 -164
- package/packages/design-system/src/components/Form/Input.tsx +0 -113
- package/packages/design-system/src/components/Form/Label.tsx +0 -56
- package/packages/design-system/src/components/Form/Radio.stories.tsx +0 -265
- package/packages/design-system/src/components/Form/Radio.tsx +0 -147
- package/packages/design-system/src/components/Form/Select.stories.tsx +0 -295
- package/packages/design-system/src/components/Form/Select.tsx +0 -160
- package/packages/design-system/src/components/Form/Textarea.stories.tsx +0 -253
- package/packages/design-system/src/components/Form/Textarea.tsx +0 -145
- package/packages/design-system/src/components/Form/index.ts +0 -8
- package/packages/design-system/src/components/Link/Link.stories.tsx +0 -128
- package/packages/design-system/src/components/Link/Link.tsx +0 -117
- package/packages/design-system/src/components/Link/index.ts +0 -3
- package/packages/design-system/src/components/Modal/Modal.stories.tsx +0 -165
- package/packages/design-system/src/components/Modal/Modal.tsx +0 -202
- package/packages/design-system/src/components/Modal/index.ts +0 -3
- package/packages/design-system/src/components/Tabs/Tabs.stories.tsx +0 -213
- package/packages/design-system/src/components/Tabs/Tabs.tsx +0 -248
- package/packages/design-system/src/components/Tabs/index.ts +0 -3
- package/packages/design-system/src/components/Toast/Toast.stories.tsx +0 -153
- package/packages/design-system/src/components/Toast/Toast.tsx +0 -175
- package/packages/design-system/src/components/Toast/ToastProvider.tsx +0 -73
- package/packages/design-system/src/components/Toast/index.ts +0 -5
- package/packages/design-system/src/hooks/useAriaLive.ts +0 -51
- package/packages/design-system/src/hooks/useFocusReturn.ts +0 -40
- package/packages/design-system/src/hooks/useFocusTrap.ts +0 -82
- package/packages/design-system/src/styles/index.ts +0 -3
- package/packages/design-system/src/tokens/breakpoints.ts +0 -28
- package/packages/design-system/src/tokens/colors.ts +0 -98
- package/packages/design-system/src/tokens/index.ts +0 -6
- package/packages/design-system/src/tokens/motion.ts +0 -41
- package/packages/design-system/src/tokens/spacing.ts +0 -24
- package/packages/design-system/src/tokens/theme.ts +0 -19
- package/packages/design-system/src/tokens/typography.ts +0 -64
- package/packages/design-system/src/utils/aria.ts +0 -108
- package/packages/design-system/src/utils/focus.ts +0 -87
- package/packages/design-system/src/utils/index.ts +0 -4
- package/packages/design-system/src/utils/keyboard.ts +0 -77
- package/packages/design-system/tsconfig.json +0 -17
- package/public/logo.png +0 -0
- package/scripts/fix-storybook-paths.js +0 -53
- package/tsconfig.json +0 -20
- /package/{packages/design-system/src → dist}/components/Button/Button.css +0 -0
- /package/{packages/design-system/src → dist}/components/DataTable/DataTable.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Checkbox.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Fieldset.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Input.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Label.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Radio.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Select.css +0 -0
- /package/{packages/design-system/src → dist}/components/Form/Textarea.css +0 -0
- /package/{packages/design-system/src → dist}/components/Link/Link.css +0 -0
- /package/{packages/design-system/src → dist}/components/Modal/Modal.css +0 -0
- /package/{packages/design-system/src → dist}/components/Tabs/Tabs.css +0 -0
- /package/{packages/design-system/src → dist}/components/Toast/Toast.css +0 -0
- /package/{packages/design-system/src → dist}/components/Toast/ToastProvider.css +0 -0
- /package/{packages/design-system/src → dist}/styles/components.css +0 -0
- /package/{packages/design-system/src → dist}/styles/global.css +0 -0
package/README.md
CHANGED
|
@@ -1,227 +1,252 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @a11ypros/a11y-ui-components
|
|
2
2
|
|
|
3
|
-
An
|
|
3
|
+
An accessibility-first React UI component library built with WCAG 2.1/2.2 Level AA compliance. Every component has been carefully crafted by a certified WAS (Web Accessibility Specialist) to ensure your applications are usable by everyone, regardless of their abilities or the assistive technologies they use.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- **WCAG 2.1/2.2 Compliant
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **AI Audit Assistant**: Paste JSX code and get WCAG compliance reviews with code suggestions
|
|
7
|
+
- ✅ **WCAG 2.1/2.2 Level AA Compliant** - Built with accessibility as a core requirement
|
|
8
|
+
- ✅ **TypeScript** - Full TypeScript support with type definitions included
|
|
9
|
+
- ✅ **Tree-shakeable** - ES modules with side-effect-free exports for optimal bundle sizes
|
|
10
|
+
- ✅ **Keyboard Navigation** - Full keyboard support for all interactive components
|
|
11
|
+
- ✅ **Screen Reader Friendly** - Proper ARIA labels and semantic HTML
|
|
12
|
+
- ✅ **Focus Management** - Built-in focus trap and focus return utilities
|
|
13
|
+
- ✅ **Modern React** - Built for React 18+ with hooks and modern patterns
|
|
15
14
|
|
|
16
|
-
##
|
|
15
|
+
## Installation
|
|
17
16
|
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
│ └── design-system/ # Component library
|
|
21
|
-
│ ├── src/
|
|
22
|
-
│ │ ├── components/ # React components
|
|
23
|
-
│ │ ├── tokens/ # Design tokens
|
|
24
|
-
│ │ ├── hooks/ # Custom hooks
|
|
25
|
-
│ │ ├── utils/ # Utility functions
|
|
26
|
-
│ │ └── styles/ # Global styles
|
|
27
|
-
│ └── package.json
|
|
28
|
-
├── apps/
|
|
29
|
-
│ └── web/ # Next.js app
|
|
30
|
-
│ ├── app/
|
|
31
|
-
│ │ ├── (docs)/ # Documentation pages
|
|
32
|
-
│ │ └── api/ # API routes
|
|
33
|
-
│ └── package.json
|
|
34
|
-
├── .storybook/ # Storybook configuration
|
|
35
|
-
└── package.json # Root workspace config
|
|
17
|
+
```bash
|
|
18
|
+
npm install @a11ypros/a11y-ui-components
|
|
36
19
|
```
|
|
37
20
|
|
|
38
|
-
|
|
21
|
+
or
|
|
39
22
|
|
|
40
|
-
|
|
23
|
+
```bash
|
|
24
|
+
yarn add @a11ypros/a11y-ui-components
|
|
25
|
+
```
|
|
41
26
|
|
|
42
|
-
|
|
43
|
-
- npm or pnpm
|
|
27
|
+
## Peer Dependencies
|
|
44
28
|
|
|
45
|
-
|
|
29
|
+
This package requires React 18+ and React DOM 18+:
|
|
46
30
|
|
|
47
|
-
1. Clone the repository:
|
|
48
31
|
```bash
|
|
49
|
-
|
|
50
|
-
cd PORTFOLIO
|
|
32
|
+
npm install react react-dom
|
|
51
33
|
```
|
|
52
34
|
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
npm install
|
|
56
|
-
```
|
|
35
|
+
## Quick Start
|
|
57
36
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
37
|
+
### 1. Import CSS
|
|
38
|
+
|
|
39
|
+
Import the global styles in your application entry point:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
// In your main CSS file or entry point
|
|
43
|
+
import '@a11ypros/a11y-ui-components/styles';
|
|
62
44
|
```
|
|
63
45
|
|
|
64
|
-
|
|
46
|
+
Or import component-specific styles:
|
|
65
47
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
npm run dev
|
|
48
|
+
```tsx
|
|
49
|
+
import '@a11ypros/a11y-ui-components/styles/components';
|
|
69
50
|
```
|
|
70
51
|
|
|
71
|
-
2.
|
|
72
|
-
|
|
73
|
-
|
|
52
|
+
### 2. Import and Use Components
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { Button, Input, Modal } from '@a11ypros/a11y-ui-components';
|
|
56
|
+
|
|
57
|
+
function App() {
|
|
58
|
+
return (
|
|
59
|
+
<div>
|
|
60
|
+
<Button>Click me</Button>
|
|
61
|
+
<Input label="Email" type="email" />
|
|
62
|
+
<Modal isOpen={true} onClose={() => {}}>
|
|
63
|
+
<p>Modal content</p>
|
|
64
|
+
</Modal>
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
74
68
|
```
|
|
75
69
|
|
|
76
|
-
|
|
70
|
+
## Available Components
|
|
71
|
+
|
|
72
|
+
### Form Components
|
|
73
|
+
- **Input** - Accessible text input with label and error handling
|
|
74
|
+
- **Textarea** - Multi-line text input
|
|
75
|
+
- **Select** - Dropdown select with keyboard navigation
|
|
76
|
+
- **Checkbox** - Accessible checkbox with proper labeling
|
|
77
|
+
- **Radio** - Radio button group with fieldset support
|
|
78
|
+
- **Label** - Accessible form label component
|
|
79
|
+
- **Fieldset** - Form fieldset for grouping related inputs
|
|
80
|
+
|
|
81
|
+
### UI Components
|
|
82
|
+
- **Button** - Accessible button with multiple variants
|
|
83
|
+
- **Link** - Accessible link component
|
|
84
|
+
- **Modal** - Accessible modal dialog with focus trap
|
|
85
|
+
- **Tabs** - Keyboard-navigable tab component
|
|
86
|
+
- **DataTable** - Accessible data table with sorting
|
|
87
|
+
- **Toast** - Accessible toast notification system
|
|
88
|
+
- **ToastProvider** - Context provider for toast notifications
|
|
89
|
+
|
|
90
|
+
### Hooks
|
|
91
|
+
- **useFocusTrap** - Trap focus within a container
|
|
92
|
+
- **useFocusReturn** - Return focus to previous element
|
|
93
|
+
- **useAriaLive** - Manage ARIA live regions for announcements
|
|
77
94
|
|
|
78
|
-
|
|
95
|
+
### Utilities
|
|
96
|
+
- **aria** - ARIA attribute utilities
|
|
97
|
+
- **keyboard** - Keyboard event utilities
|
|
98
|
+
- **focus** - Focus management utilities
|
|
79
99
|
|
|
80
|
-
###
|
|
100
|
+
### Design Tokens
|
|
101
|
+
- **colors** - Color palette and theme tokens
|
|
102
|
+
- **typography** - Typography scale and font tokens
|
|
103
|
+
- **spacing** - Spacing scale tokens
|
|
104
|
+
- **breakpoints** - Responsive breakpoint tokens
|
|
105
|
+
- **motion** - Animation and transition tokens
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
- **Link**: Semantic link component with external link detection
|
|
84
|
-
- **Modal**: Focus-trapped modal dialog with ARIA support
|
|
85
|
-
- **DataTable**: Accessible table with keyboard navigation and sorting
|
|
86
|
-
- **Toast**: Notification system with ARIA live regions
|
|
87
|
-
- **Tabs**: Tab component with arrow key navigation
|
|
88
|
-
- **Form Components**: Input, Textarea, Select, Checkbox, Radio, Fieldset, Label
|
|
107
|
+
## Documentation
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
📚 **[View Full Documentation & Storybook](https://ui.a11ypros.com/storybook)**
|
|
110
|
+
|
|
111
|
+
Browse all components, see live examples, and explore accessibility features in our interactive Storybook documentation.
|
|
112
|
+
|
|
113
|
+
## Usage Examples
|
|
114
|
+
|
|
115
|
+
### Form with Validation
|
|
91
116
|
|
|
92
117
|
```tsx
|
|
93
|
-
import {
|
|
118
|
+
import { Input, Button, Label } from '@a11ypros/a11y-ui-components';
|
|
119
|
+
|
|
120
|
+
function LoginForm() {
|
|
121
|
+
const [email, setEmail] = useState('');
|
|
122
|
+
const [error, setError] = useState('');
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<form>
|
|
126
|
+
<Input
|
|
127
|
+
label="Email"
|
|
128
|
+
type="email"
|
|
129
|
+
value={email}
|
|
130
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
131
|
+
error={error}
|
|
132
|
+
required
|
|
133
|
+
/>
|
|
134
|
+
<Button type="submit">Sign In</Button>
|
|
135
|
+
</form>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Modal Dialog
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { Modal, Button } from '@a11ypros/a11y-ui-components';
|
|
144
|
+
import { useState } from 'react';
|
|
145
|
+
|
|
146
|
+
function App() {
|
|
147
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
94
148
|
|
|
95
|
-
function MyComponent() {
|
|
96
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
97
|
-
|
|
98
149
|
return (
|
|
99
150
|
<>
|
|
100
|
-
<Button
|
|
101
|
-
Open Modal
|
|
102
|
-
</Button>
|
|
103
|
-
|
|
151
|
+
<Button onClick={() => setIsOpen(true)}>Open Modal</Button>
|
|
104
152
|
<Modal
|
|
105
153
|
isOpen={isOpen}
|
|
106
154
|
onClose={() => setIsOpen(false)}
|
|
107
|
-
title="
|
|
155
|
+
title="Confirm Action"
|
|
108
156
|
>
|
|
109
|
-
<
|
|
157
|
+
<p>Are you sure you want to proceed?</p>
|
|
158
|
+
<Button onClick={() => setIsOpen(false)}>Confirm</Button>
|
|
110
159
|
</Modal>
|
|
111
160
|
</>
|
|
112
|
-
)
|
|
161
|
+
);
|
|
113
162
|
}
|
|
114
163
|
```
|
|
115
164
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Each component documents its WCAG 2.1/2.2 compliance:
|
|
119
|
-
|
|
120
|
-
- **1.3.1** Info and Relationships (semantic HTML)
|
|
121
|
-
- **1.4.3** Contrast (Minimum) - via design tokens
|
|
122
|
-
- **2.1.1** Keyboard (all interactive elements)
|
|
123
|
-
- **2.4.7** Focus Visible
|
|
124
|
-
- **2.5.3** Label in Name
|
|
125
|
-
- **4.1.2** Name, Role, Value (ARIA)
|
|
126
|
-
- **4.1.3** Status Messages (for Toast)
|
|
165
|
+
### Toast Notifications
|
|
127
166
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
The AI Audit Assistant analyzes JSX code snippets for accessibility issues:
|
|
167
|
+
```tsx
|
|
168
|
+
import { ToastProvider, useToast, Button } from '@a11ypros/a11y-ui-components';
|
|
131
169
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
170
|
+
function App() {
|
|
171
|
+
return (
|
|
172
|
+
<ToastProvider>
|
|
173
|
+
<MyComponent />
|
|
174
|
+
</ToastProvider>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
137
177
|
|
|
138
|
-
|
|
178
|
+
function MyComponent() {
|
|
179
|
+
const { addToast } = useToast();
|
|
139
180
|
|
|
140
|
-
|
|
181
|
+
return (
|
|
182
|
+
<Button
|
|
183
|
+
onClick={() =>
|
|
184
|
+
addToast({
|
|
185
|
+
message: 'Action completed successfully!',
|
|
186
|
+
type: 'success',
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
>
|
|
190
|
+
Show Toast
|
|
191
|
+
</Button>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
```
|
|
141
195
|
|
|
142
|
-
|
|
143
|
-
2. Add it to `apps/web/.env.local`:
|
|
144
|
-
```
|
|
145
|
-
ANTHROPIC_API_KEY=your_key_here
|
|
146
|
-
```
|
|
196
|
+
## Important Note on Accessibility
|
|
147
197
|
|
|
148
|
-
|
|
198
|
+
> **Note**: While these components are built with accessibility in mind and meet WCAG 2.1/2.2 Level AA standards, **simply using these components does not guarantee an accessible application**. These components are foundational building blocks that must be used properly within the larger consuming application with accessibility in mind.
|
|
149
199
|
|
|
150
|
-
|
|
200
|
+
To ensure your application is truly accessible, consider:
|
|
151
201
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
202
|
+
- **Proper Implementation**: Use components according to their documented patterns and accessibility guidelines
|
|
203
|
+
- **Application-Level Considerations**: Ensure proper page structure, heading hierarchy, and landmark regions
|
|
204
|
+
- **Content Accessibility**: Write clear, descriptive text and provide alternative text for images
|
|
205
|
+
- **Testing**: Regularly test your application with keyboard navigation and screen readers
|
|
206
|
+
- **User Experience**: Consider the full user journey and how components work together
|
|
156
207
|
|
|
157
|
-
|
|
158
|
-
--spacing-4: 1rem;
|
|
208
|
+
## Internationalization (i18n)
|
|
159
209
|
|
|
160
|
-
|
|
161
|
-
--font-size-base: 1rem;
|
|
162
|
-
--font-weight-semibold: 600;
|
|
210
|
+
Currently, all screen reader text and ARIA labels are provided in English. Full i18n support is a high-priority feature coming soon to ensure global accessibility.
|
|
163
211
|
|
|
164
|
-
|
|
165
|
-
--motion-duration-normal: 200ms;
|
|
166
|
-
```
|
|
212
|
+
## Tree Shaking
|
|
167
213
|
|
|
168
|
-
|
|
214
|
+
This package is fully tree-shakeable. Import only what you need:
|
|
169
215
|
|
|
170
|
-
|
|
216
|
+
```tsx
|
|
217
|
+
// ✅ Good - tree-shakeable
|
|
218
|
+
import { Button } from '@a11ypros/a11y-ui-components';
|
|
171
219
|
|
|
172
|
-
|
|
173
|
-
|
|
220
|
+
// ✅ Also good - import specific utilities
|
|
221
|
+
import { useFocusTrap } from '@a11ypros/a11y-ui-components';
|
|
174
222
|
```
|
|
175
223
|
|
|
176
|
-
|
|
177
|
-
- Usage examples
|
|
178
|
-
- Accessibility notes
|
|
179
|
-
- Keyboard interaction tables
|
|
180
|
-
- WCAG compliance information
|
|
224
|
+
## TypeScript Support
|
|
181
225
|
|
|
182
|
-
|
|
226
|
+
Full TypeScript definitions are included. No need to install `@types` packages.
|
|
183
227
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
npm run build
|
|
187
|
-
```
|
|
228
|
+
```tsx
|
|
229
|
+
import { Button, ButtonProps } from '@a11ypros/a11y-ui-components';
|
|
188
230
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
231
|
+
const props: ButtonProps = {
|
|
232
|
+
variant: 'primary',
|
|
233
|
+
size: 'medium',
|
|
234
|
+
children: 'Click me',
|
|
235
|
+
};
|
|
192
236
|
```
|
|
193
237
|
|
|
194
|
-
## Testing Accessibility
|
|
195
|
-
|
|
196
|
-
### Automated Testing
|
|
197
|
-
|
|
198
|
-
Storybook includes the `@storybook/addon-a11y` addon for automated accessibility checks.
|
|
199
|
-
|
|
200
|
-
### Manual Testing
|
|
201
|
-
|
|
202
|
-
1. **Keyboard Navigation**: Test all components with keyboard only (Tab, Arrow keys, Enter/Space)
|
|
203
|
-
2. **Screen Reader**: Test with NVDA (Windows), VoiceOver (macOS), or JAWS
|
|
204
|
-
3. **Focus Indicators**: Ensure all interactive elements have visible focus styles
|
|
205
|
-
4. **Color Contrast**: Verify text meets WCAG AA contrast ratios (4.5:1)
|
|
206
|
-
|
|
207
238
|
## Contributing
|
|
208
239
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
1. Follow the existing component structure
|
|
212
|
-
2. Include proper ARIA attributes
|
|
213
|
-
3. Add keyboard navigation support
|
|
214
|
-
4. Include focus management
|
|
215
|
-
5. Add Storybook stories with accessibility documentation
|
|
216
|
-
6. Test with keyboard and screen readers
|
|
240
|
+
Contributions are welcome! Please see our [GitHub repository](https://github.com/ryan0122/a11ypros-components) for contribution guidelines.
|
|
217
241
|
|
|
218
242
|
## License
|
|
219
243
|
|
|
220
|
-
MIT
|
|
244
|
+
MIT © [A11y Pros](https://a11ypros.com)
|
|
221
245
|
|
|
222
|
-
##
|
|
246
|
+
## Links
|
|
223
247
|
|
|
224
|
-
- [
|
|
225
|
-
- [
|
|
226
|
-
- [
|
|
248
|
+
- 📦 [npm package](https://www.npmjs.com/package/@a11ypros/a11y-ui-components)
|
|
249
|
+
- 📚 [Documentation & Storybook](https://ui.a11ypros.com/storybook)
|
|
250
|
+
- 🐛 [Issue Tracker](https://github.com/ryan0122/a11ypros-components/issues)
|
|
251
|
+
- 💻 [Source Code](https://github.com/ryan0122/a11ypros-components)
|
|
227
252
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './Button.css';
|
|
3
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
4
|
+
/**
|
|
5
|
+
* Visual variant of the button
|
|
6
|
+
*/
|
|
7
|
+
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
|
|
8
|
+
/**
|
|
9
|
+
* Size of the button
|
|
10
|
+
*/
|
|
11
|
+
size?: 'sm' | 'md' | 'lg';
|
|
12
|
+
/**
|
|
13
|
+
* Whether the button is in a loading state
|
|
14
|
+
*/
|
|
15
|
+
loading?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* ARIA label for the button (required if no visible text)
|
|
18
|
+
*/
|
|
19
|
+
'aria-label'?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Accessible Button component
|
|
23
|
+
*
|
|
24
|
+
* WCAG Compliance:
|
|
25
|
+
* - 2.1.1 Keyboard: Full keyboard support (Enter/Space)
|
|
26
|
+
* - 2.4.7 Focus Visible: Clear focus indicators
|
|
27
|
+
* - 4.1.2 Name, Role, Value: Proper ARIA attributes
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```tsx
|
|
31
|
+
* <Button variant="primary" onClick={handleClick}>
|
|
32
|
+
* Click me
|
|
33
|
+
* </Button>
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAttributes<HTMLButtonElement>>;
|
|
37
|
+
//# sourceMappingURL=Button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,cAAc,CAAA;AAErB,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAChF;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAA;IAEtD;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAEzB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,uFA2FlB,CAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { createActivationHandler } from '../../utils/keyboard';
|
|
4
|
+
import { getAriaLabel, getBusyAttributes } from '../../utils/aria';
|
|
5
|
+
import './Button.css';
|
|
6
|
+
/**
|
|
7
|
+
* Accessible Button component
|
|
8
|
+
*
|
|
9
|
+
* WCAG Compliance:
|
|
10
|
+
* - 2.1.1 Keyboard: Full keyboard support (Enter/Space)
|
|
11
|
+
* - 2.4.7 Focus Visible: Clear focus indicators
|
|
12
|
+
* - 4.1.2 Name, Role, Value: Proper ARIA attributes
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* <Button variant="primary" onClick={handleClick}>
|
|
17
|
+
* Click me
|
|
18
|
+
* </Button>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const Button = React.forwardRef(({ variant = 'primary', size = 'md', loading = false, disabled, children, className = '', onClick, onKeyDown, 'aria-label': ariaLabel, ...props }, ref) => {
|
|
22
|
+
const isDisabled = disabled || loading;
|
|
23
|
+
const handleKeyDown = React.useCallback((event) => {
|
|
24
|
+
// Handle activation keys
|
|
25
|
+
const activationHandler = createActivationHandler((e) => {
|
|
26
|
+
if (!isDisabled && onClick) {
|
|
27
|
+
onClick(e);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
activationHandler(event);
|
|
31
|
+
// Call user's onKeyDown if provided
|
|
32
|
+
if (onKeyDown) {
|
|
33
|
+
onKeyDown(event);
|
|
34
|
+
}
|
|
35
|
+
}, [isDisabled, onClick, onKeyDown]);
|
|
36
|
+
const ariaProps = {
|
|
37
|
+
...getAriaLabel(ariaLabel),
|
|
38
|
+
...getBusyAttributes(loading),
|
|
39
|
+
...props,
|
|
40
|
+
};
|
|
41
|
+
const classes = [
|
|
42
|
+
'btn',
|
|
43
|
+
`btn--${variant}`,
|
|
44
|
+
`btn--${size}`,
|
|
45
|
+
loading && 'btn--loading',
|
|
46
|
+
className,
|
|
47
|
+
]
|
|
48
|
+
.filter(Boolean)
|
|
49
|
+
.join(' ');
|
|
50
|
+
return (_jsxs("button", { ref: ref, type: "button", className: classes, disabled: isDisabled, onClick: onClick, onKeyDown: handleKeyDown, "aria-disabled": isDisabled, ...ariaProps, children: [loading && (_jsx("span", { className: "btn__spinner", "aria-hidden": "true", children: _jsx("svg", { className: "btn__spinner-icon", width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("circle", { className: "btn__spinner-circle", cx: "8", cy: "8", r: "6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeDasharray: "31.416", strokeDashoffset: "31.416" }) }) })), _jsx("span", { className: "btn__content", children: children })] }));
|
|
51
|
+
});
|
|
52
|
+
Button.displayName = 'Button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Button/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACjC,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Button } from './Button';
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import './DataTable.css';
|
|
3
|
+
export interface DataTableColumn<T> {
|
|
4
|
+
key: string;
|
|
5
|
+
header: string;
|
|
6
|
+
render?: (row: T, index: number) => React.ReactNode;
|
|
7
|
+
sortable?: boolean;
|
|
8
|
+
width?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DataTableProps<T> {
|
|
11
|
+
/**
|
|
12
|
+
* Data rows
|
|
13
|
+
*/
|
|
14
|
+
data: T[];
|
|
15
|
+
/**
|
|
16
|
+
* Column definitions
|
|
17
|
+
*/
|
|
18
|
+
columns: DataTableColumn<T>[];
|
|
19
|
+
/**
|
|
20
|
+
* Key function to get unique ID for each row
|
|
21
|
+
*/
|
|
22
|
+
getRowId: (row: T) => string;
|
|
23
|
+
/**
|
|
24
|
+
* Whether rows are selectable
|
|
25
|
+
*/
|
|
26
|
+
selectable?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Selected row IDs
|
|
29
|
+
*/
|
|
30
|
+
selectedRows?: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Callback when selection changes
|
|
33
|
+
*/
|
|
34
|
+
onSelectionChange?: (selectedIds: string[]) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Sort configuration
|
|
37
|
+
*/
|
|
38
|
+
sortConfig?: {
|
|
39
|
+
column: string;
|
|
40
|
+
direction: 'asc' | 'desc';
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Callback when sort changes
|
|
44
|
+
*/
|
|
45
|
+
onSortChange?: (column: string, direction: 'asc' | 'desc') => void;
|
|
46
|
+
/**
|
|
47
|
+
* Caption for the table (required for accessibility)
|
|
48
|
+
*/
|
|
49
|
+
caption?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Accessible DataTable component
|
|
53
|
+
*
|
|
54
|
+
* WCAG Compliance:
|
|
55
|
+
* - 1.3.1 Info and Relationships: Semantic table structure
|
|
56
|
+
* - 2.1.1 Keyboard: Arrow keys, Home/End navigation
|
|
57
|
+
* - 4.1.2 Name, Role, Value: Proper ARIA attributes
|
|
58
|
+
* - 4.1.3 Status Messages: Sort announcements
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <DataTable
|
|
63
|
+
* data={users}
|
|
64
|
+
* columns={columns}
|
|
65
|
+
* getRowId={(user) => user.id}
|
|
66
|
+
* caption="User list"
|
|
67
|
+
* />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare function DataTable<T extends Record<string, any>>({ data, columns, getRowId, selectable, selectedRows, onSelectionChange, sortConfig, onSortChange, caption, }: DataTableProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
71
|
+
//# sourceMappingURL=DataTable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../../src/components/DataTable/DataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAA;AAI5D,OAAO,iBAAiB,CAAA;AAExB,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAA;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,cAAc,CAAC,CAAC;IAC/B;;OAEG;IACH,IAAI,EAAE,CAAC,EAAE,CAAA;IAET;;OAEG;IACH,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,CAAA;IAE7B;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IAE5B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IAEvB;;OAEG;IACH,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IAEnD;;OAEG;IACH,UAAU,CAAC,EAAE;QACX,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;KAC1B,CAAA;IAED;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,GAAG,MAAM,KAAK,IAAI,CAAA;IAElE;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACvD,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,UAAkB,EAClB,YAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,YAAY,EACZ,OAAO,GACR,EAAE,cAAc,CAAC,CAAC,CAAC,2CAoMnB"}
|