@kalink-ui/seedly 0.34.4 → 0.35.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 (144) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +34 -0
  3. package/docs/component-theming.md +295 -0
  4. package/docs/theming-strategy.md +69 -0
  5. package/docs/tone-system.md +139 -0
  6. package/docs/value-and-scope.md +65 -0
  7. package/package.json +4 -3
  8. package/src/components/alert-dialog/alert-dialog-action.tsx +0 -2
  9. package/src/components/alert-dialog/alert-dialog-cancel.tsx +0 -1
  10. package/src/components/alert-dialog/alert-dialog-content.css.ts +1 -1
  11. package/src/components/alert-dialog/alert-dialog-content.tsx +13 -6
  12. package/src/components/alert-dialog/alert-dialog-footer.css.ts +3 -3
  13. package/src/components/alert-dialog/alert-dialog-footer.tsx +2 -2
  14. package/src/components/alert-dialog/alert-dialog-header.tsx +4 -4
  15. package/src/components/alert-dialog/index.ts +9 -0
  16. package/src/components/box/box.css.ts +137 -39
  17. package/src/components/box/box.responsive.ts +2 -2
  18. package/src/components/box/box.tsx +2 -3
  19. package/src/components/box/index.ts +1 -1
  20. package/src/components/button/button.css.ts +142 -149
  21. package/src/components/button/button.responsive.ts +2 -2
  22. package/src/components/button/button.tsx +44 -31
  23. package/src/components/button/index.ts +2 -2
  24. package/src/components/button-icon/button-icon.css.ts +26 -62
  25. package/src/components/button-icon/button-icon.responsive.ts +2 -2
  26. package/src/components/button-icon/button-icon.tsx +5 -7
  27. package/src/components/card/card.css.ts +1 -5
  28. package/src/components/card/card.tsx +11 -11
  29. package/src/components/center/center.css.ts +61 -21
  30. package/src/components/center/center.responsive.ts +2 -2
  31. package/src/components/center/center.tsx +4 -6
  32. package/src/components/center/index.ts +1 -1
  33. package/src/components/cluster/cluster.css.ts +37 -99
  34. package/src/components/cluster/cluster.responsive.ts +13 -2
  35. package/src/components/cluster/cluster.tsx +6 -5
  36. package/src/components/cluster/index.ts +5 -1
  37. package/src/components/command/command-empty.tsx +36 -4
  38. package/src/components/command/command-group.css.ts +23 -7
  39. package/src/components/command/command-group.tsx +30 -6
  40. package/src/components/command/command-input.css.ts +2 -2
  41. package/src/components/command/command-item.tsx +26 -2
  42. package/src/components/command/command-list.css.ts +2 -2
  43. package/src/components/command/command-list.responsive.ts +2 -2
  44. package/src/components/command/command-list.tsx +1 -2
  45. package/src/components/command/command-separator.tsx +7 -5
  46. package/src/components/cover/cover.css.ts +29 -8
  47. package/src/components/cover/cover.tsx +13 -13
  48. package/src/components/cover/index.ts +2 -2
  49. package/src/components/divider/divider.css.ts +9 -4
  50. package/src/components/form-field/form-field-context.ts +3 -0
  51. package/src/components/form-field/form-field-item.tsx +3 -3
  52. package/src/components/form-field/form-field-message.tsx +34 -3
  53. package/src/components/form-field/form-field.css.ts +78 -16
  54. package/src/components/form-field/form-field.tsx +5 -0
  55. package/src/components/form-field/index.ts +1 -1
  56. package/src/components/frame/frame.css.ts +96 -59
  57. package/src/components/frame/frame.responsive.ts +9 -0
  58. package/src/components/frame/frame.tsx +11 -5
  59. package/src/components/frame/index.ts +1 -1
  60. package/src/components/grid/grid-child.tsx +14 -10
  61. package/src/components/grid/grid.css.ts +56 -148
  62. package/src/components/grid/grid.tsx +40 -18
  63. package/src/components/grid/index.ts +4 -3
  64. package/src/components/heading/heading.css.ts +4 -4
  65. package/src/components/heading/heading.responsive.ts +6 -6
  66. package/src/components/heading/heading.tsx +3 -4
  67. package/src/components/heading/index.ts +1 -1
  68. package/src/components/input/index.ts +4 -1
  69. package/src/components/input/input-wrapper.tsx +20 -8
  70. package/src/components/input/input.css.ts +121 -93
  71. package/src/components/input/input.responsive.ts +9 -0
  72. package/src/components/input/input.tsx +7 -1
  73. package/src/components/label/label.css.ts +2 -2
  74. package/src/components/label/label.tsx +23 -3
  75. package/src/components/layout-maps.ts +120 -0
  76. package/src/components/loader/index.ts +2 -1
  77. package/src/components/loader/loader.css.ts +91 -54
  78. package/src/components/loader/moon-loader.responsive.ts +2 -2
  79. package/src/components/loader/moon-loader.tsx +4 -5
  80. package/src/components/loader-overlay/loader-overlay.css.ts +3 -3
  81. package/src/components/loader-overlay/loader-overlay.tsx +5 -2
  82. package/src/components/menu/index.ts +2 -2
  83. package/src/components/menu/menu-item.css.ts +102 -46
  84. package/src/components/menu/menu-separator.css.ts +27 -15
  85. package/src/components/menu/menu-separator.responsive.ts +2 -2
  86. package/src/components/overlay/overlay.css.ts +1 -1
  87. package/src/components/popover/index.ts +1 -1
  88. package/src/components/popover/popover-content.css.ts +69 -52
  89. package/src/components/popover/popover-content.tsx +22 -6
  90. package/src/components/scroll-area/scroll-area.css.ts +3 -3
  91. package/src/components/scroll-area/scroll-bar.tsx +2 -2
  92. package/src/components/select/index.ts +4 -5
  93. package/src/components/select/select-content.css.ts +1 -1
  94. package/src/components/select/select-content.tsx +2 -2
  95. package/src/components/select/select-item.tsx +11 -3
  96. package/src/components/select/select-trigger.css.ts +14 -18
  97. package/src/components/select/select-trigger.tsx +18 -8
  98. package/src/components/select/select.tsx +10 -6
  99. package/src/components/sheet/index.ts +9 -0
  100. package/src/components/sheet/sheet-content.css.ts +2 -2
  101. package/src/components/sheet/sheet-content.tsx +25 -7
  102. package/src/components/sheet/sheet-description.tsx +5 -7
  103. package/src/components/sheet/sheet-footer.tsx +3 -1
  104. package/src/components/sheet/sheet-header.css.ts +1 -1
  105. package/src/components/sheet/sheet-header.tsx +3 -3
  106. package/src/components/sheet/sheet-overlay.tsx +3 -4
  107. package/src/components/sheet/sheet-title.tsx +1 -1
  108. package/src/components/sidebar/index.ts +5 -1
  109. package/src/components/sidebar/sidebar.css.ts +35 -9
  110. package/src/components/sidebar/sidebar.tsx +7 -10
  111. package/src/components/skeleton/skeleton.css.ts +23 -14
  112. package/src/components/skeleton/skeleton.tsx +26 -7
  113. package/src/components/stack/index.ts +1 -1
  114. package/src/components/stack/stack.css.ts +18 -46
  115. package/src/components/stack/stack.tsx +1 -2
  116. package/src/components/switcher/index.ts +5 -1
  117. package/src/components/switcher/switcher.css.ts +105 -72
  118. package/src/components/switcher/switcher.responsive.ts +2 -2
  119. package/src/components/switcher/switcher.tsx +5 -5
  120. package/src/components/text/text.css.ts +93 -105
  121. package/src/components/text/text.responsive.ts +3 -63
  122. package/src/components/text/text.tsx +16 -28
  123. package/src/components/text-field/index.ts +1 -2
  124. package/src/components/text-field/text-field.tsx +5 -7
  125. package/src/components/textarea/textarea-input.tsx +30 -3
  126. package/src/components/textarea/textarea.css.ts +12 -7
  127. package/src/components/textarea/textarea.tsx +9 -3
  128. package/src/components/visually-hidden/visually-hidden.css.ts +16 -10
  129. package/src/styles/define-responsive-properties.ts +5 -1
  130. package/src/styles/index.ts +12 -0
  131. package/src/styles/responsive.ts +72 -43
  132. package/src/styles/system-contract.css.ts +22 -3
  133. package/src/styles/theme/sprout-ref.css.ts +107 -0
  134. package/src/styles/theme/sprout.css.ts +259 -0
  135. package/src/styles/tone.ts +69 -0
  136. package/src/styles/typography.responsive.css.ts +35 -0
  137. package/src/styles/typography.responsive.ts +104 -0
  138. package/src/utils/arg-types/index.ts +1 -0
  139. package/src/utils/arg-types/responsive-arg.ts +28 -0
  140. package/src/utils/index.ts +1 -0
  141. package/src/components/command/command-item.css.ts +0 -32
  142. package/src/components/select/select.css.ts +0 -3
  143. package/src/components/sheet/sheet-body.css.ts +0 -68
  144. package/src/components/text-field/text-field.css.ts +0 -3
