@a11ypros/a11y-ui-components 1.0.0 → 1.0.1
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/.storybook/custom.css +69 -0
- package/.storybook/main.ts +46 -0
- package/.storybook/manager.ts +26 -0
- package/.storybook/package.json +6 -0
- package/.storybook/preview.tsx +31 -0
- package/.storybook/public/logo.png +0 -0
- package/.storybook/vite.config.ts +24 -0
- package/.storybook/welcome.mdx +97 -0
- package/DEPLOYMENT.md +154 -0
- package/README.md +227 -0
- package/apps/web/app/(docs)/audit/audit.css +269 -0
- package/apps/web/app/(docs)/audit/page.tsx +271 -0
- package/apps/web/app/(docs)/components/button/page.tsx +49 -0
- package/apps/web/app/(docs)/components/form/page.tsx +92 -0
- package/apps/web/app/(docs)/components/link/page.tsx +31 -0
- package/apps/web/app/(docs)/components/modal/page.tsx +41 -0
- package/apps/web/app/(docs)/components/page.tsx +37 -0
- package/apps/web/app/(docs)/components/table/page.tsx +54 -0
- package/apps/web/app/(docs)/components/tabs/page.tsx +61 -0
- package/apps/web/app/(docs)/components/toast/page.tsx +51 -0
- package/apps/web/app/api/audit/route.ts +128 -0
- package/apps/web/app/favicon.ico +0 -0
- package/apps/web/app/layout.tsx +20 -0
- package/apps/web/app/page.tsx +17 -0
- package/apps/web/app/styles/globals.css +5 -0
- package/apps/web/next-env.d.ts +5 -0
- package/apps/web/next.config.js +21 -0
- package/apps/web/package.json +28 -0
- package/apps/web/public/_headers +17 -0
- package/apps/web/public/_redirects +31 -0
- package/apps/web/public/logo.png +0 -0
- package/apps/web/tsconfig.json +29 -0
- package/netlify/functions/audit.ts +163 -0
- package/netlify.toml +37 -0
- package/package.json +30 -58
- package/packages/design-system/README.md +252 -0
- package/packages/design-system/package.json +68 -0
- package/packages/design-system/scripts/copy-css.js +63 -0
- package/packages/design-system/src/components/Button/Button.stories.tsx +228 -0
- package/packages/design-system/src/components/Button/Button.tsx +137 -0
- package/packages/design-system/src/components/Button/index.ts +3 -0
- package/packages/design-system/src/components/DataTable/DataTable.stories.tsx +211 -0
- package/packages/design-system/src/components/DataTable/DataTable.tsx +293 -0
- package/packages/design-system/src/components/DataTable/index.ts +3 -0
- package/packages/design-system/src/components/Form/Checkbox.stories.tsx +252 -0
- package/packages/design-system/src/components/Form/Checkbox.tsx +114 -0
- package/packages/design-system/src/components/Form/Fieldset.stories.tsx +210 -0
- package/packages/design-system/src/components/Form/Fieldset.tsx +71 -0
- package/packages/design-system/src/components/Form/Input.stories.tsx +164 -0
- package/packages/design-system/src/components/Form/Input.tsx +113 -0
- package/packages/design-system/src/components/Form/Label.tsx +56 -0
- package/packages/design-system/src/components/Form/Radio.stories.tsx +265 -0
- package/packages/design-system/src/components/Form/Radio.tsx +147 -0
- package/packages/design-system/src/components/Form/Select.stories.tsx +295 -0
- package/packages/design-system/src/components/Form/Select.tsx +160 -0
- package/packages/design-system/src/components/Form/Textarea.stories.tsx +253 -0
- package/packages/design-system/src/components/Form/Textarea.tsx +145 -0
- package/packages/design-system/src/components/Form/index.ts +8 -0
- package/packages/design-system/src/components/Link/Link.stories.tsx +128 -0
- package/packages/design-system/src/components/Link/Link.tsx +117 -0
- package/packages/design-system/src/components/Link/index.ts +3 -0
- package/packages/design-system/src/components/Modal/Modal.stories.tsx +165 -0
- package/packages/design-system/src/components/Modal/Modal.tsx +202 -0
- package/packages/design-system/src/components/Modal/index.ts +3 -0
- package/packages/design-system/src/components/Tabs/Tabs.stories.tsx +213 -0
- package/packages/design-system/src/components/Tabs/Tabs.tsx +248 -0
- package/packages/design-system/src/components/Tabs/index.ts +3 -0
- package/packages/design-system/src/components/Toast/Toast.stories.tsx +153 -0
- package/packages/design-system/src/components/Toast/Toast.tsx +175 -0
- package/packages/design-system/src/components/Toast/ToastProvider.tsx +73 -0
- package/packages/design-system/src/components/Toast/index.ts +5 -0
- package/packages/design-system/src/hooks/useAriaLive.ts +51 -0
- package/packages/design-system/src/hooks/useFocusReturn.ts +40 -0
- package/packages/design-system/src/hooks/useFocusTrap.ts +82 -0
- package/{dist/index.js → packages/design-system/src/index.ts} +4 -0
- package/packages/design-system/src/styles/index.ts +3 -0
- package/packages/design-system/src/tokens/breakpoints.ts +28 -0
- package/packages/design-system/src/tokens/colors.ts +98 -0
- package/packages/design-system/src/tokens/index.ts +6 -0
- package/packages/design-system/src/tokens/motion.ts +41 -0
- package/packages/design-system/src/tokens/spacing.ts +24 -0
- package/packages/design-system/src/tokens/theme.ts +19 -0
- package/packages/design-system/src/tokens/typography.ts +64 -0
- package/packages/design-system/src/utils/aria.ts +108 -0
- package/packages/design-system/src/utils/focus.ts +87 -0
- package/packages/design-system/src/utils/index.ts +4 -0
- package/packages/design-system/src/utils/keyboard.ts +77 -0
- package/packages/design-system/tsconfig.json +17 -0
- package/public/logo.png +0 -0
- package/scripts/fix-storybook-paths.js +53 -0
- package/tsconfig.json +20 -0
- package/dist/components/Button/Button.d.ts +0 -37
- package/dist/components/Button/Button.d.ts.map +0 -1
- package/dist/components/Button/Button.js +0 -52
- package/dist/components/Button/index.d.ts +0 -3
- package/dist/components/Button/index.d.ts.map +0 -1
- package/dist/components/Button/index.js +0 -1
- package/dist/components/DataTable/DataTable.d.ts +0 -71
- package/dist/components/DataTable/DataTable.d.ts.map +0 -1
- package/dist/components/DataTable/DataTable.js +0 -122
- package/dist/components/DataTable/index.d.ts +0 -3
- package/dist/components/DataTable/index.d.ts.map +0 -1
- package/dist/components/DataTable/index.js +0 -1
- package/dist/components/Form/Checkbox.d.ts +0 -36
- package/dist/components/Form/Checkbox.d.ts.map +0 -1
- package/dist/components/Form/Checkbox.js +0 -39
- package/dist/components/Form/Fieldset.d.ts +0 -33
- package/dist/components/Form/Fieldset.d.ts.map +0 -1
- package/dist/components/Form/Fieldset.js +0 -34
- package/dist/components/Form/Input.d.ts +0 -37
- package/dist/components/Form/Input.d.ts.map +0 -1
- package/dist/components/Form/Input.js +0 -41
- package/dist/components/Form/Label.d.ts +0 -30
- package/dist/components/Form/Label.d.ts.map +0 -1
- package/dist/components/Form/Label.js +0 -30
- package/dist/components/Form/Radio.d.ts +0 -53
- package/dist/components/Form/Radio.d.ts.map +0 -1
- package/dist/components/Form/Radio.js +0 -39
- package/dist/components/Form/Select.d.ts +0 -51
- package/dist/components/Form/Select.d.ts.map +0 -1
- package/dist/components/Form/Select.js +0 -49
- package/dist/components/Form/Textarea.d.ts +0 -44
- package/dist/components/Form/Textarea.d.ts.map +0 -1
- package/dist/components/Form/Textarea.js +0 -43
- package/dist/components/Form/index.d.ts +0 -8
- package/dist/components/Form/index.d.ts.map +0 -1
- package/dist/components/Form/index.js +0 -7
- package/dist/components/Link/Link.d.ts +0 -34
- package/dist/components/Link/Link.d.ts.map +0 -1
- package/dist/components/Link/Link.js +0 -48
- package/dist/components/Link/index.d.ts +0 -3
- package/dist/components/Link/index.d.ts.map +0 -1
- package/dist/components/Link/index.js +0 -1
- package/dist/components/Modal/Modal.d.ts +0 -64
- package/dist/components/Modal/Modal.d.ts.map +0 -1
- package/dist/components/Modal/Modal.js +0 -108
- package/dist/components/Modal/index.d.ts +0 -3
- package/dist/components/Modal/index.d.ts.map +0 -1
- package/dist/components/Modal/index.js +0 -1
- package/dist/components/Tabs/Tabs.d.ts +0 -63
- package/dist/components/Tabs/Tabs.d.ts.map +0 -1
- package/dist/components/Tabs/Tabs.js +0 -134
- package/dist/components/Tabs/index.d.ts +0 -3
- package/dist/components/Tabs/index.d.ts.map +0 -1
- package/dist/components/Tabs/index.js +0 -1
- package/dist/components/Toast/Toast.d.ts +0 -59
- package/dist/components/Toast/Toast.d.ts.map +0 -1
- package/dist/components/Toast/Toast.js +0 -91
- package/dist/components/Toast/ToastProvider.d.ts +0 -22
- package/dist/components/Toast/ToastProvider.d.ts.map +0 -1
- package/dist/components/Toast/ToastProvider.js +0 -33
- package/dist/components/Toast/index.d.ts +0 -5
- package/dist/components/Toast/index.d.ts.map +0 -1
- package/dist/components/Toast/index.js +0 -2
- package/dist/hooks/useAriaLive.d.ts +0 -9
- package/dist/hooks/useAriaLive.d.ts.map +0 -1
- package/dist/hooks/useAriaLive.js +0 -39
- package/dist/hooks/useFocusReturn.d.ts +0 -9
- package/dist/hooks/useFocusReturn.d.ts.map +0 -1
- package/dist/hooks/useFocusReturn.js +0 -33
- package/dist/hooks/useFocusTrap.d.ts +0 -9
- package/dist/hooks/useFocusTrap.d.ts.map +0 -1
- package/dist/hooks/useFocusTrap.js +0 -68
- package/dist/index.d.ts +0 -22
- package/dist/index.d.ts.map +0 -1
- package/dist/styles/index.d.ts +0 -3
- package/dist/styles/index.d.ts.map +0 -1
- package/dist/styles/index.js +0 -1
- package/dist/tokens/breakpoints.d.ts +0 -25
- package/dist/tokens/breakpoints.d.ts.map +0 -1
- package/dist/tokens/breakpoints.js +0 -23
- package/dist/tokens/colors.d.ts +0 -81
- package/dist/tokens/colors.d.ts.map +0 -1
- package/dist/tokens/colors.js +0 -86
- package/dist/tokens/index.d.ts +0 -6
- package/dist/tokens/index.d.ts.map +0 -1
- package/dist/tokens/index.js +0 -5
- package/dist/tokens/motion.d.ts +0 -30
- package/dist/tokens/motion.d.ts.map +0 -1
- package/dist/tokens/motion.js +0 -34
- package/dist/tokens/spacing.d.ts +0 -22
- package/dist/tokens/spacing.d.ts.map +0 -1
- package/dist/tokens/spacing.js +0 -20
- package/dist/tokens/theme.d.ts +0 -159
- package/dist/tokens/theme.d.ts.map +0 -1
- package/dist/tokens/theme.js +0 -15
- package/dist/tokens/typography.d.ts +0 -45
- package/dist/tokens/typography.d.ts.map +0 -1
- package/dist/tokens/typography.js +0 -56
- package/dist/utils/aria.d.ts +0 -60
- package/dist/utils/aria.d.ts.map +0 -1
- package/dist/utils/aria.js +0 -86
- package/dist/utils/focus.d.ts +0 -30
- package/dist/utils/focus.d.ts.map +0 -1
- package/dist/utils/focus.js +0 -80
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -3
- package/dist/utils/keyboard.d.ts +0 -38
- package/dist/utils/keyboard.d.ts.map +0 -1
- package/dist/utils/keyboard.js +0 -59
- /package/{dist → packages/design-system/src}/components/Button/Button.css +0 -0
- /package/{dist → packages/design-system/src}/components/DataTable/DataTable.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Checkbox.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Fieldset.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Input.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Label.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Radio.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Select.css +0 -0
- /package/{dist → packages/design-system/src}/components/Form/Textarea.css +0 -0
- /package/{dist → packages/design-system/src}/components/Link/Link.css +0 -0
- /package/{dist → packages/design-system/src}/components/Modal/Modal.css +0 -0
- /package/{dist → packages/design-system/src}/components/Tabs/Tabs.css +0 -0
- /package/{dist → packages/design-system/src}/components/Toast/Toast.css +0 -0
- /package/{dist → packages/design-system/src}/components/Toast/ToastProvider.css +0 -0
- /package/{dist → packages/design-system/src}/styles/components.css +0 -0
- /package/{dist → packages/design-system/src}/styles/global.css +0 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/* Custom Storybook styles */
|
|
2
|
+
|
|
3
|
+
/* Override Storybook's default bright blue link color */
|
|
4
|
+
.sbdocs a,
|
|
5
|
+
.sbdocs a:link,
|
|
6
|
+
.docs-story a,
|
|
7
|
+
.docs-story a:link {
|
|
8
|
+
color: #0e8168 !important;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.sbdocs a:hover,
|
|
12
|
+
.docs-story a:hover {
|
|
13
|
+
color: #075985 !important;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.sbdocs a:visited,
|
|
17
|
+
.docs-story a:visited {
|
|
18
|
+
color: #0369a1 !important;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Fix controls pane button hover states - ensure text is visible */
|
|
22
|
+
.sb-controls button:hover,
|
|
23
|
+
.sb-controls button:focus,
|
|
24
|
+
[data-testid="control-buttons-container"] button:hover,
|
|
25
|
+
[data-testid="control-buttons-container"] button:focus,
|
|
26
|
+
button[aria-label*="Set"]:hover,
|
|
27
|
+
button[aria-label*="Set"]:focus,
|
|
28
|
+
button[aria-label*="Reset"]:hover,
|
|
29
|
+
button[aria-label*="Reset"]:focus,
|
|
30
|
+
[id*="storybook-panel"] button:hover,
|
|
31
|
+
[id*="storybook-panel"] button:focus {
|
|
32
|
+
color: #171717 !important;
|
|
33
|
+
background-color: #f5f5f5 !important;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Ensure button text is visible in all states */
|
|
37
|
+
.sb-controls button,
|
|
38
|
+
[data-testid="control-buttons-container"] button,
|
|
39
|
+
button[aria-label*="Set"],
|
|
40
|
+
button[aria-label*="Reset"],
|
|
41
|
+
[id*="storybook-panel"] button {
|
|
42
|
+
color: #171717 !important;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Override left sidebar navigation hover colors to match color scheme */
|
|
46
|
+
.sidebar-container [role="menuitem"]:hover,
|
|
47
|
+
.sidebar-container [role="menuitem"]:focus,
|
|
48
|
+
.sidebar-container a:hover,
|
|
49
|
+
.sidebar-container a:focus,
|
|
50
|
+
[data-nodetype="story"]:hover,
|
|
51
|
+
[data-nodetype="story"]:focus,
|
|
52
|
+
[data-nodetype="component"]:hover,
|
|
53
|
+
[data-nodetype="component"]:focus,
|
|
54
|
+
[data-nodetype="group"]:hover,
|
|
55
|
+
[data-nodetype="group"]:focus {
|
|
56
|
+
background-color: #f5f5f5 !important;
|
|
57
|
+
color: #0e8168 !important;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Override selected state to use primary color */
|
|
61
|
+
.sidebar-container [role="menuitem"][aria-selected="true"],
|
|
62
|
+
.sidebar-container [role="menuitem"][aria-current="true"],
|
|
63
|
+
[data-nodetype="story"][aria-selected="true"],
|
|
64
|
+
[data-nodetype="component"][aria-selected="true"] {
|
|
65
|
+
background-color: #f0f9ff !important;
|
|
66
|
+
color: #0e8168 !important;
|
|
67
|
+
border-left-color: #0e8168 !important;
|
|
68
|
+
}
|
|
69
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { StorybookConfig } from '@storybook/react-vite'
|
|
2
|
+
|
|
3
|
+
const config: StorybookConfig = {
|
|
4
|
+
stories: [
|
|
5
|
+
'../.storybook/welcome.mdx',
|
|
6
|
+
'../packages/design-system/src/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
|
|
7
|
+
addons: [
|
|
8
|
+
'@storybook/addon-links',
|
|
9
|
+
'@storybook/addon-a11y',
|
|
10
|
+
'@storybook/addon-docs',
|
|
11
|
+
],
|
|
12
|
+
framework: {
|
|
13
|
+
name: '@storybook/react-vite',
|
|
14
|
+
options: {
|
|
15
|
+
viteConfigPath: '.storybook/vite.config.ts',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
viteFinal: async (config) => {
|
|
19
|
+
config.define = {
|
|
20
|
+
...config.define,
|
|
21
|
+
'process.env': {},
|
|
22
|
+
'process': { env: {} },
|
|
23
|
+
}
|
|
24
|
+
return config
|
|
25
|
+
},
|
|
26
|
+
docs: {
|
|
27
|
+
autodocs: 'tag',
|
|
28
|
+
},
|
|
29
|
+
typescript: {
|
|
30
|
+
check: false,
|
|
31
|
+
reactDocgen: 'react-docgen-typescript',
|
|
32
|
+
reactDocgenTypescriptOptions: {
|
|
33
|
+
shouldExtractLiteralValuesFromEnum: true,
|
|
34
|
+
propFilter: (prop) => (prop.parent ? !/node_modules/.test(prop.parent.fileName) : true),
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
core: {
|
|
38
|
+
disableTelemetry: true,
|
|
39
|
+
},
|
|
40
|
+
staticDirs: ['../public'],
|
|
41
|
+
// Base path is configured in vite.config.ts to use /storybook-static/
|
|
42
|
+
// This ensures assets use absolute paths that match where files are located
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default config
|
|
46
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { addons } from '@storybook/manager-api'
|
|
2
|
+
import { create } from '@storybook/theming'
|
|
3
|
+
import './custom.css'
|
|
4
|
+
|
|
5
|
+
const theme = create({
|
|
6
|
+
base: 'light',
|
|
7
|
+
brandTitle: 'A11y Pros Design System',
|
|
8
|
+
brandUrl: '/storybook',
|
|
9
|
+
brandImage: '/storybook-static/logo.png', // Path to your logo file (served from staticDirs)
|
|
10
|
+
brandTarget: '_self',
|
|
11
|
+
|
|
12
|
+
colorPrimary: '#0e8168',
|
|
13
|
+
colorSecondary: '#001d2f',
|
|
14
|
+
|
|
15
|
+
// Toolbar colors
|
|
16
|
+
barTextColor: '#171717',
|
|
17
|
+
barSelectedColor: '#0e8168', // Selected nav item color (matches colorPrimary)
|
|
18
|
+
barHoverColor: '#f5f5f5', // Hover color for nav items in left sidebar
|
|
19
|
+
barBg: '#ffffff',
|
|
20
|
+
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
addons.setConfig({
|
|
24
|
+
theme,
|
|
25
|
+
})
|
|
26
|
+
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Preview } from '@storybook/react'
|
|
2
|
+
import '../packages/design-system/src/styles/global.css'
|
|
3
|
+
import './custom.css'
|
|
4
|
+
|
|
5
|
+
const preview: Preview = {
|
|
6
|
+
parameters: {
|
|
7
|
+
actions: { argTypesRegex: '^on[A-Z].*' },
|
|
8
|
+
controls: {
|
|
9
|
+
matchers: {
|
|
10
|
+
color: /(background|color)$/i,
|
|
11
|
+
date: /Date$/i,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
a11y: {
|
|
15
|
+
config: {
|
|
16
|
+
rules: [
|
|
17
|
+
{
|
|
18
|
+
id: 'color-contrast',
|
|
19
|
+
enabled: true,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
docs: {
|
|
25
|
+
toc: false,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export default preview
|
|
31
|
+
|
|
Binary file
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
base: '/storybook-static/',
|
|
5
|
+
define: {
|
|
6
|
+
'process.env': {},
|
|
7
|
+
'process': {
|
|
8
|
+
env: {},
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
build: {
|
|
12
|
+
// Ensure assets use absolute paths
|
|
13
|
+
assetsDir: 'assets',
|
|
14
|
+
// Disable source maps in production to avoid eval issues
|
|
15
|
+
sourcemap: false,
|
|
16
|
+
// Ensure proper minification
|
|
17
|
+
minify: 'esbuild',
|
|
18
|
+
},
|
|
19
|
+
// Ensure proper module resolution
|
|
20
|
+
resolve: {
|
|
21
|
+
preserveSymlinks: false,
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks';
|
|
2
|
+
|
|
3
|
+
<Meta title="Welcome" />
|
|
4
|
+
|
|
5
|
+
# Welcome to the A11y Pros Accessible Design System
|
|
6
|
+
|
|
7
|
+
Welcome to our **accessibility-first React UI component library**. This design system provides a comprehensive collection of fully accessible components built with React, TypeScript, and modern web standards.
|
|
8
|
+
|
|
9
|
+
[View on GitHub](https://github.com/ryan0122/a11ypros-components) • [Live Documentation](https://ui.a11ypros.com)
|
|
10
|
+
|
|
11
|
+
## About This Design System
|
|
12
|
+
|
|
13
|
+
This design system is **authored with accessibility in mind by a certified WAS (Web Accessibility Specialist)**. Every component has been carefully crafted to meet WCAG 2.1/2.2 Level AA standards, ensuring that your applications are usable by everyone, regardless of their abilities or the assistive technologies they use.
|
|
14
|
+
|
|
15
|
+
**Note**: Currently, English is the only supported language for screen reader text and ARIA labels. Internationalization (i18n) support is coming soon.
|
|
16
|
+
|
|
17
|
+
### Key Features
|
|
18
|
+
|
|
19
|
+
- **Fully Accessible Components**: All React UI components are fully accessible, featuring proper ARIA attributes, keyboard navigation, and screen reader support
|
|
20
|
+
- **WCAG 2.1/2.2 Compliant**: Components follow accessibility best practices and meet WCAG Level AA standards
|
|
21
|
+
- **Keyboard Navigation**: Complete keyboard support for all interactive elements
|
|
22
|
+
- **Focus Management**: Proper focus trapping and return focus patterns for modals and dialogs
|
|
23
|
+
- **Semantic HTML**: Components use semantic HTML with ARIA enhancements where needed
|
|
24
|
+
- **Reduced Motion Support**: Respects `prefers-reduced-motion` media query
|
|
25
|
+
- **High Contrast Support**: Supports `prefers-contrast` for better visibility
|
|
26
|
+
- **Design Token System**: Consistent spacing, colors, typography, and motion tokens
|
|
27
|
+
|
|
28
|
+
## Available Components
|
|
29
|
+
|
|
30
|
+
Our component library includes:
|
|
31
|
+
|
|
32
|
+
- **Button**: Accessible button with variants, sizes, and loading states
|
|
33
|
+
- **Link**: Semantic link component with external link detection
|
|
34
|
+
- **Modal**: Focus-trapped modal dialog with ARIA support
|
|
35
|
+
- **DataTable**: Accessible table with keyboard navigation and sorting
|
|
36
|
+
- **Toast**: Notification system with ARIA live regions
|
|
37
|
+
- **Tabs**: Tab component with arrow key navigation
|
|
38
|
+
- **Form Components**: Input, Textarea, Select, Checkbox, Radio, Fieldset, Label
|
|
39
|
+
|
|
40
|
+
## Coming Soon
|
|
41
|
+
|
|
42
|
+
The following components are currently in development and will be available soon:
|
|
43
|
+
|
|
44
|
+
- **DatePicker**: Accessible date selection component with keyboard navigation
|
|
45
|
+
- **Banner**: Alert banner component with ARIA live region support
|
|
46
|
+
- **Phone Text Field**: Specialized input field for phone numbers with formatting
|
|
47
|
+
- **Combobox**: Accessible autocomplete/combobox component with ARIA 1.2 patterns
|
|
48
|
+
|
|
49
|
+
## Getting Started
|
|
50
|
+
|
|
51
|
+
Browse the component stories in the sidebar to explore each component's:
|
|
52
|
+
- Usage examples
|
|
53
|
+
- Accessibility features
|
|
54
|
+
- Keyboard interaction patterns
|
|
55
|
+
- WCAG compliance information
|
|
56
|
+
- Props and API documentation
|
|
57
|
+
|
|
58
|
+
## Accessibility First
|
|
59
|
+
|
|
60
|
+
As a **certified WAS web accessibility specialist**, I've ensured that every component in this library:
|
|
61
|
+
|
|
62
|
+
- Uses semantic HTML elements
|
|
63
|
+
- Implements proper ARIA attributes
|
|
64
|
+
- Supports full keyboard navigation
|
|
65
|
+
- Provides visible focus indicators
|
|
66
|
+
- Meets WCAG contrast requirements
|
|
67
|
+
- Works seamlessly with screen readers
|
|
68
|
+
- Handles focus management appropriately
|
|
69
|
+
|
|
70
|
+
Each component story includes detailed accessibility documentation, so you can understand how to use these components in an accessible way.
|
|
71
|
+
|
|
72
|
+
## Important Note on Accessibility
|
|
73
|
+
|
|
74
|
+
> **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.
|
|
75
|
+
|
|
76
|
+
To ensure your application is truly accessible, consider:
|
|
77
|
+
|
|
78
|
+
- **Proper Implementation**: Use components according to their documented patterns and accessibility guidelines
|
|
79
|
+
- **Application-Level Considerations**: Ensure proper page structure, heading hierarchy, and landmark regions
|
|
80
|
+
- **Content Accessibility**: Write clear, descriptive text and provide alternative text for images
|
|
81
|
+
- **Testing**: Regularly test your application with keyboard navigation and screen readers
|
|
82
|
+
- **User Experience**: Consider the full user journey and how components work together
|
|
83
|
+
|
|
84
|
+
These components provide a solid foundation, but accessibility is achieved through thoughtful implementation across your entire application.
|
|
85
|
+
|
|
86
|
+
## Design Tokens
|
|
87
|
+
|
|
88
|
+
The design system uses CSS custom properties for theming, ensuring consistency across your application while maintaining accessibility standards for color contrast and spacing.
|
|
89
|
+
|
|
90
|
+
## Need Help?
|
|
91
|
+
|
|
92
|
+
Explore the component stories to see examples, accessibility notes, and implementation details. Each component is documented with its WCAG compliance information and keyboard interaction patterns.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
**Built with accessibility in mind by a certified WAS web accessibility specialist.**
|
|
97
|
+
|
package/DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Deployment Guide for ui.a11ypros.com
|
|
2
|
+
|
|
3
|
+
This guide covers deploying the component library and Storybook to Netlify at `ui.a11ypros.com`.
|
|
4
|
+
|
|
5
|
+
## What's Configured
|
|
6
|
+
|
|
7
|
+
✅ **Netlify Configuration** (`netlify.toml`)
|
|
8
|
+
- Builds Storybook and Next.js app
|
|
9
|
+
- Serves Storybook at `/storybook`
|
|
10
|
+
- Routes API calls to Netlify Functions
|
|
11
|
+
|
|
12
|
+
✅ **Next.js Static Export**
|
|
13
|
+
- Configured for static site generation
|
|
14
|
+
- Outputs to `apps/web/out`
|
|
15
|
+
|
|
16
|
+
✅ **Storybook Build**
|
|
17
|
+
- Builds to `apps/web/public/storybook-static`
|
|
18
|
+
- Accessible at `ui.a11ypros.com/storybook`
|
|
19
|
+
|
|
20
|
+
✅ **Netlify Function**
|
|
21
|
+
- Audit API converted to serverless function
|
|
22
|
+
- Located at `netlify/functions/audit.ts`
|
|
23
|
+
- Accessible via `/api/audit` (auto-redirected)
|
|
24
|
+
|
|
25
|
+
## Deployment Steps
|
|
26
|
+
|
|
27
|
+
### 1. Connect Repository to Netlify
|
|
28
|
+
|
|
29
|
+
1. Go to [Netlify Dashboard](https://app.netlify.com)
|
|
30
|
+
2. Click "Add new site" → "Import an existing project"
|
|
31
|
+
3. Connect your Git provider and select this repository
|
|
32
|
+
|
|
33
|
+
### 2. Configure Build Settings
|
|
34
|
+
|
|
35
|
+
Netlify should auto-detect `netlify.toml`, but verify:
|
|
36
|
+
- **Base directory:** `.` (root)
|
|
37
|
+
- **Build command:** `npm install && npm run build-storybook && npm run build --workspace=apps/web`
|
|
38
|
+
- **Publish directory:** `apps/web/out`
|
|
39
|
+
|
|
40
|
+
### 3. Set Environment Variables
|
|
41
|
+
|
|
42
|
+
Go to **Site settings → Environment variables** and add:
|
|
43
|
+
- `ANTHROPIC_API_KEY` - Your Anthropic API key for the audit function
|
|
44
|
+
|
|
45
|
+
### 4. Configure Custom Domain
|
|
46
|
+
|
|
47
|
+
1. Go to **Site settings → Domain management**
|
|
48
|
+
2. Click "Add custom domain"
|
|
49
|
+
3. Enter `ui.a11ypros.com`
|
|
50
|
+
4. Follow Netlify's DNS instructions:
|
|
51
|
+
- Add a **CNAME** record at your domain provider:
|
|
52
|
+
```
|
|
53
|
+
Type: CNAME
|
|
54
|
+
Name: ui
|
|
55
|
+
Value: [your-netlify-site-name].netlify.app
|
|
56
|
+
```
|
|
57
|
+
5. Wait for DNS propagation (5-60 minutes)
|
|
58
|
+
|
|
59
|
+
### 5. Deploy
|
|
60
|
+
|
|
61
|
+
- Netlify will automatically deploy on every push to your main branch
|
|
62
|
+
- Or click "Deploy site" to deploy manually
|
|
63
|
+
|
|
64
|
+
## URLs After Deployment
|
|
65
|
+
|
|
66
|
+
- **Main App:** `https://ui.a11ypros.com`
|
|
67
|
+
- **Storybook:** `https://ui.a11ypros.com/storybook`
|
|
68
|
+
- **Audit API:** `https://ui.a11ypros.com/api/audit` (POST)
|
|
69
|
+
|
|
70
|
+
## How It Works
|
|
71
|
+
|
|
72
|
+
1. **Build Process:**
|
|
73
|
+
- Installs dependencies
|
|
74
|
+
- Builds Storybook → `apps/web/public/storybook-static`
|
|
75
|
+
- Builds Next.js app → `apps/web/out` (includes Storybook from public/)
|
|
76
|
+
|
|
77
|
+
2. **Routing:**
|
|
78
|
+
- `/storybook/*` → Served from `/storybook-static/*`
|
|
79
|
+
- `/api/audit` → Redirected to `/.netlify/functions/audit`
|
|
80
|
+
- `/*` → Next.js SPA routes
|
|
81
|
+
|
|
82
|
+
3. **Netlify Function:**
|
|
83
|
+
- Serverless function handles the audit API
|
|
84
|
+
- Uses `ANTHROPIC_API_KEY` environment variable
|
|
85
|
+
- Supports CORS for cross-origin requests
|
|
86
|
+
|
|
87
|
+
## Troubleshooting
|
|
88
|
+
|
|
89
|
+
### Build Fails
|
|
90
|
+
|
|
91
|
+
- Check Node.js version (should be 18+)
|
|
92
|
+
- Verify all dependencies are in `package.json`
|
|
93
|
+
- Check build logs in Netlify dashboard
|
|
94
|
+
|
|
95
|
+
### Storybook Not Loading
|
|
96
|
+
|
|
97
|
+
- Verify Storybook build completed successfully
|
|
98
|
+
- Check that `apps/web/public/storybook-static` exists
|
|
99
|
+
- Verify redirect rules in `netlify.toml`
|
|
100
|
+
|
|
101
|
+
### API Not Working
|
|
102
|
+
|
|
103
|
+
- Ensure `ANTHROPIC_API_KEY` is set in Netlify environment variables
|
|
104
|
+
- Check Netlify Function logs in dashboard
|
|
105
|
+
- Verify the function is deployed (check Functions tab)
|
|
106
|
+
|
|
107
|
+
### DNS Issues
|
|
108
|
+
|
|
109
|
+
- Wait for DNS propagation (can take up to 48 hours, usually 5-60 minutes)
|
|
110
|
+
- Verify CNAME record is correct
|
|
111
|
+
- Check DNS propagation with `dig ui.a11ypros.com`
|
|
112
|
+
|
|
113
|
+
## Local Testing
|
|
114
|
+
|
|
115
|
+
Test the build locally before deploying:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Install dependencies
|
|
119
|
+
npm install
|
|
120
|
+
|
|
121
|
+
# Build Storybook
|
|
122
|
+
npm run build-storybook
|
|
123
|
+
|
|
124
|
+
# Build Next.js app
|
|
125
|
+
npm run build --workspace=apps/web
|
|
126
|
+
|
|
127
|
+
# Test locally (optional)
|
|
128
|
+
npx serve apps/web/out
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Visit `http://localhost:3000` for the app and `http://localhost:3000/storybook` for Storybook.
|
|
132
|
+
|
|
133
|
+
## File Structure
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
├── netlify.toml # Netlify configuration
|
|
137
|
+
├── netlify/
|
|
138
|
+
│ └── functions/
|
|
139
|
+
│ └── audit.ts # Netlify Function for audit API
|
|
140
|
+
├── apps/
|
|
141
|
+
│ └── web/
|
|
142
|
+
│ ├── public/
|
|
143
|
+
│ │ └── storybook-static/ # Storybook build output
|
|
144
|
+
│ └── out/ # Next.js build output
|
|
145
|
+
└── package.json # Root dependencies
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Notes
|
|
149
|
+
|
|
150
|
+
- The Next.js app uses static export, so no server-side features
|
|
151
|
+
- API routes are converted to Netlify Functions
|
|
152
|
+
- Storybook is served as static files alongside the app
|
|
153
|
+
- All routes are client-side (SPA mode)
|
|
154
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Accessible Design System + AI Audit Assistant
|
|
2
|
+
|
|
3
|
+
An opinionated, accessibility-first design system built with React, TypeScript, and Next.js, featuring an AI-powered accessibility audit assistant powered by Anthropic's Claude API.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **WCAG 2.1/2.2 Compliant Components**: All components follow accessibility best practices
|
|
8
|
+
- **Design Token System**: Consistent spacing, colors, typography, and motion tokens
|
|
9
|
+
- **Keyboard Navigation**: Full keyboard support for all interactive elements
|
|
10
|
+
- **Focus Management**: Proper focus trapping and return focus patterns
|
|
11
|
+
- **ARIA Support**: Semantic HTML with ARIA enhancements where needed
|
|
12
|
+
- **Reduced Motion**: Respects `prefers-reduced-motion` media query
|
|
13
|
+
- **High Contrast**: Supports `prefers-contrast` for better visibility
|
|
14
|
+
- **AI Audit Assistant**: Paste JSX code and get WCAG compliance reviews with code suggestions
|
|
15
|
+
|
|
16
|
+
## Project Structure
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
├── packages/
|
|
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
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Getting Started
|
|
39
|
+
|
|
40
|
+
### Prerequisites
|
|
41
|
+
|
|
42
|
+
- Node.js 18+
|
|
43
|
+
- npm or pnpm
|
|
44
|
+
|
|
45
|
+
### Installation
|
|
46
|
+
|
|
47
|
+
1. Clone the repository:
|
|
48
|
+
```bash
|
|
49
|
+
git clone <repository-url>
|
|
50
|
+
cd PORTFOLIO
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
2. Install dependencies:
|
|
54
|
+
```bash
|
|
55
|
+
npm install
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
3. Set up environment variables:
|
|
59
|
+
Create a `.env.local` file in `apps/web/`:
|
|
60
|
+
```bash
|
|
61
|
+
ANTHROPIC_API_KEY=your_api_key_here
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Development
|
|
65
|
+
|
|
66
|
+
1. Start the Next.js development server:
|
|
67
|
+
```bash
|
|
68
|
+
npm run dev
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
2. Start Storybook (in a separate terminal):
|
|
72
|
+
```bash
|
|
73
|
+
npm run storybook
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The Next.js app will be available at `http://localhost:3000` and Storybook at `http://localhost:6006`.
|
|
77
|
+
|
|
78
|
+
## Component Library
|
|
79
|
+
|
|
80
|
+
### Available Components
|
|
81
|
+
|
|
82
|
+
- **Button**: Accessible button with variants, sizes, and loading states
|
|
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
|
|
89
|
+
|
|
90
|
+
### Usage Example
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { Button, Input, Modal } from '@a11ypros/a11y-ui-components'
|
|
94
|
+
|
|
95
|
+
function MyComponent() {
|
|
96
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<>
|
|
100
|
+
<Button variant="primary" onClick={() => setIsOpen(true)}>
|
|
101
|
+
Open Modal
|
|
102
|
+
</Button>
|
|
103
|
+
|
|
104
|
+
<Modal
|
|
105
|
+
isOpen={isOpen}
|
|
106
|
+
onClose={() => setIsOpen(false)}
|
|
107
|
+
title="Example Modal"
|
|
108
|
+
>
|
|
109
|
+
<Input label="Email" type="email" required />
|
|
110
|
+
</Modal>
|
|
111
|
+
</>
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## WCAG Compliance
|
|
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)
|
|
127
|
+
|
|
128
|
+
## AI Audit Assistant
|
|
129
|
+
|
|
130
|
+
The AI Audit Assistant analyzes JSX code snippets for accessibility issues:
|
|
131
|
+
|
|
132
|
+
1. Navigate to `/audit` in the Next.js app
|
|
133
|
+
2. Paste your JSX code
|
|
134
|
+
3. Click "Run Accessibility Audit"
|
|
135
|
+
4. Review issues grouped by WCAG Success Criteria
|
|
136
|
+
5. See code suggestions for each issue
|
|
137
|
+
|
|
138
|
+
### API Setup
|
|
139
|
+
|
|
140
|
+
The audit assistant requires an Anthropic API key:
|
|
141
|
+
|
|
142
|
+
1. Get your API key from [Anthropic](https://console.anthropic.com/)
|
|
143
|
+
2. Add it to `apps/web/.env.local`:
|
|
144
|
+
```
|
|
145
|
+
ANTHROPIC_API_KEY=your_key_here
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Design Tokens
|
|
149
|
+
|
|
150
|
+
The design system uses CSS custom properties for theming:
|
|
151
|
+
|
|
152
|
+
```css
|
|
153
|
+
/* Colors */
|
|
154
|
+
--color-primary-500: #0ea5e9;
|
|
155
|
+
--color-text-primary: #171717;
|
|
156
|
+
|
|
157
|
+
/* Spacing */
|
|
158
|
+
--spacing-4: 1rem;
|
|
159
|
+
|
|
160
|
+
/* Typography */
|
|
161
|
+
--font-size-base: 1rem;
|
|
162
|
+
--font-weight-semibold: 600;
|
|
163
|
+
|
|
164
|
+
/* Motion */
|
|
165
|
+
--motion-duration-normal: 200ms;
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Storybook
|
|
169
|
+
|
|
170
|
+
View all components and their documentation in Storybook:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npm run storybook
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Each component story includes:
|
|
177
|
+
- Usage examples
|
|
178
|
+
- Accessibility notes
|
|
179
|
+
- Keyboard interaction tables
|
|
180
|
+
- WCAG compliance information
|
|
181
|
+
|
|
182
|
+
## Building
|
|
183
|
+
|
|
184
|
+
Build the Next.js app:
|
|
185
|
+
```bash
|
|
186
|
+
npm run build
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Build Storybook:
|
|
190
|
+
```bash
|
|
191
|
+
npm run build-storybook
|
|
192
|
+
```
|
|
193
|
+
|
|
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
|
+
## Contributing
|
|
208
|
+
|
|
209
|
+
When adding new components:
|
|
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
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT
|
|
221
|
+
|
|
222
|
+
## Resources
|
|
223
|
+
|
|
224
|
+
- [WCAG 2.1 Guidelines](https://www.w3.org/WAI/WCAG21/quickref/)
|
|
225
|
+
- [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/)
|
|
226
|
+
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
|
|
227
|
+
|