@fpkit/acss 6.0.0 → 6.2.0

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 (176) hide show
  1. package/libs/{chunk-DIJBIOFE.js → chunk-2ZJV6KQ3.js} +3 -3
  2. package/libs/{chunk-LXODKKA3.cjs → chunk-3D6WUYSL.cjs} +4 -4
  3. package/libs/{chunk-2JCDEC32.js → chunk-3ENBUQIB.js} +3 -3
  4. package/libs/{chunk-NCGVF2QS.cjs → chunk-3RVZZZWX.cjs} +4 -4
  5. package/libs/{chunk-M7JLT62Q.js → chunk-4F6SI5V5.js} +2 -2
  6. package/libs/chunk-4KJP3L35.js +7 -0
  7. package/libs/chunk-4KJP3L35.js.map +1 -0
  8. package/libs/chunk-66C2J4IX.cjs +13 -0
  9. package/libs/chunk-66C2J4IX.cjs.map +1 -0
  10. package/libs/{chunk-3XJC4XUG.js → chunk-6ADHES7B.js} +2 -2
  11. package/libs/{chunk-AOFQDQVS.cjs → chunk-6WMLG4O5.cjs} +3 -3
  12. package/libs/{chunk-Q7OAQLUT.js → chunk-AQAI6COH.js} +2 -2
  13. package/libs/{chunk-6BUJZ4DJ.cjs → chunk-BVPUT2PP.cjs} +3 -3
  14. package/libs/{chunk-F64GE6RG.cjs → chunk-GVVCXXKI.cjs} +4 -4
  15. package/libs/{chunk-75YQDONV.cjs → chunk-H4JRUNKU.cjs} +6 -6
  16. package/libs/{chunk-G3TFKMWB.js → chunk-H6A2CUWA.js} +5 -5
  17. package/libs/{chunk-2GJHKWEK.cjs → chunk-LQPWXSCK.cjs} +3 -3
  18. package/libs/{chunk-IBUTNPTQ.js → chunk-M5ES7OWP.js} +2 -2
  19. package/libs/{chunk-AWZLSWDO.js → chunk-MAG46S3P.js} +2 -2
  20. package/libs/{chunk-KAR3HDXK.js → chunk-MJJKNHVH.js} +2 -2
  21. package/libs/{chunk-5CJPTDK3.cjs → chunk-OZM455LO.cjs} +3 -3
  22. package/libs/{chunk-NPWHQVYB.cjs → chunk-QU5AQQ4S.cjs} +3 -3
  23. package/libs/{chunk-U5VA34SU.js → chunk-RQSMWB3J.js} +2 -2
  24. package/libs/{chunk-5QSNJQVH.cjs → chunk-S7NIA6PI.cjs} +3 -3
  25. package/libs/{chunk-MBWI67UT.js → chunk-SPESKPUA.js} +2 -2
  26. package/libs/{chunk-PMWL5XZ4.js → chunk-SQ44OCJ2.js} +3 -3
  27. package/libs/{chunk-EKJYOCLY.cjs → chunk-VISQ434C.cjs} +3 -3
  28. package/libs/{chunk-AFINOD2L.cjs → chunk-VN2CVD4H.cjs} +3 -3
  29. package/libs/{chunk-M5JARVJD.cjs → chunk-WTWGTWVI.cjs} +3 -3
  30. package/libs/{chunk-TF3GQKOY.js → chunk-X2RDXWH5.js} +2 -2
  31. package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
  32. package/libs/components/breadcrumbs/breadcrumb.d.cts +1 -1
  33. package/libs/components/breadcrumbs/breadcrumb.d.ts +1 -1
  34. package/libs/components/breadcrumbs/breadcrumb.js +3 -3
  35. package/libs/components/button.cjs +4 -4
  36. package/libs/components/button.d.cts +1 -1
  37. package/libs/components/button.d.ts +1 -1
  38. package/libs/components/button.js +2 -2
  39. package/libs/components/card.cjs +7 -7
  40. package/libs/components/card.d.cts +1 -1
  41. package/libs/components/card.d.ts +1 -1
  42. package/libs/components/card.js +2 -2
  43. package/libs/components/dialog/dialog.cjs +7 -7
  44. package/libs/components/dialog/dialog.js +5 -5
  45. package/libs/components/form/fields.cjs +4 -4
  46. package/libs/components/form/fields.d.cts +1 -1
  47. package/libs/components/form/fields.d.ts +1 -1
  48. package/libs/components/form/fields.js +2 -2
  49. package/libs/components/form/form.css +1 -1
  50. package/libs/components/form/form.css.map +1 -1
  51. package/libs/components/form/form.min.css +2 -2
  52. package/libs/components/form/select.css +1 -0
  53. package/libs/components/form/select.css.map +1 -0
  54. package/libs/components/form/select.min.css +3 -0
  55. package/libs/components/form/textarea.cjs +4 -4
  56. package/libs/components/form/textarea.js +2 -2
  57. package/libs/components/heading/heading.cjs +3 -3
  58. package/libs/components/heading/heading.d.cts +2 -2
  59. package/libs/components/heading/heading.d.ts +2 -2
  60. package/libs/components/heading/heading.js +2 -2
  61. package/libs/components/icons/icon.cjs +4 -4
  62. package/libs/components/icons/icon.d.cts +2 -2
  63. package/libs/components/icons/icon.d.ts +2 -2
  64. package/libs/components/icons/icon.js +2 -2
  65. package/libs/components/layout/landmarks.css +1 -1
  66. package/libs/components/layout/landmarks.css.map +1 -1
  67. package/libs/components/layout/landmarks.min.css +2 -2
  68. package/libs/components/link/link.cjs +6 -6
  69. package/libs/components/link/link.js +2 -2
  70. package/libs/components/list/list.cjs +5 -5
  71. package/libs/components/list/list.d.cts +2 -2
  72. package/libs/components/list/list.d.ts +2 -2
  73. package/libs/components/list/list.js +2 -2
  74. package/libs/components/modal.cjs +4 -4
  75. package/libs/components/modal.js +3 -3
  76. package/libs/components/nav/nav.cjs +7 -7
  77. package/libs/components/nav/nav.d.cts +2 -2
  78. package/libs/components/nav/nav.d.ts +2 -2
  79. package/libs/components/nav/nav.js +3 -3
  80. package/libs/components/text/text.cjs +5 -5
  81. package/libs/components/text/text.d.cts +1 -1
  82. package/libs/components/text/text.d.ts +1 -1
  83. package/libs/components/text/text.js +2 -2
  84. package/libs/{heading-81eef89a.d.ts → heading-064675b6.d.ts} +1 -1
  85. package/libs/hooks.cjs +4 -4
  86. package/libs/hooks.d.cts +1 -1
  87. package/libs/hooks.d.ts +1 -1
  88. package/libs/hooks.js +3 -3
  89. package/libs/{icons-df8e744f.d.ts → icons-48788561.d.ts} +1 -1
  90. package/libs/icons.cjs +3 -3
  91. package/libs/icons.d.cts +2 -2
  92. package/libs/icons.d.ts +2 -2
  93. package/libs/icons.js +2 -2
  94. package/libs/index.cjs +56 -55
  95. package/libs/index.cjs.map +1 -1
  96. package/libs/index.css +1 -1
  97. package/libs/index.css.map +1 -1
  98. package/libs/index.d.cts +43 -6
  99. package/libs/index.d.ts +43 -6
  100. package/libs/index.js +27 -27
  101. package/libs/index.js.map +1 -1
  102. package/libs/{list.types-d26de310.d.ts → list.types-bf2c44c1.d.ts} +1 -1
  103. package/libs/{ui-d01b50d4.d.ts → ui-993fc2e2.d.ts} +5 -2
  104. package/package.json +4 -7
  105. package/src/components/alert/alert.stories.tsx +1 -1
  106. package/src/components/alert/elements/dismiss-button.stories.tsx +1 -2
  107. package/src/components/badge/badge.stories.tsx +1 -1
  108. package/src/components/breadcrumbs/breadcrumb.stories.tsx +1 -2
  109. package/src/components/buttons/button.stories.tsx +1 -3
  110. package/src/components/cards/card.stories.tsx +1 -1
  111. package/src/components/cards/card.test.tsx +1 -1
  112. package/src/components/details/details.stories.tsx +1 -2
  113. package/src/components/dialog/dialog-modal.stories.tsx +1 -2
  114. package/src/components/dialog/dialog.stories.tsx +1 -1
  115. package/src/components/dialog/views/dialog-header.stories.tsx +1 -2
  116. package/src/components/form/CHECKBOX-STYLES.mdx +1 -1
  117. package/src/components/form/CHECKBOX.mdx +1 -1
  118. package/src/components/form/form.scss +4 -14
  119. package/src/components/form/form.stories.tsx +1 -1
  120. package/src/components/form/input.stories.tsx +1 -1
  121. package/src/components/form/select.scss +97 -0
  122. package/src/components/form/select.stories.tsx +225 -9
  123. package/src/components/form/select.test.tsx +541 -0
  124. package/src/components/form/select.tsx +133 -16
  125. package/src/components/heading/heading.stories.tsx +1 -2
  126. package/src/components/images/figure.stories.tsx +1 -2
  127. package/src/components/images/img.stories.tsx +1 -1
  128. package/src/components/layout/README.mdx +1117 -0
  129. package/src/components/layout/STYLES.mdx +159 -4
  130. package/src/components/layout/fieldset.stories.tsx +387 -0
  131. package/src/components/layout/landmarks.scss +115 -2
  132. package/src/components/layout/landmarks.stories.tsx +2 -6
  133. package/src/components/layout/landmarks.tsx +96 -27
  134. package/src/components/nav/nav.stories.tsx +1 -2
  135. package/src/components/text/text.stories.tsx +1 -1
  136. package/src/components/text-to-speech/TextToSpeech.stories.tsx +1 -1
  137. package/src/components/title/title.stories.tsx +1 -2
  138. package/src/components/ui.tsx +11 -4
  139. package/src/styles/form/form.css +75 -14
  140. package/src/styles/form/form.css.map +1 -1
  141. package/src/styles/form/select.css +75 -0
  142. package/src/styles/form/select.css.map +1 -0
  143. package/src/styles/index.css +157 -14
  144. package/src/styles/index.css.map +1 -1
  145. package/src/styles/layout/landmarks.css +83 -0
  146. package/src/styles/layout/landmarks.css.map +1 -1
  147. package/libs/chunk-DDSXKOUB.js +0 -7
  148. package/libs/chunk-DDSXKOUB.js.map +0 -1
  149. package/libs/chunk-EJ6KYBFE.cjs +0 -13
  150. package/libs/chunk-EJ6KYBFE.cjs.map +0 -1
  151. /package/libs/{chunk-DIJBIOFE.js.map → chunk-2ZJV6KQ3.js.map} +0 -0
  152. /package/libs/{chunk-LXODKKA3.cjs.map → chunk-3D6WUYSL.cjs.map} +0 -0
  153. /package/libs/{chunk-2JCDEC32.js.map → chunk-3ENBUQIB.js.map} +0 -0
  154. /package/libs/{chunk-NCGVF2QS.cjs.map → chunk-3RVZZZWX.cjs.map} +0 -0
  155. /package/libs/{chunk-M7JLT62Q.js.map → chunk-4F6SI5V5.js.map} +0 -0
  156. /package/libs/{chunk-3XJC4XUG.js.map → chunk-6ADHES7B.js.map} +0 -0
  157. /package/libs/{chunk-AOFQDQVS.cjs.map → chunk-6WMLG4O5.cjs.map} +0 -0
  158. /package/libs/{chunk-Q7OAQLUT.js.map → chunk-AQAI6COH.js.map} +0 -0
  159. /package/libs/{chunk-6BUJZ4DJ.cjs.map → chunk-BVPUT2PP.cjs.map} +0 -0
  160. /package/libs/{chunk-F64GE6RG.cjs.map → chunk-GVVCXXKI.cjs.map} +0 -0
  161. /package/libs/{chunk-75YQDONV.cjs.map → chunk-H4JRUNKU.cjs.map} +0 -0
  162. /package/libs/{chunk-G3TFKMWB.js.map → chunk-H6A2CUWA.js.map} +0 -0
  163. /package/libs/{chunk-2GJHKWEK.cjs.map → chunk-LQPWXSCK.cjs.map} +0 -0
  164. /package/libs/{chunk-IBUTNPTQ.js.map → chunk-M5ES7OWP.js.map} +0 -0
  165. /package/libs/{chunk-AWZLSWDO.js.map → chunk-MAG46S3P.js.map} +0 -0
  166. /package/libs/{chunk-KAR3HDXK.js.map → chunk-MJJKNHVH.js.map} +0 -0
  167. /package/libs/{chunk-5CJPTDK3.cjs.map → chunk-OZM455LO.cjs.map} +0 -0
  168. /package/libs/{chunk-NPWHQVYB.cjs.map → chunk-QU5AQQ4S.cjs.map} +0 -0
  169. /package/libs/{chunk-U5VA34SU.js.map → chunk-RQSMWB3J.js.map} +0 -0
  170. /package/libs/{chunk-5QSNJQVH.cjs.map → chunk-S7NIA6PI.cjs.map} +0 -0
  171. /package/libs/{chunk-MBWI67UT.js.map → chunk-SPESKPUA.js.map} +0 -0
  172. /package/libs/{chunk-PMWL5XZ4.js.map → chunk-SQ44OCJ2.js.map} +0 -0
  173. /package/libs/{chunk-EKJYOCLY.cjs.map → chunk-VISQ434C.cjs.map} +0 -0
  174. /package/libs/{chunk-AFINOD2L.cjs.map → chunk-VN2CVD4H.cjs.map} +0 -0
  175. /package/libs/{chunk-M5JARVJD.cjs.map → chunk-WTWGTWVI.cjs.map} +0 -0
  176. /package/libs/{chunk-TF3GQKOY.js.map → chunk-X2RDXWH5.js.map} +0 -0
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { U as UI } from './ui-d01b50d4.js';
2
+ import { U as UI } from './ui-993fc2e2.js';
3
3
 
