@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.
- package/libs/{chunk-DIJBIOFE.js → chunk-2ZJV6KQ3.js} +3 -3
- package/libs/{chunk-LXODKKA3.cjs → chunk-3D6WUYSL.cjs} +4 -4
- package/libs/{chunk-2JCDEC32.js → chunk-3ENBUQIB.js} +3 -3
- package/libs/{chunk-NCGVF2QS.cjs → chunk-3RVZZZWX.cjs} +4 -4
- package/libs/{chunk-M7JLT62Q.js → chunk-4F6SI5V5.js} +2 -2
- package/libs/chunk-4KJP3L35.js +7 -0
- package/libs/chunk-4KJP3L35.js.map +1 -0
- package/libs/chunk-66C2J4IX.cjs +13 -0
- package/libs/chunk-66C2J4IX.cjs.map +1 -0
- package/libs/{chunk-3XJC4XUG.js → chunk-6ADHES7B.js} +2 -2
- package/libs/{chunk-AOFQDQVS.cjs → chunk-6WMLG4O5.cjs} +3 -3
- package/libs/{chunk-Q7OAQLUT.js → chunk-AQAI6COH.js} +2 -2
- package/libs/{chunk-6BUJZ4DJ.cjs → chunk-BVPUT2PP.cjs} +3 -3
- package/libs/{chunk-F64GE6RG.cjs → chunk-GVVCXXKI.cjs} +4 -4
- package/libs/{chunk-75YQDONV.cjs → chunk-H4JRUNKU.cjs} +6 -6
- package/libs/{chunk-G3TFKMWB.js → chunk-H6A2CUWA.js} +5 -5
- package/libs/{chunk-2GJHKWEK.cjs → chunk-LQPWXSCK.cjs} +3 -3
- package/libs/{chunk-IBUTNPTQ.js → chunk-M5ES7OWP.js} +2 -2
- package/libs/{chunk-AWZLSWDO.js → chunk-MAG46S3P.js} +2 -2
- package/libs/{chunk-KAR3HDXK.js → chunk-MJJKNHVH.js} +2 -2
- package/libs/{chunk-5CJPTDK3.cjs → chunk-OZM455LO.cjs} +3 -3
- package/libs/{chunk-NPWHQVYB.cjs → chunk-QU5AQQ4S.cjs} +3 -3
- package/libs/{chunk-U5VA34SU.js → chunk-RQSMWB3J.js} +2 -2
- package/libs/{chunk-5QSNJQVH.cjs → chunk-S7NIA6PI.cjs} +3 -3
- package/libs/{chunk-MBWI67UT.js → chunk-SPESKPUA.js} +2 -2
- package/libs/{chunk-PMWL5XZ4.js → chunk-SQ44OCJ2.js} +3 -3
- package/libs/{chunk-EKJYOCLY.cjs → chunk-VISQ434C.cjs} +3 -3
- package/libs/{chunk-AFINOD2L.cjs → chunk-VN2CVD4H.cjs} +3 -3
- package/libs/{chunk-M5JARVJD.cjs → chunk-WTWGTWVI.cjs} +3 -3
- package/libs/{chunk-TF3GQKOY.js → chunk-X2RDXWH5.js} +2 -2
- package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
- package/libs/components/breadcrumbs/breadcrumb.d.cts +1 -1
- package/libs/components/breadcrumbs/breadcrumb.d.ts +1 -1
- package/libs/components/breadcrumbs/breadcrumb.js +3 -3
- package/libs/components/button.cjs +4 -4
- package/libs/components/button.d.cts +1 -1
- package/libs/components/button.d.ts +1 -1
- package/libs/components/button.js +2 -2
- package/libs/components/card.cjs +7 -7
- package/libs/components/card.d.cts +1 -1
- package/libs/components/card.d.ts +1 -1
- package/libs/components/card.js +2 -2
- package/libs/components/dialog/dialog.cjs +7 -7
- package/libs/components/dialog/dialog.js +5 -5
- package/libs/components/form/fields.cjs +4 -4
- package/libs/components/form/fields.d.cts +1 -1
- package/libs/components/form/fields.d.ts +1 -1
- package/libs/components/form/fields.js +2 -2
- package/libs/components/form/form.css +1 -1
- package/libs/components/form/form.css.map +1 -1
- package/libs/components/form/form.min.css +2 -2
- package/libs/components/form/select.css +1 -0
- package/libs/components/form/select.css.map +1 -0
- package/libs/components/form/select.min.css +3 -0
- package/libs/components/form/textarea.cjs +4 -4
- package/libs/components/form/textarea.js +2 -2
- package/libs/components/heading/heading.cjs +3 -3
- package/libs/components/heading/heading.d.cts +2 -2
- package/libs/components/heading/heading.d.ts +2 -2
- package/libs/components/heading/heading.js +2 -2
- package/libs/components/icons/icon.cjs +4 -4
- package/libs/components/icons/icon.d.cts +2 -2
- package/libs/components/icons/icon.d.ts +2 -2
- package/libs/components/icons/icon.js +2 -2
- package/libs/components/layout/landmarks.css +1 -1
- package/libs/components/layout/landmarks.css.map +1 -1
- package/libs/components/layout/landmarks.min.css +2 -2
- package/libs/components/link/link.cjs +6 -6
- package/libs/components/link/link.js +2 -2
- package/libs/components/list/list.cjs +5 -5
- package/libs/components/list/list.d.cts +2 -2
- package/libs/components/list/list.d.ts +2 -2
- package/libs/components/list/list.js +2 -2
- package/libs/components/modal.cjs +4 -4
- package/libs/components/modal.js +3 -3
- package/libs/components/nav/nav.cjs +7 -7
- package/libs/components/nav/nav.d.cts +2 -2
- package/libs/components/nav/nav.d.ts +2 -2
- package/libs/components/nav/nav.js +3 -3
- package/libs/components/text/text.cjs +5 -5
- package/libs/components/text/text.d.cts +1 -1
- package/libs/components/text/text.d.ts +1 -1
- package/libs/components/text/text.js +2 -2
- package/libs/{heading-81eef89a.d.ts → heading-064675b6.d.ts} +1 -1
- package/libs/hooks.cjs +4 -4
- package/libs/hooks.d.cts +1 -1
- package/libs/hooks.d.ts +1 -1
- package/libs/hooks.js +3 -3
- package/libs/{icons-df8e744f.d.ts → icons-48788561.d.ts} +1 -1
- package/libs/icons.cjs +3 -3
- package/libs/icons.d.cts +2 -2
- package/libs/icons.d.ts +2 -2
- package/libs/icons.js +2 -2
- package/libs/index.cjs +56 -55
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +43 -6
- package/libs/index.d.ts +43 -6
- package/libs/index.js +27 -27
- package/libs/index.js.map +1 -1
- package/libs/{list.types-d26de310.d.ts → list.types-bf2c44c1.d.ts} +1 -1
- package/libs/{ui-d01b50d4.d.ts → ui-993fc2e2.d.ts} +5 -2
- package/package.json +4 -7
- package/src/components/alert/alert.stories.tsx +1 -1
- package/src/components/alert/elements/dismiss-button.stories.tsx +1 -2
- package/src/components/badge/badge.stories.tsx +1 -1
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +1 -2
- package/src/components/buttons/button.stories.tsx +1 -3
- package/src/components/cards/card.stories.tsx +1 -1
- package/src/components/cards/card.test.tsx +1 -1
- package/src/components/details/details.stories.tsx +1 -2
- package/src/components/dialog/dialog-modal.stories.tsx +1 -2
- package/src/components/dialog/dialog.stories.tsx +1 -1
- package/src/components/dialog/views/dialog-header.stories.tsx +1 -2
- package/src/components/form/CHECKBOX-STYLES.mdx +1 -1
- package/src/components/form/CHECKBOX.mdx +1 -1
- package/src/components/form/form.scss +4 -14
- package/src/components/form/form.stories.tsx +1 -1
- package/src/components/form/input.stories.tsx +1 -1
- package/src/components/form/select.scss +97 -0
- package/src/components/form/select.stories.tsx +225 -9
- package/src/components/form/select.test.tsx +541 -0
- package/src/components/form/select.tsx +133 -16
- package/src/components/heading/heading.stories.tsx +1 -2
- package/src/components/images/figure.stories.tsx +1 -2
- package/src/components/images/img.stories.tsx +1 -1
- package/src/components/layout/README.mdx +1117 -0
- package/src/components/layout/STYLES.mdx +159 -4
- package/src/components/layout/fieldset.stories.tsx +387 -0
- package/src/components/layout/landmarks.scss +115 -2
- package/src/components/layout/landmarks.stories.tsx +2 -6
- package/src/components/layout/landmarks.tsx +96 -27
- package/src/components/nav/nav.stories.tsx +1 -2
- package/src/components/text/text.stories.tsx +1 -1
- package/src/components/text-to-speech/TextToSpeech.stories.tsx +1 -1
- package/src/components/title/title.stories.tsx +1 -2
- package/src/components/ui.tsx +11 -4
- package/src/styles/form/form.css +75 -14
- package/src/styles/form/form.css.map +1 -1
- package/src/styles/form/select.css +75 -0
- package/src/styles/form/select.css.map +1 -0
- package/src/styles/index.css +157 -14
- package/src/styles/index.css.map +1 -1
- package/src/styles/layout/landmarks.css +83 -0
- package/src/styles/layout/landmarks.css.map +1 -1
- package/libs/chunk-DDSXKOUB.js +0 -7
- package/libs/chunk-DDSXKOUB.js.map +0 -1
- package/libs/chunk-EJ6KYBFE.cjs +0 -13
- package/libs/chunk-EJ6KYBFE.cjs.map +0 -1
- /package/libs/{chunk-DIJBIOFE.js.map → chunk-2ZJV6KQ3.js.map} +0 -0
- /package/libs/{chunk-LXODKKA3.cjs.map → chunk-3D6WUYSL.cjs.map} +0 -0
- /package/libs/{chunk-2JCDEC32.js.map → chunk-3ENBUQIB.js.map} +0 -0
- /package/libs/{chunk-NCGVF2QS.cjs.map → chunk-3RVZZZWX.cjs.map} +0 -0
- /package/libs/{chunk-M7JLT62Q.js.map → chunk-4F6SI5V5.js.map} +0 -0
- /package/libs/{chunk-3XJC4XUG.js.map → chunk-6ADHES7B.js.map} +0 -0
- /package/libs/{chunk-AOFQDQVS.cjs.map → chunk-6WMLG4O5.cjs.map} +0 -0
- /package/libs/{chunk-Q7OAQLUT.js.map → chunk-AQAI6COH.js.map} +0 -0
- /package/libs/{chunk-6BUJZ4DJ.cjs.map → chunk-BVPUT2PP.cjs.map} +0 -0
- /package/libs/{chunk-F64GE6RG.cjs.map → chunk-GVVCXXKI.cjs.map} +0 -0
- /package/libs/{chunk-75YQDONV.cjs.map → chunk-H4JRUNKU.cjs.map} +0 -0
- /package/libs/{chunk-G3TFKMWB.js.map → chunk-H6A2CUWA.js.map} +0 -0
- /package/libs/{chunk-2GJHKWEK.cjs.map → chunk-LQPWXSCK.cjs.map} +0 -0
- /package/libs/{chunk-IBUTNPTQ.js.map → chunk-M5ES7OWP.js.map} +0 -0
- /package/libs/{chunk-AWZLSWDO.js.map → chunk-MAG46S3P.js.map} +0 -0
- /package/libs/{chunk-KAR3HDXK.js.map → chunk-MJJKNHVH.js.map} +0 -0
- /package/libs/{chunk-5CJPTDK3.cjs.map → chunk-OZM455LO.cjs.map} +0 -0
- /package/libs/{chunk-NPWHQVYB.cjs.map → chunk-QU5AQQ4S.cjs.map} +0 -0
- /package/libs/{chunk-U5VA34SU.js.map → chunk-RQSMWB3J.js.map} +0 -0
- /package/libs/{chunk-5QSNJQVH.cjs.map → chunk-S7NIA6PI.cjs.map} +0 -0
- /package/libs/{chunk-MBWI67UT.js.map → chunk-SPESKPUA.js.map} +0 -0
- /package/libs/{chunk-PMWL5XZ4.js.map → chunk-SQ44OCJ2.js.map} +0 -0
- /package/libs/{chunk-EKJYOCLY.cjs.map → chunk-VISQ434C.cjs.map} +0 -0
- /package/libs/{chunk-AFINOD2L.cjs.map → chunk-VN2CVD4H.cjs.map} +0 -0
- /package/libs/{chunk-M5JARVJD.cjs.map → chunk-WTWGTWVI.cjs.map} +0 -0
- /package/libs/{chunk-TF3GQKOY.js.map → chunk-X2RDXWH5.js.map} +0 -0
|
@@ -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
|
|
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.
|
|
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 .
|
|
28
|
-
"lint-fix": "eslint . --
|
|
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": "
|
|
126
|
+
"gitHead": "6bdffe9311776c02c96d2592d65123b4b6c0e92a"
|
|
130
127
|
}
|
|
@@ -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.
|
|
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.",
|
|
@@ -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.
|
|
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.
|
|
@@ -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.
|
|
8
|
+
title: "FP.React Components/Card",
|
|
9
9
|
tags: ["stable", "autodocs"],
|
|
10
10
|
component: Card,
|
|
11
11
|
args: {
|
|
@@ -29,7 +29,7 @@ const content = (
|
|
|
29
29
|
const icon = <Icons.Add />;
|
|
30
30
|
|
|
31
31
|
const meta: Meta<typeof Details> = {
|
|
32
|
-
title: "FP.
|
|
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.
|
|
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:
|
|
@@ -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.
|
|
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,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:
|
|
14
|
+
--input-radius: var(--radius);
|
|
13
15
|
--input-fs: var(--fs);
|
|
14
|
-
--input-width: clamp(
|
|
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.
|
|
13
|
+
title: "FP.React Forms/Form",
|
|
14
14
|
tags: ["stable", "autodocs"],
|
|
15
15
|
component: FormComponent,
|
|
16
16
|
parameters: {
|
|
@@ -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.
|
|
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: "
|
|
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
|
|
21
|
-
<Select.Option
|
|
22
|
-
<Select.Option
|
|
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
|
|
36
|
-
<Select.Option
|
|
37
|
-
<Select.Option
|
|
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
|
-
|
|
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;
|