@a11ypros/a11y-ui-components 1.0.1 → 1.0.2

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 (217) hide show
  1. package/README.md +182 -157
  2. package/dist/components/Button/Button.d.ts +37 -0
  3. package/dist/components/Button/Button.d.ts.map +1 -0
  4. package/dist/components/Button/Button.js +52 -0
  5. package/dist/components/Button/index.d.ts +3 -0
  6. package/dist/components/Button/index.d.ts.map +1 -0
  7. package/dist/components/Button/index.js +1 -0
  8. package/dist/components/DataTable/DataTable.d.ts +71 -0
  9. package/dist/components/DataTable/DataTable.d.ts.map +1 -0
  10. package/dist/components/DataTable/DataTable.js +122 -0
  11. package/dist/components/DataTable/index.d.ts +3 -0
  12. package/dist/components/DataTable/index.d.ts.map +1 -0
  13. package/dist/components/DataTable/index.js +1 -0
  14. package/dist/components/Form/Checkbox.d.ts +36 -0
  15. package/dist/components/Form/Checkbox.d.ts.map +1 -0
  16. package/dist/components/Form/Checkbox.js +39 -0
  17. package/dist/components/Form/Fieldset.d.ts +33 -0
  18. package/dist/components/Form/Fieldset.d.ts.map +1 -0
  19. package/dist/components/Form/Fieldset.js +34 -0
  20. package/dist/components/Form/Input.d.ts +37 -0
  21. package/dist/components/Form/Input.d.ts.map +1 -0
  22. package/dist/components/Form/Input.js +41 -0
  23. package/dist/components/Form/Label.d.ts +30 -0
  24. package/dist/components/Form/Label.d.ts.map +1 -0
  25. package/dist/components/Form/Label.js +30 -0
  26. package/dist/components/Form/Radio.d.ts +53 -0
  27. package/dist/components/Form/Radio.d.ts.map +1 -0
  28. package/dist/components/Form/Radio.js +39 -0
  29. package/dist/components/Form/Select.d.ts +51 -0
  30. package/dist/components/Form/Select.d.ts.map +1 -0
  31. package/dist/components/Form/Select.js +49 -0
  32. package/dist/components/Form/Textarea.d.ts +44 -0
  33. package/dist/components/Form/Textarea.d.ts.map +1 -0
  34. package/dist/components/Form/Textarea.js +43 -0
  35. package/dist/components/Form/index.d.ts +8 -0
  36. package/dist/components/Form/index.d.ts.map +1 -0
  37. package/dist/components/Form/index.js +7 -0
  38. package/dist/components/Link/Link.d.ts +34 -0
  39. package/dist/components/Link/Link.d.ts.map +1 -0
  40. package/dist/components/Link/Link.js +48 -0
  41. package/dist/components/Link/index.d.ts +3 -0
  42. package/dist/components/Link/index.d.ts.map +1 -0
  43. package/dist/components/Link/index.js +1 -0
  44. package/dist/components/Modal/Modal.d.ts +64 -0
  45. package/dist/components/Modal/Modal.d.ts.map +1 -0
  46. package/dist/components/Modal/Modal.js +108 -0
  47. package/dist/components/Modal/index.d.ts +3 -0
  48. package/dist/components/Modal/index.d.ts.map +1 -0
  49. package/dist/components/Modal/index.js +1 -0
  50. package/dist/components/Tabs/Tabs.d.ts +63 -0
  51. package/dist/components/Tabs/Tabs.d.ts.map +1 -0
  52. package/dist/components/Tabs/Tabs.js +134 -0
  53. package/dist/components/Tabs/index.d.ts +3 -0
  54. package/dist/components/Tabs/index.d.ts.map +1 -0
  55. package/dist/components/Tabs/index.js +1 -0
  56. package/dist/components/Toast/Toast.d.ts +59 -0
  57. package/dist/components/Toast/Toast.d.ts.map +1 -0
  58. package/dist/components/Toast/Toast.js +91 -0
  59. package/dist/components/Toast/ToastProvider.d.ts +22 -0
  60. package/dist/components/Toast/ToastProvider.d.ts.map +1 -0
  61. package/dist/components/Toast/ToastProvider.js +33 -0
  62. package/dist/components/Toast/index.d.ts +5 -0
  63. package/dist/components/Toast/index.d.ts.map +1 -0
  64. package/dist/components/Toast/index.js +2 -0
  65. package/dist/hooks/useAriaLive.d.ts +9 -0
  66. package/dist/hooks/useAriaLive.d.ts.map +1 -0
  67. package/dist/hooks/useAriaLive.js +39 -0
  68. package/dist/hooks/useFocusReturn.d.ts +9 -0
  69. package/dist/hooks/useFocusReturn.d.ts.map +1 -0
  70. package/dist/hooks/useFocusReturn.js +33 -0
  71. package/dist/hooks/useFocusTrap.d.ts +9 -0
  72. package/dist/hooks/useFocusTrap.d.ts.map +1 -0
  73. package/dist/hooks/useFocusTrap.js +68 -0
  74. package/dist/index.d.ts +22 -0
  75. package/dist/index.d.ts.map +1 -0
  76. package/{packages/design-system/src/index.ts → dist/index.js} +0 -4
  77. package/dist/styles/index.d.ts +3 -0
  78. package/dist/styles/index.d.ts.map +1 -0
  79. package/dist/styles/index.js +1 -0
  80. package/dist/tokens/breakpoints.d.ts +25 -0
  81. package/dist/tokens/breakpoints.d.ts.map +1 -0
  82. package/dist/tokens/breakpoints.js +23 -0
  83. package/dist/tokens/colors.d.ts +81 -0
  84. package/dist/tokens/colors.d.ts.map +1 -0
  85. package/dist/tokens/colors.js +86 -0
  86. package/dist/tokens/index.d.ts +6 -0
  87. package/dist/tokens/index.d.ts.map +1 -0
  88. package/dist/tokens/index.js +5 -0
  89. package/dist/tokens/motion.d.ts +30 -0
  90. package/dist/tokens/motion.d.ts.map +1 -0
  91. package/dist/tokens/motion.js +34 -0
  92. package/dist/tokens/spacing.d.ts +22 -0
  93. package/dist/tokens/spacing.d.ts.map +1 -0
  94. package/dist/tokens/spacing.js +20 -0
  95. package/dist/tokens/theme.d.ts +159 -0
  96. package/dist/tokens/theme.d.ts.map +1 -0
  97. package/dist/tokens/theme.js +15 -0
  98. package/dist/tokens/typography.d.ts +45 -0
  99. package/dist/tokens/typography.d.ts.map +1 -0
  100. package/dist/tokens/typography.js +56 -0
  101. package/dist/utils/aria.d.ts +60 -0
  102. package/dist/utils/aria.d.ts.map +1 -0
  103. package/dist/utils/aria.js +86 -0
  104. package/dist/utils/focus.d.ts +30 -0
  105. package/dist/utils/focus.d.ts.map +1 -0
  106. package/dist/utils/focus.js +80 -0
  107. package/dist/utils/index.d.ts +4 -0
  108. package/dist/utils/index.d.ts.map +1 -0
  109. package/dist/utils/index.js +3 -0
  110. package/dist/utils/keyboard.d.ts +38 -0
  111. package/dist/utils/keyboard.d.ts.map +1 -0
  112. package/dist/utils/keyboard.js +59 -0
  113. package/package.json +58 -31
  114. package/.storybook/custom.css +0 -69
  115. package/.storybook/main.ts +0 -46
  116. package/.storybook/manager.ts +0 -26
  117. package/.storybook/package.json +0 -6
  118. package/.storybook/preview.tsx +0 -31
  119. package/.storybook/public/logo.png +0 -0
  120. package/.storybook/vite.config.ts +0 -24
  121. package/.storybook/welcome.mdx +0 -97
  122. package/DEPLOYMENT.md +0 -154
  123. package/apps/web/app/(docs)/audit/audit.css +0 -269
  124. package/apps/web/app/(docs)/audit/page.tsx +0 -271
  125. package/apps/web/app/(docs)/components/button/page.tsx +0 -49
  126. package/apps/web/app/(docs)/components/form/page.tsx +0 -92
  127. package/apps/web/app/(docs)/components/link/page.tsx +0 -31
  128. package/apps/web/app/(docs)/components/modal/page.tsx +0 -41
  129. package/apps/web/app/(docs)/components/page.tsx +0 -37
  130. package/apps/web/app/(docs)/components/table/page.tsx +0 -54
  131. package/apps/web/app/(docs)/components/tabs/page.tsx +0 -61
  132. package/apps/web/app/(docs)/components/toast/page.tsx +0 -51
  133. package/apps/web/app/api/audit/route.ts +0 -128
  134. package/apps/web/app/favicon.ico +0 -0
  135. package/apps/web/app/layout.tsx +0 -20
  136. package/apps/web/app/page.tsx +0 -17
  137. package/apps/web/app/styles/globals.css +0 -5
  138. package/apps/web/next-env.d.ts +0 -5
  139. package/apps/web/next.config.js +0 -21
  140. package/apps/web/package.json +0 -28
  141. package/apps/web/public/_headers +0 -17
  142. package/apps/web/public/_redirects +0 -31
  143. package/apps/web/public/logo.png +0 -0
  144. package/apps/web/tsconfig.json +0 -29
  145. package/netlify/functions/audit.ts +0 -163
  146. package/netlify.toml +0 -37
  147. package/packages/design-system/README.md +0 -252
  148. package/packages/design-system/package.json +0 -68
  149. package/packages/design-system/scripts/copy-css.js +0 -63
  150. package/packages/design-system/src/components/Button/Button.stories.tsx +0 -228
  151. package/packages/design-system/src/components/Button/Button.tsx +0 -137
  152. package/packages/design-system/src/components/Button/index.ts +0 -3
  153. package/packages/design-system/src/components/DataTable/DataTable.stories.tsx +0 -211
  154. package/packages/design-system/src/components/DataTable/DataTable.tsx +0 -293
  155. package/packages/design-system/src/components/DataTable/index.ts +0 -3
  156. package/packages/design-system/src/components/Form/Checkbox.stories.tsx +0 -252
  157. package/packages/design-system/src/components/Form/Checkbox.tsx +0 -114
  158. package/packages/design-system/src/components/Form/Fieldset.stories.tsx +0 -210
  159. package/packages/design-system/src/components/Form/Fieldset.tsx +0 -71
  160. package/packages/design-system/src/components/Form/Input.stories.tsx +0 -164
  161. package/packages/design-system/src/components/Form/Input.tsx +0 -113
  162. package/packages/design-system/src/components/Form/Label.tsx +0 -56
  163. package/packages/design-system/src/components/Form/Radio.stories.tsx +0 -265
  164. package/packages/design-system/src/components/Form/Radio.tsx +0 -147
  165. package/packages/design-system/src/components/Form/Select.stories.tsx +0 -295
  166. package/packages/design-system/src/components/Form/Select.tsx +0 -160
  167. package/packages/design-system/src/components/Form/Textarea.stories.tsx +0 -253
  168. package/packages/design-system/src/components/Form/Textarea.tsx +0 -145
  169. package/packages/design-system/src/components/Form/index.ts +0 -8
  170. package/packages/design-system/src/components/Link/Link.stories.tsx +0 -128
  171. package/packages/design-system/src/components/Link/Link.tsx +0 -117
  172. package/packages/design-system/src/components/Link/index.ts +0 -3
  173. package/packages/design-system/src/components/Modal/Modal.stories.tsx +0 -165
  174. package/packages/design-system/src/components/Modal/Modal.tsx +0 -202
  175. package/packages/design-system/src/components/Modal/index.ts +0 -3
  176. package/packages/design-system/src/components/Tabs/Tabs.stories.tsx +0 -213
  177. package/packages/design-system/src/components/Tabs/Tabs.tsx +0 -248
  178. package/packages/design-system/src/components/Tabs/index.ts +0 -3
  179. package/packages/design-system/src/components/Toast/Toast.stories.tsx +0 -153
  180. package/packages/design-system/src/components/Toast/Toast.tsx +0 -175
  181. package/packages/design-system/src/components/Toast/ToastProvider.tsx +0 -73
  182. package/packages/design-system/src/components/Toast/index.ts +0 -5
  183. package/packages/design-system/src/hooks/useAriaLive.ts +0 -51
  184. package/packages/design-system/src/hooks/useFocusReturn.ts +0 -40
  185. package/packages/design-system/src/hooks/useFocusTrap.ts +0 -82
  186. package/packages/design-system/src/styles/index.ts +0 -3
  187. package/packages/design-system/src/tokens/breakpoints.ts +0 -28
  188. package/packages/design-system/src/tokens/colors.ts +0 -98
  189. package/packages/design-system/src/tokens/index.ts +0 -6
  190. package/packages/design-system/src/tokens/motion.ts +0 -41
  191. package/packages/design-system/src/tokens/spacing.ts +0 -24
  192. package/packages/design-system/src/tokens/theme.ts +0 -19
  193. package/packages/design-system/src/tokens/typography.ts +0 -64
  194. package/packages/design-system/src/utils/aria.ts +0 -108
  195. package/packages/design-system/src/utils/focus.ts +0 -87
  196. package/packages/design-system/src/utils/index.ts +0 -4
  197. package/packages/design-system/src/utils/keyboard.ts +0 -77
  198. package/packages/design-system/tsconfig.json +0 -17
  199. package/public/logo.png +0 -0
  200. package/scripts/fix-storybook-paths.js +0 -53
  201. package/tsconfig.json +0 -20
  202. /package/{packages/design-system/src → dist}/components/Button/Button.css +0 -0
  203. /package/{packages/design-system/src → dist}/components/DataTable/DataTable.css +0 -0
  204. /package/{packages/design-system/src → dist}/components/Form/Checkbox.css +0 -0
  205. /package/{packages/design-system/src → dist}/components/Form/Fieldset.css +0 -0
  206. /package/{packages/design-system/src → dist}/components/Form/Input.css +0 -0
  207. /package/{packages/design-system/src → dist}/components/Form/Label.css +0 -0
  208. /package/{packages/design-system/src → dist}/components/Form/Radio.css +0 -0
  209. /package/{packages/design-system/src → dist}/components/Form/Select.css +0 -0
  210. /package/{packages/design-system/src → dist}/components/Form/Textarea.css +0 -0
  211. /package/{packages/design-system/src → dist}/components/Link/Link.css +0 -0
  212. /package/{packages/design-system/src → dist}/components/Modal/Modal.css +0 -0
  213. /package/{packages/design-system/src → dist}/components/Tabs/Tabs.css +0 -0
  214. /package/{packages/design-system/src → dist}/components/Toast/Toast.css +0 -0
  215. /package/{packages/design-system/src → dist}/components/Toast/ToastProvider.css +0 -0
  216. /package/{packages/design-system/src → dist}/styles/components.css +0 -0
  217. /package/{packages/design-system/src → dist}/styles/global.css +0 -0
