@fpkit/acss 0.5.8 → 0.5.10

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 (59) hide show
  1. package/libs/components/buttons/button.css +1 -1
  2. package/libs/components/buttons/button.css.map +1 -1
  3. package/libs/components/buttons/button.min.css +2 -2
  4. package/libs/index.cjs +2 -2
  5. package/libs/index.cjs.map +1 -1
  6. package/libs/index.css +1 -1
  7. package/libs/index.css.map +1 -1
  8. package/libs/index.d.cts +1 -6
  9. package/libs/index.d.ts +1 -6
  10. package/libs/index.js +2 -2
  11. package/libs/index.js.map +1 -1
  12. package/package.json +6 -2
  13. package/src/components/README.mdx +1 -1
  14. package/src/components/alert/README.mdx +1 -1
  15. package/src/components/alert/alert.stories.tsx +2 -2
  16. package/src/components/alert/elements/README.mdx +1 -1
  17. package/src/components/alert/elements/dismiss-button.stories.tsx +2 -2
  18. package/src/components/badge/badge.mdx +1 -1
  19. package/src/components/badge/badge.stories.tsx +2 -2
  20. package/src/components/breadcrumbs/README.mdx +91 -0
  21. package/src/components/breadcrumbs/breadcrumb.stories.tsx +2 -2
  22. package/src/components/breadcrumbs/breadcrumb.tsx +92 -87
  23. package/src/components/buttons/README.mdx +1 -1
  24. package/src/components/buttons/button.scss +3 -3
  25. package/src/components/buttons/button.stories.tsx +2 -2
  26. package/src/components/buttons/button.test.tsx +1 -1
  27. package/src/components/cards/card.stories.tsx +2 -2
  28. package/src/components/details/README.mdx +1 -1
  29. package/src/components/details/details.stories.tsx +2 -2
  30. package/src/components/dialog/README.mdx +1 -1
  31. package/src/components/dialog/dialog-modal.stories.tsx +2 -2
  32. package/src/components/dialog/dialog-modal.tsx +1 -1
  33. package/src/components/dialog/dialog.stories.tsx +2 -2
  34. package/src/components/dialog/views/README.mdx +1 -1
  35. package/src/components/dialog/views/dialog-header.stories.tsx +2 -2
  36. package/src/components/form/form.stories.tsx +2 -2
  37. package/src/components/form/input.stories.tsx +2 -2
  38. package/src/components/form/inputs.tsx +18 -24
  39. package/src/components/form/select.stories.tsx +2 -2
  40. package/src/components/fp.test.tsx +52 -50
  41. package/src/components/heading/heading.stories.tsx +2 -2
  42. package/src/components/icons/icon.stories.tsx +1 -1
  43. package/src/components/images/figure.stories.tsx +2 -2
  44. package/src/components/images/img.stories.tsx +2 -2
  45. package/src/components/layout/footer.stories.tsx +10 -19
  46. package/src/components/layout/landmarks.stories.tsx +22 -24
  47. package/src/components/layout/main.stories.tsx +21 -25
  48. package/src/components/link/link.stories.tsx +2 -2
  49. package/src/components/list/list.stories.tsx +2 -2
  50. package/src/components/nav/nav.stories.tsx +2 -2
  51. package/src/components/popover/popover.stories.tsx +2 -2
  52. package/src/components/progress/progress.stories.tsx +1 -1
  53. package/src/components/tag/tag.stories.tsx +2 -2
  54. package/src/components/text/text.stories.tsx +2 -2
  55. package/src/components/text-to-speech/TextToSpeech.stories.tsx +1 -1
  56. package/src/decorators/instructions.tsx +2 -1
  57. package/src/patterns/page/page-header.stories.tsx +2 -2
  58. package/src/styles/buttons/button.css +3 -3
  59. package/src/styles/index.css +3 -3
