@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
@@ -1,13 +1,14 @@
1
1
  import {
2
2
  assignVars,
3
3
  createThemeContract,
4
- fallbackVar,
5
4
  globalStyle,
6
5
  } from '@vanilla-extract/css';
7
6
  import { calc } from '@vanilla-extract/css-utils';
8
7
  import { recipe, type RecipeVariants } from '@vanilla-extract/recipes';
9
8
 
10
9
  import {
10
+ createToneAssignments,
11
+ createToneStyles,
11
12
  createResponsiveVariants,
12
13
  defaultMedia,
13
14
  sys,
@@ -20,8 +21,9 @@ export const buttonVars = createThemeContract({
20
21
  borderRadius: null,
21
22
  textTransform: null,
22
23
  color: {
23
- text: null,
24
+ foreground: null,
24
25
  background: null,
26
+ outline: null,
25
27
  },
26
28
  spacing: {
27
29
  block: null,
@@ -38,7 +40,41 @@ export const buttonVars = createThemeContract({
38
40
  },
39
41
  });
40
42
 
43
+ const buttonToneVars = createThemeContract({
44
+ base: null,
45
+ onBase: null,
46
+ });
47
+
41
48
  // Extracted variant style maps for responsive overrides
49
+ const buttonVariantVars = createThemeContract({
50
+ foreground: null,
51
+ background: null,
52
+ outline: null,
53
+ });
54
+
55
+ const buttonColorDefaults = assignVars(buttonVars.color, {
56
+ foreground: sys.surface.foreground,
57
+ background: 'transparent',
58
+ outline: 'transparent',
59
+ });
60
+
61
+ const buttonVariantDefaults = assignVars(buttonVariantVars, {
62
+ foreground: buttonVars.color.foreground,
63
+ background: buttonVars.color.background,
64
+ outline: buttonVars.color.outline,
65
+ });
66
+
67
+ const buttonToneOverlay = assignVars(buttonVariantVars, {
68
+ foreground: buttonToneVars.base,
69
+ background: buttonToneVars.base,
70
+ outline: buttonToneVars.base,
71
+ });
72
+
73
+ const buttonToneAssignments = createToneAssignments(buttonToneVars);
74
+ const buttonToneDefaults = buttonToneAssignments.neutral;
75
+
76
+ export const buttonToneStyles = createToneStyles(buttonToneVars);
77
+
42
78
  export const buttonVariantStyles = {
43
79
  /**
44
80
  * The main variation of the button
@@ -48,10 +84,13 @@ export const buttonVariantStyles = {
48
84
  '@layer': {
49
85
  [components]: {
50
86
  vars: {
51
- ...assignVars(buttonVars.color, {
52
- text: sys.color.background,
53
- background: sys.color.foreground,
54
- }),
87
+ ...buttonColorDefaults,
88
+ ...buttonToneOverlay,
89
+ [buttonVariantVars.foreground]: buttonToneVars.onBase,
90
+ [buttonVariantVars.background]: buttonToneVars.base,
91
+ [buttonVariantVars.outline]: 'transparent',
92
+ ...buttonToneDefaults,
93
+
55
94
  ...assignVars(buttonVars.border, {
56
95
  width: '1px',
57
96
  style: 'solid',
@@ -60,19 +99,17 @@ export const buttonVariantStyles = {
60
99
  },
61
100
  ':hover': {
62
101
  vars: {
63
- [buttonVars.color.background]:
64
- `color-mix(in srgb, ${sys.color.foreground}, ${sys.color.background} calc(100% * ${sys.state.hovered.opacity}))`,
102
+ [buttonVariantVars.background]: `color-mix(in srgb, ${buttonToneVars.base}, ${buttonToneVars.onBase} calc(100% * ${sys.state.hovered.opacity}))`,
103
+
65
104
  [buttonVars.shadow.level]: sys.elevation.minimal,
66
105
  },
67
106
  },
68
107
  ':disabled': {
69
108
  vars: {
70
- ...assignVars(buttonVars.color, {
71
- text: `color-mix(in srgb, ${sys.color.background} calc(100% * ${sys.state.muted.light}), transparent)`,
72
- background: `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.muted.dark}), transparent)`,
73
- }),
109
+ [buttonVariantVars.foreground]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.disabled.text}), transparent)`,
110
+ [buttonVariantVars.background]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.disabled.background}), transparent)`,
74
111
  [buttonVars.shadow.level]: sys.elevation.none,
75
- [buttonVars.border.color]: `transparent`,
112
+ [buttonVars.border.color]: 'transparent',
76
113
  },
77
114
  },
78
115
  },
@@ -82,30 +119,28 @@ export const buttonVariantStyles = {
82
119
  '@layer': {
83
120
  [components]: {
84
121
  vars: {
85
- ...assignVars(buttonVars.color, {
86
- text: sys.color.foreground,
87
- background: 'unset',
88
- }),
122
+ ...buttonColorDefaults,
123
+ ...buttonToneOverlay,
124
+ [buttonVariantVars.background]: 'unset',
125
+ ...buttonToneDefaults,
89
126
  ...assignVars(buttonVars.border, {
90
127
  width: '1px',
91
128
  style: 'solid',
92
- color: sys.color.foreground,
129
+ color: buttonVariantVars.outline,
93
130
  }),
94
131
  },
95
132
  selectors: {
96
133
  '&:hover': {
97
134
  vars: {
98
- [buttonVars.color.background]:
99
- `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.hovered.opacity}), transparent)`,
135
+ [buttonVariantVars.background]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.hovered.opacity}), transparent)`,
100
136
  },
101
137
  },
102
138
  '&:disabled': {
103
139
  vars: {
104
- [buttonVars.color.background]: 'unset',
105
- [buttonVars.color.text]:
106
- `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.muted.dark}), transparent)`,
140
+ [buttonVariantVars.background]: 'unset',
141
+ [buttonVariantVars.foreground]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.disabled.text}), transparent)`,
107
142
  [buttonVars.border.color]:
108
- `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.muted.dark}), transparent)`,
143
+ `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.disabled.border}), transparent)`,
109
144
  },
110
145
  },
111
146
  },
@@ -116,10 +151,11 @@ export const buttonVariantStyles = {
116
151
  '@layer': {
117
152
  [components]: {
118
153
  vars: {
119
- ...assignVars(buttonVars.color, {
120
- text: sys.color.foreground,
121
- background: 'unset',
122
- }),
154
+ ...buttonColorDefaults,
155
+ ...buttonToneOverlay,
156
+ [buttonVariantVars.background]: 'unset',
157
+ [buttonVariantVars.outline]: 'transparent',
158
+ ...buttonToneDefaults,
123
159
  ...assignVars(buttonVars.border, {
124
160
  width: '1px',
125
161
  style: 'solid',
@@ -129,15 +165,13 @@ export const buttonVariantStyles = {
129
165
  selectors: {
130
166
  '&:hover': {
131
167
  vars: {
132
- [buttonVars.color.background]:
133
- `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.hovered.opacity}), transparent)`,
168
+ [buttonVariantVars.background]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.hovered.opacity}), transparent)`,
134
169
  },
135
170
  },
136
171
  '&:disabled': {
137
172
  vars: {
138
- [buttonVars.color.background]: 'unset',
139
- [buttonVars.color.text]:
140
- `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.muted.dark}), transparent)`,
173
+ [buttonVariantVars.background]: 'unset',
174
+ [buttonVariantVars.foreground]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.disabled.text}), transparent)`,
141
175
  },
142
176
  },
143
177
  },
@@ -148,30 +182,32 @@ export const buttonVariantStyles = {
148
182
  '@layer': {
149
183
  [components]: {
150
184
  display: 'inline-flex',
151
-
152
185
  textDecoration: 'none',
153
-
154
186
  vars: {
155
- ...assignVars(buttonVars.color, {
156
- text: sys.color.foreground,
157
- background: 'unset',
158
- }),
187
+ ...buttonColorDefaults,
188
+ ...buttonToneOverlay,
189
+ [buttonVariantVars.background]: 'unset',
190
+ [buttonVariantVars.outline]: 'transparent',
191
+ ...buttonToneDefaults,
159
192
  ...assignVars(buttonVars.spacing, {
160
193
  block: '0',
161
194
  inline: '0',
162
195
  inner: '0',
163
196
  }),
197
+ ...assignVars(buttonVars.border, {
198
+ width: '0',
199
+ style: 'solid',
200
+ color: 'transparent',
201
+ }),
164
202
  },
165
203
  selectors: {
166
204
  '&:hover': {
167
205
  textDecoration: 'underline',
168
206
  },
169
-
170
207
  '&:disabled': {
171
208
  textDecoration: 'none',
172
209
  vars: {
173
- [buttonVars.color.text]:
174
- `color-mix(in srgb, ${sys.color.foreground} calc(100% * ${sys.state.muted.dark}), transparent)`,
210
+ [buttonVariantVars.foreground]: `color-mix(in srgb, ${buttonToneVars.base} calc(100% * ${sys.state.disabled.text}), transparent)`,
175
211
  },
176
212
  },
177
213
  },
@@ -180,6 +216,40 @@ export const buttonVariantStyles = {
180
216
  },
181
217
  } as const;
182
218
 
219
+ const compactSpacingStyle = {
220
+ '@layer': {
221
+ [components]: {
222
+ vars: {
223
+ [buttonVars.spacing.block]: '0',
224
+ [buttonVars.spacing.inline]: '0',
225
+ },
226
+ },
227
+ },
228
+ };
229
+
230
+ const compactSpacingVariants = (['sm', 'md', 'lg'] as const).flatMap((size) => [
231
+ {
232
+ variants: {
233
+ variant: 'bare',
234
+ size,
235
+ },
236
+ style: compactSpacingStyle,
237
+ },
238
+ {
239
+ variants: {
240
+ variant: 'link',
241
+ size,
242
+ },
243
+ style: compactSpacingStyle,
244
+ },
245
+ ]) as {
246
+ variants: {
247
+ variant: 'bare' | 'link';
248
+ size: 'sm' | 'md' | 'lg';
249
+ };
250
+ style: typeof compactSpacingStyle;
251
+ }[];
252
+
183
253
  export const buttonSizeStyles = {
184
254
  sm: {
185
255
  '@layer': {
@@ -228,18 +298,28 @@ export const buttonRecipe = recipe({
228
298
  paddingBlock: buttonVars.spacing.block,
229
299
  paddingInline: buttonVars.spacing.inline,
230
300
 
231
- color: buttonVars.color.text,
232
- textTransform: fallbackVar(buttonVars.textTransform, 'unset'),
233
- backgroundColor: buttonVars.color.background,
234
- borderRadius: fallbackVar(
235
- buttonVars.borderRadius,
236
- sys.shape.corner.none,
237
- ),
301
+ color: buttonVariantVars.foreground,
302
+ textTransform: buttonVars.textTransform,
303
+
304
+ backgroundColor: buttonVariantVars.background,
305
+ borderRadius: buttonVars.borderRadius,
238
306
  borderWidth: buttonVars.border.width,
239
307
  borderStyle: buttonVars.border.style,
240
308
  borderColor: buttonVars.border.color,
241
309
  boxShadow: buttonVars.shadow.level,
242
310
 
311
+ vars: {
312
+ ...buttonColorDefaults,
313
+ ...buttonVariantDefaults,
314
+ ...buttonToneDefaults,
315
+ [buttonVars.borderRadius]: sys.shape.corner.none,
316
+ [buttonVars.textTransform]: 'unset',
317
+ [buttonVars.border.width]: '0',
318
+ [buttonVars.border.style]: 'solid',
319
+ [buttonVars.border.color]: 'transparent',
320
+ [buttonVars.shadow.level]: sys.elevation.none,
321
+ },
322
+
243
323
  transition: transition(
244
324
  ['background-color', 'box-shadow', 'border-color', 'color'],
245
325
  { duration: 'short.3' },
@@ -255,109 +335,17 @@ export const buttonRecipe = recipe({
255
335
  variants: {
256
336
  variant: buttonVariantStyles,
257
337
  size: buttonSizeStyles,
338
+ tone: buttonToneStyles,
258
339
  },
259
340
 
260
- compoundVariants: [
261
- {
262
- variants: {
263
- variant: 'bare',
264
- size: 'sm',
265
- },
266
- style: {
267
- '@layer': {
268
- [components]: {
269
- vars: {
270
- [buttonVars.spacing.block]: '0',
271
- [buttonVars.spacing.inline]: '0',
272
- },
273
- },
274
- },
275
- },
276
- },
277
- {
278
- variants: {
279
- variant: 'bare',
280
- size: 'md',
281
- },
282
- style: {
283
- '@layer': {
284
- [components]: {
285
- vars: {
286
- [buttonVars.spacing.block]: '0',
287
- [buttonVars.spacing.inline]: '0',
288
- },
289
- },
290
- },
291
- },
292
- },
293
- {
294
- variants: {
295
- variant: 'bare',
296
- size: 'lg',
297
- },
298
- style: {
299
- '@layer': {
300
- [components]: {
301
- vars: {
302
- [buttonVars.spacing.block]: '0',
303
- [buttonVars.spacing.inline]: '0',
304
- },
305
- },
306
- },
307
- },
308
- },
309
- {
310
- variants: {
311
- variant: 'link',
312
- size: 'sm',
313
- },
314
- style: {
315
- '@layer': {
316
- [components]: {
317
- vars: {
318
- [buttonVars.spacing.block]: '0',
319
- [buttonVars.spacing.inline]: '0',
320
- },
321
- },
322
- },
323
- },
324
- },
325
- {
326
- variants: {
327
- variant: 'link',
328
- size: 'md',
329
- },
330
- style: {
331
- '@layer': {
332
- [components]: {
333
- vars: {
334
- [buttonVars.spacing.block]: '0',
335
- [buttonVars.spacing.inline]: '0',
336
- },
337
- },
338
- },
339
- },
340
- },
341
- {
342
- variants: {
343
- variant: 'link',
344
- size: 'lg',
345
- },
346
- style: {
347
- '@layer': {
348
- [components]: {
349
- vars: {
350
- [buttonVars.spacing.block]: '0',
351
- [buttonVars.spacing.inline]: '0',
352
- },
353
- },
354
- },
355
- },
356
- },
357
- ],
341
+ defaultVariants: {
342
+ tone: 'neutral',
343
+ },
344
+
345
+ compoundVariants: compactSpacingVariants,
358
346
  });
359
347
 
360
- export const buttonLabel = recipe({
348
+ export const buttonLabelRecipe = recipe({
361
349
  variants: {
362
350
  size: {
363
351
  sm: [typography.label.small],
@@ -367,7 +355,7 @@ export const buttonLabel = recipe({
367
355
  },
368
356
  });
369
357
 
370
- export const buttonSlot = recipe({
358
+ export const buttonSlotRecipe = recipe({
371
359
  base: {
372
360
  flexShrink: 0,
373
361
  },
@@ -437,5 +425,10 @@ export const variantAt = createResponsiveVariants({
437
425
  media: defaultMedia,
438
426
  });
439
427
 
428
+ export const toneAt = createResponsiveVariants({
429
+ styles: buttonToneStyles,
430
+ media: defaultMedia,
431
+ });
432
+
440
433
  // Note: buttonLabel uses typography class composition. For responsive
441
434
  // behaviors on text, prefer driving size via the root button's size.
@@ -1,10 +1,10 @@
1
1
  import { defaultOrder, responsiveRecipe } from '../../styles/responsive';
2
2
 
3
- import { buttonRecipe, sizeAt, variantAt } from './button.css';
3
+ import { buttonRecipe, sizeAt, toneAt, variantAt } from './button.css';
4
4
 
5
5
  export const buttonResponsive = responsiveRecipe({
6
6
  recipe: buttonRecipe,
7
- at: { size: sizeAt, variant: variantAt },
7
+ at: { size: sizeAt, tone: toneAt, variant: variantAt },
8
8
  order: defaultOrder,
9
9
  });
10
10
 
@@ -2,28 +2,20 @@ import { PolymorphicComponentProps } from '@kalink-ui/dibbly';
2
2
  import { clsx } from 'clsx';
3
3
  import { ComponentType, ElementType, ReactNode } from 'react';
4
4
 
5
- import { buttonLabel, buttonSlot, ButtonVariants } from './button.css';
5
+ import {
6
+ buildTypographyOverrides,
7
+ getResponsiveBase,
8
+ mapResponsiveSizeToTypography,
9
+ type Responsive,
10
+ } from '../../styles';
11
+
12
+ import {
13
+ buttonLabelRecipe,
14
+ buttonSlotRecipe,
15
+ ButtonVariants,
16
+ } from './button.css';
6
17
  import { buttonResponsive } from './button.responsive';
7
18
 
8
- import type { Responsive } from '../../styles/responsive';
9
-
10
- function getBase<T extends string | number>(value: Responsive<T> | undefined) {
11
- if (value == null) {
12
- return undefined as T | undefined;
13
- }
14
-
15
- if (Array.isArray(value)) {
16
- return (value[0] ?? undefined) as T | undefined;
17
- }
18
-
19
- if (typeof value === 'object') {
20
- const obj = value as Partial<Record<string, T>> & { xs?: T };
21
- return obj.xs as T | undefined;
22
- }
23
-
24
- return value as T;
25
- }
26
-
27
19
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
28
20
  export type ButtonTypes = 'button' | 'a' | ComponentType<any>;
29
21
 
@@ -32,23 +24,24 @@ export type ButtonProps<TUse extends ButtonTypes> =
32
24
  Omit<ButtonVariants, 'size' | 'variant'> & {
33
25
  startSlot?: ReactNode;
34
26
  endSlot?: ReactNode;
35
- children?: string;
27
+ children?: ReactNode;
36
28
  size?: Responsive<NonNullable<ButtonVariants['size']>>;
37
29
  variant?: Responsive<NonNullable<ButtonVariants['variant']>>;
30
+ tone?: Responsive<NonNullable<ButtonVariants['tone']>>;
38
31
  };
39
32
 
40
33
  export function Button<TUse extends ButtonTypes>(props: ButtonProps<TUse>) {
41
- const { children, startSlot, endSlot, size = 'md', ...rest } = props;
34
+ const { children, startSlot, endSlot, size = 'md', tone, ...rest } = props;
42
35
 
43
36
  return (
44
- <ButtonRoot {...rest} size={size}>
37
+ <ButtonRoot {...rest} size={size} tone={tone}>
45
38
  {startSlot && (
46
39
  <ButtonSlot use="span" position="start">
47
40
  {startSlot}
48
41
  </ButtonSlot>
49
42
  )}
50
43
  {children && (
51
- <ButtonLabel use="span" size={getBase(size) ?? 'md'}>
44
+ <ButtonLabel use="span" size={size}>
52
45
  {children}
53
46
  </ButtonLabel>
54
47
  )}
@@ -66,18 +59,25 @@ export type ButtonRootProps<TUse extends ButtonTypes> =
66
59
  Omit<ButtonVariants, 'size' | 'variant'> & {
67
60
  size?: Responsive<NonNullable<ButtonVariants['size']>>;
68
61
  variant?: Responsive<NonNullable<ButtonVariants['variant']>>;
62
+ tone?: Responsive<NonNullable<ButtonVariants['tone']>>;
69
63
  };
70
64
 
71
65
  export function ButtonRoot<TUse extends ButtonTypes>(
72
66
  props: ButtonRootProps<TUse>,
73
67
  ) {
74
- const { use: Comp = 'button', className, variant, size, ...rest } = props;
68
+ const {
69
+ use: Comp = 'button',
70
+ className,
71
+ variant,
72
+ size,
73
+ tone,
74
+ ...rest
75
+ } = props;
75
76
 
76
77
  return (
77
78
  <Comp
78
- className={clsx(buttonResponsive({ variant, size }), className)}
79
- /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
80
- {...(rest as any)}
79
+ className={buttonResponsive({ variant, size, tone }, className)}
80
+ {...(rest as Record<string, unknown>)}
81
81
  />
82
82
  );
83
83
  }
@@ -85,16 +85,29 @@ export function ButtonRoot<TUse extends ButtonTypes>(
85
85
  export type ButtonLabelProps<TUse extends ElementType> =
86
86
  PolymorphicComponentProps<TUse> & {
87
87
  children?: ReactNode;
88
- size?: ButtonVariants['size'];
88
+ size?: Responsive<NonNullable<ButtonVariants['size']>>;
89
89
  };
90
90
 
91
91
  export function ButtonLabel<TUse extends ElementType>(
92
92
  props: ButtonLabelProps<TUse>,
93
93
  ) {
94
94
  const { use: Comp = 'span', children, className, size, ...rest } = props;
95
+ const baseSize = getResponsiveBase(size) ?? 'md';
96
+ const typographySize = mapResponsiveSizeToTypography(size);
97
+ const typographyOverrides = buildTypographyOverrides({
98
+ variant: 'label',
99
+ size: typographySize,
100
+ });
95
101
 
96
102
  return (
97
- <Comp className={clsx(buttonLabel({ size }), className)} {...rest}>
103
+ <Comp
104
+ className={clsx(
105
+ buttonLabelRecipe({ size: baseSize }),
106
+ typographyOverrides,
107
+ className,
108
+ )}
109
+ {...rest}
110
+ >
98
111
  {children}
99
112
  </Comp>
100
113
  );
@@ -118,7 +131,7 @@ export function ButtonSlot<TUse extends ElementType>(
118
131
  } = props;
119
132
 
120
133
  return (
121
- <Comp className={clsx(buttonSlot({ position }), className)} {...rest}>
134
+ <Comp className={clsx(buttonSlotRecipe({ position }), className)} {...rest}>
122
135
  {children}
123
136
  </Comp>
124
137
  );
@@ -13,7 +13,7 @@ export {
13
13
  export {
14
14
  buttonRecipe,
15
15
  buttonVars,
16
- buttonSlot,
17
- buttonLabel,
16
+ buttonSlotRecipe,
17
+ buttonLabelRecipe,
18
18
  type ButtonVariants,
19
19
  } from './button.css';