@@ -1,49 +0,0 @@
1
- 'use client'
2
-
3
- import { Button } from '@a11ypros/a11y-ui-components'
4
-
5
- export default function ButtonPage() {
6
- return (
7
- <main style={{ padding: '2rem' }}>
8
- <h1>Button Component</h1>
9
- <p>Accessible button component with full keyboard support.</p>
10
-
11
- <section style={{ marginTop: '2rem' }}>
12
- <h2>Variants</h2>
13
- <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
14
- <Button variant="primary">Primary</Button>
15
- <Button variant="secondary">Secondary</Button>
16
- <Button variant="ghost">Ghost</Button>
17
- <Button variant="danger">Danger</Button>
18
- </div>
19
- </section>
20
-
21
- <section style={{ marginTop: '2rem' }}>
22
- <h2>Sizes</h2>
23
- <div style={{ display: 'flex', gap: '1rem', alignItems: 'center', flexWrap: 'wrap' }}>
24
- <Button size="sm">Small</Button>
25
- <Button size="md">Medium</Button>
26
- <Button size="lg">Large</Button>
27
- </div>
28
- </section>
29
-
30
- <section style={{ marginTop: '2rem' }}>
31
- <h2>States</h2>
32
- <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
33
- <Button loading>Loading</Button>
34
- <Button disabled>Disabled</Button>
35
- </div>
36
- </section>
37
-
38
- <section style={{ marginTop: '2rem' }}>
39
- <h2>Accessibility</h2>
40
- <ul>
41
- <li>WCAG 2.1.1 Keyboard: Full keyboard support (Enter/Space)</li>
42
- <li>WCAG 2.4.7 Focus Visible: Clear focus indicators</li>
43
- <li>WCAG 4.1.2 Name, Role, Value: Proper ARIA attributes</li>
44
- </ul>
45
- </section>
46
- </main>
47
- )
48
- }
49
-
@@ -1,92 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { Input, Textarea, Select, Checkbox, Radio, Fieldset, Label } from '@a11ypros/a11y-ui-components'
5
-
6
- export default function FormPage() {
7
- const [email, setEmail] = useState('')
8
- const [message, setMessage] = useState('')
9
- const [country, setCountry] = useState('')
10
- const [agree, setAgree] = useState(false)
11
- const [size, setSize] = useState('')
12
-
13
- return (
14
- <main style={{ padding: '2rem' }}>
15
- <h1>Form Components</h1>
16
- <p>Accessible form components with proper labels and ARIA attributes.</p>
17
-
18
- <section style={{ marginTop: '2rem' }}>
19
- <h2>Input</h2>
20
- <Input
21
- label="Email address"
22
- type="email"
23
- value={email}
24
- onChange={(e) => setEmail(e.target.value)}
25
- placeholder="you@example.com"
26
- required
27
- />
28
- </section>
29
-
30
- <section style={{ marginTop: '2rem' }}>
31
- <h2>Textarea</h2>
32
- <Textarea
33
- label="Message"
34
- value={message}
35
- onChange={(e) => setMessage(e.target.value)}
36
- maxLength={500}
37
- showCount
38
- />
39
- </section>
40
-
41
- <section style={{ marginTop: '2rem' }}>
42
- <h2>Select</h2>
43
- <Select
44
- label="Country"
45
- options={[
46
- { value: 'us', label: 'United States' },
47
- { value: 'ca', label: 'Canada' },
48
- { value: 'uk', label: 'United Kingdom' },
49
- ]}
50
- value={country}
51
- onChange={(e) => setCountry(e.target.value)}
52
- />
53
- </section>
54
-
55
- <section style={{ marginTop: '2rem' }}>
56
- <h2>Checkbox</h2>
57
- <Checkbox
58
- id="agree"
59
- label="I agree to the terms and conditions"
60
- checked={agree}
61
- onChange={(e) => setAgree(e.target.checked)}
62
- />
63
- </section>
64
-
65
- <section style={{ marginTop: '2rem' }}>
66
- <h2>Radio</h2>
67
- <Radio
68
- name="size"
69
- label="Size"
70
- options={[
71
- { value: 's', label: 'Small' },
72
- { value: 'm', label: 'Medium' },
73
- { value: 'l', label: 'Large' },
74
- ]}
75
- value={size}
76
- onChange={(e) => setSize(e.target.value)}
77
- />
78
- </section>
79
-
80
- <section style={{ marginTop: '2rem' }}>
81
- <h2>Accessibility</h2>
82
- <ul>
83
- <li>WCAG 1.3.1 Info and Relationships: Proper label-input association</li>
84
- <li>WCAG 2.5.3 Label in Name: Label text matches accessible name</li>
85
- <li>WCAG 4.1.2 Name, Role, Value: Proper ARIA attributes</li>
86
- <li>WCAG 4.1.3 Status Messages: Error messages announced</li>
87
- </ul>
88
- </section>
89
- </main>
90
- )
91
- }
92
-
@@ -1,31 +0,0 @@
1
- 'use client'
2
-
3
- import { Link } from '@a11ypros/a11y-ui-components'
4
-
5
- export default function LinkPage() {
6
- return (
7
- <main style={{ padding: '2rem' }}>
8
- <h1>Link Component</h1>
9
- <p>Accessible link component with external link detection.</p>
10
-
11
- <section style={{ marginTop: '2rem' }}>
12
- <h2>Examples</h2>
13
- <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
14
- <Link href="/components">Internal Link</Link>
15
- <Link href="https://example.com" external>External Link</Link>
16
- <Link href="#main-content" skip>Skip Link</Link>
17
- </div>
18
- </section>
19
-
20
- <section style={{ marginTop: '2rem' }}>
21
- <h2>Accessibility</h2>
22
- <ul>
23
- <li>WCAG 2.4.4 Link Purpose: Clear link text or aria-label</li>
24
- <li>WCAG 2.4.7 Focus Visible: Clear focus indicators</li>
25
- <li>WCAG 4.1.2 Name, Role, Value: Proper semantic HTML</li>
26
- </ul>
27
- </section>
28
- </main>
29
- )
30
- }
31
-
@@ -1,41 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { Modal, Button } from '@a11ypros/a11y-ui-components'
5
-
6
- export default function ModalPage() {
7
- const [isOpen, setIsOpen] = useState(false)
8
-
9
- return (
10
- <main style={{ padding: '2rem' }}>
11
- <h1>Modal Component</h1>
12
- <p>Accessible modal dialog with focus trap and keyboard support.</p>
13
-
14
- <section style={{ marginTop: '2rem' }}>
15
- <h2>Example</h2>
16
- <Button onClick={() => setIsOpen(true)}>Open Modal</Button>
17
- <Modal
18
- isOpen={isOpen}
19
- onClose={() => setIsOpen(false)}
20
- title="Example Modal"
21
- >
22
- <p>This is a modal dialog. Press ESC to close or click outside.</p>
23
- <div style={{ marginTop: '1rem' }}>
24
- <Button onClick={() => setIsOpen(false)}>Close</Button>
25
- </div>
26
- </Modal>
27
- </section>
28
-
29
- <section style={{ marginTop: '2rem' }}>
30
- <h2>Accessibility</h2>
31
- <ul>
32
- <li>WCAG 2.1.1 Keyboard: ESC key support, focus trap</li>
33
- <li>WCAG 2.1.2 No Keyboard Trap: Focus returns to trigger</li>
34
- <li>WCAG 2.4.3 Focus Order: Focus trapped within modal</li>
35
- <li>WCAG 4.1.2 Name, Role, Value: ARIA modal pattern</li>
36
- </ul>
37
- </section>
38
- </main>
39
- )
40
- }
41
-
@@ -1,37 +0,0 @@
1
- 'use client'
2
-
3
- import Link from 'next/link'
4
- import { Button, Link as DesignSystemLink } from '@a11ypros/a11y-ui-components'
5
-
6
- export default function ComponentsPage() {
7
- return (
8
- <main>
9
- <h1>Design System Components</h1>
10
- <p>Browse and test all accessible components in the design system.</p>
11
-
12
- <nav>
13
- <h2>Components</h2>
14
- <ul>
15
- <li><Link href="/components/button">Button</Link></li>
16
- <li><Link href="/components/link">Link</Link></li>
17
- <li><Link href="/components/modal">Modal</Link></li>
18
- <li><Link href="/components/form">Form Components</Link></li>
19
- <li><Link href="/components/table">Data Table</Link></li>
20
- <li><Link href="/components/toast">Toast</Link></li>
21
- <li><Link href="/components/tabs">Tabs</Link></li>
22
- </ul>
23
- </nav>
24
-
25
- <section>
26
- <h2>Quick Examples</h2>
27
- <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap', marginTop: '1rem' }}>
28
- <Button variant="primary">Primary Button</Button>
29
- <Button variant="secondary">Secondary Button</Button>
30
- <Button variant="ghost">Ghost Button</Button>
31
- <DesignSystemLink href="/audit">Go to Audit Tool</DesignSystemLink>
32
- </div>
33
- </section>
34
- </main>
35
- )
36
- }
37
-
@@ -1,54 +0,0 @@
1
- 'use client'
2
-
3
- import { useState } from 'react'
4
- import { DataTable } from '@a11ypros/a11y-ui-components'
5
-
6
- const sampleData = [
7
- { id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin' },
8
- { id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
9
- { id: '3', name: 'Bob Johnson', email: 'bob@example.com', role: 'User' },
10
- ]
11
-
12
- const columns = [
13
- { key: 'name', header: 'Name', sortable: true },
14
- { key: 'email', header: 'Email', sortable: true },
15
- { key: 'role', header: 'Role', sortable: true },
16
- ]
17
-
18
- export default function TablePage() {
19
- const [selectedRows, setSelectedRows] = useState<string[]>([])
20
- const [sortConfig, setSortConfig] = useState<{ column: string; direction: 'asc' | 'desc' } | undefined>()
21
-
22
- return (
23
- <main style={{ padding: '2rem' }}>
24
- <h1>DataTable Component</h1>
25
- <p>Accessible data table with keyboard navigation and sorting.</p>
26
-
27
- <section style={{ marginTop: '2rem' }}>
28
- <h2>Example</h2>
29
- <DataTable
30
- data={sampleData}
31
- columns={columns}
32
- getRowId={(row) => row.id}
33
- selectable
34
- selectedRows={selectedRows}
35
- onSelectionChange={setSelectedRows}
36
- sortConfig={sortConfig}
37
- onSortChange={(column, direction) => setSortConfig({ column, direction })}
38
- caption="User list"
39
- />
40
- </section>
41
-
42
- <section style={{ marginTop: '2rem' }}>
43
- <h2>Accessibility</h2>
44
- <ul>
45
- <li>WCAG 1.3.1 Info and Relationships: Semantic table structure</li>
46
- <li>WCAG 2.1.1 Keyboard: Arrow keys, Home/End navigation</li>
47
- <li>WCAG 4.1.2 Name, Role, Value: Proper ARIA attributes</li>
48
- <li>WCAG 4.1.3 Status Messages: Sort announcements</li>
49
- </ul>
50
- </section>
51
- </main>
52
- )
53
- }
54
-
@@ -1,61 +0,0 @@
1
- 'use client'
2
-
3
- import { Tabs } from '@a11ypros/a11y-ui-components'
4
-
5
- export default function TabsPage() {
6
- return (
7
- <main style={{ padding: '2rem' }}>
8
- <h1>Tabs Component</h1>
9
- <p>Accessible tabs component with arrow key navigation.</p>
10
-
11
- <section style={{ marginTop: '2rem' }}>
12
- <h2>Example</h2>
13
- <Tabs
14
- aria-label="Settings tabs"
15
- items={[
16
- {
17
- id: 'general',
18
- label: 'General',
19
- content: (
20
- <div>
21
- <h3>General Settings</h3>
22
- <p>Configure general application settings here.</p>
23
- </div>
24
- ),
25
- },
26
- {
27
- id: 'account',
28
- label: 'Account',
29
- content: (
30
- <div>
31
- <h3>Account Settings</h3>
32
- <p>Manage your account preferences.</p>
33
- </div>
34
- ),
35
- },
36
- {
37
- id: 'privacy',
38
- label: 'Privacy',
39
- content: (
40
- <div>
41
- <h3>Privacy Settings</h3>
42
- <p>Control your privacy and data settings.</p>
43
- </div>
44
- ),
45
- },
46
- ]}
47
- />
48
- </section>
49
-
50
- <section style={{ marginTop: '2rem' }}>
51
- <h2>Accessibility</h2>
52
- <ul>
53
- <li>WCAG 2.1.1 Keyboard: Arrow key navigation, Home/End support</li>
54
- <li>WCAG 4.1.2 Name, Role, Value: ARIA tabs pattern</li>
55
- <li>WCAG 2.4.3 Focus Order: Proper focus management</li>
56
- </ul>
57
- </section>
58
- </main>
59
- )
60
- }
61
-
@@ -1,51 +0,0 @@
1
- 'use client'
2
-
3
- import { ToastProvider, useToast } from '@a11ypros/a11y-ui-components'
4
- import { Button } from '@a11ypros/a11y-ui-components'
5
-
6
- function ToastDemo() {
7
- const { addToast } = useToast()
8
-
9
- return (
10
- <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
11
- <Button onClick={() => addToast({ message: 'Info message', type: 'info' })}>
12
- Show Info Toast
13
- </Button>
14
- <Button onClick={() => addToast({ message: 'Success!', type: 'success' })}>
15
- Show Success Toast
16
- </Button>
17
- <Button onClick={() => addToast({ message: 'Warning message', type: 'warning' })}>
18
- Show Warning Toast
19
- </Button>
20
- <Button onClick={() => addToast({ message: 'Error occurred', type: 'error' })}>
21
- Show Error Toast
22
- </Button>
23
- </div>
24
- )
25
- }
26
-
27
- export default function ToastPage() {
28
- return (
29
- <main style={{ padding: '2rem' }}>
30
- <h1>Toast Component</h1>
31
- <p>Accessible toast notifications with ARIA live regions.</p>
32
-
33
- <section style={{ marginTop: '2rem' }}>
34
- <h2>Examples</h2>
35
- <ToastProvider>
36
- <ToastDemo />
37
- </ToastProvider>
38
- </section>
39
-
40
- <section style={{ marginTop: '2rem' }}>
41
- <h2>Accessibility</h2>
42
- <ul>
43
- <li>WCAG 4.1.3 Status Messages: ARIA live region announcements</li>
44
- <li>WCAG 2.1.1 Keyboard: ESC key support</li>
45
- <li>WCAG 4.1.2 Name, Role, Value: Proper ARIA attributes</li>
46
- </ul>
47
- </section>
48
- </main>
49
- )
50
- }
51
-
@@ -1,128 +0,0 @@
1
- import { NextRequest, NextResponse } from 'next/server'
2
- import Anthropic from '@anthropic-ai/sdk'
3
-
4
- const anthropic = new Anthropic({
5
- apiKey: process.env.ANTHROPIC_API_KEY || '',
6
- })
7
-
8
- export interface AuditIssue {
9
- wcagSC: string // WCAG Success Criterion (e.g., "1.3.1", "2.4.7")
10
- severity: 'error' | 'warning' | 'info'
11
- message: string
12
- suggestion: string
13
- codeSuggestion?: string
14
- }
15
-
16
- export interface AuditResponse {
17
- issues: AuditIssue[]
18
- summary: string
19
- }
20
-
21
- const WCAG_PROMPT = `You are an accessibility expert reviewing JSX/React code for WCAG 2.1 and 2.2 compliance.
22
-
23
- Analyze the provided JSX code snippet and identify accessibility issues. For each issue:
24
- 1. Map it to the specific WCAG Success Criterion (SC) number (e.g., "1.3.1", "2.4.7", "4.1.2")
25
- 2. Determine severity: "error" (violates WCAG), "warning" (may cause issues), or "info" (best practice)
26
- 3. Provide a clear message explaining the issue
27
- 4. Suggest how to fix it
28
- 5. If applicable, provide corrected code
29
-
30
- Focus on:
31
- - Semantic HTML (1.3.1)
32
- - Keyboard accessibility (2.1.1, 2.1.2)
33
- - Focus management (2.4.7)
34
- - ARIA usage (4.1.2, 4.1.3)
35
- - Color contrast (1.4.3)
36
- - Form labels (2.5.3)
37
- - Status messages (4.1.3)
38
-
39
- Return your response as a JSON object with this structure:
40
- {
41
- "issues": [
42
- {
43
- "wcagSC": "2.4.7",
44
- "severity": "error",
45
- "message": "Button lacks visible focus indicator",
46
- "suggestion": "Add focus-visible styles with 2px outline",
47
- "codeSuggestion": "button:focus-visible { outline: 2px solid #0ea5e9; }"
48
- }
49
- ],
50
- "summary": "Found 3 issues: 2 errors, 1 warning"
51
- }
52
-
53
- Only return valid JSON, no markdown formatting.`
54
-
55
- export async function POST(request: NextRequest) {
56
- try {
57
- const { code } = await request.json()
58
-
59
- if (!code || typeof code !== 'string') {
60
- return NextResponse.json(
61
- { error: 'Code snippet is required' },
62
- { status: 400 }
63
- )
64
- }
65
-
66
- if (!process.env.ANTHROPIC_API_KEY) {
67
- return NextResponse.json(
68
- { error: 'ANTHROPIC_API_KEY environment variable is not set' },
69
- { status: 500 }
70
- )
71
- }
72
-
73
- const message = await anthropic.messages.create({
74
- model: 'claude-sonnet-4-20250514',
75
- max_tokens: 4096,
76
- messages: [
77
- {
78
- role: 'user',
79
- content: `${WCAG_PROMPT}\n\nCode to review:\n\`\`\`jsx\n${code}\n\`\`\``,
80
- },
81
- ],
82
- })
83
-
84
- const content = message.content[0]
85
- if (content.type !== 'text') {
86
- throw new Error('Unexpected response type from Anthropic')
87
- }
88
-
89
- // Parse the JSON response
90
- let auditResult: AuditResponse
91
- try {
92
- // Extract JSON from the response (handle markdown code blocks if present)
93
- let jsonText = content.text.trim()
94
- if (jsonText.startsWith('```')) {
95
- jsonText = jsonText.replace(/^```(?:json)?\n/, '').replace(/\n```$/, '')
96
- }
97
- auditResult = JSON.parse(jsonText)
98
- } catch (parseError) {
99
- // If parsing fails, try to extract JSON from the text
100
- const jsonMatch = content.text.match(/\{[\s\S]*\}/)
101
- if (jsonMatch) {
102
- auditResult = JSON.parse(jsonMatch[0])
103
- } else {
104
- throw new Error('Failed to parse audit response as JSON')
105
- }
106
- }
107
-
108
- // Validate response structure
109
- if (!auditResult.issues || !Array.isArray(auditResult.issues)) {
110
- auditResult = {
111
- issues: [],
112
- summary: 'No issues found or invalid response format',
113
- }
114
- }
115
-
116
- return NextResponse.json(auditResult)
117
- } catch (error) {
118
- console.error('Audit API error:', error)
119
- return NextResponse.json(
120
- {
121
- error: 'Failed to perform accessibility audit',
122
- message: error instanceof Error ? error.message : 'Unknown error',
123
- },
124
- { status: 500 }
125
- )
126
- }
127
- }
128
-
Binary file
@@ -1,20 +0,0 @@
1
- import type { Metadata } from 'next'
2
- import './styles/globals.css'
3
-
4
- export const metadata: Metadata = {
5
- title: 'Accessible Design System',
6
- description: 'An accessible design system with AI-powered accessibility auditing',
7
- }
8
-
9
- export default function RootLayout({
10
- children,
11
- }: {
12
- children: React.ReactNode
13
- }) {
14
- return (
15
- <html lang="en">
16
- <body>{children}</body>
17
- </html>
18
- )
19
- }
20
-
@@ -1,17 +0,0 @@
1
- import Link from 'next/link'
2
-
3
- export default function Home() {
4
- return (
5
- <main>
6
- <nav>
7
- <ul>
8
- <li><Link href="/components">Components</Link></li>
9
- <li><Link href="/audit">AI Audit Assistant</Link></li>
10
- </ul>
11
- </nav>
12
- <h1>Accessible Design System</h1>
13
- <p>Welcome to the accessible design system documentation.</p>
14
- </main>
15
- )
16
- }
17
-
@@ -1,5 +0,0 @@
1
- /* Import design system global styles */
2
- @import '../../../../packages/design-system/src/styles/global.css';
3
-
4
- /* App-specific global styles */
5
-
@@ -1,5 +0,0 @@
1
- /// <reference types="next" />
2
- /// <reference types="next/image-types/global" />
3
-
4
- // NOTE: This file should not be edited
5
- // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
@@ -1,21 +0,0 @@
1
- /** @type {import('next').NextConfig} */
2
- const nextConfig = {
3
- transpilePackages: ['@a11ypros/a11y-ui-components'],
4
- // Enable static export for Netlify
5
- output: 'export',
6
- // Disable image optimization for static export
7
- images: {
8
- unoptimized: true,
9
- },
10
- // Increase static page generation timeout (default is 60s)
11
- staticPageGenerationTimeout: 120,
12
- webpack: (config) => {
13
- config.resolve.alias = {
14
- ...config.resolve.alias,
15
- }
16
- return config
17
- },
18
- }
19
-
20
- module.exports = nextConfig
21
-
@@ -1,28 +0,0 @@
1
- {
2
- "name": "@apps/web",
3
- "version": "0.1.0",
4
- "private": true,
5
- "scripts": {
6
- "dev": "next dev",
7
- "build": "next build",
8
- "start": "next start",
9
- "lint": "next lint"
10
- },
11
- "dependencies": {
12
- "@anthropic-ai/sdk": "^0.20.0",
13
- "@a11ypros/a11y-ui-components": "*",
14
- "next": "^14.1.0",
15
- "react": "^18.2.0",
16
- "react-dom": "^18.2.0",
17
- "react-syntax-highlighter": "^15.5.0",
18
- "prismjs": "^1.29.0"
19
- },
20
- "devDependencies": {
21
- "@types/node": "^20.11.5",
22
- "@types/react": "^18.2.48",
23
- "@types/react-dom": "^18.2.18",
24
- "@types/react-syntax-highlighter": "^15.5.11",
25
- "typescript": "^5.3.3"
26
- }
27
- }
28
-
@@ -1,17 +0,0 @@
1
- # Headers for Storybook - VERY permissive CSP to allow eval
2
- # IMPORTANT: Order matters - more specific paths must come first
3
- # The _headers file is processed AFTER netlify.toml, so this will override any CSP
4
- f# This CSP works for both local development and production
5
-
6
- # Storybook root - must come first to match /storybook before catch-all
7
- # 'unsafe-eval' must be in script-src (not default-src) for Storybook to work
8
- /storybook
9
- Content-Security-Policy: default-src 'self' 'unsafe-inline' data: blob: http: https: ws: wss:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob: http: https:; style-src 'self' 'unsafe-inline' data: http: https:; img-src 'self' data: blob: http: https:; font-src 'self' data: http: https:; connect-src 'self' ws: wss: blob: http: https:; worker-src 'self' blob: http: https:; frame-src 'self' http: https:; frame-ancestors 'self';
10
-
11
- # Storybook sub-paths
12
- /storybook/*
13
- Content-Security-Policy: default-src 'self' 'unsafe-inline' data: blob: http: https: ws: wss:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob: http: https:; style-src 'self' 'unsafe-inline' data: http: https:; img-src 'self' data: blob: http: https:; font-src 'self' data: http: https:; connect-src 'self' ws: wss: blob: http: https:; worker-src 'self' blob: http: https:; frame-src 'self' http: https:; frame-ancestors 'self';
14
-
15
- # Storybook static files
16
- /storybook-static/*
17
- Content-Security-Policy: default-src 'self' 'unsafe-inline' data: blob: http: https: ws: wss:; script-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob: http: https:; style-src 'self' 'unsafe-inline' data: http: https:; img-src 'self' data: blob: http: https:; font-src 'self' data: http: https:; connect-src 'self' ws: wss: blob: http: https:; worker-src 'self' blob: http: https:; frame-src 'self' http: https:; frame-ancestors 'self';