@@ -0,0 +1,91 @@
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ <Meta title="FP.REACT Components/Breadcrumb/Readme" />
4
+
5
+ # Breadcrumb Component
6
+
7
+ ## Summary
8
+
9
+ The `Breadcrumb` component is used to display a breadcrumb navigation for the
10
+ current page. It supports custom routes, starting routes, and truncation of long
11
+ breadcrumb names.
12
+
13
+ ## Features
14
+
15
+ - Customizable routes and starting route
16
+ - Truncation of long breadcrumb names
17
+ - Customizable spacer between breadcrumb items
18
+ - Accessible with ARIA labels
19
+
20
+ ## Props
21
+
22
+ ```ts
23
+ type customRoute = {
24
+ path?: string;
25
+ name: string;
26
+ url?: string;
27
+ };
28
+
29
+ type BreadcrumbProps = {
30
+ routes?: customRoute[];
31
+ startRoute?: React.ReactNode;
32
+ startRouteUrl?: string;
33
+ spacer?: React.ReactNode;
34
+ currentRoute?: string;
35
+ ariaLabelPrefix?: string;
36
+ truncateLength?: number;
37
+ linkProps?: React.ComponentProps<typeof Link>;
38
+ } & React.ComponentProps<typeof UI>;
39
+ ```
40
+
41
+ ## Technical Details
42
+
43
+ The `Breadcrumb` component uses the `UI` and `Link` components for rendering the
44
+ breadcrumb items and links. It also uses the `Truncate` utility to truncate long
45
+ breadcrumb names.
46
+
47
+ ## Usage Example
48
+
49
+ ### Basic Usage
50
+
51
+ ```tsx
52
+ import Breadcrumb from './breadcrumb'
53
+
54
+ const routes = [
55
+ { path: '/home', name: 'Home' },
56
+ { path: '/about', name: 'About' },
57
+ { path: '/contact', name: 'Contact' },
58
+ ]
59
+
60
+ <Breadcrumb routes={routes} currentRoute="/about" />
61
+ ```
62
+
63
+ ### Advanced Usage
64
+
65
+ ```tsx
66
+ import Breadcrumb from './breadcrumb'
67
+
68
+ const routes = [
69
+ { path: '/home', name: 'Home' },
70
+ { path: '/about', name: 'About Us', url: '/about-us' },
71
+ { path: '/contact', name: 'Contact Us', url: '/contact-us' },
72
+ ]
73
+
74
+ <Breadcrumb
75
+ routes={routes}
76
+ currentRoute="/contact"
77
+ startRoute="Dashboard"
78
+ startRouteUrl="/dashboard"
79
+ spacer={<span className="mx-2">/</span>}
80
+ ariaLabelPrefix="You are here:"
81
+ truncateLength={10}
82
+ linkProps={{ className: 'text-blue-500 hover:underline' }}
83
+ />
84
+ ```
85
+
86
+ ### Additional Notes
87
+
88
+ - Ensure to provide meaningful names for the routes to enhance accessibility.
89
+ - Customize the `spacer` prop to match your design requirements.
90
+ - Use the `truncateLength` prop to control the maximum length of breadcrumb
91
+ names.
@@ -1,5 +1,5 @@
1
- import type { StoryObj, Meta } from "@storybook/react";
2
- import { within, fn, expect } from "@storybook/test";
1
+ import type { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, fn, expect } from "storybook/test";
3
3
 
4
4
  import Breadcrumb from "./breadcrumb";
5
5
 
@@ -1,38 +1,38 @@
1
1
  // Code: Breadcrumb component
2
- import React from 'react'
3
- import UI from '#components/ui'
4
- import { Truncate } from '#libs/content'
5
- import Link from '#components/link/link'
2
+ import React from "react";
3
+ import UI from "#components/ui";
4
+ import { Truncate } from "#libs/content";
5
+ import Link from "#components/link/link";
6
6
 
7
7
  // TYPES
8
8
 
