@fpkit/acss 0.4.4

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 (297) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +52 -0
  3. package/dist/chunk-77CZU5XZ.cjs +9 -0
  4. package/dist/chunk-77CZU5XZ.cjs.map +1 -0
  5. package/dist/chunk-D43FJIRQ.cjs +31 -0
  6. package/dist/chunk-D43FJIRQ.cjs.map +1 -0
  7. package/dist/chunk-GJWMCDFS.js +9 -0
  8. package/dist/chunk-GJWMCDFS.js.map +1 -0
  9. package/dist/chunk-PCDUGD3C.js +5 -0
  10. package/dist/chunk-PCDUGD3C.js.map +1 -0
  11. package/dist/hooks.cjs +10 -0
  12. package/dist/hooks.cjs.map +1 -0
  13. package/dist/hooks.d.cts +32 -0
  14. package/dist/hooks.d.ts +32 -0
  15. package/dist/hooks.js +8 -0
  16. package/dist/hooks.js.map +1 -0
  17. package/dist/icon-e6044c73.d.ts +227 -0
  18. package/dist/icons.cjs +73 -0
  19. package/dist/icons.cjs.map +1 -0
  20. package/dist/icons.d.cts +252 -0
  21. package/dist/icons.d.ts +252 -0
  22. package/dist/icons.js +4 -0
  23. package/dist/icons.js.map +1 -0
  24. package/dist/index.cjs +59 -0
  25. package/dist/index.cjs.map +1 -0
  26. package/dist/index.d.cts +566 -0
  27. package/dist/index.d.ts +566 -0
  28. package/dist/index.js +11 -0
  29. package/dist/index.js.map +1 -0
  30. package/libs/chunk-GCGKYLDG.js +7 -0
  31. package/libs/chunk-GCGKYLDG.js.map +1 -0
  32. package/libs/chunk-PDD4N5P5.cjs +10 -0
  33. package/libs/chunk-PDD4N5P5.cjs.map +1 -0
  34. package/libs/chunk-QHIABQNQ.js +8 -0
  35. package/libs/chunk-QHIABQNQ.js.map +1 -0
  36. package/libs/chunk-ZOHIKF6I.cjs +31 -0
  37. package/libs/chunk-ZOHIKF6I.cjs.map +1 -0
  38. package/libs/components/badge/badge.css +1 -0
  39. package/libs/components/badge/badge.css.map +1 -0
  40. package/libs/components/badge/badge.min.css +3 -0
  41. package/libs/components/breadcrumbs/breadcrumb.css +1 -0
  42. package/libs/components/breadcrumbs/breadcrumb.css.map +1 -0
  43. package/libs/components/breadcrumbs/breadcrumb.min.css +3 -0
  44. package/libs/components/buttons/button.css +1 -0
  45. package/libs/components/buttons/button.css.map +1 -0
  46. package/libs/components/buttons/button.min.css +3 -0
  47. package/libs/components/cards/card-style.css +1 -0
  48. package/libs/components/cards/card-style.css.map +1 -0
  49. package/libs/components/cards/card-style.min.css +3 -0
  50. package/libs/components/cards/card.css +1 -0
  51. package/libs/components/cards/card.css.map +1 -0
  52. package/libs/components/cards/card.min.css +3 -0
  53. package/libs/components/details/details.css +1 -0
  54. package/libs/components/details/details.css.map +1 -0
  55. package/libs/components/details/details.min.css +3 -0
  56. package/libs/components/form/form.css +1 -0
  57. package/libs/components/form/form.css.map +1 -0
  58. package/libs/components/form/form.min.css +3 -0
  59. package/libs/components/icons/icon.css +1 -0
  60. package/libs/components/icons/icon.css.map +1 -0
  61. package/libs/components/icons/icon.min.css +3 -0
  62. package/libs/components/images/img.css +1 -0
  63. package/libs/components/images/img.css.map +1 -0
  64. package/libs/components/images/img.min.css +3 -0
  65. package/libs/components/layout/landmarks.css +1 -0
  66. package/libs/components/layout/landmarks.css.map +1 -0
  67. package/libs/components/layout/landmarks.min.css +3 -0
  68. package/libs/components/link/link.css +1 -0
  69. package/libs/components/link/link.css.map +1 -0
  70. package/libs/components/link/link.min.css +3 -0
  71. package/libs/components/nav/nav.css +1 -0
  72. package/libs/components/nav/nav.css.map +1 -0
  73. package/libs/components/nav/nav.min.css +3 -0
  74. package/libs/components/progress/progress.css +1 -0
  75. package/libs/components/progress/progress.css.map +1 -0
  76. package/libs/components/progress/progress.min.css +3 -0
  77. package/libs/components/styles/index.css +1 -0
  78. package/libs/components/styles/index.css.map +1 -0
  79. package/libs/components/styles/index.min.css +3 -0
  80. package/libs/components/tag/tag.css +1 -0
  81. package/libs/components/tag/tag.css.map +1 -0
  82. package/libs/components/tag/tag.min.css +3 -0
  83. package/libs/components/text-to-speech/text-to-speech.css +1 -0
  84. package/libs/components/text-to-speech/text-to-speech.css.map +1 -0
  85. package/libs/components/text-to-speech/text-to-speech.min.css +3 -0
  86. package/libs/hooks.cjs +12 -0
  87. package/libs/hooks.cjs.map +1 -0
  88. package/libs/hooks.d.cts +32 -0
  89. package/libs/hooks.d.ts +32 -0
  90. package/libs/hooks.js +3 -0
  91. package/libs/hooks.js.map +1 -0
  92. package/libs/icons-1f5afc0c.d.ts +318 -0
  93. package/libs/icons.cjs +12 -0
  94. package/libs/icons.cjs.map +1 -0
  95. package/libs/icons.d.cts +2 -0
  96. package/libs/icons.d.ts +2 -0
  97. package/libs/icons.js +3 -0
  98. package/libs/icons.js.map +1 -0
  99. package/libs/index.cjs +71 -0
  100. package/libs/index.cjs.map +1 -0
  101. package/libs/index.css +1 -0
  102. package/libs/index.css.map +1 -0
  103. package/libs/index.d.cts +551 -0
  104. package/libs/index.d.ts +551 -0
  105. package/libs/index.js +11 -0
  106. package/libs/index.js.map +1 -0
  107. package/package.json +125 -0
  108. package/src/App.css +42 -0
  109. package/src/App.tsx +35 -0
  110. package/src/__snapshots__/App.test.tsx.snap +56 -0
  111. package/src/components/.gitkeep +0 -0
  112. package/src/components/__snapshots__/fp.test.tsx.snap +3 -0
  113. package/src/components/badge/badge.scss +20 -0
  114. package/src/components/badge/badge.stories.tsx +54 -0
  115. package/src/components/badge/badge.tsx +17 -0
  116. package/src/components/breadcrumbs/bc-item.tsx +20 -0
  117. package/src/components/breadcrumbs/breadcrumb.scss +35 -0
  118. package/src/components/breadcrumbs/breadcrumb.stories.tsx +92 -0
  119. package/src/components/breadcrumbs/breadcrumb.tsx +218 -0
  120. package/src/components/buttons/button.scss +115 -0
  121. package/src/components/buttons/button.stories.tsx +57 -0
  122. package/src/components/buttons/button.test.tsx +104 -0
  123. package/src/components/buttons/button.tsx +64 -0
  124. package/src/components/cards/card-style.scss +0 -0
  125. package/src/components/cards/card.scss +43 -0
  126. package/src/components/cards/card.stories.tsx +114 -0
  127. package/src/components/cards/card.test.tsx +30 -0
  128. package/src/components/cards/card.tsx +135 -0
  129. package/src/components/cards/flex-card.tsx +15 -0
  130. package/src/components/details/details.scss +75 -0
  131. package/src/components/details/details.stories.tsx +122 -0
  132. package/src/components/details/details.tsx +77 -0
  133. package/src/components/form/README.mdx +70 -0
  134. package/src/components/form/fields.tsx +45 -0
  135. package/src/components/form/form.scss +87 -0
  136. package/src/components/form/form.stories.tsx +49 -0
  137. package/src/components/form/form.tsx +71 -0
  138. package/src/components/form/input.stories.tsx +155 -0
  139. package/src/components/form/inputs.tsx +84 -0
  140. package/src/components/form/select.stories.tsx +38 -0
  141. package/src/components/form/select.tsx +112 -0
  142. package/src/components/form/textarea.tsx +87 -0
  143. package/src/components/fp.test.tsx +56 -0
  144. package/src/components/fp.tsx +78 -0
  145. package/src/components/heading/heading.stories.tsx +75 -0
  146. package/src/components/heading/heading.tsx +27 -0
  147. package/src/components/icons/components/add.tsx +42 -0
  148. package/src/components/icons/components/arrow-down.tsx +52 -0
  149. package/src/components/icons/components/arrow-left.tsx +49 -0
  150. package/src/components/icons/components/arrow-right.tsx +52 -0
  151. package/src/components/icons/components/arrow-up.tsx +49 -0
  152. package/src/components/icons/components/chat.tsx +44 -0
  153. package/src/components/icons/components/code.tsx +50 -0
  154. package/src/components/icons/components/copy.tsx +51 -0
  155. package/src/components/icons/components/down.tsx +33 -0
  156. package/src/components/icons/components/home.tsx +57 -0
  157. package/src/components/icons/components/left.tsx +43 -0
  158. package/src/components/icons/components/minus.tsx +42 -0
  159. package/src/components/icons/components/pause-solid.tsx +48 -0
  160. package/src/components/icons/components/pause.tsx +63 -0
  161. package/src/components/icons/components/play-solid.tsx +44 -0
  162. package/src/components/icons/components/play.tsx +51 -0
  163. package/src/components/icons/components/remove.tsx +42 -0
  164. package/src/components/icons/components/resume-solid.tsx +52 -0
  165. package/src/components/icons/components/resume.tsx +57 -0
  166. package/src/components/icons/components/right.tsx +43 -0
  167. package/src/components/icons/components/star.tsx +38 -0
  168. package/src/components/icons/components/stop-solid.tsx +44 -0
  169. package/src/components/icons/components/stop.tsx +54 -0
  170. package/src/components/icons/components/svg.tsx +44 -0
  171. package/src/components/icons/components/up.tsx +31 -0
  172. package/src/components/icons/components/user.tsx +46 -0
  173. package/src/components/icons/icon.scss +15 -0
  174. package/src/components/icons/icon.stories.tsx +208 -0
  175. package/src/components/icons/icon.tsx +100 -0
  176. package/src/components/icons/index.ts +29 -0
  177. package/src/components/icons/types.ts +12 -0
  178. package/src/components/images/README.mdx +43 -0
  179. package/src/components/images/figure.stories.tsx +34 -0
  180. package/src/components/images/figure.tsx +44 -0
  181. package/src/components/images/img.scss +43 -0
  182. package/src/components/images/img.stories.tsx +24 -0
  183. package/src/components/images/img.test.tsx +43 -0
  184. package/src/components/images/img.tsx +93 -0
  185. package/src/components/images/place-holder.png +0 -0
  186. package/src/components/kit.tsx +56 -0
  187. package/src/components/layout/_header.scss +72 -0
  188. package/src/components/layout/footer.stories.tsx +34 -0
  189. package/src/components/layout/landmarks.scss +51 -0
  190. package/src/components/layout/landmarks.stories.tsx +54 -0
  191. package/src/components/layout/landmarks.tsx +149 -0
  192. package/src/components/layout/main.stories.tsx +90 -0
  193. package/src/components/link/link.scss +92 -0
  194. package/src/components/link/link.stories.tsx +74 -0
  195. package/src/components/link/link.tsx +48 -0
  196. package/src/components/list/list.stories.tsx +52 -0
  197. package/src/components/list/list.tsx +74 -0
  198. package/src/components/modal/dialog.tsx +50 -0
  199. package/src/components/modal/modal.tsx +85 -0
  200. package/src/components/nav/nav.scss +90 -0
  201. package/src/components/nav/nav.stories.tsx +96 -0
  202. package/src/components/nav/nav.tsx +76 -0
  203. package/src/components/popover/node_modules/.vitest/results.json +1 -0
  204. package/src/components/popover/popover.stories.tsx +31 -0
  205. package/src/components/popover/popover.test.tsx +39 -0
  206. package/src/components/popover/popover.tsx +85 -0
  207. package/src/components/progress/progress.scss +70 -0
  208. package/src/components/progress/progress.stories.tsx +51 -0
  209. package/src/components/progress/progress.tsx +82 -0
  210. package/src/components/readme.stories.mdx +7 -0
  211. package/src/components/styles/index.css +520 -0
  212. package/src/components/styles/index.css.map +1 -0
  213. package/src/components/tables/table-elements.tsx +57 -0
  214. package/src/components/tables/table.tsx +57 -0
  215. package/src/components/tag/tag.scss +56 -0
  216. package/src/components/tag/tag.stories.tsx +39 -0
  217. package/src/components/tag/tag.tsx +25 -0
  218. package/src/components/text/text.stories.tsx +67 -0
  219. package/src/components/text/text.tsx +93 -0
  220. package/src/components/text-to-speech/README.mdx +192 -0
  221. package/src/components/text-to-speech/TextInput.tsx +19 -0
  222. package/src/components/text-to-speech/TextToSpeech.stories.tsx +145 -0
  223. package/src/components/text-to-speech/TextToSpeech.tsx +94 -0
  224. package/src/components/text-to-speech/text-to-speech.scss +31 -0
  225. package/src/components/text-to-speech/useTextToSpeech.mdx +182 -0
  226. package/src/components/text-to-speech/useTextToSpeech.tsx +176 -0
  227. package/src/components/text-to-speech/views/TextToSpeechControls.tsx +117 -0
  228. package/src/components/ui.tsx +67 -0
  229. package/src/favicon.svg +15 -0
  230. package/src/hooks/popover/__snapshots__/popover.test.tsx.snap +88 -0
  231. package/src/hooks/popover/node_modules/.vitest/results.json +1 -0
  232. package/src/hooks/popover/popover.tsx +71 -0
  233. package/src/hooks/popover/use-popover.tsx +83 -0
  234. package/src/hooks.ts +1 -0
  235. package/src/icons.ts +1 -0
  236. package/src/index.css +13 -0
  237. package/src/index.scss +19 -0
  238. package/src/index.ts +35 -0
  239. package/src/libs/content.ts +30 -0
  240. package/src/logo.svg +7 -0
  241. package/src/main.tsx +10 -0
  242. package/src/patterns/.gitkeep +0 -0
  243. package/src/patterns/page/page-header.stories.tsx +44 -0
  244. package/src/patterns/page/page-header.tsx +78 -0
  245. package/src/sass/_elements.scss +17 -0
  246. package/src/sass/_globals.scss +162 -0
  247. package/src/sass/_layout.scss +51 -0
  248. package/src/sass/_loading-animation.scss +35 -0
  249. package/src/sass/_mixins.scss +10 -0
  250. package/src/sass/_properties.scss +106 -0
  251. package/src/sass/_reset.scss +183 -0
  252. package/src/sass/_type.scss +43 -0
  253. package/src/setupTest.ts +1 -0
  254. package/src/styles/badge/badge.css +22 -0
  255. package/src/styles/badge/badge.css.map +1 -0
  256. package/src/styles/breadcrumbs/breadcrumb.css +42 -0
  257. package/src/styles/breadcrumbs/breadcrumb.css.map +1 -0
  258. package/src/styles/buttons/button.css +93 -0
  259. package/src/styles/buttons/button.css.map +1 -0
  260. package/src/styles/cards/card-style.css +3 -0
  261. package/src/styles/cards/card-style.css.map +1 -0
  262. package/src/styles/cards/card.css +48 -0
  263. package/src/styles/cards/card.css.map +1 -0
  264. package/src/styles/details/details.css +69 -0
  265. package/src/styles/details/details.css.map +1 -0
  266. package/src/styles/dropdowns/dropdown.css.map +1 -0
  267. package/src/styles/form/form.css +93 -0
  268. package/src/styles/form/form.css.map +1 -0
  269. package/src/styles/form/style.css.map +1 -0
  270. package/src/styles/icons/icon.css +16 -0
  271. package/src/styles/icons/icon.css.map +1 -0
  272. package/src/styles/images/img.css +42 -0
  273. package/src/styles/images/img.css.map +1 -0
  274. package/src/styles/index.css +1330 -0
  275. package/src/styles/index.css.map +1 -0
  276. package/src/styles/layout/landmarks.css +155 -0
  277. package/src/styles/layout/landmarks.css.map +1 -0
  278. package/src/styles/link/link.css +88 -0
  279. package/src/styles/link/link.css.map +1 -0
  280. package/src/styles/nav/nav.css +85 -0
  281. package/src/styles/nav/nav.css.map +1 -0
  282. package/src/styles/progress/progress.css +54 -0
  283. package/src/styles/progress/progress.css.map +1 -0
  284. package/src/styles/progress/sass/progress.css.map +1 -0
  285. package/src/styles/styles/index.css +562 -0
  286. package/src/styles/styles/index.css.map +1 -0
  287. package/src/styles/tag/badge.css.map +1 -0
  288. package/src/styles/tag/tag.css +71 -0
  289. package/src/styles/tag/tag.css.map +1 -0
  290. package/src/styles/text-to-speech/text-to-speech.css +32 -0
  291. package/src/styles/text-to-speech/text-to-speech.css.map +1 -0
  292. package/src/test/setup.ts +6 -0
  293. package/src/types/component-props.ts +36 -0
  294. package/src/types/index.ts +2 -0
  295. package/src/types/input-props.ts +28 -0
  296. package/src/types/shared.ts +57 -0
  297. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,92 @@
