@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.
Files changed (217) hide show
  1. package/.storybook/custom.css +69 -0
  2. package/.storybook/main.ts +46 -0
  3. package/.storybook/manager.ts +26 -0
  4. package/.storybook/package.json +6 -0
  5. package/.storybook/preview.tsx +31 -0
  6. package/.storybook/public/logo.png +0 -0
  7. package/.storybook/vite.config.ts +24 -0
  8. package/.storybook/welcome.mdx +97 -0
  9. package/DEPLOYMENT.md +154 -0
  10. package/README.md +227 -0
  11. package/apps/web/app/(docs)/audit/audit.css +269 -0
  12. package/apps/web/app/(docs)/audit/page.tsx +271 -0
  13. package/apps/web/app/(docs)/components/button/page.tsx +49 -0
  14. package/apps/web/app/(docs)/components/form/page.tsx +92 -0
  15. package/apps/web/app/(docs)/components/link/page.tsx +31 -0
  16. package/apps/web/app/(docs)/components/modal/page.tsx +41 -0
  17. package/apps/web/app/(docs)/components/page.tsx +37 -0
  18. package/apps/web/app/(docs)/components/table/page.tsx +54 -0
  19. package/apps/web/app/(docs)/components/tabs/page.tsx +61 -0
  20. package/apps/web/app/(docs)/components/toast/page.tsx +51 -0
  21. package/apps/web/app/api/audit/route.ts +128 -0
  22. package/apps/web/app/favicon.ico +0 -0
  23. package/apps/web/app/layout.tsx +20 -0
  24. package/apps/web/app/page.tsx +17 -0
  25. package/apps/web/app/styles/globals.css +5 -0
  26. package/apps/web/next-env.d.ts +5 -0
  27. package/apps/web/next.config.js +21 -0
  28. package/apps/web/package.json +28 -0
  29. package/apps/web/public/_headers +17 -0
  30. package/apps/web/public/_redirects +31 -0
  31. package/apps/web/public/logo.png +0 -0
  32. package/apps/web/tsconfig.json +29 -0
  33. package/netlify/functions/audit.ts +163 -0
  34. package/netlify.toml +37 -0
  35. package/package.json +30 -58
  36. package/packages/design-system/README.md +252 -0
  37. package/packages/design-system/package.json +68 -0
  38. package/packages/design-system/scripts/copy-css.js +63 -0
  39. package/packages/design-system/src/components/Button/Button.stories.tsx +228 -0
  40. package/packages/design-system/src/components/Button/Button.tsx +137 -0
  41. package/packages/design-system/src/components/Button/index.ts +3 -0
  42. package/packages/design-system/src/components/DataTable/DataTable.stories.tsx +211 -0
  43. package/packages/design-system/src/components/DataTable/DataTable.tsx +293 -0
  44. package/packages/design-system/src/components/DataTable/index.ts +3 -0
  45. package/packages/design-system/src/components/Form/Checkbox.stories.tsx +252 -0
  46. package/packages/design-system/src/components/Form/Checkbox.tsx +114 -0
  47. package/packages/design-system/src/components/Form/Fieldset.stories.tsx +210 -0
  48. package/packages/design-system/src/components/Form/Fieldset.tsx +71 -0
  49. package/packages/design-system/src/components/Form/Input.stories.tsx +164 -0
  50. package/packages/design-system/src/components/Form/Input.tsx +113 -0
  51. package/packages/design-system/src/components/Form/Label.tsx +56 -0
  52. package/packages/design-system/src/components/Form/Radio.stories.tsx +265 -0
  53. package/packages/design-system/src/components/Form/Radio.tsx +147 -0
  54. package/packages/design-system/src/components/Form/Select.stories.tsx +295 -0
  55. package/packages/design-system/src/components/Form/Select.tsx +160 -0
  56. package/packages/design-system/src/components/Form/Textarea.stories.tsx +253 -0
  57. package/packages/design-system/src/components/Form/Textarea.tsx +145 -0
  58. package/packages/design-system/src/components/Form/index.ts +8 -0
  59. package/packages/design-system/src/components/Link/Link.stories.tsx +128 -0
  60. package/packages/design-system/src/components/Link/Link.tsx +117 -0
  61. package/packages/design-system/src/components/Link/index.ts +3 -0
  62. package/packages/design-system/src/components/Modal/Modal.stories.tsx +165 -0
  63. package/packages/design-system/src/components/Modal/Modal.tsx +202 -0
  64. package/packages/design-system/src/components/Modal/index.ts +3 -0
  65. package/packages/design-system/src/components/Tabs/Tabs.stories.tsx +213 -0
  66. package/packages/design-system/src/components/Tabs/Tabs.tsx +248 -0
  67. package/packages/design-system/src/components/Tabs/index.ts +3 -0
  68. package/packages/design-system/src/components/Toast/Toast.stories.tsx +153 -0
  69. package/packages/design-system/src/components/Toast/Toast.tsx +175 -0
  70. package/packages/design-system/src/components/Toast/ToastProvider.tsx +73 -0
  71. package/packages/design-system/src/components/Toast/index.ts +5 -0
  72. package/packages/design-system/src/hooks/useAriaLive.ts +51 -0
  73. package/packages/design-system/src/hooks/useFocusReturn.ts +40 -0
  74. package/packages/design-system/src/hooks/useFocusTrap.ts +82 -0
  75. package/{dist/index.js → packages/design-system/src/index.ts} +4 -0
  76. package/packages/design-system/src/styles/index.ts +3 -0
  77. package/packages/design-system/src/tokens/breakpoints.ts +28 -0
  78. package/packages/design-system/src/tokens/colors.ts +98 -0
  79. package/packages/design-system/src/tokens/index.ts +6 -0
  80. package/packages/design-system/src/tokens/motion.ts +41 -0
  81. package/packages/design-system/src/tokens/spacing.ts +24 -0
  82. package/packages/design-system/src/tokens/theme.ts +19 -0
  83. package/packages/design-system/src/tokens/typography.ts +64 -0
  84. package/packages/design-system/src/utils/aria.ts +108 -0
  85. package/packages/design-system/src/utils/focus.ts +87 -0
  86. package/packages/design-system/src/utils/index.ts +4 -0
  87. package/packages/design-system/src/utils/keyboard.ts +77 -0
  88. package/packages/design-system/tsconfig.json +17 -0
  89. package/public/logo.png +0 -0
  90. package/scripts/fix-storybook-paths.js +53 -0
  91. package/tsconfig.json +20 -0
  92. package/dist/components/Button/Button.d.ts +0 -37
  93. package/dist/components/Button/Button.d.ts.map +0 -1
  94. package/dist/components/Button/Button.js +0 -52
  95. package/dist/components/Button/index.d.ts +0 -3
  96. package/dist/components/Button/index.d.ts.map +0 -1
  97. package/dist/components/Button/index.js +0 -1
  98. package/dist/components/DataTable/DataTable.d.ts +0 -71
  99. package/dist/components/DataTable/DataTable.d.ts.map +0 -1
  100. package/dist/components/DataTable/DataTable.js +0 -122
  101. package/dist/components/DataTable/index.d.ts +0 -3
  102. package/dist/components/DataTable/index.d.ts.map +0 -1
  103. package/dist/components/DataTable/index.js +0 -1
  104. package/dist/components/Form/Checkbox.d.ts +0 -36
  105. package/dist/components/Form/Checkbox.d.ts.map +0 -1
  106. package/dist/components/Form/Checkbox.js +0 -39
  107. package/dist/components/Form/Fieldset.d.ts +0 -33
  108. package/dist/components/Form/Fieldset.d.ts.map +0 -1
  109. package/dist/components/Form/Fieldset.js +0 -34
  110. package/dist/components/Form/Input.d.ts +0 -37
  111. package/dist/components/Form/Input.d.ts.map +0 -1
  112. package/dist/components/Form/Input.js +0 -41
  113. package/dist/components/Form/Label.d.ts +0 -30
  114. package/dist/components/Form/Label.d.ts.map +0 -1
  115. package/dist/components/Form/Label.js +0 -30
  116. package/dist/components/Form/Radio.d.ts +0 -53
  117. package/dist/components/Form/Radio.d.ts.map +0 -1
  118. package/dist/components/Form/Radio.js +0 -39
  119. package/dist/components/Form/Select.d.ts +0 -51
  120. package/dist/components/Form/Select.d.ts.map +0 -1
  121. package/dist/components/Form/Select.js +0 -49
  122. package/dist/components/Form/Textarea.d.ts +0 -44
  123. package/dist/components/Form/Textarea.d.ts.map +0 -1
  124. package/dist/components/Form/Textarea.js +0 -43
  125. package/dist/components/Form/index.d.ts +0 -8
  126. package/dist/components/Form/index.d.ts.map +0 -1
  127. package/dist/components/Form/index.js +0 -7
  128. package/dist/components/Link/Link.d.ts +0 -34
  129. package/dist/components/Link/Link.d.ts.map +0 -1
  130. package/dist/components/Link/Link.js +0 -48
  131. package/dist/components/Link/index.d.ts +0 -3
  132. package/dist/components/Link/index.d.ts.map +0 -1
  133. package/dist/components/Link/index.js +0 -1
  134. package/dist/components/Modal/Modal.d.ts +0 -64
  135. package/dist/components/Modal/Modal.d.ts.map +0 -1
  136. package/dist/components/Modal/Modal.js +0 -108
  137. package/dist/components/Modal/index.d.ts +0 -3
  138. package/dist/components/Modal/index.d.ts.map +0 -1
  139. package/dist/components/Modal/index.js +0 -1
  140. package/dist/components/Tabs/Tabs.d.ts +0 -63
  141. package/dist/components/Tabs/Tabs.d.ts.map +0 -1
  142. package/dist/components/Tabs/Tabs.js +0 -134
  143. package/dist/components/Tabs/index.d.ts +0 -3
  144. package/dist/components/Tabs/index.d.ts.map +0 -1
  145. package/dist/components/Tabs/index.js +0 -1
  146. package/dist/components/Toast/Toast.d.ts +0 -59
  147. package/dist/components/Toast/Toast.d.ts.map +0 -1
  148. package/dist/components/Toast/Toast.js +0 -91
  149. package/dist/components/Toast/ToastProvider.d.ts +0 -22
  150. package/dist/components/Toast/ToastProvider.d.ts.map +0 -1
  151. package/dist/components/Toast/ToastProvider.js +0 -33
  152. package/dist/components/Toast/index.d.ts +0 -5
  153. package/dist/components/Toast/index.d.ts.map +0 -1
  154. package/dist/components/Toast/index.js +0 -2
  155. package/dist/hooks/useAriaLive.d.ts +0 -9
  156. package/dist/hooks/useAriaLive.d.ts.map +0 -1
  157. package/dist/hooks/useAriaLive.js +0 -39
  158. package/dist/hooks/useFocusReturn.d.ts +0 -9
  159. package/dist/hooks/useFocusReturn.d.ts.map +0 -1
  160. package/dist/hooks/useFocusReturn.js +0 -33
  161. package/dist/hooks/useFocusTrap.d.ts +0 -9
  162. package/dist/hooks/useFocusTrap.d.ts.map +0 -1
  163. package/dist/hooks/useFocusTrap.js +0 -68
  164. package/dist/index.d.ts +0 -22
  165. package/dist/index.d.ts.map +0 -1
  166. package/dist/styles/index.d.ts +0 -3
  167. package/dist/styles/index.d.ts.map +0 -1
  168. package/dist/styles/index.js +0 -1
  169. package/dist/tokens/breakpoints.d.ts +0 -25
  170. package/dist/tokens/breakpoints.d.ts.map +0 -1
  171. package/dist/tokens/breakpoints.js +0 -23
  172. package/dist/tokens/colors.d.ts +0 -81
  173. package/dist/tokens/colors.d.ts.map +0 -1
  174. package/dist/tokens/colors.js +0 -86
  175. package/dist/tokens/index.d.ts +0 -6
  176. package/dist/tokens/index.d.ts.map +0 -1
  177. package/dist/tokens/index.js +0 -5
  178. package/dist/tokens/motion.d.ts +0 -30
  179. package/dist/tokens/motion.d.ts.map +0 -1
  180. package/dist/tokens/motion.js +0 -34
  181. package/dist/tokens/spacing.d.ts +0 -22
  182. package/dist/tokens/spacing.d.ts.map +0 -1
  183. package/dist/tokens/spacing.js +0 -20
  184. package/dist/tokens/theme.d.ts +0 -159
  185. package/dist/tokens/theme.d.ts.map +0 -1
  186. package/dist/tokens/theme.js +0 -15
  187. package/dist/tokens/typography.d.ts +0 -45
  188. package/dist/tokens/typography.d.ts.map +0 -1
  189. package/dist/tokens/typography.js +0 -56
  190. package/dist/utils/aria.d.ts +0 -60
  191. package/dist/utils/aria.d.ts.map +0 -1
  192. package/dist/utils/aria.js +0 -86
  193. package/dist/utils/focus.d.ts +0 -30
  194. package/dist/utils/focus.d.ts.map +0 -1
  195. package/dist/utils/focus.js +0 -80
  196. package/dist/utils/index.d.ts +0 -4
  197. package/dist/utils/index.d.ts.map +0 -1
  198. package/dist/utils/index.js +0 -3
  199. package/dist/utils/keyboard.d.ts +0 -38
  200. package/dist/utils/keyboard.d.ts.map +0 -1
  201. package/dist/utils/keyboard.js +0 -59
  202. /package/{dist → packages/design-system/src}/components/Button/Button.css +0 -0
  203. /package/{dist → packages/design-system/src}/components/DataTable/DataTable.css +0 -0
  204. /package/{dist → packages/design-system/src}/components/Form/Checkbox.css +0 -0
  205. /package/{dist → packages/design-system/src}/components/Form/Fieldset.css +0 -0
  206. /package/{dist → packages/design-system/src}/components/Form/Input.css +0 -0
  207. /package/{dist → packages/design-system/src}/components/Form/Label.css +0 -0
  208. /package/{dist → packages/design-system/src}/components/Form/Radio.css +0 -0
  209. /package/{dist → packages/design-system/src}/components/Form/Select.css +0 -0
  210. /package/{dist → packages/design-system/src}/components/Form/Textarea.css +0 -0
  211. /package/{dist → packages/design-system/src}/components/Link/Link.css +0 -0
  212. /package/{dist → packages/design-system/src}/components/Modal/Modal.css +0 -0
  213. /package/{dist → packages/design-system/src}/components/Tabs/Tabs.css +0 -0
  214. /package/{dist → packages/design-system/src}/components/Toast/Toast.css +0 -0
  215. /package/{dist → packages/design-system/src}/components/Toast/ToastProvider.css +0 -0
  216. /package/{dist → packages/design-system/src}/styles/components.css +0 -0
  217. /package/{dist → packages/design-system/src}/styles/global.css +0 -0
