lapikit 0.7.3 → 0.7.5

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 (71) hide show
  1. package/dist/@types/components.d.ts +1 -7
  2. package/dist/@types/dom.d.ts +4 -3
  3. package/dist/@types/props.d.ts +3 -3
  4. package/dist/animations/ripple.js +8 -2
  5. package/dist/components/accordion/accordion.svelte +192 -228
  6. package/dist/components/accordion/accordion.types.d.ts +5 -7
  7. package/dist/components/accordion/modules/accordion-item.svelte +144 -140
  8. package/dist/components/alert/alert.svelte +246 -293
  9. package/dist/components/alert/alert.types.d.ts +5 -5
  10. package/dist/components/app/app.svelte +25 -43
  11. package/dist/components/appbar/appbar.svelte +205 -190
  12. package/dist/components/appbar/appbar.types.d.ts +6 -6
  13. package/dist/components/aspect-ratio/aspect-ratio.svelte +43 -63
  14. package/dist/components/avatar/avatar.svelte +169 -161
  15. package/dist/components/avatar/avatar.types.d.ts +3 -4
  16. package/dist/components/btn/btn.svelte +432 -466
  17. package/dist/components/btn/btn.types.d.ts +5 -6
  18. package/dist/components/card/card.svelte +24 -23
  19. package/dist/components/card/card.types.d.ts +2 -2
  20. package/dist/components/card/modules/card-content.svelte +4 -1
  21. package/dist/components/card/modules/card-title.svelte +4 -1
  22. package/dist/components/chip/chip.svelte +416 -464
  23. package/dist/components/chip/chip.types.d.ts +5 -5
  24. package/dist/components/dialog/dialog.svelte +184 -175
  25. package/dist/components/dialog/dialog.types.d.ts +6 -6
  26. package/dist/components/dropdown/dropdown.svelte +149 -144
  27. package/dist/components/dropdown/dropdown.types.d.ts +4 -11
  28. package/dist/components/field/field.svelte +474 -0
  29. package/dist/components/field/field.svelte.d.ts +4 -0
  30. package/dist/components/field/field.types.d.ts +46 -0
  31. package/dist/components/field/field.types.js +1 -0
  32. package/dist/components/icon/icon.svelte +67 -96
  33. package/dist/components/icon/icon.types.d.ts +2 -1
  34. package/dist/components/index.d.ts +2 -0
  35. package/dist/components/index.js +1 -0
  36. package/dist/components/list/list.svelte +193 -194
  37. package/dist/components/list/list.types.d.ts +5 -7
  38. package/dist/components/list/modules/list-item.svelte +134 -147
  39. package/dist/components/modal/modal.js +9 -9
  40. package/dist/components/modal/modal.svelte +239 -222
  41. package/dist/components/modal/modal.types.d.ts +6 -6
  42. package/dist/components/popover/popover.svelte +125 -127
  43. package/dist/components/popover/popover.types.d.ts +4 -11
  44. package/dist/components/separator/separator.svelte +56 -87
  45. package/dist/components/separator/separator.types.d.ts +1 -1
  46. package/dist/components/spacer/spacer.svelte +6 -25
  47. package/dist/components/textfield/textfield.svelte +94 -543
  48. package/dist/components/textfield/textfield.types.d.ts +13 -33
  49. package/dist/components/toolbar/toolbar.svelte +216 -211
  50. package/dist/components/toolbar/toolbar.types.d.ts +8 -9
  51. package/dist/components/tooltip/tooltip.svelte +201 -266
  52. package/dist/components/tooltip/tooltip.types.d.ts +3 -10
  53. package/dist/constants.js +1 -0
  54. package/dist/escaping.js +0 -1
  55. package/dist/html-mapped.d.ts +1 -15
  56. package/dist/html-mapped.js +0 -19
  57. package/dist/labs/sheet/sheet.svelte +27 -22
  58. package/dist/utils/color.d.ts +2 -2
  59. package/dist/utils/color.js +2 -1
  60. package/dist/utils/components.d.ts +10 -10
  61. package/dist/utils/components.js +16 -75
  62. package/dist/utils/floating.d.ts +58 -0
  63. package/dist/utils/floating.js +131 -0
  64. package/dist/utils/index.d.ts +1 -0
  65. package/dist/utils/index.js +1 -0
  66. package/dist/utils/outside.d.ts +3 -1
  67. package/dist/utils/outside.js +15 -3
  68. package/package.json +6 -3
  69. package/dist/components/dropdown/dropdown.svelte.js +0 -148
  70. package/dist/components/popover/popover.svelte.js +0 -134
  71. package/dist/components/tooltip/tooltip.svelte.js +0 -131
@@ -1,6 +1,5 @@
1
1
  <script lang="ts">
2
- import { useClassName, useElevation, useStyles } from '../../utils';
3
- import { makeComponentProps } from '../../html-mapped';
2
+ import { useComponentAttrs, useElevation } from '../../utils';
4
3
  import { ripple } from '../../animations';
5
4
  import type { ButtonProps } from './btn.types.js';
6
5
 
@@ -8,8 +7,8 @@
8
7
  ref = $bindable(),
9
8
  is = 'button',
10
9
  children,