4
4
  /**
5
5
  * Props for the List component.
@@ -101,7 +101,8 @@ type PolymorphicComponentPropWithRef<C extends React.ElementType, Props = {}> =
101
101
  * Styles are always rendered regardless of this prop value.
102
102
  * @property {React.CSSProperties} [styles] - Inline styles to apply (overrides defaultStyles)
103
103
  * @property {React.CSSProperties} [defaultStyles] - Base styles that can be overridden by styles prop
104
- * @property {string} [classes] - CSS class names to apply to the element
104
+ * @property {string} [classes] - CSS class names to apply to the element (custom prop)
105
+ * @property {string} [className] - CSS class names to apply to the element (React standard prop)
105
106
  * @property {string} [id] - HTML id attribute
106
107
  * @property {React.ReactNode} [children] - Child elements to render
107
108
  *
@@ -119,6 +120,7 @@ type UIProps<C extends React.ElementType> = PolymorphicComponentPropWithRef<C, {
119
120
  styles?: React.CSSProperties;
120
121
  defaultStyles?: React.CSSProperties;
121
122
  classes?: string;
123
+ className?: string;
122
124
  id?: string;
123
125
  children?: React.ReactNode;
124
126
  }>;
@@ -166,7 +168,8 @@ type UIComponent = (<C extends React.ElementType = "div">(props: UIProps<C>) =>
166
168
  *
167
169
  * @param {C} [as='div'] - The HTML element type to render. Defaults to 'div'.
168
170
  * @param {React.CSSProperties} [styles] - Inline styles to apply. Overrides defaultStyles.
169
- * @param {string} [classes] - CSS class names to apply to the element.
171
+ * @param {string} [classes] - CSS class names to apply (custom prop). Takes precedence over className.
172
+ * @param {string} [className] - CSS class names to apply (React standard). Used if classes is not provided.
170
173
  * @param {React.CSSProperties} [defaultStyles] - Base styles that can be overridden by styles prop.
171
174
  * @param {React.ReactNode} [children] - Child elements to render inside the component.
172
175
  * @param {PolymorphicRef<C>} [ref] - Forwarded ref with proper typing for the element type.
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@fpkit/acss",
3
3
  "description": "A lightweight React UI library for building modern and accessible components that leverage CSS custom properties for reactive Styles.",
4
4
  "private": false,
5
- "version": "6.0.0",
5
+ "version": "6.2.0",
6
6
  "engines": {
7
7
  "node": ">=22.12.0",
8
8
  "npm": ">=8.0.0"
@@ -24,8 +24,8 @@
24
24
  "test:coverage": "vitest --coverage",
25
25
  "test:ui:coverage": "vitest --coverage --ui",
26
26
  "test:snapshot": "vitest --run --update",
27
- "lint": "eslint . --ext .jsx,.tsx",
28
- "lint-fix": "eslint . --ext .jsx,.tsx"
27
+ "lint": "eslint .",
28
+ "lint-fix": "eslint . --fix"
29
29
  },
30
30
  "dependencies": {
31
31
  "focus-trap": "^7.5.2",
@@ -47,9 +47,6 @@
47
47
  "@vitest/ui": "^0.33.0",
48
48
  "autoprefixer": "^10.4.16",
49
49
  "c8": "^8.0.0",
50
- "eslint": "^8.56.0",
51
- "eslint-config-prettier": "^9.1.0",
52
- "eslint-plugin-prettier": "^5.1.3",
53
50
  "happy-dom": "^10.5.2",
54
51
  "jsdom": "^22.1.0",
55
52
  "npm-run-all": "^4.1.5",
@@ -126,5 +123,5 @@
126
123
  "publishConfig": {
127
124
  "access": "public"
128
125
  },
129
- "gitHead": "e2b6bacdd039449151941bcd9e04fe1980c2a632"
126
+ "gitHead": "6bdffe9311776c02c96d2592d65123b4b6c0e92a"
130
127
  }
@@ -35,7 +35,7 @@ const instructions = (
35
35
  );
36
36
 
37
37
  const meta: Meta<typeof Alert> = {
38
- title: "FP.REACT Components/Alert",
38
+ title: "FP.React Components/Alert",
39
39
  component: Alert,
40
40
  tags: ["beta"],
41
41
  parameters: {
@@ -3,11 +3,10 @@ import { within, expect } from "storybook/test";
3
3
  import DismissButton from "./dismiss-button";
4
4
 
5
5
  const meta: Meta<typeof DismissButton> = {
6
- title: "FP.REACT Elements/DismissButton",
6
+ title: "FP.React Elements/DismissButton",
7
7
  component: DismissButton,
8
8
  tags: ["new"],
9
9
  parameters: {
10
- actions: { argTypesRegex: "^on.*" },
11
10
  docs: {
12
11
  description: {
13
12
  component: "A button component used to dismiss alerts.",
@@ -5,7 +5,7 @@ import Badge from "./badge";
5
5
  import "./badge.scss";
6
6
 
7
7
  const meta: Meta<typeof Badge> = {
8
- title: "FP.REACT Components/Badge",
8
+ title: "FP.React Components/Badge",
9
9
  component: Badge,
10
10
  tags: ["beta", "accessible"],
11
11
  parameters: {
@@ -6,11 +6,10 @@ import Breadcrumb from "./breadcrumb";
6
6
  const linkClicked = fn();
7
7
 
8
8
  const meta: Meta<typeof Breadcrumb> = {
9
- title: "FP.REACT Components/Breadcrumb",
9
+ title: "FP.React Components/Breadcrumb",
10
10
  component: Breadcrumb,
11
11
  tags: ["autodocs"],
12
12
  parameters: {
13
- actions: { argTypesRegex: "^on.*" },
14
13
  docs: {
15
14
  description: {
16
15
  component: `A WCAG 2.1 AA compliant breadcrumb navigation component that helps users understand their current location within a site hierarchy.
@@ -14,9 +14,7 @@ const meta = {
14
14
  children: "Click me",
15
15
  onClick: buttonClicked,
16
16
  },
17
- parameters: {
18
- actions: { argTypesRegex: "^on.*" },
19
- },
17
+ parameters: {},
20
18
  } as Meta;
21
19
 
22
20
  export default meta;
@@ -5,7 +5,7 @@ const content =
5
5
  "Enim aliquip excepteur veniam esse culpa. Et exercitation incididunt occaecat incididunt proident consectetur. Voluptate elit reprehenderit nulla reprehenderit excepteur tempor adipisicing officia eiusmod est id aute. Nisi do et nulla fugiat enim id pariatur ex. Culpa aliquip excepteur velit fugiat qui magna deserunt adipisicing dolore quis. Esse proident qui consectetur Lorem id fugiat elit amet proident enim deserunt dolore sit.";
6
6
 
7
7
  const meta: Meta<typeof Card> = {
8
- title: "FP.REACT Components/Card",
8
+ title: "FP.React Components/Card",
9
9
  tags: ["stable", "autodocs"],
10
10
  component: Card,
11
11
  args: {
@@ -50,7 +50,7 @@ describe('Card', () => {
50
50
  it('applies default shadow class', () => {
51
51
  render(<Card data-testid="card">Content</Card>)
52
52
  const card = screen.getByTestId('card')
53
- expect(card).toHaveClass('shadow')
53
+ expect(card).toHaveClass('shadow-sm')
54
54
  })
55
55
  })
56
56
 
@@ -29,7 +29,7 @@ const content = (
29
29
  const icon = <Icons.Add />;
30
30
 
31
31
  const meta: Meta<typeof Details> = {
32
- title: "FP.REACT Components/Details",
32
+ title: "FP.React Components/Details",
33
33
  component: Details,
34
34
  tags: ["stable"],
35
35
  parameters: {
@@ -77,7 +77,6 @@ const meta: Meta<typeof Details> = {
77
77
  icon: icon,
78
78
  summary: <>Summary Section</>,
79
79
  },
80
- actions: { argTypesRegex: "^on.*" },
81
80
  decorators: [
82
81
  (Story) => (
83
82
  <div className="container" style={{ minWidth: "50vw" }}>
@@ -4,11 +4,10 @@ import { within, expect, userEvent, waitFor } from "storybook/test";
4
4
  import DialogModal from "./dialog-modal";
5
5
  import WithInstructions from "#/decorators/instructions";
6
6
  const meta: Meta<typeof DialogModal> = {
7
- title: "FP.REACT Components/Dialog/DialogModal",
7
+ title: "FP.React Components/Dialog/DialogModal",
8
8
  component: DialogModal,
9
9
  tags: ["autodocs", "experimental"],
10
10
  parameters: {
11
- actions: { argTypesRegex: "^on.*" },
12
11
  docs: {
13
12
  description: {
14
13
  component:
@@ -28,7 +28,7 @@ const buttonDecorator = [
28
28
  ];
29
29
 
30
30
  const meta: Meta<typeof Dialog> = {
31
- title: "FP.REACT Components/Dialog/Dialogs",
31
+ title: "FP.React Components/Dialog/Dialogs",
32
32
  component: Dialog,
33
33
  tags: ["alpha"],
34
34
  parameters: {
@@ -4,11 +4,10 @@ import { within, expect } from "storybook/test";
4
4
  import DialogHeader from "./dialog-header";
5
5
 
6
6
  const meta: Meta<typeof DialogHeader> = {
7
- title: "FP.REACT Components/Dialog/Views/DialogHeader",
7
+ title: "FP.React Components/Dialog/Views/DialogHeader",
8
8
  component: DialogHeader,
9
9
  parameters: {
10
10
  layout: "centered",
11
- actions: { argTypesRegex: "^on.*" },
12
11
  docs: {
13
12
  description: {
14
13
  component:
@@ -1,6 +1,6 @@
1
1
  import { Meta } from "@storybook/addon-docs/blocks";
2
2
 
3
- <Meta title="FP.REACT Forms/Checkbox/Styles" />
3
+ <Meta title="FP.REACT Forms/Inputs/Checkbox/Styles" />
4
4
 
5
5
  # Checkbox CSS Documentation
6
6
 
@@ -1,7 +1,7 @@
1
1
  import { Meta, Canvas, Story, Controls } from "@storybook/addon-docs/blocks";
2
2
  import * as CheckboxStories from "./input.stories";
3
3
 
4
- <Meta title="FP.REACT Forms/Checkbox/Guide" />
4
+ <Meta title="FP.REACT Forms/Inputs/Checkbox/Guide" />
5
5
 
6
6
  # Checkbox Component
7
7
 
@@ -1,5 +1,7 @@
1
1
  // Import checkbox wrapper component styles
2
2
  @use "./checkbox";
3
+ // Import select component styles
4
+ @use "./select";
3
5
 
4
6
  :root {
5
7
  --input-border-color: var(--color-border);
@@ -9,9 +11,9 @@
9
11
  --input-outline: thin solid var(--input-border-color);
10
12
  --input-padding-inline: 0.6rem;
11
13
  --input-padding-block: 0.4rem;
12
- --input-radius: --var(--radius);
14
+ --input-radius: var(--radius);
13
15
  --input-fs: var(--fs);
14
- --input-width: clamp(200px, 100%, 500px);
16
+ --input-width: clamp(12.5rem, 100%, 31.25rem);
15
17
 
16
18
  // Focus state variables (NEW - for accessibility)
17
19
  --input-focus-outline: medium solid var(--input-border-color);
@@ -28,7 +30,6 @@
28
30
  --placeholder-fs: smaller;
29
31
 
30
32
  --form-direction: column;
31
- --select-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><polyline points='6,9 10,13 14,9' stroke='%23000000' stroke-width='1.5' fill='none' /></svg>");
32
33
 
33
34
  /* ==========================================================================
34
35
  Size Tokens
@@ -145,14 +146,3 @@ input[type="checkbox"] {
145
146
  no-repeat center center;
146
147
  }
147
148
  }
148
-
149
- select {
150
- border: var(--input-outline);
151
- outline: none;
152
- -webkit-appearance: none; /* Remove default arrow in Chrome and Safari */
153
- -moz-appearance: none; /* Remove default arrow in Firefox */
154
- appearance: none; /* Remove default arrow in other browsers */
155
- background: var(--select-arrow) no-repeat;
156
- background-position: right 0.5rem top 50%;
157
- padding-inline-end: 0;
158
- }
@@ -10,7 +10,7 @@ import "./form.scss";
10
10
  const FormComponent = Form as unknown as typeof Form;