@@ -6,7 +6,7 @@ import { ComponentPropsWithRef } from 'react';
6
6
  import { Heading, HeadingProps, HeadingTypes } from '../heading';
7
7
  import { TextProps } from '../text';
8
8
 
9
- type SheetTitleProps<TUse extends HeadingTypes> = ComponentPropsWithRef<
9
+ export type SheetTitleProps<TUse extends HeadingTypes> = ComponentPropsWithRef<
10
10
  typeof Title
11
11
  > &
12
12
  HeadingProps<TUse>;
@@ -1,2 +1,6 @@
1
1
  export { Sidebar } from './sidebar';
2
- export { sidebarRecipe, type SidebarVariants } from './sidebar.css';
2
+ export {
3
+ sidebarRecipe,
4
+ sidebarVars,
5
+ type SidebarVariants,
6
+ } from './sidebar.css';
@@ -1,22 +1,46 @@
1
- import { createVar, globalStyle } from '@vanilla-extract/css';
1
+ import {
2
+ assignVars,
3
+ createThemeContract,
4
+ globalStyle,
5
+ } from '@vanilla-extract/css';
2
6
  import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
3
7
 
4
8
  import {
5
9
  createResponsiveVariants,
6
10
  defaultMedia,
7
- sys,
8
11
  mapContractVars,
12
+ sys,
9
13
  } from '../../styles';
