@a-type/ui 1.8.18 → 2.0.1

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 (84) hide show
  1. package/README.md +1 -58
  2. package/dist/cjs/colors.stories.d.ts +13 -0
  3. package/dist/cjs/colors.stories.js +29 -0
  4. package/dist/cjs/colors.stories.js.map +1 -0
  5. package/dist/cjs/components/button/classes.js +9 -9
  6. package/dist/cjs/components/button/classes.js.map +1 -1
  7. package/dist/cjs/components/card/Card.d.ts +2 -2
  8. package/dist/cjs/components/card/Card.js +4 -4
  9. package/dist/cjs/components/card/Card.js.map +1 -1
  10. package/dist/cjs/components/checkbox/Checkbox.js +1 -1
  11. package/dist/cjs/components/checkbox/Checkbox.js.map +1 -1
  12. package/dist/cjs/components/datePicker/DatePicker.js +3 -1
  13. package/dist/cjs/components/datePicker/DatePicker.js.map +1 -1
  14. package/dist/cjs/components/horizontalList/HorizontalList.js +3 -3
  15. package/dist/cjs/components/horizontalList/HorizontalList.js.map +1 -1
  16. package/dist/cjs/components/richEditor/index.js +1 -1
  17. package/dist/cjs/components/scrollArea/ScrollArea.js +1 -1
  18. package/dist/cjs/components/scrollArea/ScrollArea.js.map +1 -1
  19. package/dist/cjs/components/slider/Slider.js +1 -1
  20. package/dist/cjs/components/slider/Slider.js.map +1 -1
  21. package/dist/cjs/components/tabs/tabs.js +1 -1
  22. package/dist/cjs/components/tabs/tabs.js.map +1 -1
  23. package/dist/cjs/components/toggleGroup/toggleGroup.js +1 -1
  24. package/dist/cjs/components/toggleGroup/toggleGroup.js.map +1 -1
  25. package/dist/cjs/components/typography/typography.js +3 -3
  26. package/dist/cjs/themes.stories.d.ts +2 -0
  27. package/dist/cjs/themes.stories.js +67 -1
  28. package/dist/cjs/themes.stories.js.map +1 -1
  29. package/dist/cjs/uno/colors.d.ts +14 -0
  30. package/dist/cjs/uno/colors.js +59 -0
  31. package/dist/cjs/uno/colors.js.map +1 -0
  32. package/dist/cjs/uno.preset.d.ts +5 -4
  33. package/dist/cjs/uno.preset.js +85 -261
  34. package/dist/cjs/uno.preset.js.map +1 -1
  35. package/dist/css/main.css +846 -784
  36. package/dist/esm/colors.stories.d.ts +13 -0
  37. package/dist/esm/colors.stories.js +26 -0
  38. package/dist/esm/colors.stories.js.map +1 -0
  39. package/dist/esm/components/button/classes.js +9 -9
  40. package/dist/esm/components/button/classes.js.map +1 -1
  41. package/dist/esm/components/card/Card.d.ts +2 -2
  42. package/dist/esm/components/card/Card.js +4 -4
  43. package/dist/esm/components/card/Card.js.map +1 -1
  44. package/dist/esm/components/checkbox/Checkbox.js +1 -1
  45. package/dist/esm/components/checkbox/Checkbox.js.map +1 -1
  46. package/dist/esm/components/datePicker/DatePicker.js +3 -1
  47. package/dist/esm/components/datePicker/DatePicker.js.map +1 -1
  48. package/dist/esm/components/horizontalList/HorizontalList.js +3 -3
  49. package/dist/esm/components/horizontalList/HorizontalList.js.map +1 -1
  50. package/dist/esm/components/richEditor/index.js +1 -1
  51. package/dist/esm/components/scrollArea/ScrollArea.js +1 -1
  52. package/dist/esm/components/scrollArea/ScrollArea.js.map +1 -1
  53. package/dist/esm/components/slider/Slider.js +1 -1
  54. package/dist/esm/components/slider/Slider.js.map +1 -1
  55. package/dist/esm/components/tabs/tabs.js +1 -1
  56. package/dist/esm/components/tabs/tabs.js.map +1 -1
  57. package/dist/esm/components/toggleGroup/toggleGroup.js +1 -1
  58. package/dist/esm/components/toggleGroup/toggleGroup.js.map +1 -1
  59. package/dist/esm/components/typography/typography.js +3 -3
  60. package/dist/esm/themes.stories.d.ts +2 -0
  61. package/dist/esm/themes.stories.js +67 -1
  62. package/dist/esm/themes.stories.js.map +1 -1
  63. package/dist/esm/uno/colors.d.ts +14 -0
  64. package/dist/esm/uno/colors.js +54 -0
  65. package/dist/esm/uno/colors.js.map +1 -0
  66. package/dist/esm/uno.preset.d.ts +5 -4
  67. package/dist/esm/uno.preset.js +84 -260
  68. package/dist/esm/uno.preset.js.map +1 -1
  69. package/package.json +1 -1
  70. package/src/colors.stories.tsx +53 -0
  71. package/src/components/button/classes.tsx +12 -12
  72. package/src/components/card/Card.tsx +5 -5
  73. package/src/components/checkbox/Checkbox.tsx +1 -1
  74. package/src/components/datePicker/DatePicker.tsx +1 -0
  75. package/src/components/horizontalList/HorizontalList.tsx +3 -3
  76. package/src/components/richEditor/index.tsx +3 -3
  77. package/src/components/scrollArea/ScrollArea.tsx +1 -1
  78. package/src/components/slider/Slider.tsx +2 -2
  79. package/src/components/tabs/tabs.tsx +1 -1
  80. package/src/components/toggleGroup/toggleGroup.tsx +1 -1
  81. package/src/components/typography/typography.tsx +3 -3
  82. package/src/themes.stories.tsx +95 -1
  83. package/src/uno/colors.ts +68 -0
  84. package/src/uno.preset.ts +96 -322
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-type/ui",
3
- "version": "1.8.18",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "/dist",
@@ -0,0 +1,53 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { Box } from './components/index.js';
3
+
4
+ const meta = {
5
+ title: 'colors',
6
+ argTypes: {},
7
+ parameters: {
8
+ controls: { expanded: true },
9
+ },
10
+ } satisfies Meta;
11
+
12
+ export default meta;
13
+
14
+ type Story = StoryObj;
15
+
16
+ export const Default: Story = {
17
+ render() {
18
+ return (
19
+ <Box d="col">
20
+ <Range className="theme-lemon" />
21
+ <Range className="theme-leek" />
22
+ <Range className="theme-tomato" />
23
+ <Range className="theme-eggplant" />
24
+ <Range className="theme-blueberry" />
25
+ <Range className="theme-salt" />
26
+ </Box>
27
+ );
28
+ },
29
+ };
30
+
31
+ function Swatch({ className }: { className?: string }) {
32
+ return (
33
+ <div
34
+ className={className}
35
+ style={{
36
+ width: '100px',
37
+ height: '100px',
38
+ }}
39
+ />
40
+ );
41
+ }
42
+
43
+ function Range({ className }: { className?: string }) {
44
+ return (
45
+ <Box className={className}>
46
+ <Swatch className="bg-primary-wash" />
47
+ <Swatch className="bg-primary-light" />
48
+ <Swatch className="bg-primary" />
49
+ <Swatch className="bg-primary-dark" />
50
+ <Swatch className="bg-primary-ink" />
51
+ </Box>
52
+ );
53
+ }
@@ -15,11 +15,11 @@ export function getButtonClassName({
15
15
  return classNames(
16
16
  'layer-components:(px-4 py-2 bg-[var(--bg-neutral,var(--bg))] [--webkit-tap-highlight-color:transparent] [line-height:1] text-size-md font-inherit border border-solid border-transparent rounded-lg cursor-pointer font-bold flex flex-row gap-1 items-center relative overflow-visible select-none all:transition duration-200 whitespace-nowrap ring-bg)',
17
17
  'layer-components:()',
18
- 'layer-components:hover:(bg-[var(--bg)] bg-darken-2 ring-4)',
18
+ 'layer-components:hover:(bg-[var(--bg)] bg-darken-1 ring-4)',
19
19
  'layer-components:focus:outline-off',
20
- 'layer-components:focus-visible:(bg-[var(--bg)] outline-off bg-darken-7 ring-6)',
21
- 'layer-components:[&[data-focus=true]]:(bg-[var(--bg)] ring-6 bg-darken-7)',
22
- 'layer-components:active:(bg-[var(--bg)] bg-darken-7 ring-8)',
20
+ 'layer-components:focus-visible:(bg-[var(--bg)] outline-off bg-darken-1 ring-6)',
21
+ 'layer-components:[&[data-focus=true]]:(bg-[var(--bg)] ring-6 bg-darken-1)',
22
+ 'layer-components:active:(bg-[var(--bg)] bg-darken-1 ring-8)',
23
23
  'important:disabled:(opacity-50 cursor-default bg-[var(--bg)] shadow-none ring-none)',
24
24
  'important:[&[data-disabled=true]]:(opacity-50 cursor-default bg-[var(--bg)] shadow-none)',
25
25
  colors[color ?? 'default'],
@@ -36,14 +36,14 @@ export function getButtonClassName({
36
36
  }
37
37
 
38
38
  const colors = {
39
- primary: `layer-variants:[&.btn-color-primary]:([--bg:var(--color-primary-light)] shadow-sm color-black border-primary-dark focus-visible:([--bg:var(--color-primary)]))`,
40
- accent: `layer-variants:[&.btn-color-accent]:([--bg:var(--color-accent-wash)] shadow-sm color-black border-accent-dark focus-visible:([--bg:var(--color-accent-light)]))`,
41
- default: `layer-variants:[&.btn-color-default]:([--bg:var(--color-white)] shadow-sm color-black border-gray-dark)`,
42
- ghost: `layer-variants:[&.btn-color-ghost]:([--bg-neutral:transparent] [--bg:var(--color-light-blend)] color-darkBlend hover:bg-darken-3 focus-visible:(bg-darken-5) [&[data-focus=true]]:(bg-darken-5) active:bg-darken-6)`,
43
- destructive: `layer-variants:[&.btn-color-destructive]:([--bg:var(--color-attention-light)] shadow-sm border-attention-dark color-black hover:([--bg:var(--colors-attention)]))`,
44
- ghostDestructive: `layer-variants:[&.btn-color-ghostDestructive]:([--bg-neutral:transparent] [--bg:var(--color-attention-light)] color-attention-dark hover:(bg-darken-1 color-black) focus-visible:(bg-darken-2 color-black) active:bg-darken-2)`,
45
- ghostAccent: `layer-variants:[&.btn-color-ghostAccent]:([--bg-neutral:transparent] [--bg:var(--color-accent-wash)] color-accent-dark hover:bg-darken-2 focus-visible:bg-darken-6 active:bg-darken-6)`,
46
- contrast: `layer-variants:[&.btn-color-contrast]:([--bg:var(--color-black)] color-white border-black hover:bg-lighten-1 focus-visible:bg-lighten-5 active:bg-lighten-4)`,
39
+ primary: `layer-variants:[&.btn-color-primary]:([--bg:var(--color-primary)] shadow-sm color-black border-primary-dark)`,
40
+ accent: `layer-variants:[&.btn-color-accent]:([--bg-neutral:var(--color-accent-wash)] [--bg:var(--color-accent-light)] shadow-sm color-black border-accent-dark)`,
41
+ default: `layer-variants:[&.btn-color-default]:([--bg-neutral:var(--color-white)] [--bg:var(--color-gray-light)] shadow-sm color-black border-gray-dark)`,
42
+ ghost: `layer-variants:[&.btn-color-ghost]:([--bg-neutral:transparent] [--bg:oklch(from_var(--color-gray)_l_c_h/50%)] color-dark-blend)`,
43
+ destructive: `layer-variants:[&.btn-color-destructive]:([--bg:var(--color-attention)] shadow-sm border-attention-dark color-black ))`,
44
+ ghostDestructive: `layer-variants:[&.btn-color-ghostDestructive]:([--bg-neutral:transparent] [--bg:var(--color-attention-light)] color-attention-dark hover:(color-black) focus-visible:(color-black))`,
45
+ ghostAccent: `layer-variants:[&.btn-color-ghostAccent]:([--bg-neutral:transparent] [--bg:var(--color-accent-wash)] color-accent-dark hover:bg-darken-4)`,
46
+ contrast: `layer-variants:[&.btn-color-contrast]:([--bg:var(--color-black)] color-white border-black hover:bg-lighten-1 focus-visible:bg-lighten-1 active:bg-lighten-1)`,
47
47
  unstyled: `layer-variants:(bg-transparent hover:(bg-transparent) focus:(bg-transparent) active:(bg-transparent) color-inherit border-none shadow-none hover:(shadow-none) focus:(shadow-none) active:(shadow-none) p-0 items-start font-inherit font-normal rounded-none text-size-inherit transition-none)`,
48
48
  };
49
49
  export const buttonColorClasses = colors;
@@ -8,7 +8,7 @@ import { SlotDiv } from '../utility/SlotDiv.js';
8
8
 
9
9
  export const CardRoot = withClassName(
10
10
  withProps(Box, { container: 'reset' }),
11
- 'layer-components:(flex flex-col border-light rounded-lg text-lg overflow-hidden h-max-content relative bg-wash bg-darken-0.5 text-black shadow-sm)',
11
+ 'layer-components:(flex flex-col border-light rounded-lg text-lg overflow-hidden h-max-content relative bg-wash bg-darken-1 text-black shadow-sm)',
12
12
  'layer-variants:[&[data-borderless=true]]:(border-none shadow-md)',
13
13
  );
14
14
 
@@ -59,14 +59,14 @@ export function CardMain({
59
59
 
60
60
  export const CardTitle = withClassName(
61
61
  'div',
62
- 'layer-components:(flex flex-col gap-1 mt-0 bg-white py-2 px-3 rounded-lg rounded-bl-none rounded-tr-none w-auto mr-auto border border-solid border-grayDarkBlend text-md max-h-80px overflow-hidden text-ellipsis max-w-full text-inherit font-semibold relative z-1 transition-colors)',
62
+ 'layer-components:(flex flex-col gap-1 mt-0 bg-white py-2 px-3 rounded-lg rounded-bl-none rounded-tr-none w-auto mr-auto border border-solid border-gray-dark-blend text-md max-h-80px overflow-hidden text-ellipsis max-w-full text-inherit font-semibold relative z-1 transition-colors)',
63
63
  'layer-components:[[data-compact=true]_&]:(py-1 text-sm)',
64
- 'layer-components:[[data-interactive=true]:hover>&]:(bg-darken-4)',
64
+ 'layer-components:[[data-interactive=true]:hover>&]:(bg-darken-2)',
65
65
  );
66
66
 
67
67
  const CardContentRoot = withClassName(
68
68
  'div',
69
- 'layer-components:(flex flex-col gap-1 px-2 py-1 bg-lightBlend text-black rounded-md mx-2 my-0.5 border border-solid border-gray-darkBlend text-xs relative z-1)',
69
+ 'layer-components:(flex flex-col gap-1 px-2 py-1 bg-light-blend text-black rounded-md mx-2 my-0.5 border border-solid border-gray-dark-blend text-xs relative z-1)',
70
70
  'layer-variants:[[data-compact=true]_&]:(py-0 px-1 my-0 text-xs)',
71
71
  'layer-variants:[&[data-unstyled=true]]:(p-0 [background:unset] border-none)',
72
72
  );
@@ -90,7 +90,7 @@ export const CardFooter = withClassName(
90
90
 
91
91
  export const CardActions = withClassName(
92
92
  'div',
93
- 'layer-components:(ml-0 mr-auto flex flex-row gap-2 items-center bg-white rounded-lg p-0 border border-solid border-grayDarkBlend)',
93
+ 'layer-components:(ml-0 mr-auto flex flex-row gap-2 items-center bg-white rounded-lg p-0 border border-solid border-gray-dark-blend)',
94
94
  );
95
95
 
96
96
  export const CardMenu = withClassName(
@@ -11,7 +11,7 @@ export const CheckboxRoot = withClassName(
11
11
  classNames(
12
12
  'layer-components:(w-28px h-28px flex-shrink-0 relative bg-white border-default transition rounded-lg shadow-sm)',
13
13
  'layer-components:focus-visible:(outline-off shadow-focus)',
14
- 'layer-components:[&[data-state=checked]]:(bg-primary-light border-primary-dark)',
14
+ 'layer-components:[&[data-state=checked]]:(bg-primary border-primary-dark)',
15
15
  'layer-components:[&:hover:not(:disabled)]:shadow-[0_0_0_1px_var(--color-black)]',
16
16
  'layer-components:[&:disabled]:(bg-transparent border-gray-light shadow-none)',
17
17
  ),
@@ -222,6 +222,7 @@ const CalendarDay = withClassName(
222
222
  'disabled:(opacity-50 cursor-default)',
223
223
  // today dot
224
224
  "[&[data-today]]:before:(content-[''] absolute left-[2px] top-[2px] w-[6px] h-[6px] rounded-lg bg-primary)",
225
+ // calendar edges
225
226
  '[&[data-top-edge]]:(border-t-gray)',
226
227
  '[&[data-bottom-edge]]:(border-b-gray)',
227
228
  '[&[data-first-column]]:(border-l-gray)',
@@ -68,9 +68,9 @@ export function HorizontalList({
68
68
  }
69
69
  const contentWidth = content.offsetWidth;
70
70
  const containerHeight = container.offsetHeight;
71
- if (open) {
71
+ const containerWidth = container.offsetWidth;
72
+ if (open && contentWidth > containerWidth) {
72
73
  // measure content width and animate to container width
73
- const containerWidth = container.offsetWidth;
74
74
  rememberedWidth.current = contentWidth;
75
75
  content.style.setProperty('width', `${containerWidth}px`);
76
76
  content.style.setProperty('flex-wrap', 'wrap');
@@ -158,7 +158,7 @@ export function HorizontalList({
158
158
  <div
159
159
  className={clsx(
160
160
  'layer-components:(px-3 pt-3 pb-4 gap-2)',
161
- 'flex flex-row gap-2 flex-shrink-0 w-max-content w-auto)',
161
+ 'flex flex-row items-center gap-2 flex-shrink-0 w-max-content w-auto)',
162
162
  contentClassName,
163
163
  )}
164
164
  ref={contentRef}
@@ -5,9 +5,9 @@ export const tipTapClassName = clsx(
5
5
  'layer-components:[&_.ProseMirror:focus]:(outline-none shadow-focus)',
6
6
  'layer-components:[&_h1,h2,h3,p]:mt-0',
7
7
  'layer-components:[&_h1]:(text-2xl font-semibold mb-md [&:not:first-child]:mt-xl)',
8
- 'layer-components:[&_h2]:(text-lg font-bold color-gray-dark color-darken-7 mb-md [&:not:first-child]:mt-lg)',
9
- 'layer-components:[&_h3]:(text-md font-500 color-gray-dark color-darken-5 mb-sm [&:not:first-child]:mt-md)',
10
- 'layer-components:[&_h4]:(text-xs color-gray-dark color-darken-3 mb-sm [&:not:first-child]:mt-md uppercase)',
8
+ 'layer-components:[&_h2]:(text-lg font-bold color-gray-dark color-darken-4 mb-md [&:not:first-child]:mt-lg)',
9
+ 'layer-components:[&_h3]:(text-md font-500 color-gray-dark color-darken-3 mb-sm [&:not:first-child]:mt-md)',
10
+ 'layer-components:[&_h4]:(text-xs color-gray-dark color-darken-1 mb-sm [&:not:first-child]:mt-md uppercase)',
11
11
  'layer-components:[&_p]:(mb-md mt-0)',
12
12
  'layer-components:[&_a]:underline',
13
13
  'layer-components:[&_blockquote]:(border-l-4 border-l-solid border-gray pl-4 mb-md mt-md ml-md)',
@@ -20,7 +20,7 @@ export const ScrollAreaRoot = function ScrollAreaRoot({
20
20
  export const ScrollAreaViewport = withClassName(
21
21
  Primitive.Viewport,
22
22
  'h-full w-full',
23
- '[background:linear-gradient(var(--v-bg)_30%,rgba(255,255,255,0))_center_top,linear-gradient(rgba(255,255,255,0),var(--v-bg)_70%)_center_bottom,radial-gradient(farthest-side_at_50%_0,hsl(from_var(--v-bg)_h_s_calc(l*0.9)),rgba(0,0,0,0))_center_top,radial-gradient(farthest-side_at_50%_100%,hsl(from_var(--v-bg)_h_s_calc(l*0.9)),rgba(0,0,0,0))_center_bottom]',
23
+ '[background:linear-gradient(var(--v-bg)_30%,rgba(255,255,255,0))_center_top,linear-gradient(rgba(255,255,255,0),var(--v-bg)_70%)_center_bottom,radial-gradient(farthest-side_at_50%_0,oklch(from_var(--v-bg)_calc(l*0.9)_c_h),rgba(0,0,0,0))_center_top,radial-gradient(farthest-side_at_50%_100%,oklch(from_var(--v-bg)_calc(l*0.9)_c_h),rgba(0,0,0,0))_center_bottom]',
24
24
  '![background-repeat:no-repeat] ![background-size:100%_40px,100%_40px,100%_14px,100%_14px]',
25
25
  '![background-attachment:local,local,scroll,scroll]',
26
26
  );
@@ -22,8 +22,8 @@ export const SliderThumb = withClassName(
22
22
  'layer-components:focus-visible:(shadow-lg ring-4 ring-accent-dark ring-opacity-50 outline-none bg-accent-light)',
23
23
  'layer-components:focus:(outline-none)',
24
24
  'layer-components:disabled:(opacity-50)',
25
- 'layer-variants:[&[data-color=primary]]:active:(bg-primary-light ring-primary-dark)',
26
- 'layer-variants:[&[data-color=primary]]:focus-visible:(bg-primary-light ring-primary-dark)',
25
+ 'layer-variants:[&[data-color=primary]]:active:(bg-primary ring-primary-dark)',
26
+ 'layer-variants:[&[data-color=primary]]:focus-visible:(bg-primary ring-primary-dark)',
27
27
  );
28
28
 
29
29
  export interface SliderProps extends SliderPrimitive.SliderProps {
@@ -19,7 +19,7 @@ export const TabsTriggerBase = withClassName(
19
19
 
20
20
  const colorClasses = {
21
21
  default: 'layer-variants:([--bg:var(--color-white)])',
22
- primary: 'layer-variants:([--bg:var(--color-primary-light)])',
22
+ primary: 'layer-variants:([--bg:var(--color-primary)])',
23
23
  };
24
24
 
25
25
  export interface TabsTriggerProps
@@ -7,7 +7,7 @@ export const ToggleGroupRoot = withClassName(
7
7
  );
8
8
  export const ToggleGroupItem = withClassName(
9
9
  ToggleGroupPrimitive.Item,
10
- 'rounded-xl color-black bg-gray-light py-sm px-md flex items-center border-none justify-center cursor-pointer hover:bg-darken-2 active:bg-darken-4 focus-visible:(shadow-focus outline-off) [&[data-state=on]]:(bg-primary-light border-black)',
10
+ 'rounded-xl color-black bg-gray-light py-sm px-md flex items-center border-none justify-center cursor-pointer hover:bg-darken-1 active:bg-darken-2 focus-visible:(shadow-focus outline-off) [&[data-state=on]]:(bg-primary border-black)',
11
11
  );
12
12
 
13
13
  export const ToggleGroup = Object.assign(ToggleGroupRoot, {
@@ -9,17 +9,17 @@ export const H1 = withClassName(
9
9
  export const H2 = withClassName(
10
10
  'h2',
11
11
  baseHeadingClass,
12
- 'layer-components:(text-lg font-title font-bold color-inherit color-lighten-2)',
12
+ 'layer-components:(text-lg font-title font-bold color-inherit color-lighten-1)',
13
13
  );
14
14
  export const H3 = withClassName(
15
15
  'h3',
16
16
  baseHeadingClass,
17
- 'layer-components:(font-title text-md font-500 color-inherit color-lighten-4)',
17
+ 'layer-components:(font-title text-md font-500 color-inherit color-lighten-2)',
18
18
  );
19
19
  export const H4 = withClassName(
20
20
  'h4',
21
21
  baseHeadingClass,
22
- 'layer-components:(text-xs uppercase color-inherit color-lighten-6)',
22
+ 'layer-components:(text-xs uppercase color-inherit color-lighten-2)',
23
23
  );
24
24
  export const H5 = withClassName('h5', baseHeadingClass);
25
25
 
@@ -1,6 +1,6 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import clsx from 'clsx';
3
- import { useState } from 'react';
3
+ import { useRef, useState } from 'react';
4
4
  import { ActionBar, ActionButton } from './components/actions/index.js';
5
5
  import { Button } from './components/button/index.js';
6
6
  import { Card } from './components/card/index.js';
@@ -42,6 +42,7 @@ import {
42
42
  import { Input } from './components/input/index.js';
43
43
  import { Tabs } from './components/tabs/tabs.js';
44
44
  import { TextArea } from './components/textArea/index.js';
45
+ import { useAnimationFrame } from './hooks.js';
45
46
  import { useOverrideTheme } from './hooks/useOverrideTheme.js';
46
47
 
47
48
  const meta = {
@@ -323,3 +324,96 @@ export const Override: Story = {
323
324
  );
324
325
  },
325
326
  };
327
+
328
+ export const Custom: Story = {
329
+ render() {
330
+ const [theme, setTheme] = useState({
331
+ '--dyn-primary-source': 70,
332
+ '--dyn-accent-source': 290,
333
+ '--global-saturation': 0.5,
334
+ '--global-border-scale': 1.5,
335
+ '--global-spacing-scale': 1,
336
+ '--global-corner-scale': 1,
337
+ '--dyn-primary-hue-rotate': 0,
338
+ '--dyn-accent-hue-rotate': 0,
339
+ });
340
+ const reroll = () => {
341
+ setTheme({
342
+ '--dyn-primary-source': Math.floor(Math.random() * 360),
343
+ '--dyn-accent-source': Math.floor(Math.random() * 360),
344
+ '--global-saturation': Math.random(),
345
+ '--global-border-scale': Math.random() * 2,
346
+ '--global-spacing-scale': Math.random() * 2,
347
+ '--global-corner-scale': Math.random() * 1.25,
348
+ '--dyn-primary-hue-rotate': Math.random() * 4 - 2,
349
+ '--dyn-accent-hue-rotate': Math.random() * 4 - 2,
350
+ });
351
+ };
352
+ return (
353
+ <Box d="col" gap items="start" style={theme as any}>
354
+ <Button onClick={reroll}>Reroll</Button>
355
+ <DemoUI className="theme" />
356
+ </Box>
357
+ );
358
+ },
359
+ };
360
+
361
+ export const Trippy: Story = {
362
+ render() {
363
+ const ref = useRef<HTMLDivElement>(null);
364
+ const values = useRef({
365
+ primarySource: 0,
366
+ accentSource: 180,
367
+ saturation: 0.5,
368
+ borderScale: 2,
369
+ spacingScale: 0.5,
370
+ cornerScale: 0.5,
371
+ });
372
+ useAnimationFrame((dt) => {
373
+ const current = ref.current;
374
+ if (!current) return;
375
+ values.current.primarySource =
376
+ (values.current.primarySource + dt / 100) % 360;
377
+ values.current.accentSource =
378
+ (values.current.accentSource + dt / 50) % 360;
379
+ values.current.saturation =
380
+ 0.5 + 0.5 * Math.sin((Date.now() / 100000) * Math.PI * 2);
381
+ values.current.borderScale =
382
+ 1.5 + 1.5 * Math.sin((Date.now() / 20000) * Math.PI * 2);
383
+ values.current.spacingScale =
384
+ 1 + Math.sin((Date.now() / 50000) * Math.PI * 2);
385
+ values.current.cornerScale = 1 + Math.sin(Date.now() / 3000);
386
+ current.style.setProperty(
387
+ '--dyn-primary-source',
388
+ values.current.primarySource.toString(),
389
+ );
390
+ current.style.setProperty(
391
+ '--dyn-accent-source',
392
+ values.current.accentSource.toString(),
393
+ );
394
+ current.style.setProperty(
395
+ '--global-saturation',
396
+ values.current.saturation.toString(),
397
+ );
398
+ current.style.setProperty(
399
+ '--global-border-scale',
400
+ values.current.borderScale.toString(),
401
+ );
402
+ current.style.setProperty(
403
+ '--global-spacing-scale',
404
+ values.current.spacingScale.toString(),
405
+ );
406
+ current.style.setProperty(
407
+ '--global-corner-scale',
408
+ values.current.cornerScale.toString(),
409
+ );
410
+ current.style.setProperty('--dyn-primary-hue-rotate', '0');
411
+ current.style.setProperty('--dyn-accent-hue-rotate', '0');
412
+ });
413
+ return (
414
+ <div ref={ref}>
415
+ <DemoUI className="theme" />
416
+ </div>
417
+ );
418
+ },
419
+ };
@@ -0,0 +1,68 @@
1
+ export const colorConstants = `
2
+ --dyn-saturation-x-wash: calc(pow(var(--global-saturation, 1), 0.6));
3
+ --dyn-saturation-x-light: calc(pow(var(--global-saturation, 1), 0.05));
4
+ --dyn-saturation-x-dark: calc(pow(var(--global-saturation, 1), 0.1));
5
+ --dyn-saturation-x-ink: calc(pow(var(--global-saturation, 1), 0.2));
6
+ `;
7
+
8
+ export const dynamicThemeComputedColors = (name: string) => `
9
+ --color-${name}: oklch(calc(90% - 35% * var(--dyn-source-mode-adjust, 0) - (var(--dyn-mode-sign, 1) * var(--dyn-${name}-base-dim, 0%))) calc(var(--dyn-${name}-sat-mult,1) * (35% - 2% * var(--dyn-source-mode-adjust, 0))) var(--dyn-${name}-source, 0));
10
+ --color-${name}-wash: oklch(from var(--color-${name}) calc(min(0.999,max(0.15, l + 0.15 * var(--dyn-mode-mult, 1)))) calc(var(--dyn-${name}-sat-mult) * (c * var(--dyn-saturation-x-wash, 1) - 0.03)) calc(h - 5 * var(--dyn-${name}-hue-rotate, 0) * var(--dyn-${name}-hue-rotate-mult, 1)));
11
+ --color-${name}-light: oklch(from var(--color-${name}) calc(l + 0.08 * var(--dyn-mode-mult, 1)) calc(var(--dyn-${name}-sat-mult) * (c * var(--dyn-saturation-x-light, 1) - 0.03)) calc(h - 0.5 * var(--dyn-${name}-hue-rotate, 0) * var(--dyn-${name}-hue-rotate-mult, 1)));
12
+ --color-${name}-dark: oklch(from var(--color-${name}) calc(l - 0.26 * var(--dyn-mode-mult, 1)) calc(var(--dyn-${name}-sat-mult) * (c * var(--dyn-saturation-x-dark, 1) + 0.01)) calc(h + 0.2 * var(--dyn-${name}-hue-rotate, 0) * var(--dyn-${name}-hue-rotate-mult, 1)));
13
+ --color-${name}-ink: oklch(from var(--color-${name}) calc(l - 0.45 * var(--dyn-mode-mult, 1)) calc(var(--dyn-${name}-sat-mult) * (c * var(--dyn-saturation-x-ink, 1) + 0.01)) calc(h + 1 * var(--dyn-${name}-hue-rotate, 0) * var(--dyn-${name}-hue-rotate-mult, 1)));
14
+
15
+ --color-${name}-gray: oklch(from var(--color-${name}) calc(l - 0.1 * var(--dyn-source-mode-adjust,0)) calc(c * 0.25 * var(--global-saturation, 1)) h);
16
+ --color-${name}-gray-wash: oklch(from var(--color-${name}-wash) calc(l - 0.1 * var(--dyn-source-mode-adjust,0)) calc(c * 0.25 * var(--global-saturation, 1)) h);
17
+ --color-${name}-gray-light: oklch(from var(--color-${name}-light) calc(l - 0.1 * var(--dyn-source-mode-adjust,0)) calc(c * 0.25 * var(--global-saturation, 1)) h);
18
+ --color-${name}-gray-dark: oklch(from var(--color-${name}-dark) calc(l - 0.1 * var(--dyn-source-mode-adjust,0)) calc(c * 0.25 * var(--global-saturation, 1)) h);
19
+ --color-${name}-gray-ink: oklch(from var(--color-${name}-ink) calc(l - 0.1 * var(--dyn-source-mode-adjust,0)) calc(c * 0.25 * var(--global-saturation, 1)) h);
20
+ `;
21
+
22
+ export const dynamicComputedVars = `
23
+ ${dynamicThemeComputedColors('primary')}
24
+ ${dynamicThemeComputedColors('accent')}
25
+
26
+ --color-gray: var(--color-primary-gray);
27
+ --color-gray-wash: var(--color-primary-gray-wash);
28
+ --color-gray-light: var(--color-primary-gray-light);
29
+ --color-gray-dark: var(--color-primary-gray-dark);
30
+ --color-gray-ink: var(--color-primary-gray-ink);
31
+
32
+ --color-wash: var(--color-gray-wash);
33
+ --palette-black: var(--color-gray-ink);
34
+ --palette-white: oklch(from var(--color-wash) calc(l + 1 / var(--dyn-mode-mult,1)) calc(c * var(--global-saturation, 1)/var(--dyn-mode-mult,1)) h);
35
+ /* A dark-mode only contrast color */
36
+ --color-dark-mode-contrast: oklch(from var(--color-gray-ink) l c h / calc(100% * var(--dyn-source-mode-adjust, 0)));
37
+ `;
38
+
39
+ export type DynamicThemeColor = {
40
+ hue: number;
41
+ hueRotate: number;
42
+ hueRotateMult?: number;
43
+ saturationMult?: number;
44
+ dim?: `${number}%`;
45
+ };
46
+
47
+ export function dynamicTheme({
48
+ primary,
49
+ accent,
50
+ }: {
51
+ primary: DynamicThemeColor;
52
+ accent: DynamicThemeColor;
53
+ }) {
54
+ return `
55
+ ${colorConstants}
56
+ --dyn-primary-hue-rotate: ${primary.hueRotate};
57
+ --dyn-primary-source: ${primary.hue};
58
+ --dyn-accent-hue-rotate: ${accent.hueRotate};
59
+ --dyn-accent-source: ${accent.hue};
60
+ --dyn-primary-hue-rotate-mult: ${primary.hueRotateMult ?? 1};
61
+ --dyn-primary-sat-mult: ${primary.saturationMult ?? 1};
62
+ --dyn-accent-hue-rotate-mult: ${accent.hueRotateMult ?? 1};
63
+ --dyn-accent-sat-mult: ${accent.saturationMult ?? 1};
64
+ --dyn-primary-base-dim: ${primary.dim ?? '0%'};
65
+ --dyn-accent-base-dim: ${accent.dim ?? '0%'};
66
+ ${dynamicComputedVars}
67
+ `;
68
+ }