@@ -1,37 +0,0 @@
1
- import React from 'react';
2
- import './Input.css';
3
- export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
4
- /**
5
- * Error message to display
6
- */
7
- error?: string;
8
- /**
9
- * Helper text to display below the input
10
- */
11
- helperText?: string;
12
- /**
13
- * Label for the input (creates associated label)
14
- */
15
- label?: string;
16
- }
17
- /**
18
- * Accessible Input component
19
- *
20
- * WCAG Compliance:
21
- * - 1.3.1 Info and Relationships: Proper label-input association
22
- * - 2.5.3 Label in Name: Label text matches accessible name
23
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
24
- * - 4.1.3 Status Messages: Error messages announced
25
- *
26
- * @example
27
- * ```tsx
28
- * <Input
29
- * id="email"
30
- * type="email"
31
- * label="Email address"
32
- * error="Please enter a valid email"
33
- * />
34
- * ```
35
- */
36
- export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
37
- //# sourceMappingURL=Input.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Input.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;IAC7E;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,KAAK,qFAmEjB,CAAA"}
@@ -1,41 +0,0 @@
1
- 'use client';
2
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
- import React from 'react';
4
- import { combineAriaDescribedBy } from '../../utils/aria';
5
- import './Input.css';
6
- /**
7
- * Accessible Input component
8
- *
9
- * WCAG Compliance:
10
- * - 1.3.1 Info and Relationships: Proper label-input association
11
- * - 2.5.3 Label in Name: Label text matches accessible name
12
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
13
- * - 4.1.3 Status Messages: Error messages announced
14
- *
15
- * @example
16
- * ```tsx
17
- * <Input
18
- * id="email"
19
- * type="email"
20
- * label="Email address"
21
- * error="Please enter a valid email"
22
- * />
23
- * ```
24
- */
25
- export const Input = React.forwardRef(({ id, error, helperText, label, className = '', 'aria-describedby': ariaDescribedBy, ...props }, ref) => {
26
- const inputId = React.useId();
27
- const finalId = id || `input-${inputId}`;
28
- const errorId = error ? `${finalId}-error` : undefined;
29
- const helperId = helperText ? `${finalId}-helper` : undefined;
30
- const describedBy = combineAriaDescribedBy(ariaDescribedBy, errorId, helperId);
31
- const classes = [
32
- 'form-input',
33
- error && 'form-input--error',
34
- props.disabled && 'form-input--disabled',
35
- className,
36
- ]
37
- .filter(Boolean)
38
- .join(' ');
39
- return (_jsxs("div", { className: "form-input-wrapper", children: [label && (_jsxs("label", { htmlFor: finalId, className: "form-label", children: [label, props.required && (_jsxs("span", { className: "form-label__required", "aria-hidden": "true", children: [' ', "*"] }))] })), _jsx("input", { ref: ref, id: finalId, className: classes, "aria-invalid": error ? true : undefined, "aria-describedby": describedBy, required: props.required ? true : undefined, ...props }), helperText && !error && (_jsx("span", { id: helperId, className: "form-helper-text", children: helperText })), error && (_jsx("span", { id: errorId, className: "form-error-text", role: "alert", children: error }))] }));
40
- });
41
- Input.displayName = 'Input';
@@ -1,30 +0,0 @@
1
- import React from 'react';
2
- import './Label.css';
3
- export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
4
- /**
5
- * Whether this label is required (shows asterisk)
6
- */
7
- required?: boolean;
8
- /**
9
- * ID of the input this label is associated with
10
- */
11
- htmlFor?: string;
12
- }
13
- /**
14
- * Accessible Label component
15
- *
16
- * WCAG Compliance:
17
- * - 1.3.1 Info and Relationships: Proper label-input association
18
- * - 2.5.3 Label in Name: Label text matches accessible name
19
- * - 4.1.2 Name, Role, Value: Proper semantic HTML
20
- *
21
- * @example
22
- * ```tsx
23
- * <Label htmlFor="email" required>
24
- * Email address
25
- * </Label>
26
- * <Input id="email" type="email" />
27
- * ```
28
- */
29
- export declare const Label: React.ForwardRefExoticComponent<LabelProps & React.RefAttributes<HTMLLabelElement>>;
30
- //# sourceMappingURL=Label.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Label.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Label.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAW,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;IAC7E;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,KAAK,qFAqBjB,CAAA"}
@@ -1,30 +0,0 @@
1
- import { jsxs as _jsxs } from "react/jsx-runtime";
2
- import React from 'react';
3
- import './Label.css';
4
- /**
5
- * Accessible Label component
6
- *
7
- * WCAG Compliance:
8
- * - 1.3.1 Info and Relationships: Proper label-input association
9
- * - 2.5.3 Label in Name: Label text matches accessible name
10
- * - 4.1.2 Name, Role, Value: Proper semantic HTML
11
- *
12
- * @example
13
- * ```tsx
14
- * <Label htmlFor="email" required>
15
- * Email address
16
- * </Label>
17
- * <Input id="email" type="email" />
18
- * ```
19
- */
20
- export const Label = React.forwardRef(({ required = false, className = '', children, ...props }, ref) => {
21
- const classes = [
22
- 'form-label',
23
- required && 'form-label--required',
24
- className,
25
- ]
26
- .filter(Boolean)
27
- .join(' ');
28
- return (_jsxs("label", { ref: ref, className: classes, ...props, children: [children, required && (_jsxs("span", { className: "form-label__required", "aria-hidden": "true", children: [' ', "*"] }))] }));
29
- });
30
- Label.displayName = 'Label';
@@ -1,53 +0,0 @@
1
- import React from 'react';
2
- import './Radio.css';
3
- export interface RadioOption {
4
- value: string;
5
- label: string;
6
- disabled?: boolean;
7
- }
8
- export interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'> {
9
- /**
10
- * Options for the radio group
11
- */
12
- options: RadioOption[];
13
- /**
14
- * Name attribute for the radio group (required)
15
- */
16
- name: string;
17
- /**
18
- * Label for the radio group
19
- */
20
- label?: string;
21
- /**
22
- * Error message to display
23
- */
24
- error?: string;
25
- /**
26
- * Helper text to display
27
- */
28
- helperText?: string;
29
- }
30
- /**
31
- * Accessible Radio component (radio group)
32
- *
33
- * WCAG Compliance:
34
- * - 1.3.1 Info and Relationships: Proper fieldset/legend structure
35
- * - 2.1.1 Keyboard: Full keyboard navigation
36
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
37
- *
38
- * @example
39
- * ```tsx
40
- * <Radio
41
- * name="size"
42
- * label="Size"
43
- * options={[
44
- * { value: 's', label: 'Small' },
45
- * { value: 'm', label: 'Medium' },
46
- * ]}
47
- * value={selected}
48
- * onChange={handleChange}
49
- * />
50
- * ```
51
- */
52
- export declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>;
53
- //# sourceMappingURL=Radio.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Radio.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Radio.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,UAAW,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC3F;;OAEG;IACH,OAAO,EAAE,WAAW,EAAE,CAAA;IAEtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IAEZ;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,KAAK,qFAkFjB,CAAA"}
@@ -1,39 +0,0 @@
1
- 'use client';
2
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
- import React from 'react';
4
- import { combineAriaDescribedBy } from '../../utils/aria';
5
- import './Radio.css';
6
- /**
7
- * Accessible Radio component (radio group)
8
- *
9
- * WCAG Compliance:
10
- * - 1.3.1 Info and Relationships: Proper fieldset/legend structure
11
- * - 2.1.1 Keyboard: Full keyboard navigation
12
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
13
- *
14
- * @example
15
- * ```tsx
16
- * <Radio
17
- * name="size"
18
- * label="Size"
19
- * options={[
20
- * { value: 's', label: 'Small' },
21
- * { value: 'm', label: 'Medium' },
22
- * ]}
23
- * value={selected}
24
- * onChange={handleChange}
25
- * />
26
- * ```
27
- */
28
- export const Radio = React.forwardRef(({ name, options, label, error, helperText, className = '', value, onChange, disabled, required, 'aria-describedby': ariaDescribedBy, ...props }, ref) => {
29
- const groupId = React.useId();
30
- const errorId = error ? `radio-${groupId}-error` : undefined;
31
- const helperId = helperText ? `radio-${groupId}-helper` : undefined;
32
- const describedBy = combineAriaDescribedBy(ariaDescribedBy, errorId, helperId);
33
- return (_jsxs("div", { className: "form-radio-wrapper", children: [label && (_jsx("div", { className: "form-radio-label", role: "group", "aria-labelledby": label ? `radio-label-${groupId}` : undefined, children: _jsxs("span", { id: `radio-label-${groupId}`, className: "form-label", children: [label, required && (_jsxs("span", { className: "form-label__required", "aria-hidden": "true", children: [' ', "*"] }))] }) })), _jsx("div", { className: "form-radio-group", role: "radiogroup", "aria-describedby": describedBy, "aria-invalid": error ? true : undefined, children: options.map((option, index) => {
34
- const optionId = `radio-${groupId}-${index}`;
35
- const isChecked = value === option.value;
36
- return (_jsxs("div", { className: "form-radio-option", children: [_jsx("input", { ref: index === 0 ? ref : undefined, id: optionId, type: "radio", name: name, value: option.value, checked: isChecked, onChange: onChange, disabled: option.disabled || disabled, required: required, className: "form-radio", ...props }), _jsx("label", { htmlFor: optionId, className: "form-radio-label", children: option.label })] }, option.value));
37
- }) }), helperText && !error && (_jsx("span", { id: helperId, className: "form-helper-text", children: helperText })), error && (_jsx("span", { id: errorId, className: "form-error-text", role: "alert", children: error }))] }));
38
- });
39
- Radio.displayName = 'Radio';
@@ -1,51 +0,0 @@
1
- import React from 'react';
2
- import './Select.css';
3
- export interface SelectOption {
4
- value: string;
5
- label: string;
6
- disabled?: boolean;
7
- }
8
- export interface SelectProps extends Omit<React.SelectHTMLAttributes<HTMLSelectElement>, 'children'> {
9
- /**
10
- * Options for the select
11
- */
12
- options: SelectOption[];
13
- /**
14
- * Error message to display
15
- */
16
- error?: string;
17
- /**
18
- * Helper text to display below the select
19
- */
20
- helperText?: string;
21
- /**
22
- * Label for the select
23
- */
24
- label?: string;
25
- /**
26
- * Placeholder option text
27
- */
28
- placeholder?: string;
29
- }
30
- /**
31
- * Accessible Select component
32
- *
33
- * WCAG Compliance:
34
- * - 1.3.1 Info and Relationships: Proper label-select association
35
- * - 2.1.1 Keyboard: Full keyboard navigation
36
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
37
- *
38
- * @example
39
- * ```tsx
40
- * <Select
41
- * id="country"
42
- * label="Country"
43
- * options={[
44
- * { value: 'us', label: 'United States' },
45
- * { value: 'ca', label: 'Canada' },
46
- * ]}
47
- * />
48
- * ```
49
- */
50
- export declare const Select: React.ForwardRefExoticComponent<SelectProps & React.RefAttributes<HTMLSelectElement>>;
51
- //# sourceMappingURL=Select.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Select.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAGzB,OAAO,cAAc,CAAA;AAErB,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,WAAY,SAAQ,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAClG;;OAEG;IACH,OAAO,EAAE,YAAY,EAAE,CAAA;IAEvB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,MAAM,uFAgGlB,CAAA"}
@@ -1,49 +0,0 @@
1
- 'use client';
2
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
- import React from 'react';
4
- import { combineAriaDescribedBy } from '../../utils/aria';
5
- import './Select.css';
6
- /**
7
- * Accessible Select component
8
- *
9
- * WCAG Compliance:
10
- * - 1.3.1 Info and Relationships: Proper label-select association
11
- * - 2.1.1 Keyboard: Full keyboard navigation
12
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
13
- *
14
- * @example
15
- * ```tsx
16
- * <Select
17
- * id="country"
18
- * label="Country"
19
- * options={[
20
- * { value: 'us', label: 'United States' },
21
- * { value: 'ca', label: 'Canada' },
22
- * ]}
23
- * />
24
- * ```
25
- */
26
- export const Select = React.forwardRef(({ id, options, error, helperText, label, placeholder, className = '', 'aria-describedby': ariaDescribedBy, ...props }, ref) => {
27
- const selectId = React.useId();
28
- const finalId = id || `select-${selectId}`;
29
- const errorId = error ? `${finalId}-error` : undefined;
30
- const helperId = helperText ? `${finalId}-helper` : undefined;
31
- const describedBy = combineAriaDescribedBy(ariaDescribedBy, errorId, helperId);
32
- const handleKeyDown = React.useCallback((event) => {
33
- // Arrow keys are handled natively by select
34
- // But we can add custom handling if needed
35
- if (props.onKeyDown) {
36
- props.onKeyDown(event);
37
- }
38
- }, [props.onKeyDown]);
39
- const classes = [
40
- 'form-select',
41
- error && 'form-select--error',
42
- props.disabled && 'form-select--disabled',
43
- className,
44
- ]
45
- .filter(Boolean)
46
- .join(' ');
47
- return (_jsxs("div", { className: "form-select-wrapper", children: [label && (_jsxs("label", { htmlFor: finalId, className: "form-label", children: [label, props.required && (_jsxs("span", { className: "form-label__required", "aria-hidden": "true", children: [' ', "*"] }))] })), _jsxs("select", { ref: ref, id: finalId, className: classes, "aria-invalid": error ? true : undefined, "aria-describedby": describedBy, onKeyDown: handleKeyDown, required: props.required ? true : undefined, ...props, children: [placeholder && (_jsx("option", { value: "", disabled: true, children: placeholder })), options.map((option) => (_jsx("option", { value: option.value, disabled: option.disabled, children: option.label }, option.value)))] }), helperText && !error && (_jsx("span", { id: helperId, className: "form-helper-text", children: helperText })), error && (_jsx("span", { id: errorId, className: "form-error-text", role: "alert", children: error }))] }));
48
- });
49
- Select.displayName = 'Select';
@@ -1,44 +0,0 @@
1
- import React from 'react';
2
- import './Textarea.css';
3
- export interface TextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
4
- /**
5
- * Error message to display
6
- */
7
- error?: string;
8
- /**
9
- * Helper text to display below the textarea
10
- */
11
- helperText?: string;
12
- /**
13
- * Label for the textarea
14
- */
15
- label?: string;
16
- /**
17
- * Maximum character count (shows counter)
18
- */
19
- maxLength?: number;
20
- /**
21
- * Whether to show character count
22
- */
23
- showCount?: boolean;
24
- }
25
- /**
26
- * Accessible Textarea component
27
- *
28
- * WCAG Compliance:
29
- * - 1.3.1 Info and Relationships: Proper label-textarea association
30
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
31
- * - 4.1.3 Status Messages: Error messages announced
32
- *
33
- * @example
34
- * ```tsx
35
- * <Textarea
36
- * id="message"
37
- * label="Message"
38
- * maxLength={500}
39
- * showCount
40
- * />
41
- * ```
42
- */
43
- export declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
44
- //# sourceMappingURL=Textarea.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../../src/components/Form/Textarea.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,gBAAgB,CAAA;AAEvB,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,sBAAsB,CAAC,mBAAmB,CAAC;IACtF;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,QAAQ,2FA0FpB,CAAA"}
@@ -1,43 +0,0 @@
1
- 'use client';
2
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
- import React from 'react';
4
- import { combineAriaDescribedBy } from '../../utils/aria';
5
- import './Textarea.css';
6
- /**
7
- * Accessible Textarea component
8
- *
9
- * WCAG Compliance:
10
- * - 1.3.1 Info and Relationships: Proper label-textarea association
11
- * - 4.1.2 Name, Role, Value: Proper ARIA attributes
12
- * - 4.1.3 Status Messages: Error messages announced
13
- *
14
- * @example
15
- * ```tsx
16
- * <Textarea
17
- * id="message"
18
- * label="Message"
19
- * maxLength={500}
20
- * showCount
21
- * />
22
- * ```
23
- */
24
- export const Textarea = React.forwardRef(({ id, error, helperText, label, maxLength, showCount = false, className = '', value, 'aria-describedby': ariaDescribedBy, ...props }, ref) => {
25
- const textareaId = React.useId();
26
- const finalId = id || `textarea-${textareaId}`;
27
- const errorId = error ? `${finalId}-error` : undefined;
28
- const helperId = helperText ? `${finalId}-helper` : undefined;
29
- const countId = showCount ? `${finalId}-count` : undefined;
30
- const describedBy = combineAriaDescribedBy(ariaDescribedBy, errorId, helperId, countId);
31
- const currentLength = typeof value === 'string' ? value.length : 0;
32
- const remainingChars = maxLength ? maxLength - currentLength : undefined;
33
- const classes = [
34
- 'form-textarea',
35
- error && 'form-textarea--error',
36
- props.disabled && 'form-textarea--disabled',
37
- className,
38
- ]
39
- .filter(Boolean)
40
- .join(' ');
41
- return (_jsxs("div", { className: "form-textarea-wrapper", children: [label && (_jsxs("label", { htmlFor: finalId, className: "form-label", children: [label, props.required && (_jsxs("span", { className: "form-label__required", "aria-hidden": "true", children: [' ', "*"] }))] })), _jsx("textarea", { ref: ref, id: finalId, className: classes, maxLength: maxLength, value: value, "aria-invalid": error ? true : undefined, "aria-describedby": describedBy, required: props.required ? true : undefined, ...props }), (showCount || helperText) && (_jsxs("div", { className: "form-textarea-footer", children: [helperText && !error && (_jsx("span", { id: helperId, className: "form-helper-text", children: helperText })), error && (_jsx("span", { id: errorId, className: "form-error-text", role: "alert", children: error })), showCount && maxLength && (_jsxs("span", { id: countId, className: "form-character-count", "aria-live": "polite", children: [currentLength, " / ", maxLength] }))] }))] }));
42
- });
43
- Textarea.displayName = 'Textarea';
@@ -1,8 +0,0 @@
1
- export * from './Input';
2
- export * from './Textarea';
3
- export * from './Select';
4
- export * from './Checkbox';
5
- export * from './Radio';
6
- export * from './Fieldset';
7
- export * from './Label';
8
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Form/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,UAAU,CAAA;AACxB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
@@ -1,7 +0,0 @@
1
- export * from './Input';
2
- export * from './Textarea';
3
- export * from './Select';
4
- export * from './Checkbox';
5
- export * from './Radio';
6
- export * from './Fieldset';
7
- export * from './Label';
@@ -1,34 +0,0 @@
1
- import React from 'react';
2
- import './Link.css';
3
- export interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
4
- /**
5
- * Whether this is an external link
6
- * Automatically adds rel="noopener noreferrer" for security
7
- */
8
- external?: boolean;
9
- /**
10
- * Whether this is a skip link (for keyboard navigation)
11
- */
12
- skip?: boolean;
13
- /**
14
- * ARIA label for the link (required if no visible text)
15
- */
16
- 'aria-label'?: string;
17
- }
18
- /**
19
- * Accessible Link component
20
- *
21
- * WCAG Compliance:
22
- * - 2.4.4 Link Purpose: Clear link text or aria-label
23
- * - 2.4.7 Focus Visible: Clear focus indicators
24
- * - 4.1.2 Name, Role, Value: Proper semantic HTML
25
- *
26
- * @example
27
- * ```tsx
28
- * <Link href="/about" external>
29
- * Learn more
30
- * </Link>
31
- * ```
32
- */
33
- export declare const Link: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
34
- //# sourceMappingURL=Link.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Link.d.ts","sourceRoot":"","sources":["../../../src/components/Link/Link.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,YAAY,CAAA;AAEnB,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAC9E;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;OAEG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,IAAI,qFA2EhB,CAAA"}
@@ -1,48 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React from 'react';
4
- import './Link.css';
5
- /**
6
- * Accessible Link component
7
- *
8
- * WCAG Compliance:
9
- * - 2.4.4 Link Purpose: Clear link text or aria-label
10
- * - 2.4.7 Focus Visible: Clear focus indicators
11
- * - 4.1.2 Name, Role, Value: Proper semantic HTML
12
- *
13
- * @example
14
- * ```tsx
15
- * <Link href="/about" external>
16
- * Learn more
17
- * </Link>
18
- * ```
19
- */
20
- export const Link = React.forwardRef(({ external = false, skip = false, href, rel, target, className = '', children, 'aria-label': ariaLabel, ...props }, ref) => {
21
- // Determine if link is external based on href or explicit prop
22
- const isExternal = external ||
23
- (href && (href.startsWith('http') || href.startsWith('//')));
24
- // Build rel attribute
25
- const relAttributes = React.useMemo(() => {
26
- const attrs = new Set(rel?.split(' ') || []);
27
- if (isExternal) {
28
- attrs.add('noopener');
29
- attrs.add('noreferrer');
30
- }
31
- return Array.from(attrs).join(' ');
32
- }, [isExternal, rel]);
33
- // Set target for external links
34
- const linkTarget = isExternal && !target ? '_blank' : target;
35
- const classes = [
36
- 'link',
37
- skip && 'link--skip',
38
- className,
39
- ]
40
- .filter(Boolean)
41
- .join(' ');
42
- // Skip links should use button semantics if no href
43
- if (skip && !href) {
44
- return (_jsx("button", { ref: ref, className: classes, "aria-label": ariaLabel, ...props, children: children }));
45
- }
46
- return (_jsxs("a", { ref: ref, href: href, rel: relAttributes || undefined, target: linkTarget, className: classes, "aria-label": ariaLabel, ...props, children: [children, isExternal && (_jsxs("span", { className: "link__external-icon", "aria-hidden": "true", children: [' ', _jsx("span", { "aria-label": "(opens in new tab)", children: "\u2197" })] }))] }));
47
- });
48
- Link.displayName = 'Link';
@@ -1,3 +0,0 @@
1
- export { Link } from './Link';
2
- export type { LinkProps } from './Link';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Link/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA"}
@@ -1 +0,0 @@
1
- export { Link } from './Link';
@@ -1,64 +0,0 @@
1
- import React from 'react';
2
- import './Modal.css';
3
- export interface ModalProps {
4
- /**
5
- * Whether the modal is open
6
- */
7
- isOpen: boolean;
8
- /**
9
- * Callback when modal should close
10
- */
11
- onClose: () => void;
12
- /**
13
- * Title of the modal (required for accessibility)
14
- */
15
- title: string;
16
- /**
17
- * Content of the modal
18
- */
19
- children: React.ReactNode;
20
- /**
21
- * Whether to close on backdrop click
22
- */
23
- closeOnBackdropClick?: boolean;
24
- /**
25
- * Whether to close on ESC key press
26
- */
27
- closeOnEscape?: boolean;
28
- /**
29
- * Size of the modal
30
- */
31
- size?: 'sm' | 'md' | 'lg' | 'full';
32
- /**
33
- * Element to return focus to when modal closes
34
- */
35
- returnFocusTo?: HTMLElement | null;
36
- }
37
- /**
38
- * Accessible Modal component using HTML5 dialog element
39
- *
40
- * Uses the native `<dialog>` element which provides:
41
- * - Built-in focus management and focus trapping
42
- * - Automatic body scroll prevention
43
- * - Native backdrop overlay
44
- * - ESC key handling (configurable)
45
- *
46
- * WCAG Compliance:
47
- * - 2.1.1 Keyboard: ESC key support, built-in focus trap
48
- * - 2.1.2 No Keyboard Trap: Focus returns to trigger
49
- * - 2.4.3 Focus Order: Focus trapped within modal (native behavior)
50
- * - 4.1.2 Name, Role, Value: ARIA modal pattern
51
- *
52
- * @example
53
- * ```tsx
54
- * <Modal
55
- * isOpen={isOpen}
56
- * onClose={() => setIsOpen(false)}
57
- * title="Confirm Action"
58
- * >
59
- * <p>Are you sure?</p>
60
- * </Modal>
61
- * ```
62
- */
63
- export declare const Modal: React.FC<ModalProps>;
64
- //# sourceMappingURL=Modal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/components/Modal/Modal.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA4B,MAAM,OAAO,CAAA;AAGhD,OAAO,aAAa,CAAA;AAEpB,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,MAAM,EAAE,OAAO,CAAA;IAEf;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAA;IAEnB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAA;IAEb;;OAEG;IACH,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IAEzB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAA;IAElC;;OAEG;IACH,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CA2HtC,CAAA"}