10
14
  import { components } from '../../styles/layers.css';
11
15
 
12
- export const sideWidthVar = createVar();
13
- export const contentMinWidthVar = createVar();
16
+ export const sidebarVars = createThemeContract({
17
+ spacing: {
18
+ gap: null,
19
+ },
20
+ layout: {
21
+ sideWidth: null,
22
+ contentMinWidth: null,
23
+ },
24
+ });
25
+
26
+ const sidebarSpacingDefaults = assignVars(sidebarVars.spacing, {
27
+ gap: sys.spacing[0],
28
+ });
29
+
30
+ const sidebarLayoutDefaults = assignVars(sidebarVars.layout, {
31
+ sideWidth: 'auto',
32
+ contentMinWidth: '50%',
33
+ });
14
34
 
15
35
  // Shared variant styles to support responsive overrides
16
36
  export const sidebarSpacingStyles = mapContractVars(sys.spacing, (key) => ({
17
37
  '@layer': {
18
38
  [components]: {
19
- gap: sys.spacing[key],
39
+ vars: {
40
+ ...assignVars(sidebarVars.spacing, {
41
+ gap: sys.spacing[key],
42
+ }),
43
+ },
20
44
  },
21
45
  },
22
46
  }));
@@ -27,9 +51,11 @@ export const sidebarRecipe = recipe({
27
51
  [components]: {
28
52
  display: 'flex',
29
53
  flexWrap: 'wrap',
54
+ gap: sidebarVars.spacing.gap,
30
55
 
31
56
  vars: {
32
- [contentMinWidthVar]: '50%',
57
+ ...sidebarSpacingDefaults,
58
+ ...sidebarLayoutDefaults,
33
59
  },
34
60
  },
35
61
  },
@@ -82,7 +108,7 @@ globalStyle(`${sidebarRecipe.classNames.base} > *`, {
82
108
  globalStyle(`${sidebarRecipe.classNames.variants.sideWidth.true} > *`, {
83
109
  '@layer': {
84
110
  [components]: {
85
- flexBasis: sideWidthVar,
111
+ flexBasis: sidebarVars.layout.sideWidth,
86
112
  },
87
113
  },
88
114
  });
@@ -92,7 +118,7 @@ globalStyle(`${sidebarRecipe.classNames.variants.side.left} > :last-child`, {
92
118
  [components]: {
93
119
  flexBasis: 0,
94
120
  flexGrow: 999,
95
- minInlineSize: contentMinWidthVar,
121
+ minInlineSize: sidebarVars.layout.contentMinWidth,
96
122
  },
97
123
  },
98
124
  });
@@ -102,7 +128,7 @@ globalStyle(`${sidebarRecipe.classNames.variants.side.right} > :first-child`, {
102
128
  [components]: {
103
129
  flexBasis: 0,
104
130
  flexGrow: 999,
105
- minInlineSize: contentMinWidthVar,
131
+ minInlineSize: sidebarVars.layout.contentMinWidth,
106
132
  },
107
133
  },
108
134
  });
@@ -2,14 +2,9 @@
2
2
 
3
3
  import { PolymorphicComponentProps } from '@kalink-ui/dibbly';
4
4
  import { assignInlineVars } from '@vanilla-extract/dynamic';
5
- import { clsx } from 'clsx';
6
5
  import { ElementType } from 'react';
7
6
 
8
- import {
9
- contentMinWidthVar,
10
- SidebarVariants,
11
- sideWidthVar,
12
- } from './sidebar.css';
7
+ import { SidebarVariants, sidebarVars } from './sidebar.css';
13
8
  import { sidebarResponsive } from './sidebar.responsive';
14
9
 
15
10
  import type { Responsive } from '../../styles/responsive';
@@ -50,13 +45,15 @@ export function Sidebar<TUse extends ElementType>({
50
45
 
51
46
  return (
52
47
  <Comp
53
- className={clsx(
54
- sidebarResponsive({ side, sideWidth: !!sideWidth, spacing, noStretch }),
48
+ className={sidebarResponsive(
49
+ { side, sideWidth: !!sideWidth, spacing, noStretch },
55
50
  className,
56
51
  )}
57
52
  style={assignInlineVars({
58
- ...(sideWidth && { [sideWidthVar]: sideWidth }),
59
- ...(contentMinWidth && { [contentMinWidthVar]: contentMinWidth }),
53
+ ...(sideWidth && { [sidebarVars.layout.sideWidth]: sideWidth }),
54
+ ...(contentMinWidth && {
55
+ [sidebarVars.layout.contentMinWidth]: contentMinWidth,
56
+ }),
60
57
  })}
61
58
  {...rest}
62
59
  />
@@ -18,13 +18,13 @@ const pulseKeyframe = keyframes({
18
18
  },
19
19
  });
20
20
 
21
- export const skeleton = recipe({
21
+ export const skeletonRecipe = recipe({
22
22
  base: {
23
23
  '@layer': {
24
24
  [components]: {
25
25
  display: 'block',
26
26
 
27
- backgroundColor: `color-mix(in srgb, ${sys.color.foreground} 10%, transparent)`,
27
+ backgroundColor: `color-mix(in srgb, ${sys.surface.foreground} 10%, transparent)`,
28
28
 
29
29
  animationName: pulseKeyframe,
30
30
  animationDuration: '1500ms',
@@ -37,20 +37,17 @@ export const skeleton = recipe({
37
37
 
38
38
  variants: {
39
39
  type: {
40
- text: [
41
- typography.body.medium,
42
- {
43
- '@layer': {
44
- [components]: {
45
- selectors: {
46
- '&:empty::before': {
47
- content: '"\\00a0"',
48
- },
40
+ text: {
41
+ '@layer': {
42
+ [components]: {
43
+ selectors: {
44
+ '&:empty::before': {
45
+ content: '"\\00a0"',
49
46
  },
50
47
  },
51
48
  },
52
49
  },
53
- ],
50
+ },
54
51
 
55
52
  field: {
56
53
  '@layer': {
@@ -81,6 +78,12 @@ export const skeleton = recipe({
81
78
  },
82
79
  },
83
80
 
81
+ size: {
82
+ sm: typography.body.small,
83
+ md: typography.body.medium,
84
+ lg: typography.body.large,
85
+ },
86
+
84
87
  withChildren: {
85
88
  true: {
86
89
  '@layer': {
@@ -118,10 +121,16 @@ export const skeleton = recipe({
118
121
  },
119
122
  },
120
123
  },
124
+
125
+ defaultVariants: {
126
+ size: 'md',
127
+ },
121
128
  });
122
129
 
123
- globalStyle(`${skeleton.classNames.variants.withChildren.true} *`, {
130
+ globalStyle(`${skeletonRecipe.classNames.variants.withChildren.true} *`, {
124
131
  visibility: 'hidden',
125
132
  });
126
133
 
127
- export type SkeletonVariants = NonNullable<RecipeVariants<typeof skeleton>>;
134
+ export type SkeletonVariants = NonNullable<
135
+ RecipeVariants<typeof skeletonRecipe>
136
+ >;
@@ -1,32 +1,51 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { Children, ElementType } from 'react';
3
3
 
4
+ import {
5
+ buildTypographyOverrides,
6
+ getResponsiveBase,
7
+ mapResponsiveSizeToTypography,
8
+ type Responsive,
9
+ } from '../../styles';
4
10
  import { Box, BoxProps } from '../box';
5
11
 
6
- import { skeleton, SkeletonVariants } from './skeleton.css';
12
+ import { skeletonRecipe, SkeletonVariants } from './skeleton.css';
7
13
 
8
14
  export type SkeletonProps<TUse extends ElementType> = Omit<
9
15
  SkeletonVariants,
10
- 'withChildren'
16
+ 'withChildren' | 'size'
11
17
  > &
12
- BoxProps<TUse>;
18
+ BoxProps<TUse> & {
19
+ size?: Responsive<NonNullable<SkeletonVariants['size']>>;
20
+ };
13
21
 
14
- export const Skeleton = <TUse extends ElementType>({
22
+ export function Skeleton<TUse extends ElementType>({
15
23
  children,
16
24
  className,
17
25
  type = 'text',
18
26
  radius = 'small',
27
+ size,
19
28
  ...props
20
- }: SkeletonProps<TUse>) => {
29
+ }: SkeletonProps<TUse>) {
21
30
  const withChildren = Children.count(children) > 0;
31
+ const baseSize = getResponsiveBase(size) ?? 'md';
32
+ const typographySize = mapResponsiveSizeToTypography(size);
33
+ const typographyOverrides =
34
+ type === 'text'
35
+ ? buildTypographyOverrides({ variant: 'body', size: typographySize })
36
+ : undefined;
22
37
 
23
38
  return (
24
39
  <Box
25
- className={clsx(skeleton({ withChildren, type }), className)}
40
+ className={clsx(
41
+ skeletonRecipe({ withChildren, type, size: baseSize }),
42
+ typographyOverrides,
43
+ className,
44
+ )}
26
45
  radius={radius}
27
46
  {...props}
28
47
  >
29
48
  {children}
30
49
  </Box>
31
50
  );
32
- };
51
+ }
@@ -1,2 +1,2 @@
1
1
  export { Stack, type StackProps } from './stack';
2
- export { stackRecipe, type StackVariants } from './stack.css';
2
+ export { stackRecipe, stackVars, type StackVariants } from './stack.css';
@@ -1,60 +1,28 @@
1
- import { createVar } from '@vanilla-extract/css';
1
+ import { assignVars, createThemeContract } from '@vanilla-extract/css';
2
2
  import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
3
3
 
4
- import { sys, mapContractVars } from '../../styles';
4
+ import { sys } from '../../styles';
5
5
  import { components } from '../../styles/layers.css';
6
6
  import {
7
7
  createResponsiveVariants,
8
8
  defaultMedia,
9
9
  } from '../../styles/responsive';
10
+ import { createSpacingVarStyles, flexAlignItemsStyles } from '../layout-maps';
10
11
 
11
- const spacing = createVar({
12
- syntax: '<length>',
13
- initialValue: sys.spacing['0'],
14
- inherits: false,
12
+ export const stackVars = createThemeContract({
13
+ spacing: {
14
+ gap: null,
15
+ },
16
+ });
17
+
18
+ const stackSpacingDefaults = assignVars(stackVars.spacing, {
19
+ gap: sys.spacing[0],
15
20
  });
16
21
 
17
22
  // Shared variant style maps so we can reuse them for responsive overrides
18
- export const stackSpacingStyles = mapContractVars(sys.spacing, (key) => ({
19
- '@layer': {
20
- [components]: {
21
- vars: {
22
- [spacing]: sys.spacing[key],
23
- },
24
- },
25
- },
26
- }));
23
+ export const stackSpacingStyles = createSpacingVarStyles(stackVars.spacing);
27
24
 
28
- export const stackAlignStyles = {
29
- start: {
30
- '@layer': {
31
- [components]: {
32
- alignItems: 'flex-start',
33
- },
34
- },
35
- },
36
- center: {
37
- '@layer': {
38
- [components]: {
39
- alignItems: 'center',
40
- },
41
- },
42
- },
43
- end: {
44
- '@layer': {
45
- [components]: {
46
- alignItems: 'flex-end',
47
- },
48
- },
49
- },
50
- stretch: {
51
- '@layer': {
52
- [components]: {
53
- alignItems: 'stretch',
54
- },
55
- },
56
- },
57
- } as const;
25
+ export const stackAlignStyles = flexAlignItemsStyles;
58
26
 
59
27
  export const stackRecipe = recipe({
60
28
  base: {
@@ -63,7 +31,11 @@ export const stackRecipe = recipe({
63
31
  display: 'flex',
64
32
  flexDirection: 'column',
65
33
  alignItems: 'flex-start',
66
- gap: spacing,
34
+ gap: stackVars.spacing.gap,
35
+
36
+ vars: {
37
+ ...stackSpacingDefaults,
38
+ },
67
39
  },
68
40
  },
69
41
  },
@@ -1,5 +1,4 @@
1
1
  import { PolymorphicComponentProps } from '@kalink-ui/dibbly';
2
- import { clsx } from 'clsx';
3
2
  import { ElementType } from 'react';
4
3
 
5
4
  import { StackVariants } from './stack.css';
@@ -34,7 +33,7 @@ export function Stack<TUse extends ElementType = 'div'>({
34
33
 
35
34
  return (
36
35
  <Comp
37
- className={clsx(stackResponsive({ spacing, align }), className)}
36
+ className={stackResponsive({ spacing, align }, className)}
38
37
  {...rest}
39
38
  />
40
39
  );
@@ -1,2 +1,6 @@
1
1
  export { Switcher, type SwitcherProps } from './switcher';
2
- export { switcherRecipe, type SwitcherVariants } from './switcher.css';
2
+ export {
3
+ switcherRecipe,
4
+ switcherVars,
5
+ type SwitcherVariants,
6
+ } from './switcher.css';
@@ -1,35 +1,87 @@
1
- import { createVar, globalStyle } from '@vanilla-extract/css';
1
+ import {
2
+ assignVars,
3
+ createThemeContract,
4
+ globalStyle,
5
+ } from '@vanilla-extract/css';
2
6
  import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
3
7
 
4
8
  import {
5
9
  createResponsiveVariants,
6
10
  defaultMedia,
7
- sys,
8
11
  mapContractVars,
12
+ sys,
9
13
  } from '../../styles';
10
14
  import { components } from '../../styles/layers.css';
11
15
 
12
- export const thresholdVar = createVar();
13
- export const limitVar = createVar();
16
+ export const switcherVars = createThemeContract({
17
+ spacing: {
18
+ gap: null,
19
+ },
20
+ layout: {
21
+ threshold: null,
22
+ },
23
+ });
24
+
25
+ const switcherSpacingDefaults = assignVars(switcherVars.spacing, {
26
+ gap: sys.spacing[0],
27
+ });
28
+
29
+ const switcherLayoutDefaults = assignVars(switcherVars.layout, {
30
+ threshold: sys.layout.measure,
31
+ });
14
32
 
15
33
  // Shared variant styles to support responsive overrides
16
34
  export const switcherSpacingStyles = mapContractVars(sys.spacing, (key) => ({
17
35
  '@layer': {
18
36
  [components]: {
19
- gap: sys.spacing[key],
37
+ vars: {
38
+ ...assignVars(switcherVars.spacing, {
39
+ gap: sys.spacing[key],
40
+ }),
41
+ },
20
42
  },
21
43
  },
22
44
  }));
23
45
 
46
+ export const switcherLimitStyles = {
47
+ 2: {
48
+ '@layer': {
49
+ [components]: {},
50
+ },
51
+ },
52
+ 3: {
53
+ '@layer': {
54
+ [components]: {},
55
+ },
56
+ },
57
+ 4: {
58
+ '@layer': {
59
+ [components]: {},
60
+ },
61
+ },
62
+ 5: {
63
+ '@layer': {
64
+ [components]: {},
65
+ },
66
+ },
67
+ 6: {
68
+ '@layer': {
69
+ [components]: {},
70
+ },
71
+ },
72
+ } as const;
73
+
24
74
  export const switcherRecipe = recipe({
25
75
  base: {
26
76
  '@layer': {
27
77
  [components]: {
28
78
  display: 'flex',
29
79
  flexWrap: 'wrap',
80
+ gap: switcherVars.spacing.gap,
30
81
 
31
82
  vars: {
32
- [thresholdVar]: sys.layout.measure,
83
+ ...switcherSpacingDefaults,
84
+ ...switcherLayoutDefaults,
33
85
  },
34
86
  },
35
87
  },
@@ -44,89 +96,35 @@ export const switcherRecipe = recipe({
44
96
  /**
45
97
  * The maximum number of elements allowed to appear in the horizontal configuration
46
98
  */
47
- limit: {
48
- 2: {},
49
- 3: {},
50
- 4: {},
51
- 5: {},
52
- 6: {},
53
- },
99
+ limit: switcherLimitStyles,
54
100
  },
55
101
  });
56
102
 
103
+ const limitValues = [2, 3, 4, 5, 6] as const;
104
+
105
+ const limitSelector = (limitClass: string, limit: number) =>
106
+ `${limitClass} > :nth-last-child(n+${limit + 1}), ${limitClass} > :nth-last-child(n+${limit + 1}) ~ *`;
107
+
57
108
  globalStyle(`${switcherRecipe.classNames.base} > *`, {
58
109
  '@layer': {
59
110
  [components]: {
60
- flexBasis: `calc((${thresholdVar} - 100%) * 999)`,
111
+ flexBasis: `calc((${switcherVars.layout.threshold} - 100%) * 999)`,
61
112
  flexGrow: 1,
62
113
  },
63
114
  },
64
115
  });
65
116
 
66
- globalStyle(
67
- `${switcherRecipe.classNames.variants.limit[2]} > :nth-last-child(n+3), ${
68
- switcherRecipe.classNames.variants.limit[2]
69
- } > :nth-last-child(n+3) ~ *`,
70
- {
71
- '@layer': {
72
- [components]: {
73
- flexBasis: '100%',
74
- },
75
- },
76
- },
77
- );
117
+ limitValues.forEach((limit) => {
118
+ const limitClass = switcherRecipe.classNames.variants.limit[limit];
78
119
 
79
- globalStyle(
80
- `${switcherRecipe.classNames.variants.limit[3]} > :nth-last-child(n+4), ${
81
- switcherRecipe.classNames.variants.limit[3]
82
- } > :nth-last-child(n+4) ~ *`,
83
- {
120
+ globalStyle(limitSelector(limitClass, limit), {
84
121
  '@layer': {
85
122
  [components]: {
86
123
  flexBasis: '100%',
87
124
  },
88
125
  },
89
- },
90
- );
91
-
92
- globalStyle(
93
- `${switcherRecipe.classNames.variants.limit[4]} > :nth-last-child(n+5), ${
94
- switcherRecipe.classNames.variants.limit[4]
95
- } > :nth-last-child(n+5) ~ *`,
96
- {
97
- '@layer': {
98
- [components]: {
99
- flexBasis: '100%',
100
- },
101
- },
102
- },
103
- );
104
-
105
- globalStyle(
106
- `${switcherRecipe.classNames.variants.limit[5]} > :nth-last-child(n+6), ${
107
- switcherRecipe.classNames.variants.limit[5]
108
- } > :nth-last-child(n+6) ~ *`,
109
- {
110
- '@layer': {
111
- [components]: {
112
- flexBasis: '100%',
113
- },
114
- },
115
- },
116
- );
117
-
118
- globalStyle(
119
- `${switcherRecipe.classNames.variants.limit[6]} > :nth-last-child(n+7), ${
120
- switcherRecipe.classNames.variants.limit[6]
121
- } > :nth-last-child(n+7) ~ *`,
122
- {
123
- '@layer': {
124
- [components]: {
125
- flexBasis: '100%',
126
- },
127
- },
128
- },
129
- );
126
+ });
127
+ });
130
128
 
131
129
  export type SwitcherVariants = NonNullable<
132
130
  RecipeVariants<typeof switcherRecipe>
@@ -136,3 +134,38 @@ export const spacingAt = createResponsiveVariants({
136
134
  styles: switcherSpacingStyles,
137
135
  media: defaultMedia,
138
136
  });
137
+
138
+ export const limitAt = createResponsiveVariants({
139
+ styles: switcherLimitStyles,
140
+ media: defaultMedia,
141
+ });
142
+
143
+ Object.entries(limitAt).forEach(([breakpoint, styles]) => {
144
+ const query = defaultMedia[breakpoint as keyof typeof defaultMedia];
145
+
146
+ if (!query) {
147
+ return;
148
+ }
149
+
150
+ const styleMap = styles as Record<number, string>;
151
+
152
+ limitValues.forEach((limit) => {
153
+ const limitClass = styleMap[limit];
154
+
155
+ if (!limitClass) {
156
+ return;
157
+ }
158
+
159
+ globalStyle(limitSelector(limitClass, limit), {
160
+ '@media': {
161
+ [query]: {
162
+ '@layer': {
163
+ [components]: {
164
+ flexBasis: '100%',
165
+ },
166
+ },
167
+ },
168
+ },
169
+ });
170
+ });
171
+ });
@@ -1,9 +1,9 @@
1
1
  import { defaultOrder, responsiveRecipe } from '../../styles/responsive';
2
2
 
3
- import { spacingAt, switcherRecipe } from './switcher.css';
3
+ import { limitAt, spacingAt, switcherRecipe } from './switcher.css';
4
4
 
5
5
  export const switcherResponsive = responsiveRecipe({
6
6
  recipe: switcherRecipe,
7
- at: { spacing: spacingAt },
7
+ at: { spacing: spacingAt, limit: limitAt },
8
8
  order: defaultOrder,
9
9
  });
@@ -2,22 +2,22 @@
2
2
 
3
3
  import { PolymorphicComponentProps } from '@kalink-ui/dibbly';
4
4
  import { assignInlineVars } from '@vanilla-extract/dynamic';
5
- import { clsx } from 'clsx';
6
5
  import { ElementType } from 'react';
7
6
 
8
- import { SwitcherVariants, thresholdVar } from './switcher.css';
7
+ import { SwitcherVariants, switcherVars } from './switcher.css';
9
8
  import { switcherResponsive } from './switcher.responsive';
10
9
 
11
10
  import type { Responsive } from '../../styles/responsive';
12
11
 
13
12
  export type SwitcherProps<TUse extends ElementType> =
14
13
  PolymorphicComponentProps<TUse> &
15
- Omit<SwitcherVariants, 'spacing'> & {
14
+ Omit<SwitcherVariants, 'spacing' | 'limit'> & {
16
15
  /**
17
16
  * The threshold at which to switch between horizontal and vertical layouts
18
17
  */
19
18
  threshold?: string;
20
19
  spacing?: Responsive<NonNullable<SwitcherVariants['spacing']>>;
20
+ limit?: Responsive<NonNullable<SwitcherVariants['limit']>>;
21
21
  };
22
22
 
23
23
  /**
@@ -37,9 +37,9 @@ export function Switcher<TUse extends ElementType>({
37
37
 
38
38
  return (
39
39
  <Comp
40
- className={clsx(switcherResponsive({ spacing, limit }), className)}
40
+ className={switcherResponsive({ spacing, limit }, className)}
41
41
  style={assignInlineVars({
42
- ...(threshold && { [thresholdVar]: threshold }),
42
+ ...(threshold && { [switcherVars.layout.threshold]: threshold }),
43
43
  })}
44
44
  {...props}
45
45
  />