9
9
  type customRoute = {
10
10
  /** The path or id for routing */
11
- path?: string
11
+ path?: string;
12
12
  /** The display name */
13
- name: string
13
+ name: string;
14
14
  /** The url if linking out */
15
- url?: string
16
- }
15
+ url?: string;
16
+ };
17
17
 
18
18
  type BreadcrumbProps = {
19
19
  /** Array of custom route objects */
20
- routes?: customRoute[]
20
+ routes?: customRoute[];
21
21
  /** Starting route node */
22
- startRoute?: React.ReactNode
22
+ startRoute?: React.ReactNode;
23
23
  /* Starting route url */
24
- startRouteUrl?: string
24
+ startRouteUrl?: string;
25
25
  /** Spacer node between routes */
26
- spacer?: React.ReactNode
26
+ spacer?: React.ReactNode;
27
27
  /** String representing current route */
28
- currentRoute?: string
28
+ currentRoute?: string;
29
29
  /** Prefix breadcrumb aria-label - "prefix breadcrumb" */
30
- ariaLabelPrefix?: string
30
+ ariaLabelPrefix?: string;
31
31
  /** Truncate breadcrumb text after this length */
32
- truncateLength?: number
32
+ truncateLength?: number;
33
33
  /** Link props for breadcrumb links */
34
- linkProps?: React.ComponentProps<typeof Link>
35
- } & React.ComponentProps<typeof UI>
34
+ linkProps?: React.ComponentProps<typeof Link>;
35
+ } & React.ComponentProps<typeof UI>;
36
36
 
37
37
  // Components
38
38
 
@@ -53,11 +53,17 @@ const Items = ({
53
53
  ...props
54
54
  }: React.ComponentProps<typeof UI>) => {
55
55
  return (
56
- <li data-list="unstyled inline" {...props}>
56
+ <li
57
+ id={id}
58
+ style={styles}
59
+ className={classes}
60
+ data-list="unstyled inline"
61
+ {...props}
62
+ >
57
63
  {children}
58
64
  </li>
59
- )
60
- }
65
+ );
66
+ };
61
67
 
62
68
  /**
63
69
  * List component.
@@ -70,8 +76,8 @@ const List = ({ children, ...props }: React.ComponentProps<typeof UI>) => {
70
76
  <UI as="ol" data-list="unstyled inline" {...props}>
71
77
  {children}
72
78
  </UI>
73
- )
74
- }
79
+ );
80
+ };
75
81
 
76
82
  /**
77
83
  * Nav component.
@@ -93,8 +99,8 @@ const Nav = ({
93
99
  <UI as="nav" id={id} styles={styles} className={classes} {...props}>
94
100
  <List>{children}</List>
95
101
  </UI>
96
- )
97
- }
102
+ );
103
+ };
98
104
 
99
105
  /**
100
106
  * Navigation component for breadcrumbs.
@@ -110,7 +116,7 @@ const Nav = ({
110
116
  * @param props.children - Child components.
111
117
  */
112
118
  export const Breadcrumb = ({
113
- startRoute = 'Home',
119
+ startRoute = "Home",
114
120
  startRouteUrl = "/",
115
121
  currentRoute,
116
122
  spacer = <>&#47;</>,
@@ -123,13 +129,13 @@ export const Breadcrumb = ({
123
129
  linkProps,
124
130
  ...props
125
131
  }: BreadcrumbProps): React.JSX.Element => {
126
- const [currentPath, setCurrentPath] = React.useState('')
132
+ const [currentPath, setCurrentPath] = React.useState("");
127
133
  React.useEffect(() => {
128
- const path = currentRoute || window.location.pathname
134
+ const path = currentRoute || window.location.pathname;
129
135
  if (path.length) {
130
- setCurrentPath(path)
136
+ setCurrentPath(path);
131
137
  }
132
- }, [currentRoute])
138
+ }, [currentRoute]);
133
139
 
134
140
  /**
135
141
  * Gets the path name for the given path segment.
@@ -138,23 +144,22 @@ export const Breadcrumb = ({
138
144
  * @returns The path name object for the given path segment.
139
145
  */
140
146
  const getPathName = (pathSegment: string): customRoute => {
141
- const route = routes?.find((route) => route.path === pathSegment)
147
+ const route = routes?.find((route) => route.path === pathSegment);
142
148
 
143
149
  return {
144
150
  path: route?.path || pathSegment,
145
151
  name: route?.name || pathSegment,
146
152
  url: route?.url || pathSegment,
147
- }
148
- }
153
+ };
154
+ };
149
155
 