1
+ @use '../../sass/mixins';
2
+
3
+ a[href] {
4
+ --link-decoration: none;
5
+ --link-color: #085ab7;
6
+ --link-bg: transparent;
7
+ --link-px: 0;
8
+ --link-py: 0;
9
+ --link-transition: all 0.75s ease-in-out;
10
+ --link-fs: 1rem;
11
+ --link-radius: 0.25rem;
12
+ --link-skip-ink: auto;
13
+ --link-decoration-offset: 1.5px;
14
+ --link-decoration-thickness: 3px;
15
+ --link-decoration: color: var(--link-color) var(--link-decoration-offset)
16
+ var(--link-decoration-thickness) var(--link-skip-ink);
17
+ --link-decoration-thickness: 3px;
18
+ --link-decoration: color: var(--link-color) var(--link-decoration-offset)
19
+ var(--link-decoration-thickness) var(--link-skip-ink);
20
+
21
+ color: var(--link-color);
22
+ font-size: var(--link-fs);
23
+ text-decoration: var(--link-decoration);
24
+ text-underline-offset: var(--link-decoration-offset);
25
+ text-decoration-skip-ink: var(--link-skip-ink);
26
+ background-color: var(--link-bg);
27
+ border-radius: var(--link-radius);
28
+ background-color: var(--link-bg);
29
+ border-radius: var(--link-radius);
30
+ font-weight: var(--link-weight);
31
+
32
+ > i,
33
+ > b {
34
+ font-weight: var(--link-weight);
35
+ font-style: normal;
36
+ }
37
+
38
+ &:hover {
39
+ --link-decoration: underline;
40
+ }
41
+
42
+ &:focus {
43
+ outline: none;
44
+ --link-decoration: underline;
45
+ }
46
+
47
+ &:visited,
48
+ &:active {
49
+ --link-color: currentColor;
50
+ }
51
+
52
+ &:has(> b),
53
+ &[data-link~='btn'],
54
+ &:has(> i) {
55
+ --link-button-color: var(--link-color);
56
+ --link-bg: transparent;
57
+ --link-decoration: none;
58
+ --link-border: 2px currentColor solid;
59
+ --link-fs: 0.9rem;
60
+ background-color: var(--link-bg);
61
+ font-style: normal;
62
+ font-size: var(--link-fs);
63
+ color: var(--link-button-color);
64
+ padding-inline: var(--link-fs);
65
+ padding-block: calc(var(--link-fs) - 0.4rem);
66
+ border-radius: var(--link-radius, 99rem);
67
+ display: inline-flex;
68
+ outline: var(--link-border);
69
+ &:focus {
70
+ outline: var(--link-border);
71
+ --link-decoration: none;
72
+ }
73
+ &:hover {
74
+ --link-decoration: none;
75
+ }
76
+ @include mixins.scale-transitions;
77
+ }
78
+ &[data-link~='pill'],
79
+ &:has(> i) {
80
+ --link-radius: 99rem;
81
+ --link-decoration: none;
82
+ font-style: normal;
83
+ &:hover,
84
+ &:focus {
85
+ --link-decoration: none;
86
+ }
87
+ }
88
+ }
89
+
90
+ header > section {
91
+ width: auto;
92
+ }
@@ -0,0 +1,74 @@
1
+ import { StoryObj, Meta } from '@storybook/react'
2
+
3
+ import { within, userEvent, screen } from '@storybook/testing-library'
4
+
5
+ import { expect } from '@storybook/jest'
6
+
7
+ import Link from './link'
8
+ import '../../styles/link/link.css'
9
+
10
+ const meta: Meta<typeof Link> = {
11
+ title: 'FP.React Components/Links',
12
+ component: Link,
13
+ args: {
14
+ // @ts-ignore
15
+ href: '/',
16
+ children: 'Link',
17
+ },
18
+ } as Meta
19
+
20
+ export default meta
21
+ type Story = StoryObj<typeof Link>
22
+
23
+ export const LinkComponent: Story = {
24
+ args: {},
25
+ play: async ({ canvasElement }) => {
26
+ const canvas = within(canvasElement)
27
+ const link = canvas.getByRole('link')
28
+ expect(link).toBeInTheDocument()
29
+ expect(link).toHaveTextContent('Link')
30
+ },
31
+ }
32
+
33
+ export const ExternalLink: Story = {
34
+ args: {
35
+ // @ts-ignore
36
+ href: 'https://www.google.com',
37
+ target: '_blank',
38
+ rel: 'noopener noreferrer',
39
+ prefetch: true,
40
+ children: 'Google',
41
+ },
42
+ play: async ({ canvasElement }) => {
43
+ const canvas = within(canvasElement)
44
+ const link = canvas.getByRole('link')
45
+ expect(link).toBeInTheDocument()
46
+ expect(link).toHaveTextContent('Google')
47
+ expect(link).toHaveAttribute('href', 'https://www.google.com')
48
+ expect(link).toHaveAttribute('target', '_blank')
49
+ expect(link).toHaveAttribute('rel', 'noopener noreferrer prefetch')
50
+ },
51
+ }
52
+
53
+ export const ButtonLink: Story = {
54
+ args: {
55
+ ...LinkComponent.args,
56
+ children: <b>Button Link</b>,
57
+ },
58
+ } as Story
59
+
60
+ export const ButtonPill: Story = {
61
+ args: {
62
+ ...LinkComponent.args,
63
+ children: <i>Button Link</i>,
64
+ },
65
+ } as Story
66
+
67
+ export const ButtonRounded: Story = {
68
+ args: {
69
+ ...ButtonLink.args,
70
+ styles: {
71
+ '--link-radius': 'initial',
72
+ },
73
+ },
74
+ } as Story
@@ -0,0 +1,48 @@
1
+ import UI from '../ui'
2
+ import React from 'react'
3
+
4
+ export type LinkProps = {
5
+ /** Applies button styling to the link */
6
+ btnStyle?: boolean
7
+ } & React.ComponentProps<typeof UI> &
8
+ React.ComponentProps<'a'>
9
+
10
+ export const Link = ({
11
+ href,
12
+ target,
13
+ rel,
14
+ children,
15
+ styles,
16
+ prefetch,
17
+ btnStyle,
18
+ onPointerDown,
19
+ ...props
20
+ }: LinkProps) => {
21
+ let relValue = rel
22
+
23
+ if (target === '_blank')
24
+ relValue = `noopener noreferrer ${prefetch ? 'prefetch' : ''}`
25
+
26
+ const handleOnpointerDown = (e: React.PointerEvent<HTMLAnchorElement>) => {
27
+ if (onPointerDown) onPointerDown?.(e)
28
+ }
29
+
30
+ return (
31
+ <UI
32
+ as="a"
33
+ href={href}
34
+ target={target}
35
+ styles={styles}
36
+ rel={relValue}
37
+ onPointerDown={handleOnpointerDown}
38
+ data-btn={btnStyle}
39
+ prefetch={prefetch}
40
+ {...props}
41
+ >
42
+ {children}
43
+ </UI>
44
+ )
45
+ }
46
+
47
+ export default Link
48
+ Link.displayName = 'Link'
@@ -0,0 +1,52 @@
1
+ import React from 'react'
2
+
3
+ import { StoryObj, Meta } from '@storybook/react'
4
+
5
+ import { within, userEvent } from '@storybook/testing-library'
6
+
7
+ import { expect } from '@storybook/jest'
8
+
9
+ import List from './list'
10
+
11
+ const meta: Meta<typeof List> = {
12
+ title: 'FP.React Components/List',
13
+ component: List,
14
+ } as Meta
15
+
16
+ const listElm = (
17
+ <>
18
+ <List.ListItem>Home</List.ListItem>
19
+ <List.ListItem>About</List.ListItem>
20
+ <List.ListItem>Contact</List.ListItem>
21
+ </>
22
+ )
23
+
24
+ export default meta
25
+ type Story = StoryObj<typeof List>
26
+
27
+ export const DefaultList: Story = {
28
+ args: {
29
+ children: listElm,
30
+ },
31
+ } as Story
32
+
33
+ export const UnstyledList: Story = {
34
+ args: {
35
+ ...DefaultList.args,
36
+ role: 'list',
37
+ },
38
+ parameters: {
39
+ docs: {
40
+ description: {
41
+ story: 'Another description `on the story`, with some markdown',
42
+ },
43
+ },
44
+ },
45
+ } as Story
46
+
47
+ export const InlineList: Story = {
48
+ args: {
49
+ ...UnstyledList.args,
50
+ 'data-list': 'inline',
51
+ },
52
+ } as Story
@@ -0,0 +1,74 @@
1
+ import * as React from 'react'
2
+ import UI from '../ui'
3
+
4
+ type ListProps = {
5
+ /** Type of list to render (default: 'ul') */
6
+ type?: 'ul' | 'ol' | 'dl'
7
+ /** variant of list to render (default: 'none') */
8
+ variant?: string
9
+ } & React.ComponentProps<typeof UI>
10
+
11
+ export type ListItemProps = {
12
+ /** Type of list item to render (default: 'li') */
13
+ type?: 'li' | 'dt' | 'dd'
14
+ } & React.ComponentProps<typeof UI>
15
+
16
+ /**
17
+ * ListItem component
18
+ * @param type - HTML tag type for the list item (default: 'li')
19
+ * @param styles - CSS styles object
20
+ * @param children - Child elements to be rendered inside the list item
21
+ * @param props - Additional props to be passed to the underlying HTML element
22
+ * @returns A React component that renders a list item
23
+ */
24
+ export const ListItem = ({
25
+ type = 'li',
26
+ id,
27
+ styles,
28
+ children,
29
+ classes,
30
+ ...props
31
+ }: ListItemProps) => {
32
+ return (
33
+ <UI id={id} as={type} className={classes} {...props} style={styles}>
34
+ {children}
35
+ </UI>
36
+ )
37
+ }
38
+
39
+ /**
40
+ * List component renders a list element with provided props
41
+ * @param children - Child elements to render inside the list
42
+ * @param classes - CSS classes to apply
43
+ * @param type - Type of list element (default: 'ul')
44
+ * @param variant - Variant for styling purposes
45
+ * @param styles - Inline styles object
46
+ * @param role - ARIA role
47
+ * @param props - Additional props to pass to underlying element
48
+ */
49
+ export const List = ({
50
+ children,
51
+ classes,
52
+ type = 'ul',
53
+ variant,
54
+ styles,
55
+ role,
56
+ ...props
57
+ }: ListProps) => {
58
+ return (
59
+ <UI
60
+ as={type}
61
+ data-variant={variant}
62
+ className={classes}
63
+ style={styles}
64
+ role={role}
65
+ {...props}
66
+ >
67
+ {children}
68
+ </UI>
69
+ )
70
+ }
71
+
72
+ export default List
73
+ List.displayName = 'List'
74
+ List.ListItem = ListItem
@@ -0,0 +1,50 @@
1
+ import UI from '../ui'
2
+ import React from 'react'
3
+
4
+ export type DialogProps = {
5
+ /**
6
+ * React ref for dialog element
7
+ */
8
+ modalRef: React.RefObject<HTMLDialogElement>
9
+ /**
10
+ * Handle close modal event
11
+ */
12
+ closeModal?: (e: React.SyntheticEvent<HTMLDialogElement>) => void
13
+ /**
14
+ * open modal on mount
15
+ */
16
+ openOnMount?: boolean
17
+ } & React.ComponentProps<typeof UI>
18
+ /**
19
+ * Dialog component
20
+ */
21
+ export const Dialog = ({
22
+ id,
23
+ children,
24
+ classes,
25
+ modalRef,
26
+ openOnMount,
27
+ ...props
28
+ }: DialogProps) => {
29
+ const handleCloseModal = (e: React.SyntheticEvent<HTMLDialogElement>) => {
30
+ if (e.currentTarget === e.target) {
31
+ e.currentTarget.close()
32
+ }
33
+ }
34
+
35
+ return (
36
+ <UI
37
+ as="dialog"
38
+ id={id}
39
+ classes={classes}
40
+ ref={modalRef}
41
+ open={openOnMount}
42
+ onClick={handleCloseModal}
43
+ {...props}
44
+ >
45
+ {children}
46
+ </UI>
47
+ )
48
+ }
49
+
50
+ Dialog.displayName = 'Dialog'
@@ -0,0 +1,85 @@
1
+ import React from 'react'
2
+ import { ComponentProps } from '../../types'
3
+ import { Button } from '../buttons/button'
4
+ import { Dialog } from './dialog'
5
+
6
+ export interface ModalProps extends ComponentProps {
7
+ /**
8
+ * The child component/content for open button
9
+ */
10
+ openChild?: React.ReactNode
11
+ /**
12
+ * The child component/content for close button
13
+ */
14
+ closeChild?: React.ReactNode
15
+ /**
16
+ * The child component/content for modal header
17
+ */
18
+ modalHeader?: React.ReactNode
19
+ /**
20
+ * The child component/content for modal footer
21
+ */
22
+ modalFooter?: React.ReactNode
23
+ /**
24
+ * The child component/content for modal body
25
+ */
26
+ children: React.ReactNode
27
+ /**
28
+ * Open modal on mount when set to true
29
+ */
30
+ showOpen?: boolean
31
+ }
32
+ export const Modal = ({
33
+ openChild,
34
+ closeChild,
35
+ modalHeader,
36
+ modalFooter,
37
+ children,
38
+ showOpen = false,
39
+ ...props
40
+ }: ModalProps) => {
41
+ const dialogRef = React.useRef<HTMLDialogElement>(null)
42
+ const openModal = (): void => {
43
+ if (dialogRef.current) {
44
+ if(showOpen)
45
+ dialogRef.current.show()
46
+ else
47
+ dialogRef.current.showModal()
48
+ }
49
+ }
50
+ const closeModal = () => {
51
+ if (dialogRef.current) {
52
+ dialogRef.current.close()
53
+ }
54
+ }
55
+
56
+ return (
57
+ <>
58
+ <Dialog modalRef={dialogRef} openOnMount={showOpen} {...props}>
59
+ <section>
60
+ {modalHeader}
61
+ {children}
62
+ {modalFooter ?? (
63
+ <div>
64
+ <Button
65
+ type="button"
66
+ pointerDown={() => {
67
+ closeModal()
68
+ }}
69
+ >
70
+ {closeChild || 'Close'}
71
+ </Button>{' '}
72
+ </div>
73
+ )}
74
+ </section>
75
+ </Dialog>
76
+ { !showOpen && (
77
+ <Button type="button" pointerDown={openModal}>
78
+ {openChild || 'Open Modal'}
79
+ </Button>
80
+ )}
81
+ </>
82
+ )
83
+ }
84
+
85
+ Modal.displayName = 'Modal'
@@ -0,0 +1,90 @@
1
+ body > nav,
2
+ [aria-label~='navbar'], .navbar {
3
+ padding-inline: var(--nav-px, 1rem);
4
+ min-height: var(--nav-h, fit-content);
5
+
6
+ @media(max-width: 580px) {
7
+ flex-direction: column;
8
+ height: fit-content;
9
+ min-height: fit-content;
10
+ padding-block: unset;
11
+ gap: 0.5rem;
12
+ }
13
+ ul {
14
+ > li {
15
+ display: flex;
16
+ align-items: center;
17
+ list-style: none;
18
+ margin: 0;
19
+ padding: 0;
20
+ min-height: 100%;
21
+ padding-inline: var(--nav-px, 0.75rem);
22
+
23
+ &:hover {
24
+ background-color: var(--nav-hov-bg, whitesmoke);
25
+ }
26
+ &:hover:where(img) {
27
+ background-color: transparent;
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ nav {
34
+ display: var(--nav-dsp, flex);
35
+ flex-direction: var(--nav-direction, row);
36
+ width: var(--nav-w, auto);
37
+ place-items: var(--nav-align, center);
38
+ justify-content: var(--nav-justify, space-between);
39
+ margin-inline: var(--nav-mx, 0);
40
+ background-color: var(--nav-bg, initial);
41
+
42
+ > section,
43
+ > ul {
44
+ --nav-dsp: flex;
45
+ flex-direction: var(--nav-direction, row);
46
+ display: var(--nav-dsp, flex);
47
+ gap: var(--nav-gap, 0);
48
+ font-size: var(--nav-fs, 0.9rem);
49
+ align-items: var(--nav-align, center);
50
+ padding-inline: var(--nav-px, 1rem);
51
+ padding-block: var(--nav-py, 0);
52
+ height: 100%;
53
+ &[data-list~='block'] {
54
+ --nav-direction: column;
55
+ }
56
+ }
57
+
58
+ > section {
59
+ > div {
60
+ --py: 0;
61
+ }
62
+ }
63
+
64
+ ul {
65
+ > li {
66
+ display: flex;
67
+ align-items: center;
68
+ list-style: none;
69
+ margin: 0;
70
+ padding: 0;
71
+ min-height: 100%;
72
+ padding-inline: var(--nav-px, 1rem);
73
+ }
74
+ }
75
+
76
+ img[alt] {
77
+ --px: 0 var(--s1);
78
+ --w: var(--brand-w, 3.6rem);
79
+ }
80
+
81
+ &[data-variant] {
82
+ background-color: var(--nav-bg);
83
+ color: var(--nav-cl);
84
+ font-size: var(--nav-fs, 0.9rem);
85
+ }
86
+
87
+ > div {
88
+ margin-block-start: 0;
89
+ }
90
+ }
@@ -0,0 +1,96 @@
1
+ import { StoryObj, Meta } from '@storybook/react'
2
+ import { within } from '@storybook/testing-library'
3
+ import { expect } from '@storybook/jest'
4
+ import React from 'react'
5
+
6
+ import Nav from './nav'
7
+ import Link from '../link/link'
8
+
9
+ const meta: Meta<typeof Nav> = {
10
+ title: 'FP.REACT Components/Nav',
11
+ component: Nav,
12
+ parameters: {
13
+ actions: { argTypesRegex: '^on.*' },
14
+ docs: {
15
+ description: {
16
+ component: 'Nav description here...',
17
+ },
18
+ },
19
+ },
20
+ args: {
21
+ children: (
22
+ <Nav.List>
23
+ <Nav.Item>
24
+ <Link href="/">Link 1</Link>
25
+ </Nav.Item>
26
+ <Nav.Item>
27
+ <Link href="/">Link 2</Link>
28
+ </Nav.Item>
29
+ </Nav.List>
30
+ ),
31
+ id: 'nav',
32
+ classes: 'nav',
33
+ },
34
+ } as Story
35
+
36
+ export default meta
37
+ type Story = StoryObj<typeof Nav>
38
+
39
+ export const NavComponent: Story = {
40
+ args: {},
41
+ play: async ({ canvasElement }) => {
42
+ const canvas = within(canvasElement)
43
+ expect(canvas.getByText(/link/i)).toBeInTheDocument()
44
+ },
45
+ }
46
+
47
+ export const NavSection: Story = {
48
+ args: {
49
+ children: (
50
+ <>
51
+ <Nav.List>
52
+ <Nav.Item>Link 1</Nav.Item>
53
+ <Nav.Item>Link 2</Nav.Item>
54
+ </Nav.List>
55
+ </>
56
+ ),
57
+ },
58
+ play: async ({ canvasElement }) => {
59
+ const canvas = within(canvasElement)
60
+ expect(canvas.getByText('Link 1')).toBeInTheDocument()
61
+ expect(canvas.getByText('Link 2')).toBeInTheDocument()
62
+ },
63
+ } as Story
64
+
65
+ export const NavBlock: Story = {
66
+ args: {
67
+ ...NavSection.args,
68
+ children: (
69
+ <>
70
+ <Nav.List isBlock={true}>
71
+ <Nav.Item>Link 1</Nav.Item>
72
+ <Nav.Item>Link 2</Nav.Item>
73
+ </Nav.List>
74
+ </>
75
+ ),
76
+ },
77
+ } as Story
78
+
79
+ export const MultipleNavs: Story = {
80
+ args: {
81
+ ...NavSection.args,
82
+ classes: 'navbar',
83
+ children: (
84
+ <>
85
+ <Nav.List>
86
+ <Nav.Item>Link 1</Nav.Item>
87
+ <Nav.Item>Link 2</Nav.Item>
88
+ </Nav.List>
89
+ <Nav.List>
90
+ <Nav.Item>Link 1</Nav.Item>
91
+ <Nav.Item>Link 2</Nav.Item>
92
+ </Nav.List>
93
+ </>
94
+ ),
95
+ },
96
+ } as Story