polpo 0.1.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 (332) hide show
  1. package/.eslintrc.cjs +9 -0
  2. package/.storybook/decorators.tsx +61 -0
  3. package/.storybook/main.ts +47 -0
  4. package/.storybook/manager-head.html +2 -0
  5. package/.storybook/manager.ts +7 -0
  6. package/.storybook/preview-head.html +2 -0
  7. package/.storybook/preview.ts +38 -0
  8. package/.storybook/theme.ts +47 -0
  9. package/.turbo/daemon/f5c5c8fb195b01d0-turbo.log.2024-05-26 +0 -0
  10. package/.turbo/turbo-build$colon$watch.log +96 -0
  11. package/.turbo/turbo-build-storybook.log +0 -0
  12. package/.turbo/turbo-build.log +77 -0
  13. package/.turbo/turbo-lint$colon$fix.log +2 -0
  14. package/.turbo/turbo-lint.log +4 -0
  15. package/README.md +68 -0
  16. package/dist/chunk-M4KRSYE7.js +3 -0
  17. package/dist/chunk-M4KRSYE7.js.map +1 -0
  18. package/dist/chunk-U5XSMSKZ.js +3 -0
  19. package/dist/chunk-U5XSMSKZ.js.map +1 -0
  20. package/dist/get-modal-position-DPftPoU2.d.cts +28 -0
  21. package/dist/get-modal-position-DPftPoU2.d.ts +28 -0
  22. package/dist/helpers.cjs +3 -0
  23. package/dist/helpers.cjs.map +1 -0
  24. package/dist/helpers.d.cts +15 -0
  25. package/dist/helpers.d.ts +15 -0
  26. package/dist/helpers.js +3 -0
  27. package/dist/helpers.js.map +1 -0
  28. package/dist/hooks.cjs +3 -0
  29. package/dist/hooks.cjs.map +1 -0
  30. package/dist/hooks.d.cts +121 -0
  31. package/dist/hooks.d.ts +121 -0
  32. package/dist/hooks.js +3 -0
  33. package/dist/hooks.js.map +1 -0
  34. package/dist/ui.cjs +1987 -0
  35. package/dist/ui.cjs.map +1 -0
  36. package/dist/ui.d.cts +3932 -0
  37. package/dist/ui.d.ts +3932 -0
  38. package/dist/ui.js +1987 -0
  39. package/dist/ui.js.map +1 -0
  40. package/package.json +98 -0
  41. package/src/components/accordion/accordion-item.stories.tsx +128 -0
  42. package/src/components/accordion/accordion-item.tsx +119 -0
  43. package/src/components/accordion/accordion.stories.tsx +74 -0
  44. package/src/components/accordion/accordion.style.ts +42 -0
  45. package/src/components/accordion/accordion.tsx +56 -0
  46. package/src/components/accordion/index.ts +2 -0
  47. package/src/components/buttons/button/button.stories.tsx +103 -0
  48. package/src/components/buttons/button/button.style.ts +147 -0
  49. package/src/components/buttons/button/button.tsx +119 -0
  50. package/src/components/buttons/button/index.ts +1 -0
  51. package/src/components/buttons/index.ts +1 -0
  52. package/src/components/cards/flip-card/flip-card.stories.tsx +61 -0
  53. package/src/components/cards/flip-card/flip-card.style.ts +45 -0
  54. package/src/components/cards/flip-card/flip-card.tsx +55 -0
  55. package/src/components/cards/flip-card/index.ts +1 -0
  56. package/src/components/cards/hover-card/hover-card.stories.tsx +45 -0
  57. package/src/components/cards/hover-card/hover-card.style.ts +13 -0
  58. package/src/components/cards/hover-card/hover-card.tsx +71 -0
  59. package/src/components/cards/hover-card/index.ts +1 -0
  60. package/src/components/cards/index.ts +3 -0
  61. package/src/components/cards/slide-card/index.ts +1 -0
  62. package/src/components/cards/slide-card/slide-card.stories.tsx +47 -0
  63. package/src/components/cards/slide-card/slide-card.tsx +42 -0
  64. package/src/components/form/checkbox/checkbox.stories.tsx +34 -0
  65. package/src/components/form/checkbox/checkbox.style.ts +75 -0
  66. package/src/components/form/checkbox/checkbox.tsx +76 -0
  67. package/src/components/form/checkbox/index.ts +1 -0
  68. package/src/components/form/controller/controller.tsx +42 -0
  69. package/src/components/form/controller/index.ts +1 -0
  70. package/src/components/form/date-picker/date-picker.stories.tsx +38 -0
  71. package/src/components/form/date-picker/date-picker.tsx +67 -0
  72. package/src/components/form/date-picker/index.ts +1 -0
  73. package/src/components/form/field/field.stories.tsx +49 -0
  74. package/src/components/form/field/field.style.ts +79 -0
  75. package/src/components/form/field/field.tsx +83 -0
  76. package/src/components/form/field/field.types.ts +28 -0
  77. package/src/components/form/field/index.ts +2 -0
  78. package/src/components/form/form.stories.types.tsx +50 -0
  79. package/src/components/form/form.types.ts +37 -0
  80. package/src/components/form/index.ts +14 -0
  81. package/src/components/form/input/index.ts +1 -0
  82. package/src/components/form/input/input.stories.tsx +41 -0
  83. package/src/components/form/input/input.tsx +73 -0
  84. package/src/components/form/input-color/index.ts +1 -0
  85. package/src/components/form/input-color/input-color.stories.tsx +46 -0
  86. package/src/components/form/input-color/input-color.style.ts +93 -0
  87. package/src/components/form/input-color/input-color.tsx +159 -0
  88. package/src/components/form/input-file/index.ts +1 -0
  89. package/src/components/form/input-file/input-file.stories.tsx +40 -0
  90. package/src/components/form/input-file/input-file.style.ts +143 -0
  91. package/src/components/form/input-file/input-file.tsx +214 -0
  92. package/src/components/form/input-password/index.ts +1 -0
  93. package/src/components/form/input-password/input-password.stories.tsx +37 -0
  94. package/src/components/form/input-password/input-password.tsx +83 -0
  95. package/src/components/form/radio/index.ts +1 -0
  96. package/src/components/form/radio/radio.stories.tsx +43 -0
  97. package/src/components/form/radio/radio.style.ts +58 -0
  98. package/src/components/form/radio/radio.tsx +76 -0
  99. package/src/components/form/select/index.ts +1 -0
  100. package/src/components/form/select/options.tsx +140 -0
  101. package/src/components/form/select/select-option.tsx +84 -0
  102. package/src/components/form/select/select.stories.tsx +89 -0
  103. package/src/components/form/select/select.style.ts +164 -0
  104. package/src/components/form/select/select.tsx +327 -0
  105. package/src/components/form/select/select.types.ts +93 -0
  106. package/src/components/form/slider/index.ts +1 -0
  107. package/src/components/form/slider/slider.stories.tsx +40 -0
  108. package/src/components/form/slider/slider.style.ts +90 -0
  109. package/src/components/form/slider/slider.tsx +108 -0
  110. package/src/components/form/switch/index.ts +1 -0
  111. package/src/components/form/switch/switch.stories.tsx +38 -0
  112. package/src/components/form/switch/switch.style.ts +120 -0
  113. package/src/components/form/switch/switch.tsx +111 -0
  114. package/src/components/form/textarea/index.ts +1 -0
  115. package/src/components/form/textarea/textarea.stories.tsx +43 -0
  116. package/src/components/form/textarea/textarea.style.ts +7 -0
  117. package/src/components/form/textarea/textarea.tsx +76 -0
  118. package/src/components/icon/icon.stories.tsx +63 -0
  119. package/src/components/icon/icon.tsx +64 -0
  120. package/src/components/icon/icons/index.ts +18 -0
  121. package/src/components/icon/icons/object.tsx +482 -0
  122. package/src/components/icon/icons/social.tsx +72 -0
  123. package/src/components/icon/icons/symbol.tsx +776 -0
  124. package/src/components/icon/index.ts +5 -0
  125. package/src/components/image/image.stories.tsx +25 -0
  126. package/src/components/image/image.tsx +7 -0
  127. package/src/components/image/index.ts +1 -0
  128. package/src/components/index.ts +16 -0
  129. package/src/components/infinity-scroll/index.ts +1 -0
  130. package/src/components/infinity-scroll/infinity-scroll.stories.tsx +75 -0
  131. package/src/components/infinity-scroll/infinity-scroll.style.ts +30 -0
  132. package/src/components/infinity-scroll/infinity-scroll.tsx +56 -0
  133. package/src/components/line/index.ts +1 -0
  134. package/src/components/line/line.stories.tsx +67 -0
  135. package/src/components/line/line.style.ts +57 -0
  136. package/src/components/line/line.tsx +76 -0
  137. package/src/components/loaders/index.ts +1 -0
  138. package/src/components/loaders/simple-loader/index.ts +1 -0
  139. package/src/components/loaders/simple-loader/simple-loader.stories.tsx +21 -0
  140. package/src/components/loaders/simple-loader/simple-loader.style.ts +13 -0
  141. package/src/components/loaders/simple-loader/simple-loader.tsx +15 -0
  142. package/src/components/modals/action-modal/action-modal.stories.tsx +134 -0
  143. package/src/components/modals/action-modal/action-modal.style.ts +129 -0
  144. package/src/components/modals/action-modal/action-modal.tsx +150 -0
  145. package/src/components/modals/action-modal/index.ts +1 -0
  146. package/src/components/modals/aside-modal/aside-modal.stories.tsx +82 -0
  147. package/src/components/modals/aside-modal/aside-modal.style.ts +108 -0
  148. package/src/components/modals/aside-modal/aside-modal.tsx +66 -0
  149. package/src/components/modals/aside-modal/index.ts +1 -0
  150. package/src/components/modals/confirmation-modal/confirmation-modal.stories.tsx +50 -0
  151. package/src/components/modals/confirmation-modal/confirmation-modal.style.ts +17 -0
  152. package/src/components/modals/confirmation-modal/confirmation-modal.tsx +43 -0
  153. package/src/components/modals/confirmation-modal/index.ts +1 -0
  154. package/src/components/modals/index.ts +4 -0
  155. package/src/components/modals/modal/index.ts +1 -0
  156. package/src/components/modals/modal/modal.style.ts +10 -0
  157. package/src/components/modals/modal/modal.tsx +132 -0
  158. package/src/components/ripple/index.ts +1 -0
  159. package/src/components/ripple/ripple.stories.tsx +38 -0
  160. package/src/components/ripple/ripple.style.ts +33 -0
  161. package/src/components/ripple/ripple.tsx +63 -0
  162. package/src/components/smart-table/index.ts +1 -0
  163. package/src/components/smart-table/smart-table.column.tsx +63 -0
  164. package/src/components/smart-table/smart-table.helpers.tsx +59 -0
  165. package/src/components/smart-table/smart-table.hooks.ts +27 -0
  166. package/src/components/smart-table/smart-table.row.tsx +29 -0
  167. package/src/components/smart-table/smart-table.stories.tsx +301 -0
  168. package/src/components/smart-table/smart-table.style.ts +102 -0
  169. package/src/components/smart-table/smart-table.tsx +112 -0
  170. package/src/components/smart-table/smart-table.types.ts +41 -0
  171. package/src/components/tabs/index.ts +1 -0
  172. package/src/components/tabs/tabs-container.stories.tsx +159 -0
  173. package/src/components/tabs/tabs-list.tsx +131 -0
  174. package/src/components/tabs/tabs.stories.tsx +68 -0
  175. package/src/components/tabs/tabs.style.ts +132 -0
  176. package/src/components/tabs/tabs.tsx +117 -0
  177. package/src/components/tag/index.ts +1 -0
  178. package/src/components/tag/tag.stories.tsx +49 -0
  179. package/src/components/tag/tag.style.ts +24 -0
  180. package/src/components/tag/tag.tsx +44 -0
  181. package/src/components/tooltips/click-to-copy/click-to-copy.stories.tsx +39 -0
  182. package/src/components/tooltips/click-to-copy/click-to-copy.tsx +41 -0
  183. package/src/components/tooltips/click-to-copy/index.ts +1 -0
  184. package/src/components/tooltips/index.ts +2 -0
  185. package/src/components/tooltips/tooltip/index.ts +1 -0
  186. package/src/components/tooltips/tooltip/tooltip.stories.tsx +35 -0
  187. package/src/components/tooltips/tooltip/tooltip.style.ts +62 -0
  188. package/src/components/tooltips/tooltip/tooltip.tsx +45 -0
  189. package/src/components/typography/index.ts +2 -0
  190. package/src/components/typography/typography.constants.ts +43 -0
  191. package/src/components/typography/typography.stories.tsx +106 -0
  192. package/src/components/typography/typography.style.ts +76 -0
  193. package/src/components/typography/typography.tsx +79 -0
  194. package/src/contexts/fetch-context/fetch-context.tsx +114 -0
  195. package/src/contexts/fetch-context/index.ts +1 -0
  196. package/src/contexts/form-context/form-context.tsx +43 -0
  197. package/src/contexts/form-context/index.ts +1 -0
  198. package/src/contexts/index.ts +3 -0
  199. package/src/contexts/theme-context/index.ts +3 -0
  200. package/src/contexts/theme-context/theme-context.tsx +158 -0
  201. package/src/contexts/theme-context/theme.animations.ts +180 -0
  202. package/src/contexts/theme-context/theme.defaults.ts +205 -0
  203. package/src/contexts/theme-context/theme.style.ts +78 -0
  204. package/src/contexts/theme-context/themes.ts +96 -0
  205. package/src/core/http-client.d.ts +11 -0
  206. package/src/core/http-client.d.ts.map +1 -0
  207. package/src/core/http-client.ts +47 -0
  208. package/src/core/index.d.ts +2 -0
  209. package/src/core/index.d.ts.map +1 -0
  210. package/src/core/index.ts +1 -0
  211. package/src/core/variants/color.ts +36 -0
  212. package/src/core/variants/index.ts +3 -0
  213. package/src/core/variants/radius.ts +56 -0
  214. package/src/core/variants/size.ts +44 -0
  215. package/src/helpers/format-bytes.ts +11 -0
  216. package/src/helpers/format-dates.ts +11 -0
  217. package/src/helpers/get-modal-position.ts +66 -0
  218. package/src/helpers/index.ts +4 -0
  219. package/src/helpers/text/index.ts +1 -0
  220. package/src/helpers/text/to-capitalize.ts +17 -0
  221. package/src/hooks/index.ts +23 -0
  222. package/src/hooks/use-async.ts +88 -0
  223. package/src/hooks/use-classnames.ts +13 -0
  224. package/src/hooks/use-constant.ts +3 -0
  225. package/src/hooks/use-debounce.ts +15 -0
  226. package/src/hooks/use-dimensions.ts +22 -0
  227. package/src/hooks/use-event-listener.ts +71 -0
  228. package/src/hooks/use-file-reader.ts +69 -0
  229. package/src/hooks/use-hover.ts +17 -0
  230. package/src/hooks/use-in-view.ts +20 -0
  231. package/src/hooks/use-input-handlers.ts +49 -0
  232. package/src/hooks/use-media-query.ts +25 -0
  233. package/src/hooks/use-modal-in-container.ts +94 -0
  234. package/src/hooks/use-mouse-position.ts +16 -0
  235. package/src/hooks/use-observer.ts +18 -0
  236. package/src/hooks/use-on-click-outside-ref.ts +17 -0
  237. package/src/hooks/use-online-status.ts +12 -0
  238. package/src/hooks/use-render-count.ts +11 -0
  239. package/src/hooks/use-safe-dispatch.ts +22 -0
  240. package/src/hooks/use-scroll.ts +31 -0
  241. package/src/hooks/use-state-history.ts +22 -0
  242. package/src/hooks/use-toggle-values.ts +14 -0
  243. package/src/hooks/use-toggle.ts +11 -0
  244. package/src/hooks/use-viewport.ts +38 -0
  245. package/src/index.ts +5 -0
  246. package/src/layouts/flex/flex.tsx +75 -0
  247. package/src/layouts/flex/index.ts +1 -0
  248. package/src/layouts/grid/grid.tsx +86 -0
  249. package/src/layouts/grid/index.ts +1 -0
  250. package/src/layouts/index.ts +3 -0
  251. package/src/layouts/section-layout/index.ts +1 -0
  252. package/src/layouts/section-layout/section-layout.stories.tsx +55 -0
  253. package/src/layouts/section-layout/section-layout.style.ts +21 -0
  254. package/src/layouts/section-layout/section-layout.tsx +46 -0
  255. package/src/stories/GettingStarted.mdx +66 -0
  256. package/src/types/generics.ts +68 -0
  257. package/src/types/index.ts +1 -0
  258. package/svg/Name=airplane, Category=object.svg +3 -0
  259. package/svg/Name=arrow-circle, Category=symbol.svg +3 -0
  260. package/svg/Name=arrow-down, Category=symbol.svg +3 -0
  261. package/svg/Name=arrow-left, Category=symbol.svg +3 -0
  262. package/svg/Name=arrow-right, Category=symbol.svg +3 -0
  263. package/svg/Name=arrow-up, Category=symbol.svg +3 -0
  264. package/svg/Name=bell, Category=object.svg +3 -0
  265. package/svg/Name=bicycle, Category=object.svg +3 -0
  266. package/svg/Name=book-open, Category=object.svg +3 -0
  267. package/svg/Name=book-solid, Category=object.svg +6 -0
  268. package/svg/Name=box-shadow, Category=symbol.svg +5 -0
  269. package/svg/Name=calendar, Category=object.svg +3 -0
  270. package/svg/Name=camera, Category=object.svg +3 -0
  271. package/svg/Name=caret-down, Category=symbol.svg +3 -0
  272. package/svg/Name=caret-left, Category=symbol.svg +3 -0
  273. package/svg/Name=caret-right, Category=symbol.svg +3 -0
  274. package/svg/Name=caret-up, Category=symbol.svg +3 -0
  275. package/svg/Name=checkmark, Category=symbol.svg +3 -0
  276. package/svg/Name=clean-computer, Category=object.svg +10 -0
  277. package/svg/Name=codepen, Category=social.svg +3 -0
  278. package/svg/Name=creative, Category=symbol.svg +5 -0
  279. package/svg/Name=cross, Category=symbol.svg +4 -0
  280. package/svg/Name=crossed-flags, Category=object.svg +4 -0
  281. package/svg/Name=cv, Category=symbol.svg +5 -0
  282. package/svg/Name=design-ui, Category=symbol.svg +9 -0
  283. package/svg/Name=document, Category=object.svg +3 -0
  284. package/svg/Name=door-closed, Category=object.svg +3 -0
  285. package/svg/Name=door-open, Category=object.svg +3 -0
  286. package/svg/Name=double-caret-down, Category=symbol.svg +4 -0
  287. package/svg/Name=double-caret-left, Category=symbol.svg +4 -0
  288. package/svg/Name=double-caret-righ, Category=symbol.svg +4 -0
  289. package/svg/Name=double-caret-up, Category=symbol.svg +4 -0
  290. package/svg/Name=download, Category=symbol.svg +5 -0
  291. package/svg/Name=dropper, Category=object.svg +5 -0
  292. package/svg/Name=envelope, Category=object.svg +3 -0
  293. package/svg/Name=exclamation-close, Category=symbol.svg +4 -0
  294. package/svg/Name=exclamation-open, Category=symbol.svg +4 -0
  295. package/svg/Name=external-link, Category=symbol.svg +3 -0
  296. package/svg/Name=eye, Category=object.svg +4 -0
  297. package/svg/Name=eye-hidden, Category=object.svg +7 -0
  298. package/svg/Name=facebook, Category=social.svg +3 -0
  299. package/svg/Name=form, Category=symbol.svg +8 -0
  300. package/svg/Name=game-control, Category=object.svg +3 -0
  301. package/svg/Name=gear, Category=object.svg +3 -0
  302. package/svg/Name=github, Category=social.svg +3 -0
  303. package/svg/Name=house, Category=object.svg +3 -0
  304. package/svg/Name=hyphen, Category=symbol.svg +3 -0
  305. package/svg/Name=info, Category=symbol.svg +3 -0
  306. package/svg/Name=instagram, Category=social.svg +3 -0
  307. package/svg/Name=link, Category=symbol.svg +5 -0
  308. package/svg/Name=linkedin, Category=social.svg +3 -0
  309. package/svg/Name=magnifying-glass, Category=object.svg +3 -0
  310. package/svg/Name=message, Category=symbol.svg +4 -0
  311. package/svg/Name=moon, Category=object.svg +5 -0
  312. package/svg/Name=order-list, Category=symbol.svg +7 -0
  313. package/svg/Name=pencil, Category=object.svg +3 -0
  314. package/svg/Name=pin-location, Category=symbol.svg +3 -0
  315. package/svg/Name=question-mark-close, Category=symbol.svg +3 -0
  316. package/svg/Name=question-mark-open, Category=symbol.svg +3 -0
  317. package/svg/Name=share, Category=symbol.svg +5 -0
  318. package/svg/Name=spinner, Category=symbol.svg +9 -0
  319. package/svg/Name=star, Category=object.svg +3 -0
  320. package/svg/Name=star-empty, Category=object.svg +3 -0
  321. package/svg/Name=sun, Category=object.svg +11 -0
  322. package/svg/Name=text-shadow, Category=symbol.svg +4 -0
  323. package/svg/Name=thinking, Category=symbol.svg +3 -0
  324. package/svg/Name=trash-can, Category=object.svg +4 -0
  325. package/svg/Name=upload, Category=symbol.svg +5 -0
  326. package/svg/Name=user, Category=symbol.svg +4 -0
  327. package/svg/Name=warning, Category=symbol.svg +5 -0
  328. package/svg/Name=whatsapp, Category=social.svg +3 -0
  329. package/svgconfig.json +4 -0
  330. package/tsconfig.json +14 -0
  331. package/tsup.config.cjs +21 -0
  332. package/vite.config.ts +13 -0