150
156
  /** Array of path segments from current path */
151
- const segments = currentPath.split('/').filter((segment) => segment)
157
+ const segments = currentPath.split("/").filter((segment) => segment);
152
158
  /** Index of last item in segments array */
153
- const lastSegment = segments.length - 1
159
+ const lastSegment = segments.length - 1;
154
160
 
155
161
  /** Unique id for breadcrumb */
156
- const uuid = React.useId()
157
-
162
+ const uuid = React.useId();
158
163
 
159
164
  return currentPath.length ? (
160
165
  <Nav
@@ -165,62 +170,62 @@ export const Breadcrumb = ({
165
170
  aria-label={ariaLabelPrefix}
166
171
  >
167
172
  <Items key={`${startRoute}-${uuid}`}>
168
- <Link href={startRouteUrl} {...linkProps}>{startRoute}</Link>
173
+ <Link href={startRouteUrl} {...linkProps}>
174
+ {startRoute}
175
+ </Link>
169
176
  </Items>
170
177
  <>
171
- {segments.length ? (
172
- segments.map((segment: any, index: number) => {
173
- const currentSegment = getPathName(segment)
174
- const { name, url, path } = currentSegment
175
- return index === lastSegment ? (
176
- <>
177
- {typeof segments[lastSegment] === 'string' &&
178
- segments[lastSegment].length > 3 &&
179
- segments[lastSegment] !== segments[lastSegment - 1] && (
180
- <Items key={`${path || index}-${uuid}`}>
181
-
182
- <span aria-hidden="true">{spacer}</span>
183
- <a
184
- href="#"
185
- aria-current="page"
186
- aria-label={
187
- name.length > truncateLength ? name : undefined
188
- }
189
- >
190
- {Truncate(decodeURIComponent(name), truncateLength)}
191
- </a>
192
-
193
- </Items>
194
- )}
195
- </>
196
- ) : (
197
- <Items key={`${currentSegment?.name}-${uuid}`}>
198
- <span aria-hidden="true">{spacer}</span>
199
- <span>
200
- <Link
201
- href={url}
202
- aria-label={name.length > truncateLength ? name : undefined}
203
- {...linkProps}
204
- >
205
- {Truncate(decodeURIComponent(name), truncateLength)}
206
- </Link>
207
- </span>
208
- </Items>
209
- );
210
- })
211
- ) : (
212
- null
213
- )}
178
+ {segments.length
179
+ ? segments.map((segment: string, index: number) => {
180
+ const currentSegment = getPathName(segment);
181
+ const { name, url, path } = currentSegment;
182
+ return index === lastSegment ? (
183
+ <>
184
+ {typeof segments[lastSegment] === "string" &&
185
+ segments[lastSegment].length > 3 &&
186
+ segments[lastSegment] !== segments[lastSegment - 1] && (
187
+ <Items key={`${path || index}-${uuid}`}>
188
+ <span aria-hidden="true">{spacer}</span>
189
+ <a
190
+ href="#"
191
+ aria-current="page"
192
+ aria-label={
193
+ name.length > truncateLength ? name : undefined
194
+ }
195
+ >
196
+ {Truncate(decodeURIComponent(name), truncateLength)}
197
+ </a>
198
+ </Items>
199
+ )}
200
+ </>
201
+ ) : (
202
+ <Items key={`${currentSegment?.name}-${uuid}`}>
203
+ <span aria-hidden="true">{spacer}</span>
204
+ <span>
205
+ <Link
206
+ href={url}
207
+ aria-label={
208
+ name.length > truncateLength ? name : undefined
209
+ }
210
+ {...linkProps}
211
+ >
212
+ {Truncate(decodeURIComponent(name), truncateLength)}
213
+ </Link>
214
+ </span>
215
+ </Items>
216
+ );
217
+ })
218
+ : null}
214
219
  </>
215
220
  </Nav>
216
221
  ) : (
217
222
  <></>
218
- )
219
- }
223
+ );
224
+ };
220
225
 