11
- class: className = '',
12
- style: styleAttr = '',
10
+ class: className,
11
+ style: styleAttr,
13
12
  's-class': sClass,
14
13
  's-style': sStyle,
15
14
  variant = 'filled',
@@ -34,485 +33,452 @@
34
33
  icon,
35
34
  elevation,
36
35
  color,
37
- background,
38
36
  ...rest
39
37
  }: ButtonProps = $props();
40
38
 
41
- let { classProps, styleProps, restProps } = $derived(
42
- makeComponentProps(rest as Record<string, unknown>)
39
+ let attrs = $derived(
40
+ useComponentAttrs('kit-btn', { className, sClass, styleAttr, sStyle, color, active }, rest)
43
41
  );
44
-
45
42
  let elevationState = $derived(useElevation(elevation));
46
-
47
- let componentClass = $derived(
48
- useClassName({
49
- baseClass: 'kit-btn',
50
- className: `${className ?? ''}`.trim(),
51
- sClass,
52
- classProps
53
- })
54
- );
55
-
56
- let componentStyle = $derived(
57
- useStyles({
58
- styleAttr,
59
- sStyle,
60
- styleProps
61
- })
62
- );
63
-
64
- const isInput = $derived(!!input);
65
- const isDisabled = $derived(!!disabled);
66
- const tag = $derived((href && 'a') || (isInput && 'input') || is || 'button');
67
- const inputWrapperTag = $derived(type === 'checkbox' || type === 'radio' ? 'label' : 'div');
68
- const resolvedHref = $derived(isDisabled ? undefined : href);
69
- const resolvedDisabled = $derived((tag === 'button' && isDisabled) || undefined);
70
-
71
- const resolvedType = $derived(() => {
72
- if (tag !== 'button') return type;
73
- return type ?? 'button';
74
- });
75
-
76
- let resolvedStyle = $derived(
77
- [
78
- componentStyle,
79
- color ? `--kit-btn-fg:${color && `var(--kit-color-${color})`}` : '',
80
- background ? `--kit-btn-bg:${background && `var(--kit-color-${background})`}` : ''
81
- ]
82
- .filter(Boolean)
83
- .join('; ')
43
+ let hasOutline = $derived(variant === 'outline' || variant === 'surface');
44
+
45
+ let isInput = $derived(!!input || is === 'input');
46
+ let isDisabled = $derived(!!disabled);
47
+ let tag = $derived<'button' | 'a' | 'label' | 'div'>(
48
+ isInput
49
+ ? type === 'checkbox' || type === 'radio'
50
+ ? 'label'
51
+ : 'div'
52
+ : href || is === 'a'
53
+ ? 'a'
54
+ : 'button'
84
55
  );
56
+ let resolvedHref = $derived(tag === 'a' && !isDisabled ? href : undefined);
57
+ let resolvedType = $derived(tag === 'button' ? (type ?? 'button') : undefined);
58
+ let resolvedDisabled = $derived(tag === 'button' ? isDisabled : undefined);
59
+ let resolvedTabIndex = $derived(tag === 'a' && isDisabled ? -1 : undefined);
85
60
  </script>
86
61
 
87
- {#if isInput}
88
- <svelte:element
89
- this={inputWrapperTag}
90
- bind:this={ref}
91
- class={componentClass}
92
- style={resolvedStyle}
93
- data-size={size}
94
- data-variant={variant}
95
- data-loading={loading}
96
- data-active={active}
97
- data-disabled={isDisabled}
98
- data-density={density}
99
- data-rounded={rounded}
100
- aria-busy={disabled}
101
- aria-disabled={isDisabled || undefined}
102
- data-block={block}
103
- data-wide={wide}
104
- data-icon={icon}
105
- data-elevation={elevationState.base}
106
- data-elevation-hover={elevationState.hover}
107
- data-elevation-active={elevationState.active}
108
- use:ripple={{
109
- component: 'btn',
110
- disabled: noRipple || disabled
111
- }}
112
- >
113
- {#if variant === 'outline'}
114
- <span class="outline"></span>
115
- {/if}
62
+ <svelte:element
63
+ this={tag}
64
+ bind:this={ref}
65
+ class={attrs.class}
66
+ style={attrs.style}
67
+ href={resolvedHref}
68
+ type={resolvedType}
69
+ disabled={resolvedDisabled}
70
+ tabindex={resolvedTabIndex}
71
+ data-variant={variant}
72
+ data-size={size}
73
+ data-density={density}
74
+ data-rounded={rounded}
75
+ data-elevation={elevationState.base}
76
+ data-elevation-hover={elevationState.hover}
77
+ data-elevation-active={elevationState.active}
78
+ data-interactive={true}
79
+ data-active={active}
80
+ data-disabled={isDisabled}
81
+ data-loading={loading}
82
+ data-block={block}
83
+ data-wide={wide}
84
+ data-icon={icon}
85
+ aria-busy={loading || undefined}
86
+ aria-disabled={isDisabled || undefined}
87
+ use:ripple={{
88
+ component: 'btn',
89
+ disabled: noRipple || isDisabled
90
+ }}
91
+ {...isInput ? {} : attrs.rest}
92
+ >
93
+ {#if hasOutline}
94
+ <span class="outline"></span>
95
+ {/if}
96
+
97
+ {#if isInput}
116
98
  <input
117
- {...restProps}
99
+ {...attrs.rest}
100
+ class="kit-btn__input"
101
+ data-ripple-host
118
102
  type={type || 'button'}
119
103
  {checked}
120
104
  {value}
121
- aria-label={String(label || value)}
105
+ aria-label={label || (value != null ? String(value) : undefined)}
122
106
  disabled={isDisabled}
123
107
  />
124
- {#if loading}
125
- <span class="spinner">...</span>
126
- {/if}
127
- </svelte:element>
128
- {:else}
129
- <svelte:element
130
- this={tag}
131
- bind:this={ref}
132
- class={componentClass}
133
- style={resolvedStyle}
134
- type={resolvedType()}
135
- href={resolvedHref}
136
- data-size={size}
137
- data-variant={variant}
138
- data-loading={loading}
139
- data-active={active}
140
- data-disabled={isDisabled}
141
- data-density={density}
142
- data-rounded={rounded}
143
- disabled={resolvedDisabled}
144
- aria-busy={disabled}
145
- aria-disabled={isDisabled || undefined}
146
- data-block={block}
147
- data-wide={wide}
148
- data-icon={icon}
149
- data-elevation={elevationState.base}
150
- data-elevation-hover={elevationState.hover}
151
- data-elevation-active={elevationState.active}
152
- use:ripple={{
153
- component: 'btn',
154
- disabled: noRipple || disabled
155
- }}
156
- {...restProps}
157
- >
158
- {#if variant === 'outline'}
159
- <span class="outline"></span>
160
- {/if}
161
-
108
+ {:else}
162
109
  <span class="kit-btn__inner">
163
110
  {#if prepend}
164
- <span class="kit-btn__prepend">
165
- {@render prepend?.()}
166
- </span>
111
+ <span class="kit-btn__prepend">{@render prepend()}</span>
112
+ {/if}
113
+ {#if children}
114
+ <span class="kit-btn__content">{@render children()}</span>
167
115
  {/if}
168
- <span class="kit-btn__content">
169
- {@render children?.()}
170
- </span>
171
116
  {#if append}
172
- <span class="kit-btn__append">
173
- {@render append?.()}
174
- </span>
117
+ <span class="kit-btn__append">{@render append()}</span>
175
118
  {/if}
176
119
  </span>
177
-
178
- {#if loading}
179
- <span class="spinner">
180
- {#if load}
181
- {@render load?.()}
182
- {:else}
183
- ...
184
- {/if}
185
- </span>
186
- {/if}
187
- </svelte:element>
188
- {/if}
189
-
190
- <style>
191
- input {
192
- border: 0;
193
- padding: 0;
194
- background: transparent;
195
- color: inherit;
196
- cursor: pointer;
197
- }
198
- /* typography consistency */
199
- button,
200
- input,
201
- select,
202
- textarea {
203
- font: inherit;
204
- color: inherit;
205
- }
206
-
207
- /* remove native button styles */
208
- button {
209
- appearance: none;
210
- background: none;
211
- border: none;
212
- }
213
-
214
- .kit-btn {
215
- position: relative;
216
- display: inline-flex;
217
- box-sizing: border-box;
218
- align-items: center;
219
- justify-content: center;
220
- font-family: var(--kit-font);
221
- background: var(--kit-btn-bg);
222
- color: var(--kit-btn-fg);
223
- height: calc(var(--kit-btn-h) + var(--kit-btn-density-offset) / 2);
224
- padding-inline: calc(var(--kit-btn-p) + var(--kit-btn-density-offset) / 2);
225
- border-radius: var(--kit-btn-radius);
226
- text-decoration: none;
227
- white-space: nowrap;
228
- user-select: none;
229
- cursor: pointer;
230
- border: 0;
231
- transition:
232
- background 150ms ease,
233
- transform 50ms ease;
234
- }
235
-
236
- .kit-btn:hover {
237
- background: var(--kit-btn-hover-bg);
238
- color: var(--kit-btn-fg);
239
- text-decoration: var(--kit-btn-decoration);
240
- translate: 0 -1px;
241
- }
242
-
243
- .kit-btn:has(> :is(input[type='checkbox'], input[type='radio']):checked) {
244
- background: var(--kit-btn-active-bg);
245
- color: var(--kit-btn-fg);
246
- text-decoration: var(--kit-btn-decoration);
247
- }
248
-
249
- .kit-btn:has(> :is(input[type='checkbox'], input[type='radio']):checked):hover {
250
- background: var(--kit-btn-hover-bg);
251
- color: var(--kit-btn-fg);
252
- text-decoration: var(--kit-btn-decoration);
253
- }
254
-
255
- .kit-btn:active,
256
- .kit-btn[data-active='true'] {
257
- background: var(--kit-btn-active-bg);
258
- color: var(--kit-btn-fg);
259
- text-decoration: var(--kit-btn-decoration);
260
- transform: translateY(1px);
261
- }
262
-
263
- .kit-btn[data-active='true']:hover {
264
- background: var(--kit-btn-hover-bg);
265
- color: var(--kit-btn-fg);
266
- text-decoration: var(--kit-btn-decoration);
267
- }
268
-
269
- :is(.kit-btn:focus-visible, .kit-btn:has(> input:focus-visible)) {
270
- outline: 2px solid var(--kit-color-focus);
271
- outline-offset: 2px;
272
- }
273
-
274
- .kit-btn > input:focus-visible {
275
- outline: none;
276
- box-shadow: none;
277
- }
278
-
279
- .kit-btn > :is(input[type='checkbox'], input[type='radio']) {
280
- appearance: none;
281
- margin: 0;
282
- cursor: pointer;
283
- }
284
-
285
- .kit-btn > :is(input[type='checkbox'], input[type='radio']):after {
286
- content: attr(aria-label);
287
- cursor: pointer;
288
- }
289
-
290
- .kit-btn[data-wide='true'] {
291
- width: 100%;
292
- max-width: 16rem;
293
- }
294
-
295
- .kit-btn__inner {
296
- display: inline-flex;
297
- align-items: center;
298
- justify-content: center;
299
- gap: var(--kit-btn-gap);
300
- line-height: 1;
301
- }
302
-
303
- .kit-btn__content,
304
- .kit-btn__prepend,
305
- .kit-btn__append {
306
- display: inline-flex;
307
- align-items: center;
308
- justify-content: center;
309
- line-height: 1;
310
- }
311
-
312
- .kit-btn__content :global(.kit-icon),
313
- .kit-btn__prepend :global(.kit-icon),
314
- .kit-btn__append :global(.kit-icon) {
315
- display: inline-flex;
316
- align-items: center;
317
- justify-content: center;
318
- vertical-align: middle;
319
- }
320
-
321
- .kit-btn__content :global(svg),
322
- .kit-btn__prepend :global(svg),
323
- .kit-btn__append :global(svg),
324
- .kit-btn__content :global(img),
325
- .kit-btn__prepend :global(img),
326
- .kit-btn__append :global(img) {
327
- display: block;
328
- }
329
-
330
- .kit-btn[data-loading='true'] .kit-btn__inner,
331
- .kit-btn[data-loading='true'] input {
332
- opacity: 0;
333
- }
334
-
335
- .kit-btn[data-loading='true'] {
336
- pointer-events: none;
337
- user-select: none;
338
- cursor: pointer;
339
- }
340
-
341
- .spinner {
342
- position: absolute;
343
- inset: 0;
344
- display: flex;
345
- align-items: center;
346
- justify-content: center;
347
- }
348
-
349
- .kit-btn[data-block='true'] {
350
- display: flex;
351
- width: 100%;
352
- }
353
-
354
- .kit-btn[data-icon='true'] {
355
- width: max(28px, calc(var(--kit-btn-h) + var(--kit-btn-density-offset) / 2));
356
- min-width: max(28px, calc(var(--kit-btn-h) + var(--kit-btn-density-offset) / 2));
357
- padding-inline: 0;
358
- }
359
-
360
- .kit-btn[data-icon='true'] .kit-btn__inner {
361
- gap: 0;
362
- }
363
-
364
- .kit-btn[data-disabled='true'] {
365
- pointer-events: none;
366
- background: color-mix(in oklab, var(--kit-btn-bg), transparent 70%);
367
- color: color-mix(in oklab, var(--kit-btn-fg), transparent 45%);
368
- user-select: none;
369
- cursor: not-allowed;
370
- }
371
-
372
- .kit-btn[data-disabled='true'] :global(.kit-icon) {
373
- color: color-mix(in oklab, var(--kit-btn-fg), transparent 45%) !important;
374
- --kit-icon-color: color-mix(in oklab, var(--kit-btn-fg), transparent 45%) !important;
375
- }
376
-
377
- .kit-btn[data-disabled='true'] :global(.kit-icon img),
378
- .kit-btn[data-disabled='true'] :global(.kit-icon .kit-icon__mask) {
379
- opacity: 0.7;
380
- filter: grayscale(0.2);
381
- }
382
-
383
- .kit-btn[data-disabled='true'] > input {
384
- cursor: not-allowed;
385
- }
386
-
387
- /**
388
- * size
389
- * @link nothing...
390
- */
391
- .kit-btn[data-size='xs'] {
392
- --kit-btn-h: 24px;
393
- --kit-btn-p: 8px;
394
- --kit-btn-gap: var(--kit-space-compact);
395
- --kit-btn-font: 12px;
396
- }
397
- .kit-btn[data-size='xs'] :global(.kit-icon:not([data-size])) {
398
- --kit-icon-current-size: var(--kit-icon-size-xs);
399
- }
400
- .kit-btn[data-size='sm'] {
401
- --kit-btn-h: 32px;
402
- --kit-btn-p: 12px;
403
- --kit-btn-gap: var(--kit-space-default);
404
- --kit-btn-font: 13px;
405
- }
406
- .kit-btn[data-size='sm'] :global(.kit-icon:not([data-size])) {
407
- --kit-icon-current-size: var(--kit-icon-size-sm);
408
- }
409
-
410
- .kit-btn[data-size='md'] {
411
- --kit-btn-h: 40px;
412
- --kit-btn-p: 16px;
413
- --kit-btn-gap: var(--kit-space-default);
414
- --kit-btn-font: 14px;
415
- }
416
- .kit-btn[data-size='md'] :global(.kit-icon:not([data-size])) {
417
- --kit-icon-current-size: var(--kit-icon-size-md);
418
- }
419
-
420
- .kit-btn[data-size='lg'] {
421
- --kit-btn-h: 48px;
422
- --kit-btn-p: 20px;
423
- --kit-btn-gap: var(--kit-space-default);
424
- --kit-btn-font: 16px;
425
- }
426
- .kit-btn[data-size='lg'] :global(.kit-icon:not([data-size])) {
427
- --kit-icon-current-size: var(--kit-icon-size-lg);
428
- }
429
-
430
- .kit-btn[data-size='xl'] {
431
- --kit-btn-h: 56px;
432
- --kit-btn-p: 24px;
433
- --kit-btn-gap: var(--kit-space-comfortable);
434
- --kit-btn-font: 17px;
435
- }
436
- .kit-btn[data-size='xl'] :global(.kit-icon:not([data-size])) {
437
- --kit-icon-current-size: var(--kit-icon-size-xl);
438
- }
439
-
440
- /**
441
- * density
442
- * @link no links
443
- */
444
- .kit-btn[data-density='compact'] {
445
- --kit-btn-density-offset: var(--kit-density-compact);
446
- }
447
- .kit-btn[data-density='default'] {
448
- --kit-btn-density-offset: var(--kit-density-default);
449
- }
450
- .kit-btn[data-density='comfortable'] {
451
- --kit-btn-density-offset: var(--kit-density-comfortable);
452
- }
453
-
454
- /**
455
- * rounded
456
- * @link ...
457
- */
458
- .kit-btn[data-rounded='0'] {
459
- --kit-btn-radius: var(--kit-shape-none);
460
- }
461
- .kit-btn[data-rounded='xs'] {
462
- --kit-btn-radius: var(--kit-shape-xs);
463
- }
464
- .kit-btn[data-rounded='sm'] {
465
- --kit-btn-radius: var(--kit-shape-sm);
466
- }
467
- .kit-btn[data-rounded='md'] {
468
- --kit-btn-radius: var(--kit-shape-md);
469
- }
470
- .kit-btn[data-rounded='lg'] {
471
- --kit-btn-radius: var(--kit-shape-lg);
472
- }
473
- .kit-btn[data-rounded='xl'] {
474
- --kit-btn-radius: var(--kit-shape-xl);
475
- }
476
- .kit-btn[data-rounded='full'] {
477
- --kit-btn-radius: var(--kit-shape-full);
478
- }
479
-
480
- /**
481
- * variant
482
- * @link no links...
483
- */
484
- .kit-btn[data-variant='filled'] {
485
- --kit-btn-bg: var(--kit-color-surface-2);
486
- --kit-btn-fg: var(--kit-color-text);
487
-
488
- --kit-btn-hover-bg: color-mix(in oklab, var(--kit-btn-bg), black 10%);
489
- --kit-btn-active-bg: color-mix(in oklab, var(--kit-btn-bg), black 16%);
490
- }
491
- .kit-btn[data-variant='outline'] {
492
- --kit-btn-bg: transparent;
493
- --kit-btn-fg: var(--kit-color-text);
494
- --kit-btn-bd: var(--kit-btn-fg);
495
-
496
- --kit-btn-hover-bg: color-mix(in oklab, var(--kit-btn-fg), transparent 80%);
497
- --kit-btn-active-bg: color-mix(in oklab, var(--kit-btn-fg), transparent 92%);
498
- }
499
- .kit-btn[data-variant='text'] {
500
- --kit-btn-bg: transparent;
501
- --kit-btn-fg: var(--kit-color-text);
502
-
503
- --kit-btn-hover-bg: color-mix(in oklab, var(--kit-btn-fg), transparent 80%);
504
- --kit-btn-active-bg: color-mix(in oklab, var(--kit-btn-fg), transparent 92%);
505
- }
506
- .kit-btn[data-variant='link'] {
507
- --kit-btn-bg: transparent;
508
- --kit-btn-fg: var(--kit-color-text);
509
- --kit-btn-decoration: underline;
510
-
511
- height: inherit;
512
- padding: 0;
513
- }
514
-
515
- .kit-btn .outline {
516
- --outline-color: var(--kit-btn-bd);
517
- }
518
- </style>
120
+ {/if}
121
+
122
+ {#if loading}
123
+ <span class="kit-btn__spinner">
124
+ {#if load}
125
+ {@render load()}
126
+ {:else}
127
+ ...
128
+ {/if}
129
+ </span>
130
+ {/if}
131
+ </svelte:element>
132
+
133
+ <style>:where(.kit-btn) {
134
+ --kit-btn-color: initial;
135
+ --kit-btn-on-color: initial;
136
+ --kit-btn-active-fg: initial;
137
+ --kit-btn-active-shade: initial;
138
+ --kit-btn-hover-fg: initial;
139
+ --kit-btn-pressed-fg: initial;
140
+ --kit-btn-bg: var(--kit-btn-color, var(--kit-color-surface-2));
141
+ --kit-btn-fg: var(--kit-btn-on-color, var(--kit-btn-contrast, var(--kit-color-text)));
142
+ --kit-btn-ink: var(--kit-btn-color, var(--kit-color-text));
143
+ --kit-btn-hover: color-mix(in oklab, var(--kit-btn-bg), var(--kit-btn-fg) 8%);
144
+ --kit-btn-pressed: color-mix(in oklab, var(--kit-btn-bg), var(--kit-btn-fg) 14%);
145
+ --kit-btn-soft: color-mix(in oklab, var(--kit-btn-bg) 16%, transparent);
146
+ --kit-btn-border: color-mix(in oklab, var(--kit-btn-bg), var(--kit-btn-fg) 20%);
147
+ --kit-btn-active: color-mix(
148
+ in oklab,
149
+ var(--kit-btn-color),
150
+ var(--kit-btn-fg) var(--kit-btn-active-shade, 14%)
151
+ );
152
+ }
153
+ @supports (color: color(from red srgb-linear r g b)) {
154
+ :where(.kit-btn) {
155
+ --kit-btn-contrast: color(from var(--kit-btn-color) srgb-linear clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 100000, 1) clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 100000, 1) clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 100000, 1)/1);
156
+ }
157
+ }
158
+ :where(.kit-btn) {
159
+ --kit-btn-height: calc(var(--kit-btn-h) + var(--kit-btn-density-offset) / 2);
160
+ }
161
+
162
+ .kit-btn {
163
+ position: relative;
164
+ display: inline-flex;
165
+ box-sizing: border-box;
166
+ align-items: center;
167
+ justify-content: center;
168
+ height: var(--kit-btn-height);
169
+ padding-inline: calc(var(--kit-btn-p) + var(--kit-btn-density-offset) / 2);
170
+ border: 0;
171
+ border-radius: var(--kit-btn-radius);
172
+ background-color: var(--kit-btn-bg);
173
+ color: var(--kit-btn-fg);
174
+ font: inherit;
175
+ font-family: var(--kit-font);
176
+ font-size: var(--kit-btn-font);
177
+ text-decoration: none;
178
+ white-space: nowrap;
179
+ user-select: none;
180
+ transition-property: background-color, color, border-color, box-shadow;
181
+ transition-duration: var(--kit-animation-component);
182
+ transition-timing-function: ease;
183
+ }
184
+ @media (prefers-reduced-motion: reduce) {
185
+ .kit-btn {
186
+ transition: none;
187
+ }
188
+ }
189
+ .kit-btn__inner {
190
+ display: inline-flex;
191
+ align-items: center;
192
+ justify-content: center;
193
+ gap: var(--kit-btn-gap);
194
+ line-height: 1;
195
+ }
196
+ .kit-btn__content, .kit-btn__prepend, .kit-btn__append {
197
+ display: inline-flex;
198
+ align-items: center;
199
+ justify-content: center;
200
+ line-height: 1;
201
+ }
202
+ .kit-btn__content :global(.kit-icon), .kit-btn__prepend :global(.kit-icon), .kit-btn__append :global(.kit-icon) {
203
+ display: inline-flex;
204
+ align-items: center;
205
+ justify-content: center;
206
+ vertical-align: middle;
207
+ }
208
+ .kit-btn__content :global(svg),
209
+ .kit-btn__content :global(img), .kit-btn__prepend :global(svg),
210
+ .kit-btn__prepend :global(img), .kit-btn__append :global(svg),
211
+ .kit-btn__append :global(img) {
212
+ display: block;
213
+ }
214
+ .kit-btn__input {
215
+ margin: 0;
216
+ padding: 0;
217
+ border: 0;
218
+ background: transparent;
219
+ color: inherit;
220
+ font: inherit;
221
+ cursor: pointer;
222
+ }
223
+ .kit-btn__input:focus-visible {
224
+ outline: none;
225
+ }
226
+ .kit-btn__input:is([type=checkbox], [type=radio]) {
227
+ appearance: none;
228
+ }
229
+ .kit-btn__input:is([type=checkbox], [type=radio])::after {
230
+ content: attr(aria-label);
231
+ }
232
+ .kit-btn__spinner {
233
+ position: absolute;
234
+ inset: 0;
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ }
239
+ .kit-btn:has(> .kit-btn__input:focus-visible) {
240
+ outline: 2px solid var(--kit-color-focus);
241
+ outline-offset: 2px;
242
+ }
243
+ .kit-btn[data-loading=true] {
244
+ pointer-events: none;
245
+ }
246
+ .kit-btn[data-loading=true] .kit-btn__inner,
247
+ .kit-btn[data-loading=true] .kit-btn__input {
248
+ opacity: 0;
249
+ }
250
+ .kit-btn[data-block=true] {
251
+ display: flex;
252
+ width: 100%;
253
+ }
254
+ .kit-btn[data-wide=true] {
255
+ width: 100%;
256
+ max-width: 16rem;
257
+ }
258
+ .kit-btn[data-icon=true] {
259
+ width: max(1.75rem, var(--kit-btn-height));
260
+ min-width: max(1.75rem, var(--kit-btn-height));
261
+ padding-inline: 0;
262
+ }
263
+ .kit-btn[data-icon=true] .kit-btn__inner {
264
+ gap: 0;
265
+ }
266
+
267
+ /* native resets: no background here, it would beat the background of .kit-btn */
268
+ button.kit-btn {
269
+ appearance: none;
270
+ }
271
+
272
+ /**
273
+ * size
274
+ * @link https://lapikit.dev/docs/components/button#size
275
+ */
276
+ :where(.kit-btn[data-size=xs]) {
277
+ --kit-btn-h: 1.5rem;
278
+ --kit-btn-p: 0.5rem;
279
+ --kit-btn-gap: 0.25rem;
280
+ --kit-btn-font: 0.75rem;
281
+ }
282
+ :where(.kit-btn[data-size=xs]) :global(.kit-icon[data-size='default']) {
283
+ --kit-icon-current-size: var(--kit-icon-size-xs);
284
+ }
285
+
286
+ :where(.kit-btn[data-size=sm]) {
287
+ --kit-btn-h: 2rem;
288
+ --kit-btn-p: 0.75rem;
289
+ --kit-btn-gap: 0.375rem;
290
+ --kit-btn-font: var(--kit-font-xs);
291
+ }
292
+ :where(.kit-btn[data-size=sm]) :global(.kit-icon[data-size='default']) {
293
+ --kit-icon-current-size: var(--kit-icon-size-sm);
294
+ }
295
+
296
+ :where(.kit-btn[data-size=md]) {
297
+ --kit-btn-h: 2.5rem;
298
+ --kit-btn-p: 1rem;
299
+ --kit-btn-gap: 0.5rem;
300
+ --kit-btn-font: var(--kit-font-sm);
301
+ }
302
+ :where(.kit-btn[data-size=md]) :global(.kit-icon[data-size='default']) {
303
+ --kit-icon-current-size: var(--kit-icon-size-md);
304
+ }
305
+
306
+ :where(.kit-btn[data-size=lg]) {
307
+ --kit-btn-h: 3rem;
308
+ --kit-btn-p: 1.25rem;
309
+ --kit-btn-gap: 0.5625rem;
310
+ --kit-btn-font: var(--kit-font-lg);
311
+ }
312
+ :where(.kit-btn[data-size=lg]) :global(.kit-icon[data-size='default']) {
313
+ --kit-icon-current-size: var(--kit-icon-size-lg);
314
+ }
315
+
316
+ :where(.kit-btn[data-size=xl]) {
317
+ --kit-btn-h: 3.5rem;
318
+ --kit-btn-p: 1.5rem;
319
+ --kit-btn-gap: 0.625rem;
320
+ --kit-btn-font: var(--kit-font-xl);
321
+ }
322
+ :where(.kit-btn[data-size=xl]) :global(.kit-icon[data-size='default']) {
323
+ --kit-icon-current-size: var(--kit-icon-size-xl);
324
+ }
325
+
326
+ /**
327
+ * variant
328
+ * @link https://lapikit.dev/docs/components/button#variants
329
+ */
330
+ :where(.kit-btn[data-variant=tonal]) {
331
+ --kit-btn-bg: color-mix(in oklab, var(--kit-btn-ink) 16%, transparent);
332
+ --kit-btn-fg: var(--kit-btn-ink);
333
+ --kit-btn-border: transparent;
334
+ --kit-btn-active: color-mix(in oklab, var(--kit-btn-ink) 28%, transparent);
335
+ --kit-btn-active-fg: var(--kit-btn-ink);
336
+ }
337
+
338
+ :where(.kit-btn[data-variant=outline]) {
339
+ --kit-btn-bg: transparent;
340
+ --kit-btn-fg: var(--kit-btn-ink);
341
+ --kit-btn-border: var(--kit-btn-color, var(--kit-color-border));
342
+ --kit-btn-active: color-mix(in oklab, var(--kit-btn-ink) 14%, transparent);
343
+ --kit-btn-active-fg: var(--kit-btn-ink);
344
+ }
345
+
346
+ :where(.kit-btn[data-variant=surface]) {
347
+ --kit-btn-bg: color-mix(in oklab, var(--kit-btn-ink) 8%, transparent);
348
+ --kit-btn-fg: var(--kit-btn-ink);
349
+ --kit-btn-border: color-mix(in oklab, var(--kit-btn-ink) 35%, transparent);
350
+ --kit-btn-active: color-mix(in oklab, var(--kit-btn-ink) 18%, transparent);
351
+ --kit-btn-active-fg: var(--kit-btn-ink);
352
+ }
353
+
354
+ :where(.kit-btn[data-variant=text]) {
355
+ --kit-btn-bg: transparent;
356
+ --kit-btn-fg: var(--kit-btn-ink);
357
+ --kit-btn-border: transparent;
358
+ --kit-btn-active: color-mix(in oklab, var(--kit-btn-ink) 14%, transparent);
359
+ --kit-btn-active-fg: var(--kit-btn-ink);
360
+ }
361
+
362
+ :where(.kit-btn[data-variant=plain]) {
363
+ --kit-btn-bg: transparent;
364
+ --kit-btn-fg: var(--kit-btn-ink);
365
+ --kit-btn-border: transparent;
366
+ --kit-btn-hover: transparent;
367
+ --kit-btn-pressed: transparent;
368
+ --kit-btn-hover-fg: color-mix(in oklab, var(--kit-btn-fg) 72%, transparent);
369
+ --kit-btn-pressed-fg: color-mix(in oklab, var(--kit-btn-fg) 56%, transparent);
370
+ --kit-btn-active: transparent;
371
+ --kit-btn-active-fg: var(--kit-btn-color, var(--kit-color-accent));
372
+ }
373
+
374
+ :where(.kit-btn[data-variant=link]) {
375
+ --kit-btn-bg: transparent;
376
+ --kit-btn-fg: var(--kit-btn-ink);
377
+ --kit-btn-border: transparent;
378
+ --kit-btn-hover: transparent;
379
+ --kit-btn-pressed: transparent;
380
+ --kit-btn-hover-fg: color-mix(in oklab, var(--kit-btn-fg) 72%, transparent);
381
+ --kit-btn-pressed-fg: color-mix(in oklab, var(--kit-btn-fg) 56%, transparent);
382
+ --kit-btn-active: transparent;
383
+ --kit-btn-active-fg: var(--kit-btn-color, var(--kit-color-accent));
384
+ }
385
+
386
+ .kit-btn[data-variant=link] {
387
+ height: auto;
388
+ padding: 0;
389
+ text-decoration: underline;
390
+ }
391
+
392
+ :where(.kit-btn .outline) {
393
+ --outline-color: var(--kit-btn-border);
394
+ }
395
+
396
+ :where(.kit-btn[data-active=true], .kit-btn:has(> .kit-btn__input:checked)) {
397
+ --kit-btn-bg: var(--kit-btn-active, var(--kit-color-accent));
398
+ --kit-btn-fg: var(
399
+ --kit-btn-active-fg,
400
+ var(--kit-btn-on-color, var(--kit-btn-contrast, var(--kit-color-on-accent)))
401
+ );
402
+ }
403
+
404
+ /**
405
+ * interactive: hover, pressed, focus-visible and disabled
406
+ */
407
+ .kit-btn[data-interactive=true]:not([data-disabled=true]) {
408
+ cursor: pointer;
409
+ }
410
+ .kit-btn[data-interactive=true]:not([data-disabled=true]):hover {
411
+ background-color: var(--kit-btn-hover);
412
+ color: var(--kit-btn-hover-fg, var(--kit-btn-fg));
413
+ }
414
+ .kit-btn[data-interactive=true]:not([data-disabled=true]):active {
415
+ background-color: var(--kit-btn-pressed);
416
+ color: var(--kit-btn-pressed-fg, var(--kit-btn-fg));
417
+ }
418
+
419
+ .kit-btn:not([data-disabled=true]):focus-visible {
420
+ outline: 2px solid var(--kit-color-focus);
421
+ outline-offset: 2px;
422
+ }
423
+
424
+ .kit-btn[data-disabled=true] {
425
+ opacity: var(--kit-disabled-opacity, 0.55);
426
+ pointer-events: none;
427
+ user-select: none;
428
+ }
429
+
430
+ /**
431
+ * rounded
432
+ * @link https://lapikit.dev/docs/customize
433
+ */
434
+ :where(.kit-btn[data-rounded="0"]) {
435
+ --kit-btn-radius: var(--kit-shape-none);
436
+ }
437
+
438
+ :where(.kit-btn[data-rounded=xs]) {
439
+ --kit-btn-radius: var(--kit-shape-xs);
440
+ }
441
+
442
+ :where(.kit-btn[data-rounded=sm]) {
443
+ --kit-btn-radius: var(--kit-shape-sm);
444
+ }
445
+
446
+ :where(.kit-btn[data-rounded=md]) {
447
+ --kit-btn-radius: var(--kit-shape-md);
448
+ }
449
+
450
+ :where(.kit-btn[data-rounded=lg]) {
451
+ --kit-btn-radius: var(--kit-shape-lg);
452
+ }
453
+
454
+ :where(.kit-btn[data-rounded=xl]) {
455
+ --kit-btn-radius: var(--kit-shape-xl);
456
+ }
457
+
458
+ :where(.kit-btn[data-rounded=full]) {
459
+ --kit-btn-radius: var(--kit-shape-full);
460
+ }
461
+
462
+ /**
463
+ * density
464
+ * @link https://lapikit.dev/docs/components/button#density
465
+ */
466
+ :where(.kit-btn[data-density=dense]) {
467
+ --kit-btn-density-offset: var(--kit-density-dense);
468
+ }
469
+
470
+ :where(.kit-btn[data-density=compact]) {
471
+ --kit-btn-density-offset: var(--kit-density-compact);
472
+ }
473
+
474
+ :where(.kit-btn[data-density=default]) {
475
+ --kit-btn-density-offset: var(--kit-density-default);
476
+ }
477
+
478
+ :where(.kit-btn[data-density=comfortable]) {
479
+ --kit-btn-density-offset: var(--kit-density-comfortable);
480
+ }
481
+
482
+ :where(.kit-btn[data-density=spacious]) {
483
+ --kit-btn-density-offset: var(--kit-density-spacious);
484
+ }</style>