@@ -0,0 +1,159 @@
1
+ import { RadiusVariants, SizeVariants } from '../../core/variants';
2
+ import { Grid } from '../../layouts';
3
+ import { Typography } from '../typography';
4
+
5
+ import { Tabs } from './tabs';
6
+ import { TabListColor, TabListVariant } from './tabs-list';
7
+
8
+ import type { Meta, StoryObj } from '@storybook/react';
9
+
10
+ const meta: Meta<typeof Tabs.TabList> = {
11
+ title: 'Tabs/Tab List',
12
+ component: Tabs.TabList,
13
+ argTypes: {
14
+ variant: { control: 'inline-radio', options: Object.values(TabListVariant) },
15
+ size: { control: 'inline-radio', options: Object.values(SizeVariants) },
16
+ color: { control: 'inline-radio', options: [undefined, ...Object.values(TabListColor)] },
17
+ radius: { control: 'inline-radio', options: Object.values(RadiusVariants) },
18
+ direction: { control: false },
19
+ tabs: { control: false },
20
+ className: { control: false },
21
+ style: { control: false },
22
+ },
23
+ args: {
24
+ tabs: [
25
+ { id: 'home', label: 'Home' },
26
+ { id: 'about', label: 'About us' },
27
+ { id: 'products', label: 'Products' },
28
+ { id: 'categories', label: 'Categories' },
29
+ { id: 'services', label: 'Services' },
30
+ ],
31
+ },
32
+ };
33
+
34
+ export default meta;
35
+ type Story = StoryObj<typeof Tabs.TabList>;
36
+
37
+ export const Default: Story = {
38
+ args: {},
39
+ decorators: [
40
+ Story => (
41
+ <Grid gap='1em'>
42
+ <Tabs defaultOpenTab='home'>
43
+ <Story />
44
+
45
+ <Tabs.TabPanel id='home'>
46
+ <Typography variant='header4' align='center'>
47
+ Home
48
+ </Typography>
49
+ </Tabs.TabPanel>
50
+ <Tabs.TabPanel id='about'>
51
+ <Typography variant='header4' align='center'>
52
+ About us
53
+ </Typography>
54
+ </Tabs.TabPanel>
55
+ <Tabs.TabPanel id='products'>
56
+ <Typography variant='header4' align='center'>
57
+ Products
58
+ </Typography>
59
+ </Tabs.TabPanel>
60
+ <Tabs.TabPanel id='categories'>
61
+ <Typography variant='header4' align='center'>
62
+ Categories
63
+ </Typography>
64
+ </Tabs.TabPanel>
65
+ <Tabs.TabPanel id='services'>
66
+ <Typography variant='header4' align='center'>
67
+ Services
68
+ </Typography>
69
+ </Tabs.TabPanel>
70
+ </Tabs>
71
+ </Grid>
72
+ ),
73
+ ],
74
+ };
75
+
76
+ export const Vertical: Story = {
77
+ args: {
78
+ direction: 'vertical',
79
+ },
80
+ decorators: [
81
+ Story => (
82
+ <Grid gtc='auto 1fr' gap='2em' style={{ width: 700 }}>
83
+ <Tabs defaultOpenTab='home'>
84
+ <Story />
85
+
86
+ <Tabs.TabPanel id='home'>
87
+ <section>
88
+ <Typography variant='header4'>Home</Typography>
89
+ <Typography>
90
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At blanditiis, dolorem eius incidunt ipsum
91
+ labore maiores, modi nemo nisi nulla quia sunt, tenetur veritatis? Architecto asperiores excepturi quo.
92
+ Magni, maxime possimus! Adipisci facere laborum modi quod unde, velit veritatis! Voluptate!
93
+ </Typography>
94
+ </section>
95
+ </Tabs.TabPanel>
96
+ <Tabs.TabPanel id='about'>
97
+ <section>
98
+ <Typography variant='header4'>About us</Typography>
99
+ <Typography>
100
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. At, debitis eligendi est eum, facere inventore
101
+ iste neque nobis, rerum tempore vel voluptas voluptates. Maiores minima molestias mollitia nisi quidem
102
+ unde voluptatibus. Aliquam assumenda dolores earum ex laboriosam quidem quod repellendus!
103
+ </Typography>
104
+ </section>
105
+ </Tabs.TabPanel>
106
+ <Tabs.TabPanel id='products'>
107
+ <section>
108
+ <Typography variant='header4'>Products</Typography>
109
+ <Typography>
110
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet cumque cupiditate dolorum exercitationem
111
+ in laboriosam maxime, odio odit quod vitae. Autem consequuntur doloremque dolores, doloribus excepturi
112
+ fuga molestias natus nesciunt nulla obcaecati, odio quaerat quisquam reprehenderit sit tempore ullam
113
+ voluptas.
114
+ </Typography>
115
+ </section>
116
+ </Tabs.TabPanel>
117
+ <Tabs.TabPanel id='categories'>
118
+ <section>
119
+ <Typography variant='header4'>Categories</Typography>
120
+ <Typography>
121
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem cupiditate eius maxime repudiandae unde.
122
+ Ducimus eius eos illo incidunt qui! Dicta doloremque ea eaque earum error impedit iure, laboriosam
123
+ magnam maiores, odit quaerat quidem quos repudiandae sed temporibus ut voluptates.
124
+ </Typography>
125
+ </section>
126
+ </Tabs.TabPanel>
127
+ <Tabs.TabPanel id='services'>
128
+ <section>
129
+ <Typography variant='header4'>Services</Typography>
130
+ <Typography>
131
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam amet aperiam architecto autem
132
+ blanditiis cupiditate dicta eius et facere in incidunt laborum libero, maiores nam nulla odit
133
+ praesentium, quae quis sapiente sed tenetur ullam ut. Deleniti optio possimus quae sequi!
134
+ </Typography>
135
+ </section>
136
+ </Tabs.TabPanel>
137
+ </Tabs>
138
+ </Grid>
139
+ ),
140
+ ],
141
+ };
142
+
143
+ export const Variants: Story = {
144
+ argTypes: {
145
+ variant: { control: false },
146
+ },
147
+ args: {},
148
+ decorators: Default.decorators,
149
+ render: args => {
150
+ return (
151
+ <Grid gap='1em'>
152
+ <Tabs.TabList {...args} variant='solid' />
153
+ <Tabs.TabList {...args} variant='ghost' />
154
+ <Tabs.TabList {...args} variant='flat' />
155
+ <Tabs.TabList {...args} variant='line' />
156
+ </Grid>
157
+ );
158
+ },
159
+ };
@@ -0,0 +1,131 @@
1
+ import React, { useEffect, useRef, useState } from 'react';
2
+ import { useTheme } from 'styled-components';
3
+
4
+ import { ThemeColor } from '../../contexts';
5
+ import { RadiusVariants, SizeVariants, useRadiusClassName, useSizeClassName } from '../../core/variants';
6
+
7
+ import { Tabs } from './tabs';
8
+ import { TabListStyle, TabListStyleProps } from './tabs.style';
9
+
10
+ import { useClassNames } from '@polpo/hooks';
11
+
12
+ const DefaultRect = {
13
+ top: 0,
14
+ left: 0,
15
+ width: 0,
16
+ height: 0,
17
+ };
18
+
19
+ export enum TabListVariant {
20
+ SOLID = 'solid',
21
+ GHOST = 'ghost',
22
+ FLAT = 'flat',
23
+ LINE = 'line',
24
+ }
25
+
26
+ export enum TabListColor {
27
+ PRIMARY = 'primary',
28
+ SECONDARY = 'secondary',
29
+ TERTIARY = 'tertiary',
30
+ }
31
+
32
+ export enum TabListDirection {
33
+ HORIZONTAL = 'horizontal',
34
+ VERTICAL = 'vertical',
35
+ }
36
+
37
+ const getColor = (color?: ThemeColor): TabListStyleProps | null => {
38
+ if (color) {
39
+ return {
40
+ $color: color.main,
41
+ $colorContrast: color.contrast,
42
+ };
43
+ }
44
+
45
+ return null;
46
+ };
47
+
48
+ export type TabListProps = {
49
+ openTab: string;
50
+ variant?: `${TabListVariant}`;
51
+ children?: React.ReactNode;
52
+ size?: `${SizeVariants}`;
53
+ color?: `${TabListColor}`;
54
+ radius?: `${RadiusVariants}`;
55
+ direction?: `${TabListDirection}`;
56
+ className?: string;
57
+ style?: React.CSSProperties;
58
+ tabs?: Array<{
59
+ id: string;
60
+ label: React.ReactNode;
61
+ }>;
62
+ };
63
+
64
+ export const TabsList = ({
65
+ tabs = [],
66
+ variant = TabListVariant.SOLID,
67
+ radius = RadiusVariants.Full,
68
+ direction = TabListDirection.HORIZONTAL,
69
+ color,
70
+ children,
71
+ openTab,
72
+ size = SizeVariants.Medium,
73
+ className = '',
74
+ style = {},
75
+ }: TabListProps) => {
76
+ const theme = useTheme();
77
+ const containerRef = useRef<HTMLDivElement>(null);
78
+ const selectedTabRef = useRef<HTMLSpanElement>(null);
79
+ const [isSelectorActive, setIsSelectorActive] = useState(false);
80
+ const [selector, setSelector] = useState(DefaultRect);
81
+ const tabRadius = useRadiusClassName(radius);
82
+ const tabSize = useSizeClassName(size);
83
+ const containerClassNames = useClassNames({
84
+ [tabRadius]: true,
85
+ [tabSize]: true,
86
+ 'solid-variant': variant === TabListVariant.SOLID,
87
+ 'ghost-variant': variant === TabListVariant.GHOST,
88
+ 'flat-variant': variant === TabListVariant.FLAT,
89
+ 'line-variant': variant === TabListVariant.LINE,
90
+ 'vertical-direction': direction === TabListDirection.VERTICAL,
91
+ [className]: Boolean(className),
92
+ });
93
+
94
+ useEffect(() => {
95
+ const selectedRect = selectedTabRef.current?.getBoundingClientRect() ?? DefaultRect;
96
+ const containerRect = containerRef.current?.getBoundingClientRect() ?? DefaultRect;
97
+
98
+ const width = selectedRect.width;
99
+ const height = variant === TabListVariant.LINE ? 2 : selectedRect.height;
100
+ const left = selectedRect.left - containerRect.left;
101
+ const top =
102
+ variant === TabListVariant.LINE
103
+ ? selectedRect.top + selectedRect.height - containerRect.top
104
+ : selectedRect.top - containerRect.top;
105
+
106
+ setSelector({ left, top, width, height });
107
+
108
+ if (!isSelectorActive) {
109
+ setTimeout(() => {
110
+ setIsSelectorActive(true);
111
+ }, 100);
112
+ }
113
+ }, [isSelectorActive, variant, openTab]);
114
+
115
+ const containerColors: TabListStyleProps = (color && getColor(theme.colors[color])) || {
116
+ $color: theme.colors.text.main,
117
+ $colorContrast: theme.colors.background.main,
118
+ };
119
+
120
+ return (
121
+ <TabListStyle {...containerColors} className={containerClassNames} ref={containerRef} style={style}>
122
+ {Boolean(variant) && <span className={`tabs-selector ${isSelectorActive ? 'active' : ''}`} style={selector} />}
123
+ {tabs.map(({ id, label }) => (
124
+ <Tabs.Tab key={id} id={id} ref={id === openTab ? selectedTabRef : null}>
125
+ {label}
126
+ </Tabs.Tab>
127
+ ))}
128
+ {children}
129
+ </TabListStyle>
130
+ );
131
+ };
@@ -0,0 +1,68 @@
1
+ import { useState } from 'react';
2
+
3
+ import { Grid } from '../../layouts';
4
+ import { Button } from '../buttons';
5
+ import { Typography } from '../typography';
6
+
7
+ import { Tabs } from './tabs';
8
+
9
+ import type { Meta, StoryObj } from '@storybook/react';
10
+
11
+ const meta: Meta<typeof Tabs> = {
12
+ title: 'Tabs/Custom Tabs',
13
+ component: Tabs,
14
+ argTypes: {},
15
+ args: {},
16
+ render: () => {
17
+ const [selected, setSelected] = useState('');
18
+
19
+ const getButtonVariant = (id: string) => {
20
+ return selected === id ? 'solid' : 'ghost';
21
+ };
22
+
23
+ return (
24
+ <Tabs defaultOpenTab='tab-1' onChange={setSelected}>
25
+ <Grid flow='column' gap='1em' ai='center'>
26
+ <Tabs.Tab id='tab-1'>
27
+ <Button color='primary' variant={getButtonVariant('tab-1')}>
28
+ Tab 1
29
+ </Button>
30
+ </Tabs.Tab>
31
+ <Tabs.Tab id='tab-2'>
32
+ <Button color='primary' variant={getButtonVariant('tab-2')}>
33
+ Tab 2
34
+ </Button>
35
+ </Tabs.Tab>
36
+ <Tabs.Tab id='tab-3'>
37
+ <Button color='primary' variant={getButtonVariant('tab-3')}>
38
+ Tab 3
39
+ </Button>
40
+ </Tabs.Tab>
41
+ </Grid>
42
+
43
+ <Tabs.TabPanel id='tab-1'>
44
+ <Typography variant='header4' align='center'>
45
+ Tab 1 content
46
+ </Typography>
47
+ </Tabs.TabPanel>
48
+ <Tabs.TabPanel id='tab-2'>
49
+ <Typography variant='header4' align='center'>
50
+ Tab 2 content
51
+ </Typography>
52
+ </Tabs.TabPanel>
53
+ <Tabs.TabPanel id='tab-3'>
54
+ <Typography variant='header4' align='center'>
55
+ Tab 3 content
56
+ </Typography>
57
+ </Tabs.TabPanel>
58
+ </Tabs>
59
+ );
60
+ },
61
+ };
62
+
63
+ export default meta;
64
+ type Story = StoryObj<typeof Tabs>;
65
+
66
+ export const Default: Story = {
67
+ args: {},
68
+ };
@@ -0,0 +1,132 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { RadiusClassNames, SizeStyles } from '../../core/variants';
4
+
5
+ export const TabStyle = styled.span`
6
+ cursor: pointer;
7
+ user-select: none;
8
+ transition: all 300ms ease;
9
+ `;
10
+
11
+ export type TabListStyleProps = {
12
+ $color: string;
13
+ $colorContrast: string;
14
+ };
15
+
16
+ export const TabListStyle = styled.section<TabListStyleProps>`
17
+ display: grid;
18
+ grid-auto-flow: column;
19
+ gap: 1em;
20
+ align-items: center;
21
+ position: relative;
22
+ font-size: ${props => props.theme.constants.typography.label.fontSize};
23
+ border-radius: 2em;
24
+
25
+ ${SizeStyles}
26
+
27
+ .tabs-selector {
28
+ position: absolute;
29
+ background: ${props => props.$color};
30
+ color: ${props => props.$colorContrast};
31
+ border-radius: 1.5em;
32
+
33
+ &.active {
34
+ transition: all 300ms ease;
35
+ }
36
+ }
37
+
38
+ ${TabStyle} {
39
+ border-radius: 1.5em;
40
+ padding: 0.5em 1em;
41
+ z-index: 1;
42
+ text-align: center;
43
+
44
+ &.is-open {
45
+ color: ${props => props.$colorContrast};
46
+ }
47
+
48
+ &:not(.is-open):hover {
49
+ color: ${props => props.theme.colors.text.dark};
50
+ }
51
+ }
52
+
53
+ &.${RadiusClassNames.None} {
54
+ border-radius: 0;
55
+
56
+ ${TabStyle}, .tabs-selector {
57
+ border-radius: 0;
58
+ }
59
+ }
60
+
61
+ &.${RadiusClassNames.Small} {
62
+ border-radius: 0.5em;
63
+
64
+ ${TabStyle}, .tabs-selector {
65
+ border-radius: 0.3em;
66
+ }
67
+ }
68
+
69
+ &.${RadiusClassNames.Medium} {
70
+ border-radius: 1em;
71
+
72
+ ${TabStyle}, .tabs-selector {
73
+ border-radius: 0.8em;
74
+ }
75
+ }
76
+
77
+ &.${RadiusClassNames.Large} {
78
+ border-radius: 1.5em;
79
+
80
+ ${TabStyle}, .tabs-selector {
81
+ border-radius: 1.3em;
82
+ }
83
+ }
84
+
85
+ &.${RadiusClassNames.Full} {
86
+ border-radius: 1.8em;
87
+
88
+ ${TabStyle}, .tabs-selector {
89
+ border-radius: 1.6em;
90
+ }
91
+ }
92
+
93
+ &.vertical-direction {
94
+ grid-auto-flow: row;
95
+ align-items: unset;
96
+ align-content: start;
97
+ }
98
+
99
+ &.solid-variant {
100
+ background: ${props => props.theme.colors.background.paper};
101
+ color: ${props => props.theme.colors.text.main};
102
+ padding: 0.5em;
103
+ }
104
+
105
+ &.ghost-variant {
106
+ border: 1px solid ${props => props.$color};
107
+ padding: 0.5em;
108
+ }
109
+
110
+ &.flat-variant {
111
+ }
112
+
113
+ &.line-variant {
114
+ border-radius: 0;
115
+
116
+ &:not(.vertical-direction) {
117
+ border-bottom: 2px solid ${props => props.theme.colors.border.main};
118
+ }
119
+
120
+ .tabs-selector {
121
+ border-radius: 0;
122
+ }
123
+
124
+ ${TabStyle} {
125
+ border-radius: 0;
126
+
127
+ &.is-open {
128
+ color: ${props => props.$color};
129
+ }
130
+ }
131
+ }
132
+ `;
@@ -0,0 +1,117 @@
1
+ import React, { createContext, useContext, useEffect, useState } from 'react';
2
+
3
+ import { TabsList as TabListComponent, TabListProps } from './tabs-list';
4
+ import { TabStyle } from './tabs.style';
5
+
6
+ import { useClassNames } from '@polpo/hooks';
7
+
8
+ type TabsContextState = {
9
+ openTab: string;
10
+ changeOpenTab: (id: string) => void;
11
+ };
12
+
13
+ const TabsContext = createContext<TabsContextState | null>(null);
14
+
15
+ const useTab = (id: string): [boolean, () => void] => {
16
+ const context = useContext(TabsContext);
17
+
18
+ if (!context) {
19
+ throw new Error('You cant use this component out off an Tabs component');
20
+ }
21
+
22
+ const { openTab, changeOpenTab } = context;
23
+
24
+ return [openTab === id, () => changeOpenTab(id)];
25
+ };
26
+
27
+ const useTabsContext = (): TabsContextState => {
28
+ const context = useContext(TabsContext);
29
+
30
+ if (!context) {
31
+ throw new Error('You cant use this component out off an Tabs component');
32
+ }
33
+
34
+ return context;
35
+ };
36
+
37
+ type TabsProps = {
38
+ children: React.ReactNode;
39
+ defaultOpenTab: string;
40
+ onChange?: (id: string) => void;
41
+ };
42
+
43
+ export const Tabs = ({ children, defaultOpenTab, onChange }: TabsProps) => {
44
+ const [openTab, setOpenTab] = useState(defaultOpenTab);
45
+
46
+ useEffect(() => {
47
+ onChange && onChange(openTab);
48
+ }, [openTab, onChange]);
49
+
50
+ return (
51
+ <TabsContext.Provider
52
+ value={{
53
+ openTab,
54
+ changeOpenTab: id => setOpenTab(id),
55
+ }}
56
+ >
57
+ {children}
58
+ </TabsContext.Provider>
59
+ );
60
+ };
61
+
62
+ type TabProps = {
63
+ id: string;
64
+ children: React.ReactNode;
65
+ className?: string;
66
+ style?: React.CSSProperties;
67
+ onClick?: (e: React.MouseEvent<HTMLSpanElement>) => void;
68
+ };
69
+
70
+ const TabComponent = (
71
+ { id, children, className = '', style = {}, onClick }: TabProps,
72
+ ref: React.ForwardedRef<HTMLSpanElement>,
73
+ ) => {
74
+ const [isOpen, openTab] = useTab(id);
75
+ const tabClassNames = useClassNames({
76
+ [className]: !!className,
77
+ 'is-open': isOpen,
78
+ });
79
+
80
+ const handleClick = (e: React.MouseEvent<HTMLSpanElement>) => {
81
+ openTab();
82
+ onClick && onClick(e);
83
+ };
84
+
85
+ return (
86
+ <TabStyle className={tabClassNames} style={style} onClick={handleClick} ref={ref}>
87
+ {children}
88
+ </TabStyle>
89
+ );
90
+ };
91
+
92
+ const Tab = React.forwardRef(TabComponent);
93
+
94
+ type TabPanelProps = {
95
+ id: string;
96
+ children: React.ReactNode;
97
+ };
98
+
99
+ const TabPanel = ({ id, children }: TabPanelProps) => {
100
+ const [isOpen] = useTab(id);
101
+
102
+ return isOpen ? children : null;
103
+ };
104
+
105
+ const TabList = ({ children, ...props }: Omit<TabListProps, 'openTab'>) => {
106
+ const { openTab } = useTabsContext();
107
+
108
+ return (
109
+ <TabListComponent {...props} openTab={openTab}>
110
+ {children}
111
+ </TabListComponent>
112
+ );
113
+ };
114
+
115
+ Tabs.Tab = Tab;
116
+ Tabs.TabPanel = TabPanel;
117
+ Tabs.TabList = TabList;
@@ -0,0 +1 @@
1
+ export * from './tag';
@@ -0,0 +1,49 @@
1
+ import { RadiusVariants, SizeVariants } from '../../core/variants';
2
+ import { Flex } from '../../layouts';
3
+
4
+ import { Tag } from './tag';
5
+
6
+ import type { Meta, StoryObj } from '@storybook/react';
7
+
8
+ const meta: Meta<typeof Tag> = {
9
+ title: 'Tag',
10
+ component: Tag,
11
+ argTypes: {
12
+ isSelected: { control: 'boolean' },
13
+ children: { control: 'text' },
14
+ size: { control: 'inline-radio', options: Object.values(SizeVariants) },
15
+ radius: { control: 'inline-radio', options: Object.values(RadiusVariants) },
16
+ },
17
+ args: {
18
+ children: 'Tag',
19
+ isSelected: false,
20
+ },
21
+ };
22
+
23
+ export default meta;
24
+ type Story = StoryObj<typeof Tag>;
25
+
26
+ export const Single: Story = {
27
+ args: {},
28
+ };
29
+
30
+ export const Many: Story = {
31
+ args: {},
32
+ render: (args, { isSelected }) => <Tag isSelected={isSelected} {...args} />,
33
+ decorators: [
34
+ Story => (
35
+ <Flex wrap='wrap' gap='1em'>
36
+ <Story />
37
+ <Story />
38
+ <Story />
39
+ <Story />
40
+ <Story />
41
+ <Story />
42
+ <Story />
43
+ <Story />
44
+ <Story />
45
+ <Story />
46
+ </Flex>
47
+ ),
48
+ ],
49
+ };
@@ -0,0 +1,24 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { RadiusStyles, SizeStyles } from '../../core/variants';
4
+
5
+ export const TagStyle = styled.span`
6
+ padding: 0.4em 0.8em;
7
+ border-radius: 0.3em;
8
+ border: 1px solid;
9
+ background: ${props => props.theme.colors.text.main}11;
10
+ color: ${props => props.theme.colors.text.main};
11
+ transition: all 300ms ease;
12
+ display: inline-block;
13
+ font-size: ${props => props.theme.constants.typography.label.fontSize};
14
+ user-select: none;
15
+
16
+ ${SizeStyles}
17
+ ${RadiusStyles}
18
+
19
+ &:hover,
20
+ &.tag-selected {
21
+ background: ${props => props.theme.colors.primary.main};
22
+ color: ${props => props.theme.colors.primary.contrast};
23
+ }
24
+ `;