221
- export default Breadcrumb
226
+ export default Breadcrumb;
222
227
 
223
- Breadcrumb.displayName = 'BreadCrumb'
224
- Breadcrumb.Nav = Nav
225
- Breadcrumb.List = List
226
- Breadcrumb.Items = Items
228
+ Breadcrumb.displayName = "BreadCrumb";
229
+ Breadcrumb.Nav = Nav;
230
+ Breadcrumb.List = List;
231
+ Breadcrumb.Items = Items;
@@ -1,4 +1,4 @@
1
- import { Meta } from "@storybook/blocks";
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
2
 
3
3
  <Meta title="FP.REACT Components/Buttons/Readme" />
4
4
 
@@ -1,7 +1,7 @@
1
1
  button {
2
- --btn-xs: 0.6rem;
3
- --btn-sm: 0.7rem;
4
- --btn-md: 0.85rem;
2
+ --btn-xs: 0.5rem;
3
+ --btn-sm: 0.625rem;
4
+ --btn-md: 0.75rem;
5
5
  --btn-lg: 1.3125rem;
6
6
  --btn-pill: 100rem;
7
7
  --btn-height: 2.5rem;
@@ -1,5 +1,5 @@
1
- import type { StoryObj, Meta } from "@storybook/react";
2
- import { within, userEvent, expect, fn } from "@storybook/test";
1
+ import type { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, userEvent, expect, fn } from "storybook/test";
3
3
 
4
4
  import Button from "./button";
5
5
  import "./button.scss";
@@ -3,7 +3,7 @@ import { render, screen } from "@testing-library/react";
3
3
  import { Button } from "./button";
4
4
  // import user from '@testing-library/user-event'
5
5
  import jest from "jest-mock";
6
- import { userEvent } from "@storybook/test";
6
+ import { userEvent } from "storybook/test";
7
7
 
8
8
  describe("Button", () => {
9
9
  it("renders a button element with the correct label", () => {
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- // import { within, userEvent, screen } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ // import { within, userEvent, screen } from "storybook/test";
3
3
 
4
4
  import Card from "./card";
5
5
  // import './card.scss'
@@ -1,4 +1,4 @@
1
- import { Meta } from "@storybook/blocks";
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
2
 
3
3
  <Meta title="FP.REACT Components/Details/Readme" />
4
4
 
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- import { within, expect, userEvent } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, expect, userEvent } from "storybook/test";
3
3
 
4
4
  import Details from "./details";
5
5
  import Icons from "../icons/icon";
@@ -1,4 +1,4 @@
1
- import { Meta } from "@storybook/blocks";
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
2
 
3
3
  <Meta title="FP.REACT Components/Dialog/Readme" />
4
4
 
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- import { within, expect, userEvent, waitFor } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, expect, userEvent, waitFor } from "storybook/test";
3
3
 
4
4
  import DialogModal from "./dialog-modal";
5
5
  import WithInstructions from "#/decorators/instructions";
@@ -108,4 +108,4 @@ export const DialogModal: React.FC<DialogModalProps> = ({
108
108
  );
109
109
  };
110
110
  export default DialogModal;
111
- DialogModal.displayName = "Dialog Modal";
111
+ DialogModal.displayName = "DialogModal";
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta, StoryFn } from "@storybook/react";
2
- import { within, expect, userEvent } from "@storybook/test";
1
+ import { StoryObj, Meta, StoryFn } from "@storybook/react-vite";
2
+ import { within, expect, userEvent } from "storybook/test";
3
3
 
4
4
  import Dialog from "./dialog";
5
5
  import React from "react";
@@ -1,4 +1,4 @@
1
- import { Meta } from "@storybook/blocks";
1
+ import { Meta } from "@storybook/addon-docs/blocks";
2
2
 
3
3
  <Meta title="FP.REACT Views/DialogHeader/Readme" />
4
4
 
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- import { within, expect } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, expect } from "storybook/test";
3
3
 
4
4
  import DialogHeader from "./dialog-header";
5
5
 
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- import { within, expect } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, expect } from "storybook/test";
3
3
 