11
11
 
12
12
  const meta: Meta<typeof FormComponent> = {
13
- title: "FP.REACT Forms/Form",
13
+ title: "FP.React Forms/Form",
14
14
  tags: ["stable", "autodocs"],
15
15
  component: FormComponent,
16
16
  parameters: {
@@ -7,7 +7,7 @@ import { Checkbox as CheckboxComponent } from "./checkbox";
7
7
  import "./form.scss";
8
8
 
9
9
  const meta: Meta<typeof Input> = {
10
- title: "FP.REACT Forms/Inputs",
10
+ title: "FP.React Forms/Inputs",
11
11
  component: Input,
12
12
  tags: ["stable"],
13
13
  args: {},
@@ -0,0 +1,97 @@
1
+ // Select Component Styles
2
+
3
+ :root {
4
+ // Select arrow color (themeable)
5
+ --select-arrow-color: var(--color-text);
6
+
7
+ // Select width (responsive)
8
+ --select-width-mobile: 18.75rem; /* 300px minimum on mobile */
9
+ --select-width-desktop: 100%; /* Full width on larger screens */
10
+ }
11
+
12
+ select {
13
+ // Match input component styling
14
+ border: var(--input-outline);
15
+ border-radius: var(--input-radius);
16
+ outline: none;
17
+ background-color: var(--input-bg, var(--color-surface));
18
+
19
+ // Remove default browser select styling
20
+ -webkit-appearance: none; /* Remove default arrow in Chrome and Safari */
21
+ -moz-appearance: none; /* Remove default arrow in Firefox */
22
+ appearance: none; /* Remove default arrow in other browsers */
23
+
24
+ // Create themeable arrow using CSS gradients
25
+ background-image: linear-gradient(45deg, transparent 50%, var(--select-arrow-color, currentColor) 50%),
26
+ linear-gradient(135deg, var(--select-arrow-color, currentColor) 50%, transparent 50%);
27
+ background-position: calc(100% - 1.25rem) center,
28
+ calc(100% - 1rem) center;
29
+ background-size: 0.3125rem 0.3125rem,
30
+ 0.3125rem 0.3125rem;
31
+ background-repeat: no-repeat;
32
+
33
+ // Match input component height using shared padding variables
34
+ padding-inline-start: var(--input-padding-inline);
35
+ padding-inline-end: 2.5rem; // Extra space for arrow
36
+ padding-block: var(--input-padding-block);
37
+
38
+ // Responsive width: uses larger of 300px or 100% of container
39
+ width: max(var(--select-width-mobile), var(--select-width-desktop));
40
+ }
41
+
42
+ /* ==========================================================================
43
+ Option Styling with Data Attributes
44
+ ========================================================================== */
45
+
46
+ // Example: Variant-based option styling
47
+ // Uncomment and customize for your design system
48
+ /*
49
+ option[data-option="primary"] {
50
+ background-color: var(--color-primary-light, #dbeafe);
51
+ color: var(--color-primary, #2563eb);
52
+ font-weight: 600;
53
+ }
54
+
55
+ option[data-option="success"] {
56
+ background-color: var(--color-success-bg, #dcfce7);
57
+ color: var(--color-success, #16a34a);
58
+ }
59
+
60
+ option[data-option="error"] {
61
+ background-color: var(--color-error-bg, #fee2e2);
62
+ color: var(--color-error, #dc2626);
63
+ }
64
+
65
+ option[data-option="warning"] {
66
+ background-color: var(--color-warning-bg, #fef3c7);
67
+ color: var(--color-warning, #d97706);
68
+ }
69
+ */
70
+
71
+ // Example: Size-based option styling
72
+ /*
73
+ option[data-size="sm"] {
74
+ font-size: 0.875rem; // 14px
75
+ padding: 0.25rem 0.5rem;
76
+ }
77
+
78
+ option[data-size="lg"] {
79
+ font-size: 1.125rem; // 18px
80
+ padding: 0.75rem 1rem;
81
+ font-weight: 500;
82
+ }
83
+ */
84
+
85
+ // Example: Custom data attribute styling
86
+ /*
87
+ option[data-featured="true"] {
88
+ font-weight: 700;
89
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
90
+ color: white;
91
+ }
92
+
93
+ option[data-category="premium"] {
94
+ background-color: #fef3c7;
95
+ font-style: italic;
96
+ }
97
+ */
@@ -2,24 +2,26 @@ import { StoryObj, Meta } from "@storybook/react-vite";
2
2
  import { within, expect } from "storybook/test";
3
3
 
4
4
  import Select from "./select";
5
+ import "./select.scss";
5
6
  import React from "react";
7
+
6
8
  const meta: Meta<typeof Select> = {
7
- title: "FP.REACT Forms/Select",
9
+ title: "FP.React Forms/Select",
8
10
  tags: ["stable"],
9
11
  component: Select,
10
12
  parameters: {
11
13
  docs: {
12
14
  description: {
13
- component: "Base select/Combobox component",
15
+ component: "Accessible select dropdown component with themeable arrow and validation support. Follows fpkit component conventions with ref forwarding and custom styling options.",
14
16
  },
15
17
  },
16
18
  },
17
19
  args: {
18
20
  children: (
19
21
  <>
20
- <Select.Option selectValue="value" selectLabel="Option 1" />
21
- <Select.Option selectValue="value" selectLabel="Option 2" />
22
- <Select.Option selectValue="value" selectLabel="Option 3" />
22
+ <Select.Option value="option1" label="Option 1" />
23
+ <Select.Option value="option2" label="Option 2" />
24
+ <Select.Option value="option3" label="Option 3" />
23
25
  </>
24
26
  ),
25
27
  },
@@ -28,18 +30,232 @@ const meta: Meta<typeof Select> = {
28
30
  export default meta;
29
31
  type Story = StoryObj<typeof Select>;
30
32
 
33
+ /**
34
+ * Default select component with standard options using the new API
35
+ */
31
36
  export const SelectComponent: Story = {
32
37
  args: {
38
+ id: "default-select",
39
+ name: "defaultSelect",
33
40
  children: (
34
41
  <>
35
- <Select.Option selectValue="value" selectLabel="Option 1" />
36
- <Select.Option selectValue="value" selectLabel="Option 2" />
37
- <Select.Option selectValue="value" selectLabel="Option 3" />
42
+ <Select.Option value="us" label="United States" />
43
+ <Select.Option value="uk" label="United Kingdom" />
44
+ <Select.Option value="ca" label="Canada" />
45
+ <Select.Option value="au" label="Australia" />
38
46
  </>
39
47
  ),
40
48
  },
41
49
  play: async ({ canvasElement }) => {
42
50
  const canvas = within(canvasElement);
43
- expect(canvas.getByRole("combobox")).toBeInTheDocument();
51
+ const select = canvas.getByRole("combobox");
52
+ expect(select).toBeInTheDocument();
53
+ expect(select).toHaveAttribute("id", "default-select");
54
+ },
55
+ } as Story;
56
+
57
+ /**
58
+ * Select with label prop for display text
59
+ */
60
+ export const WithLabels: Story = {
61
+ args: {
62
+ children: (
63
+ <>
64
+ <Select.Option value="sm" label="Small (SM)" />
65
+ <Select.Option value="md" label="Medium (MD)" />
66
+ <Select.Option value="lg" label="Large (LG)" />
67
+ <Select.Option value="xl" label="Extra Large (XL)" />
68
+ </>
69
+ ),
70
+ },
71
+ } as Story;
72
+
73
+ /**
74
+ * Select with children instead of label prop
75
+ */
76
+ export const WithChildren: Story = {
77
+ args: {
78
+ children: (
79
+ <>
80
+ <Select.Option value="react">⚛️ React</Select.Option>
81
+ <Select.Option value="vue">💚 Vue</Select.Option>
82
+ <Select.Option value="angular">🔺 Angular</Select.Option>
83
+ <Select.Option value="svelte">🧡 Svelte</Select.Option>
84
+ </>
85
+ ),
86
+ },
87
+ } as Story;
88
+
89
+ /**
90
+ * Select with disabled options
91
+ */
92
+ export const WithDisabledOptions: Story = {
93
+ args: {
94
+ children: (
95
+ <>
96
+ <Select.Option value="available" label="Available Option" />
97
+ <Select.Option value="disabled1" label="Disabled Option" disabled />
98
+ <Select.Option value="active" label="Active Option" />
99
+ <Select.Option value="disabled2" label="Another Disabled" disabled />
100
+ </>
101
+ ),
102
+ },
103
+ } as Story;
104
+
105
+ /**
106
+ * Required select field
107
+ */
108
+ export const Required: Story = {
109
+ args: {
110
+ id: "required-select",
111
+ name: "requiredSelect",
112
+ required: true,
113
+ children: (
114
+ <>
115
+ <Select.Option value="" label="-- Select an option --" />
116
+ <Select.Option value="option1" label="Option 1" />
117
+ <Select.Option value="option2" label="Option 2" />
118
+ <Select.Option value="option3" label="Option 3" />
119
+ </>
120
+ ),
121
+ },
122
+ } as Story;
123
+
124
+ /**
125
+ * Disabled select component
126
+ */
127
+ export const Disabled: Story = {
128
+ args: {
129
+ disabled: true,
130
+ children: (
131
+ <>
132
+ <Select.Option value="option1" label="Option 1" />
133
+ <Select.Option value="option2" label="Option 2" />
134
+ </>
135
+ ),
136
+ },
137
+ } as Story;
138
+
139
+ /**
140
+ * Select with custom styling
141
+ */
142
+ export const CustomStyling: Story = {
143
+ args: {
144
+ styles: {
145
+ "--select-arrow-color": "#0066cc",
146
+ "--input-border-color": "#0066cc",
147
+ "--input-radius": "1rem",
148
+ } as React.CSSProperties,
149
+ classes: "custom-select",
150
+ children: (
151
+ <>
152
+ <Select.Option value="option1" label="Styled Option 1" />
153
+ <Select.Option value="option2" label="Styled Option 2" />
154
+ <Select.Option value="option3" label="Styled Option 3" />
155
+ </>
156
+ ),
157
+ },
158
+ } as Story;
159
+
160
+ /**
161
+ * Styled options with variant data attributes
162
+ */
163
+ export const StyledWithVariants: Story = {
164
+ args: {
165
+ children: (
166
+ <>
167
+ <Select.Option value="default" label="Default Option" />
168
+ <Select.Option value="primary" label="Primary Option" variant="primary" />
169
+ <Select.Option value="success" label="Success Option" variant="success" />
170
+ <Select.Option value="error" label="Error Option" variant="error" />
171
+ <Select.Option value="warning" label="Warning Option" variant="warning" />
172
+ </>
173
+ ),
174
+ },
175
+ parameters: {
176
+ docs: {
177
+ description: {
178
+ story: "Options with variant data attributes for CSS targeting: `option[data-option=\"primary\"]`",
179
+ },
180
+ },
181
+ },
182
+ } as Story;
183
+
184
+ /**
185
+ * Options with size variants
186
+ */
187
+ export const WithSizes: Story = {
188
+ args: {
189
+ children: (
190
+ <>
191
+ <Select.Option value="sm" label="Small Option" size="sm" />
192
+ <Select.Option value="md" label="Medium Option" size="md" />
193
+ <Select.Option value="lg" label="Large Option" size="lg" />
194
+ </>
195
+ ),
196
+ },
197
+ parameters: {
198
+ docs: {
199
+ description: {
200
+ story: "Options with size data attributes: `option[data-size=\"sm\"]`",
201
+ },
202
+ },
203
+ },
204
+ } as Story;
205
+
206
+ /**
207
+ * Options with custom data attributes
208
+ */
209
+ export const WithCustomDataAttributes: Story = {
210
+ args: {
211
+ children: (
212
+ <>
213
+ <Select.Option
214
+ value="premium"
215
+ label="Premium Plan"
216
+ dataAttributes={{ 'data-category': 'premium', 'data-featured': true }}
217
+ />
218
+ <Select.Option
219
+ value="standard"
220
+ label="Standard Plan"
221
+ dataAttributes={{ 'data-category': 'standard' }}
222
+ />
223
+ <Select.Option
224
+ value="basic"
225
+ label="Basic Plan"
226
+ dataAttributes={{ 'data-category': 'basic', 'data-price': 0 }}
227
+ />
228
+ </>
229
+ ),
230
+ },
231
+ parameters: {
232
+ docs: {
233
+ description: {
234
+ story: "Options with custom data attributes for advanced styling: `option[data-category=\"premium\"]`",
235
+ },
236
+ },
237
+ },
238
+ } as Story;
239
+
240
+ /**
241
+ * Legacy API - backwards compatibility with selectValue and selectLabel
242
+ * @deprecated Use `value` and `label` props instead
243
+ */
244
+ export const LegacyAPI: Story = {
245
+ args: {
246
+ children: (
247
+ <>
248
+ <Select.Option selectValue="legacy1" selectLabel="Legacy Option 1" />
249
+ <Select.Option selectValue="legacy2" selectLabel="Legacy Option 2" />
250
+ <Select.Option selectValue="legacy3" selectLabel="Legacy Option 3" />
251
+ </>
252
+ ),
253
+ },
254
+ parameters: {
255
+ docs: {
256
+ description: {
257
+ story: "Example using deprecated `selectValue` and `selectLabel` props. Use `value` and `label` instead.",
258
+ },
259
+ },
44
260
  },
45
261
  } as Story;