4
4
  import Form from "./form";
5
5
  import "./form.scss";
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- import { within, userEvent, expect } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, userEvent, expect } from "storybook/test";
3
3
 
4
4
  import Input from "./inputs";
5
5
  import "./form.scss";
@@ -1,25 +1,20 @@
1
- import React from 'react'
2
- import FP from '../fp'
1
+ import React from "react";
2
+ import FP from "../fp";
3
3
 
4
4
  export type InputProps = {
5
5
  /**
6
6
  * The type of the input.
7
7
  */
8
- type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'search'
8
+ type?: "text" | "password" | "email" | "number" | "tel" | "url" | "search";
9
9
 
10
10
  /**
11
11
  * Set the element as disabled
12
12
  */
13
- isDisabled?: boolean
14
- } & React.ComponentProps<typeof FP>
13
+ isDisabled?: boolean;
14
+ } & React.ComponentProps<typeof FP>;
15
15
 
16
- /**
17
- * Input component that renders an HTML input element.
18
- * @param {InputProps} props - The input component props.
19
- * @returns {JSX.Element} - The input component.
20
- */
21
16
  export const Input = ({
22
- type = 'text',
17
+ type = "text",
23
18
  name,
24
19
  value,
25
20
  placeholder,
@@ -38,29 +33,29 @@ export const Input = ({
38
33
  }: InputProps): JSX.Element => {
39
34
  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
40
35
  if (onChange && !disabled) {
41
- onChange?.(e)
36
+ onChange?.(e);
42
37
  }
43
- }
38
+ };
44
39
 
45
40
  const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
46
41
  if (onBlur && !disabled) {
47
- onBlur?.(e)
42
+ onBlur?.(e);
48
43
  }
49
- }
44
+ };
50
45
 
51
46
  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
52
47
  if (onPointerDown && !disabled) {
53
- e.preventDefault()
54
- onPointerDown?.(e)
48
+ e.preventDefault();
49
+ onPointerDown?.(e);
55
50
  }
56
- }
51
+ };
57
52
 
58
53
  return (
59
54
  <FP
60
55
  as="input"
61
56
  id={id}
62
57
  type={type}
63
- placeholder={placeholder || `${required ? '*' : ''} ${type} input `}
58
+ placeholder={placeholder || `${required ? "*" : ""} ${type} input `}
64
59
  className={classes}
65
60
  styles={styles}
66
61
  onChange={handleChange}
@@ -77,8 +72,7 @@ export const Input = ({
77
72
  readOnly={readonly}
78
73
  {...props}
79
74
  />
80
- )
81
- }
82
-
83
- Input.displayName = 'Input'
84
- export default Input
75
+ );
76
+ };
77
+ Input.displayName = "Input";
78
+ export default Input;
@@ -1,5 +1,5 @@
1
- import { StoryObj, Meta } from "@storybook/react";
2
- import { within, expect } from "@storybook/test";
1
+ import { StoryObj, Meta } from "@storybook/react-vite";
2
+ import { within, expect } from "storybook/test";
3
3
 
4
4
  import Select from "./select";
5
5
  import React from "react";