@threadlabs/looma 0.33.1 → 0.34.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 (184) hide show
  1. package/components/shared/overlay.js +8 -2
  2. package/components/shared/surface-material.js +21 -0
  3. package/components/ui-button/ui-button.html +63 -47
  4. package/components/ui-card/ui-card.html +44 -2
  5. package/components/ui-curve-editor/curve.js +10 -0
  6. package/components/ui-curve-editor/ui-curve-editor.html +181 -0
  7. package/components/ui-curve-editor/ui-curve-editor.js +51 -0
  8. package/components/ui-dialog/ui-dialog.html +62 -1
  9. package/components/ui-dialog/ui-dialog.js +9 -1
  10. package/components/ui-icon-button/ui-icon-button.html +75 -23
  11. package/components/ui-menu/ui-menu.html +60 -0
  12. package/components/ui-menu/ui-menu.js +1 -1
  13. package/components/ui-number-input/arithmetic.js +47 -0
  14. package/components/ui-number-input/ui-number-input.html +62 -0
  15. package/components/ui-number-input/ui-number-input.js +44 -0
  16. package/components/ui-popover/ui-popover.html +64 -1
  17. package/components/ui-popover/ui-popover.js +1 -1
  18. package/components/ui-slider/ui-slider.html +84 -0
  19. package/components/ui-slider/ui-slider.js +29 -0
  20. package/components/ui-tabs/ui-tabs.html +6 -1
  21. package/components/ui-text/ui-text.html +31 -6
  22. package/components/ui-tooltip/ui-tooltip.html +60 -0
  23. package/components/ui-tooltip/ui-tooltip.js +1 -1
  24. package/dist/index.js +46 -43
  25. package/docs/README.md +34 -4
  26. package/docs/card.html +16 -2
  27. package/docs/card.js +17 -2
  28. package/docs/catalog.json +1154 -144
  29. package/docs/customizer-render.mjs +35 -9
  30. package/docs/customizer.js +83 -20
  31. package/docs/documentation.css +9 -1
  32. package/docs/index.d.ts +4 -2
  33. package/docs/index.mjs +1 -1
  34. package/docs/preview.js +2 -0
  35. package/docs/render.mjs +15 -6
  36. package/docs/site.mjs +50 -9
  37. package/docs/theme-session.mjs +51 -0
  38. package/docs/theme.mjs +134 -15
  39. package/docs/value-editors.mjs +33 -0
  40. package/package.json +2 -2
  41. package/styles/ui-button.css +45 -45
  42. package/styles/ui-card.css +47 -0
  43. package/styles/ui-curve-editor.css +109 -0
  44. package/styles/ui-dialog.css +132 -0
  45. package/styles/ui-icon-button.css +63 -20
  46. package/styles/ui-menu.css +72 -0
  47. package/styles/ui-number-input.css +34 -0
  48. package/styles/ui-popover.css +74 -0
  49. package/styles/ui-slider.css +53 -0
  50. package/styles/ui-tabs.css +6 -1
  51. package/styles/ui-text.css +23 -1
  52. package/styles/ui-tooltip.css +72 -0
  53. package/theme-system.css +26 -10
  54. package/tokens.css +8 -2
  55. package/vanilla/UiButton.d.ts +1 -0
  56. package/vanilla/UiButton.js +195 -130
  57. package/vanilla/UiCard.d.ts +1 -1
  58. package/vanilla/UiCard.js +1 -1
  59. package/vanilla/UiCurveEditor.d.ts +28 -0
  60. package/vanilla/UiCurveEditor.js +134 -0
  61. package/vanilla/UiIconButton.d.ts +2 -1
  62. package/vanilla/UiIconButton.js +58 -31
  63. package/vanilla/UiNumberInput.d.ts +33 -0
  64. package/vanilla/UiNumberInput.js +79 -0
  65. package/vanilla/UiSlider.d.ts +33 -0
  66. package/vanilla/UiSlider.js +125 -0
  67. package/vanilla/UiText.d.ts +2 -2
  68. package/vanilla/UiText.js +45 -11
  69. package/vanilla/index.js +3 -0
  70. package/vue/UiButton.d.ts +6 -0
  71. package/vue/UiButton.vue +155 -56
  72. package/vue/UiCard.d.ts +2 -2
  73. package/vue/UiCard.vue +55 -5
  74. package/vue/UiCurveEditor.d.ts +53 -0
  75. package/vue/UiCurveEditor.js +2 -0
  76. package/vue/UiCurveEditor.vue +427 -0
  77. package/vue/UiDialog.vue +177 -1
  78. package/vue/UiIconButton.d.ts +8 -2
  79. package/vue/UiIconButton.vue +164 -34
  80. package/vue/UiMenu.vue +89 -0
  81. package/vue/UiNumberInput.d.ts +83 -0
  82. package/vue/UiNumberInput.js +2 -0
  83. package/vue/UiNumberInput.vue +370 -0
  84. package/vue/UiPopover.vue +92 -1
  85. package/vue/UiSlider.d.ts +83 -0
  86. package/vue/UiSlider.js +2 -0
  87. package/vue/UiSlider.vue +412 -0
  88. package/vue/UiTabs.vue +6 -1
  89. package/vue/UiText.d.ts +7 -5
  90. package/vue/UiText.vue +104 -22
  91. package/vue/UiTooltip.vue +89 -0
  92. package/vue/chunks/UiActionBar.js +1 -1
  93. package/vue/chunks/UiAffordanceScope.js +2 -2
  94. package/vue/chunks/UiAvatar.js +2 -2
  95. package/vue/chunks/UiAvatarGroup.js +2 -2
  96. package/vue/chunks/UiBadge.js +2 -2
  97. package/vue/chunks/UiBreadcrumbItem.js +2 -2
  98. package/vue/chunks/UiBreadcrumbs.js +2 -2
  99. package/vue/chunks/UiButton.js +94 -11
  100. package/vue/chunks/UiCallout.js +2 -2
  101. package/vue/chunks/UiCard.js +6 -5
  102. package/vue/chunks/UiCheckbox.js +2 -2
  103. package/vue/chunks/UiCluster.js +2 -2
  104. package/vue/chunks/UiColorPicker.js +2 -2
  105. package/vue/chunks/UiCombobox.js +2 -2
  106. package/vue/chunks/UiContainer.js +2 -2
  107. package/vue/chunks/UiContextMenu.js +2 -2
  108. package/vue/chunks/UiCover.js +2 -2
  109. package/vue/chunks/UiCurveEditor.js +413 -0
  110. package/vue/chunks/UiDescriptionItem.js +2 -2
  111. package/vue/chunks/UiDescriptionList.js +2 -2
  112. package/vue/chunks/UiDialog.js +4 -4
  113. package/vue/chunks/UiDisclosure.js +2 -2
  114. package/vue/chunks/UiEditable.js +2 -2
  115. package/vue/chunks/UiEditorBlockActions.js +2 -2
  116. package/vue/chunks/UiEditorChipEditor.js +2 -2
  117. package/vue/chunks/UiEditorCodeLanguage.js +2 -2
  118. package/vue/chunks/UiEditorFootnoteEditor.js +2 -2
  119. package/vue/chunks/UiEditorImageToolbar.js +3 -3
  120. package/vue/chunks/UiEditorInsertTableGrid.js +2 -2
  121. package/vue/chunks/UiEditorLinkCard.js +3 -3
  122. package/vue/chunks/UiEditorLinkForm.js +3 -3
  123. package/vue/chunks/UiEditorMentionMenu.js +2 -2
  124. package/vue/chunks/UiEditorMentionMenuItem.js +2 -2
  125. package/vue/chunks/UiEditorSlashMenu.js +2 -2
  126. package/vue/chunks/UiEditorSlashMenuGroup.js +2 -2
  127. package/vue/chunks/UiEditorSlashMenuItem.js +2 -2
  128. package/vue/chunks/UiEditorSurface.js +2 -2
  129. package/vue/chunks/UiEditorTableContextMenu.js +2 -2
  130. package/vue/chunks/UiEditorTableOverlay.js +2 -2
  131. package/vue/chunks/UiEditorTableToolbar.js +2 -2
  132. package/vue/chunks/UiEditorToolbar.js +2 -2
  133. package/vue/chunks/UiFloatingActionButton.js +2 -2
  134. package/vue/chunks/UiFormField.js +2 -2
  135. package/vue/chunks/UiGrid.js +2 -2
  136. package/vue/chunks/UiIcon.js +2 -2
  137. package/vue/chunks/UiIconButton.js +77 -11
  138. package/vue/chunks/UiImage.js +2 -2
  139. package/vue/chunks/UiInput.js +2 -2
  140. package/vue/chunks/UiInputGroup.js +2 -2
  141. package/vue/chunks/UiList.js +2 -2
  142. package/vue/chunks/UiListItem.js +2 -2
  143. package/vue/chunks/UiListbox.js +2 -2
  144. package/vue/chunks/UiMenu.js +3 -3
  145. package/vue/chunks/UiMenuGroup.js +2 -2
  146. package/vue/chunks/UiMenuItem.js +2 -2
  147. package/vue/chunks/UiMeter.js +2 -2
  148. package/vue/chunks/UiNavItem.js +2 -2
  149. package/vue/chunks/UiNumberInput.js +390 -0
  150. package/vue/chunks/UiPageHeader.js +2 -2
  151. package/vue/chunks/UiPopover.js +4 -4
  152. package/vue/chunks/UiRadio.js +2 -2
  153. package/vue/chunks/UiRadioGroup.js +2 -2
  154. package/vue/chunks/UiReel.js +2 -2
  155. package/vue/chunks/UiScrollArea.js +2 -2
  156. package/vue/chunks/UiSearchResultRow.js +2 -2
  157. package/vue/chunks/UiSearchShell.js +2 -2
  158. package/vue/chunks/UiSection.js +2 -2
  159. package/vue/chunks/UiSelect.js +2 -2
  160. package/vue/chunks/UiSeparator.js +2 -2
  161. package/vue/chunks/UiSidebar.js +2 -2
  162. package/vue/chunks/UiSlider.js +396 -0
  163. package/vue/chunks/UiSpinner.js +2 -2
  164. package/vue/chunks/UiStack.js +2 -2
  165. package/vue/chunks/UiStatusMessage.js +2 -2
  166. package/vue/chunks/UiSwatch.js +2 -2
  167. package/vue/chunks/UiSwitch.js +2 -2
  168. package/vue/chunks/UiSwitcher.js +2 -2
  169. package/vue/chunks/UiTable.js +2 -2
  170. package/vue/chunks/UiTabs.js +3 -3
  171. package/vue/chunks/UiText.js +53 -12
  172. package/vue/chunks/UiTextarea.js +2 -2
  173. package/vue/chunks/UiToast.js +2 -2
  174. package/vue/chunks/UiToastRegion.js +2 -2
  175. package/vue/chunks/UiTooltip.js +3 -3
  176. package/vue/chunks/UiTopBar.js +1 -1
  177. package/vue/chunks/UiTree.js +2 -2
  178. package/vue/chunks/UiTreeItem.js +2 -2
  179. package/vue/chunks/_plugin-vue_export-helper.js +68 -2
  180. package/vue/chunks/props.js +24 -1
  181. package/vue/components.css +2215 -1203
  182. package/vue/editor/index.js +623 -211
  183. package/vue/index.d.ts +3 -0
  184. package/vue/index.js +5 -2
package/vue/UiButton.vue CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  checkHydratedRoot,
8
8
  concat,
9
9
  createDispatch,
10
+ cycleCheckedComputed,
10
11
  nativeAttrs,
11
12
  preserveRootFocus,
12
13
  useComponentHost,
@@ -17,6 +18,9 @@ import {
17
18
  checkedProp,
18
19
  checkPropInput,
19
20
  type InputBindings,
21
+ inputComputed,
22
+ inputDefault,
23
+ inputRead,
20
24
  propValidityState,
21
25
  READY_INPUT,
22
26
  requireInputStatus,
@@ -79,6 +83,15 @@ const propValidityContract = {
79
83
  description: 'Deprecated alias for loading.',
80
84
  default: false,
81
85
  },
86
+ preset: {
87
+ type: { kind: 'terminal', name: 'keyword' },
88
+ required: false,
89
+ target: { attribute: 'preset' },
90
+ description:
91
+ 'A shortcut that sets appearance and tone together: primary is solid accent, standard is solid neutral, quiet is ghost neutral, and destructive is solid\n danger. A named preset takes precedence over variant and tone. Leave it at none to choose variant and tone independently.',
92
+ values: ['none', 'primary', 'standard', 'quiet', 'destructive'],
93
+ default: 'none',
94
+ },
82
95
  rel: {
83
96
  type: { kind: 'terminal', name: 'string' },
84
97
  required: false,
@@ -153,6 +166,11 @@ const props = defineProps({
153
166
  href: { type: null as unknown as PropType<string | null> },
154
167
  loading: { type: null as unknown as PropType<boolean | null> },
155
168
  pending: { type: null as unknown as PropType<boolean | null> },
169
+ preset: {
170
+ type: null as unknown as PropType<
171
+ 'none' | 'primary' | 'standard' | 'quiet' | 'destructive' | null
172
+ >,
173
+ },
156
174
  rel: { type: null as unknown as PropType<string | null> },
157
175
  shape: { type: null as unknown as PropType<'rounded' | 'pill' | null> },
158
176
  size: { type: null as unknown as PropType<'xs' | 'sm' | 'md' | 'lg' | null> },
@@ -178,6 +196,7 @@ const acceptedProps: Record<string, unknown> = {
178
196
  href: null,
179
197
  loading: false,
180
198
  pending: false,
199
+ preset: 'none',
181
200
  rel: null,
182
201
  shape: 'rounded',
183
202
  size: 'md',
@@ -193,6 +212,7 @@ const inputTracking = vuePropInputs(acceptedProps, {
193
212
  disabled: false,
194
213
  loading: false,
195
214
  pending: false,
215
+ preset: 'none',
196
216
  shape: 'rounded',
197
217
  size: 'md',
198
218
  stretch: false,
@@ -213,6 +233,8 @@ const inputTracking = vuePropInputs(acceptedProps, {
213
233
  return checkPropInput(value, { kind: 'terminal', name: 'boolean' }, true, true)
214
234
  case 'pending':
215
235
  return checkPropInput(value, { kind: 'terminal', name: 'boolean' }, true, true)
236
+ case 'preset':
237
+ return checkPropInput(value, { kind: 'terminal', name: 'keyword' }, true, true)
216
238
  case 'rel':
217
239
  return checkPropInput(value, { kind: 'terminal', name: 'string' }, true, true)
218
240
  case 'shape':
@@ -263,6 +285,11 @@ const checkedProps = computed(() => {
263
285
  props['pending'],
264
286
  props[BINDING_INPUTS_PROP],
265
287
  ) as boolean,
288
+ preset: propInputs.value<'none' | 'primary' | 'standard' | 'quiet' | 'destructive' | null>(
289
+ 'preset',
290
+ props['preset'],
291
+ props[BINDING_INPUTS_PROP],
292
+ ) as 'none' | 'primary' | 'standard' | 'quiet' | 'destructive',
266
293
  rel: propInputs.value<string | null>('rel', props['rel'], props[BINDING_INPUTS_PROP]),
267
294
  shape: propInputs.value<'rounded' | 'pill' | null>(
268
295
  'shape',
@@ -317,6 +344,68 @@ const hydrationInstance = getCurrentInstance()
317
344
  const rootArmElement = useTemplateRef<HTMLElement>('@html-next/root')
318
345
  const root = rootArmElement
319
346
  preserveRootFocus(root)
347
+ const appearance: ReturnType<typeof inputComputed<any>> = inputComputed<any>(
348
+ () =>
349
+ (({
350
+ none: inputRead(checkedProps.value.variant, propInputs.status('variant')),
351
+ primary: 'solid',
352
+ standard: 'solid',
353
+ quiet: 'ghost',
354
+ destructive: 'solid',
355
+ }) as Record<string, any>)[
356
+ inputRead(checkedProps.value.preset, propInputs.status('preset'))
357
+ ] as any,
358
+ (read) => {
359
+ const value = cycleCheckedComputed(read)
360
+ return { get: () => value.value }
361
+ },
362
+ )
363
+ let colorTonePrevious: any = null
364
+ const colorTone: ReturnType<typeof inputComputed<any>> = inputComputed<any>(
365
+ () => {
366
+ return ((objectValue: any, indexValue: any) =>
367
+ objectValue === Symbol.for('html-next.invalid-result')
368
+ || indexValue === Symbol.for('html-next.invalid-result')
369
+ ? Symbol.for('html-next.invalid-result')
370
+ : objectValue[indexValue])(
371
+ (() => {
372
+ const value = {
373
+ none: ((objectValue: any, indexValue: any) =>
374
+ objectValue === Symbol.for('html-next.invalid-result')
375
+ || indexValue === Symbol.for('html-next.invalid-result')
376
+ ? Symbol.for('html-next.invalid-result')
377
+ : objectValue[indexValue])(
378
+ {
379
+ true: 'danger',
380
+ false: inputRead(checkedProps.value.tone, propInputs.status('tone')),
381
+ },
382
+ concat(
383
+ inputRead(checkedProps.value.variant, propInputs.status('variant')) === 'danger',
384
+ ),
385
+ ),
386
+ primary: 'accent',
387
+ standard: 'neutral',
388
+ quiet: 'neutral',
389
+ destructive: 'danger',
390
+ }
391
+ return Object.values(value).some((entry: unknown) =>
392
+ entry === Symbol.for('html-next.invalid-result')
393
+ )
394
+ ? Symbol.for('html-next.invalid-result')
395
+ : value
396
+ })(),
397
+ inputRead(checkedProps.value.preset, propInputs.status('preset')),
398
+ ) as any
399
+ },
400
+ (read) => {
401
+ const value = cycleCheckedComputed(read)
402
+ return { get: () => value.value }
403
+ },
404
+ next =>
405
+ (next as unknown) === Symbol.for('html-next.invalid-result')
406
+ ? colorTonePrevious
407
+ : (colorTonePrevious = next),
408
+ )
320
409
  let guardedPrevious: any = null
321
410
  const guarded = computed(() => {
322
411
  const candidate: any = ((objectValue: any, indexValue: any) =>
@@ -596,9 +685,9 @@ const guardedBinding7 = computed(() => {
596
685
  ))
597
686
  })
598
687
  checkHydratedRoot(
599
- (checkedProps.value.variant === 'card' && checkedProps.value.as === 'a')
688
+ (appearance.get() === 'card' && checkedProps.value.as === 'a')
600
689
  ? 'a'
601
- : ((checkedProps.value.variant === 'card')
690
+ : ((appearance.get() === 'card')
602
691
  ? 'button'
603
692
  : ((checkedProps.value.as === 'a') ? 'a' : ('button'))),
604
693
  'ui-button',
@@ -614,11 +703,6 @@ const hostState = computed(() =>
614
703
  checkedProps.value.size != null && `size=${encodeURIComponent(checkedProps.value.size)}`,
615
704
  checkedProps.value.shape && 'shape',
616
705
  checkedProps.value.shape != null && `shape=${encodeURIComponent(checkedProps.value.shape)}`,
617
- checkedProps.value.variant && 'variant',
618
- checkedProps.value.variant != null
619
- && `variant=${encodeURIComponent(checkedProps.value.variant)}`,
620
- checkedProps.value.tone && 'tone',
621
- checkedProps.value.tone != null && `tone=${encodeURIComponent(checkedProps.value.tone)}`,
622
706
  checkedProps.value.loading && 'loading',
623
707
  checkedProps.value.pending && 'pending',
624
708
  ].filter(Boolean).join(' ')
@@ -651,6 +735,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
651
735
  'href',
652
736
  'loading',
653
737
  'pending',
738
+ 'preset',
654
739
  'rel',
655
740
  'shape',
656
741
  'size',
@@ -662,16 +747,20 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
662
747
  ],
663
748
  propValidity: (name: string) =>
664
749
  propValidityState({ contract: propValidityContract, values: { ...props } }, name),
750
+ computed: { appearance, colorTone },
751
+ availability: { appearance: () => appearance.status(), colorTone: () => colorTone.status() },
665
752
  })
666
753
  </script>
667
754
 
668
755
  <template>
669
756
  <a
670
- v-if="checkedProps.variant === 'card' && checkedProps.as === 'a'"
757
+ v-if="appearance.get() === 'card' && checkedProps.as === 'a'"
671
758
  class="ui-button"
672
759
  v-bind="nativeAttrs($attrs)"
673
760
  data-hn
674
761
  data-hn-ui-button
762
+ :data-appearance="attribute(appearance.get())"
763
+ :data-tone="attribute(colorTone.get())"
675
764
  :href="guarded"
676
765
  :target="checkedProps.target ?? undefined"
677
766
  :rel="checkedProps.rel ?? undefined"
@@ -685,6 +774,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
685
774
  :data-ui-button-prop-href="reflectedProp('href', 'href', checkedProps.href, undefined, false)"
686
775
  :data-ui-button-prop-loading="reflectedProp('loading', 'loading', checkedProps.loading, undefined, false)"
687
776
  :data-ui-button-prop-pending="reflectedProp('pending', 'pending', checkedProps.pending, undefined, false)"
777
+ :data-ui-button-prop-preset="reflectedProp('preset', 'preset', checkedProps.preset, undefined, false)"
688
778
  :data-ui-button-prop-rel="reflectedProp('rel', 'rel', checkedProps.rel, undefined, false)"
689
779
  :data-ui-button-prop-shape="reflectedProp('shape', 'shape', checkedProps.shape, undefined, false)"
690
780
  :data-ui-button-prop-size="reflectedProp('size', 'size', checkedProps.size, undefined, false)"
@@ -710,11 +800,13 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
710
800
  aria-hidden="true"
711
801
  /></slot></span></a>
712
802
  <button
713
- v-else-if="checkedProps.variant === 'card'"
803
+ v-else-if="appearance.get() === 'card'"
714
804
  class="ui-button"
715
805
  v-bind="nativeAttrs($attrs)"
716
806
  data-hn
717
807
  data-hn-ui-button
808
+ :data-appearance="attribute(appearance.get())"
809
+ :data-tone="attribute(colorTone.get())"
718
810
  :type="checkedProps.type ?? undefined"
719
811
  :disabled="checkedProps.disabled ?? undefined"
720
812
  :aria-disabled="guardedBinding3"
@@ -726,6 +818,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
726
818
  :data-ui-button-prop-href="reflectedProp('href', 'href', checkedProps.href, undefined, false)"
727
819
  :data-ui-button-prop-loading="reflectedProp('loading', 'loading', checkedProps.loading, undefined, false)"
728
820
  :data-ui-button-prop-pending="reflectedProp('pending', 'pending', checkedProps.pending, undefined, false)"
821
+ :data-ui-button-prop-preset="reflectedProp('preset', 'preset', checkedProps.preset, undefined, false)"
729
822
  :data-ui-button-prop-rel="reflectedProp('rel', 'rel', checkedProps.rel, undefined, false)"
730
823
  :data-ui-button-prop-shape="reflectedProp('shape', 'shape', checkedProps.shape, undefined, false)"
731
824
  :data-ui-button-prop-size="reflectedProp('size', 'size', checkedProps.size, undefined, false)"
@@ -758,6 +851,8 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
758
851
  v-bind="nativeAttrs($attrs)"
759
852
  data-hn
760
853
  data-hn-ui-button
854
+ :data-appearance="attribute(appearance.get())"
855
+ :data-tone="attribute(colorTone.get())"
761
856
  :href="guardedBinding4"
762
857
  :target="checkedProps.target ?? undefined"
763
858
  :rel="checkedProps.rel ?? undefined"
@@ -771,6 +866,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
771
866
  :data-ui-button-prop-href="reflectedProp('href', 'href', checkedProps.href, undefined, false)"
772
867
  :data-ui-button-prop-loading="reflectedProp('loading', 'loading', checkedProps.loading, undefined, false)"
773
868
  :data-ui-button-prop-pending="reflectedProp('pending', 'pending', checkedProps.pending, undefined, false)"
869
+ :data-ui-button-prop-preset="reflectedProp('preset', 'preset', checkedProps.preset, undefined, false)"
774
870
  :data-ui-button-prop-rel="reflectedProp('rel', 'rel', checkedProps.rel, undefined, false)"
775
871
  :data-ui-button-prop-shape="reflectedProp('shape', 'shape', checkedProps.shape, undefined, false)"
776
872
  :data-ui-button-prop-size="reflectedProp('size', 'size', checkedProps.size, undefined, false)"
@@ -795,6 +891,8 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
795
891
  v-bind="nativeAttrs($attrs)"
796
892
  data-hn
797
893
  data-hn-ui-button
894
+ :data-appearance="attribute(appearance.get())"
895
+ :data-tone="attribute(colorTone.get())"
798
896
  :type="checkedProps.type ?? undefined"
799
897
  :disabled="checkedProps.disabled ?? undefined"
800
898
  :aria-disabled="guardedBinding7"
@@ -806,6 +904,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
806
904
  :data-ui-button-prop-href="reflectedProp('href', 'href', checkedProps.href, undefined, false)"
807
905
  :data-ui-button-prop-loading="reflectedProp('loading', 'loading', checkedProps.loading, undefined, false)"
808
906
  :data-ui-button-prop-pending="reflectedProp('pending', 'pending', checkedProps.pending, undefined, false)"
907
+ :data-ui-button-prop-preset="reflectedProp('preset', 'preset', checkedProps.preset, undefined, false)"
809
908
  :data-ui-button-prop-rel="reflectedProp('rel', 'rel', checkedProps.rel, undefined, false)"
810
909
  :data-ui-button-prop-shape="reflectedProp('shape', 'shape', checkedProps.shape, undefined, false)"
811
910
  :data-ui-button-prop-size="reflectedProp('size', 'size', checkedProps.size, undefined, false)"
@@ -1039,7 +1138,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1039
1138
  flex: none;
1040
1139
  vertical-align: middle;
1041
1140
  }
1042
- :global(:scope:not([variant="link"]):has(.badge:not(:empty)):where([data-hn-ui-button])) {
1141
+ :global(:scope:not([data-appearance="link"]):has(.badge:not(:empty)):where([data-hn-ui-button])) {
1043
1142
  padding-block: var(--ui-space-0-5) !important;
1044
1143
  }
1045
1144
 
@@ -1083,7 +1182,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1083
1182
  var(--ui-action-inset-lg, var(--ui-space-4)) !important;
1084
1183
  font-size: var(--ui-font-size-md);
1085
1184
  }
1086
- :global(:scope[data-ui-button-state~="variant=card"]:where([data-hn-ui-button])) {
1185
+ :global(:scope[data-appearance="card"]:where([data-hn-ui-button])) {
1087
1186
  display: grid !important;
1088
1187
  grid-template-columns: auto minmax(0, 1fr) auto;
1089
1188
  align-content: center !important;
@@ -1096,10 +1195,10 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1096
1195
  box-shadow: none;
1097
1196
  background-image: none;
1098
1197
  }
1099
- :global(:scope[data-ui-button-state~="variant=card"][data-ui-button-state~="size=lg"]:where([data-hn-ui-button])) {
1198
+ :global(:scope[data-appearance="card"][size="lg"]:where([data-hn-ui-button])) {
1100
1199
  min-block-size: max(var(--ui-control-min-block-size), var(--ui-control-size-lg));
1101
1200
  }
1102
- :global(:scope[data-ui-button-state~="variant=card"]:has(.card-icon:empty):where([data-hn-ui-button])) {
1201
+ :global(:scope[data-appearance="card"]:has(.card-icon:empty):where([data-hn-ui-button])) {
1103
1202
  grid-template-columns: minmax(0, 1fr) auto;
1104
1203
  }
1105
1204
  :global(.card-icon:where([data-hn-ui-button])) {
@@ -1121,11 +1220,11 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1121
1220
  border-color: var(--ui-button-hover-border, var(--_tone-hover));
1122
1221
  background-color: var(--ui-button-hover-surface, oklch(from var(--_tone) l c h / 12%));
1123
1222
  }
1124
- :global(:scope[data-ui-button-state~="variant=card"][data-ui-button-state~="tone=neutral"]:where([data-hn-ui-button])) {
1223
+ :global(:scope[data-appearance="card"][data-tone="neutral"]:where([data-hn-ui-button])) {
1125
1224
  border-color: var(--ui-button-border, var(--ui-border));
1126
1225
  }
1127
1226
 
1128
- :global(:scope[data-ui-button-state~="variant=card"][data-ui-button-state~="tone=neutral"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1227
+ :global(:scope[data-appearance="card"][data-tone="neutral"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1129
1228
  border-color: var(--ui-button-hover-border, var(--ui-border-strong));
1130
1229
  }
1131
1230
  :global(:scope:active:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
@@ -1135,26 +1234,26 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1135
1234
  box-shadow: var(--ui-pressed);
1136
1235
  }
1137
1236
 
1138
- :global(:scope[data-ui-button-state~="variant=solid"]:where([data-hn-ui-button])),
1139
- :global(:scope[data-ui-button-state~="variant=danger"]:where([data-hn-ui-button])) {
1237
+ :global(:scope[data-appearance="solid"]:where([data-hn-ui-button])),
1238
+ :global(:scope[data-appearance="danger"]:where([data-hn-ui-button])) {
1140
1239
  border-color: var(--_tone);
1141
1240
  background-color: var(--_tone);
1142
1241
  color: var(--_on-tone);
1143
1242
  box-shadow: var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow)));
1144
1243
  }
1145
1244
 
1146
- :global(:is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1245
+ :global(:is(:scope[data-appearance="solid"], :scope[data-appearance="danger"]):hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1147
1246
  background-color: var(--_tone-hover);
1148
1247
  border-color: var(--_tone-hover);
1149
1248
  }
1150
1249
 
1151
- :global(:is(:scope[data-ui-button-state~="variant=solid"], :scope[data-ui-button-state~="variant=danger"]):active:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1250
+ :global(:is(:scope[data-appearance="solid"], :scope[data-appearance="danger"]):active:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1152
1251
  background-color: var(--_tone-active);
1153
1252
  border-color: var(--_tone-active);
1154
1253
  background-image: none;
1155
1254
  box-shadow: var(--ui-pressed);
1156
1255
  }
1157
- :global(:scope[data-ui-button-state~="tone=neutral"]:where([data-hn-ui-button])) {
1256
+ :global(:scope[data-tone="neutral"]:where([data-hn-ui-button])) {
1158
1257
  --_hue: var(--ui-text);
1159
1258
  --_hue-hover: var(--ui-text);
1160
1259
  --_hue-active: var(--ui-text);
@@ -1162,39 +1261,39 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1162
1261
  --_on-hue: var(--ui-surface);
1163
1262
  }
1164
1263
 
1165
- :global(:scope[data-ui-button-state~="tone=danger"]:where([data-hn-ui-button])),
1166
- :global(:scope[data-ui-button-state~="variant=danger"]:where([data-hn-ui-button])) {
1264
+ :global(:scope[data-tone="danger"]:where([data-hn-ui-button])),
1265
+ :global(:scope[data-appearance="danger"]:where([data-hn-ui-button])) {
1167
1266
  --_hue: var(--ui-danger);
1168
1267
  --_hue-hover: var(--ui-danger-hover);
1169
- --_hue-active: var(--ui-danger-hover);
1170
- --_hue-text: var(--ui-danger-hover);
1268
+ --_hue-active: var(--ui-danger-active, var(--ui-danger-hover));
1269
+ --_hue-text: var(--ui-danger-subtle-text);
1171
1270
  --_on-hue: var(--ui-on-danger);
1172
1271
  }
1173
1272
 
1174
- :global(:scope[data-ui-button-state~="tone=success"]:where([data-hn-ui-button])) {
1273
+ :global(:scope[data-tone="success"]:where([data-hn-ui-button])) {
1175
1274
  --_hue: var(--ui-success);
1176
- --_hue-hover: color-mix(in srgb, var(--ui-success) 85%, #000);
1177
- --_hue-active: color-mix(in srgb, var(--ui-success) 75%, #000);
1178
- --_hue-text: color-mix(in srgb, var(--ui-success) 85%, #000);
1179
- --_on-hue: var(--ui-surface);
1275
+ --_hue-hover: var(--ui-success-hover);
1276
+ --_hue-active: var(--ui-success-active);
1277
+ --_hue-text: var(--ui-success-subtle-text);
1278
+ --_on-hue: var(--ui-success-on-strong);
1180
1279
  }
1181
1280
 
1182
- :global(:scope[data-ui-button-state~="tone=warning"]:where([data-hn-ui-button])) {
1281
+ :global(:scope[data-tone="warning"]:where([data-hn-ui-button])) {
1183
1282
  --_hue: var(--ui-warning);
1184
- --_hue-hover: color-mix(in srgb, var(--ui-warning) 85%, #000);
1185
- --_hue-active: color-mix(in srgb, var(--ui-warning) 75%, #000);
1186
- --_hue-text: color-mix(in srgb, var(--ui-warning) 85%, #000);
1187
- --_on-hue: var(--ui-surface);
1283
+ --_hue-hover: var(--ui-warning-hover);
1284
+ --_hue-active: var(--ui-warning-active);
1285
+ --_hue-text: var(--ui-warning-subtle-text);
1286
+ --_on-hue: var(--ui-warning-on-strong);
1188
1287
  }
1189
1288
 
1190
- :global(:scope[data-ui-button-state~="tone=info"]:where([data-hn-ui-button])) {
1289
+ :global(:scope[data-tone="info"]:where([data-hn-ui-button])) {
1191
1290
  --_hue: var(--ui-info);
1192
- --_hue-hover: color-mix(in srgb, var(--ui-info) 85%, #000);
1193
- --_hue-active: color-mix(in srgb, var(--ui-info) 75%, #000);
1194
- --_hue-text: color-mix(in srgb, var(--ui-info) 85%, #000);
1195
- --_on-hue: var(--ui-surface);
1291
+ --_hue-hover: var(--ui-info-hover);
1292
+ --_hue-active: var(--ui-info-active);
1293
+ --_hue-text: var(--ui-info-subtle-text);
1294
+ --_on-hue: var(--ui-info-on-strong);
1196
1295
  }
1197
- :global(:scope[data-ui-button-state~="variant=field"]:where([data-hn-ui-button])) {
1296
+ :global(:scope[data-appearance="field"]:where([data-hn-ui-button])) {
1198
1297
  --_ui-field-shadow: var(--ui-shadow-sm);
1199
1298
  border-color: var(--ui-button-border, var(--ui-control-border, var(--ui-border-strong)));
1200
1299
  border-radius: var(--ui-button-radius, var(--ui-field-radius, var(--ui-radius-md)));
@@ -1207,7 +1306,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1207
1306
  box-shadow: var(--ui-button-shadow, var(--_ui-field-shadow));
1208
1307
  }
1209
1308
 
1210
- :global(:scope[data-ui-button-state~="variant=field"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1309
+ :global(:scope[data-appearance="field"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1211
1310
  border-color: var(
1212
1311
  --ui-button-hover-border,
1213
1312
  var(--ui-control-border-hover, var(--ui-text-secondary))
@@ -1218,28 +1317,28 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1218
1317
  );
1219
1318
  }
1220
1319
 
1221
- :global(:scope[data-ui-button-state~="variant=field"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1320
+ :global(:scope[data-appearance="field"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1222
1321
  --_ui-field-shadow: var(--ui-pressed);
1223
1322
  }
1224
1323
 
1225
- :global(:scope[data-ui-button-state~="variant=field"]:focus-visible:where([data-hn-ui-button])) {
1324
+ :global(:scope[data-appearance="field"]:focus-visible:where([data-hn-ui-button])) {
1226
1325
  border-color: var(--ui-control-focus, var(--ui-accent-solid));
1227
1326
  box-shadow:
1228
1327
  var(--ui-button-shadow, var(--_ui-field-shadow)),
1229
1328
  var(--ui-control-focus-halo-shadow);
1230
1329
  }
1231
1330
 
1232
- :global(:scope[data-ui-button-state~="variant=ghost"]:where([data-hn-ui-button])) {
1331
+ :global(:scope[data-appearance="ghost"]:where([data-hn-ui-button])) {
1233
1332
  border-color: transparent;
1234
1333
  background: transparent;
1235
1334
  box-shadow: none;
1236
1335
  color: var(--ui-button-ghost-text, var(--_tone-text));
1237
1336
  }
1238
- :global(:scope[data-ui-button-state~="variant=ghost"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1337
+ :global(:scope[data-appearance="ghost"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1239
1338
  background-color: var(--ui-button-ghost-hover-surface, oklch(from var(--_tone) l c h / 10%));
1240
1339
  border-color: transparent;
1241
1340
  }
1242
- :global(:scope[data-ui-button-state~="variant=ghost"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1341
+ :global(:scope[data-appearance="ghost"]:is(:active, [aria-expanded="true"]):not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1243
1342
  background-color: var(
1244
1343
  --ui-button-ghost-active-surface,
1245
1344
  color-mix(in oklch, var(--ui-surface), var(--_tone) 3%)
@@ -1256,13 +1355,13 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1256
1355
  var(--ui-focus-halo);
1257
1356
  }
1258
1357
 
1259
- :global(:scope[data-ui-button-state~="variant=solid"]:focus-visible:where([data-hn-ui-button])) {
1358
+ :global(:scope[data-appearance="solid"]:focus-visible:where([data-hn-ui-button])) {
1260
1359
  box-shadow:
1261
1360
  var(--ui-button-solid-shadow, var(--ui-action-shadow, var(--_ui-action-shadow))),
1262
1361
  var(--ui-focus-halo);
1263
1362
  }
1264
1363
 
1265
- :global(:is(:scope[data-ui-button-state~="variant=ghost"], :scope[data-ui-button-state~="variant=link"], :scope[data-ui-button-state~="variant=card"]):focus-visible:where([data-hn-ui-button])) {
1364
+ :global(:is(:scope[data-appearance="ghost"], :scope[data-appearance="link"], :scope[data-appearance="card"]):focus-visible:where([data-hn-ui-button])) {
1266
1365
  box-shadow: var(--ui-focus-halo);
1267
1366
  }
1268
1367
  :global(:scope:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])):where([data-hn-ui-button])) {
@@ -1279,7 +1378,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1279
1378
  :global(:is(:scope[data-ui-button-state~="loading"], :scope[data-ui-button-state~="pending"]):focus-visible:where([data-hn-ui-button])) {
1280
1379
  box-shadow: var(--ui-focus-halo);
1281
1380
  }
1282
- :global(:scope[data-ui-button-state~="variant=ghost"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])):where([data-hn-ui-button])) {
1381
+ :global(:scope[data-appearance="ghost"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])):where([data-hn-ui-button])) {
1283
1382
  background-color: var(--ui-disabled-surface);
1284
1383
  border-color: transparent;
1285
1384
  }
@@ -1290,14 +1389,14 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1290
1389
  }
1291
1390
  }
1292
1391
  :global(html[data-ui-input-modality="touch"]
1293
- :scope[data-ui-button-state~="variant=link"]:where([data-hn-ui-button])),
1392
+ :scope[data-appearance="link"]:where([data-hn-ui-button])),
1294
1393
  :global(html[data-ui-input-modality="touch"]
1295
1394
  :scope[data-ui-button-state~="size=xs"]:where([data-hn-ui-button])) {
1296
1395
  position: relative;
1297
1396
  }
1298
1397
 
1299
1398
  :global(html[data-ui-input-modality="touch"]
1300
- :scope[data-ui-button-state~="variant=link"]:where([data-hn-ui-button])::after),
1399
+ :scope[data-appearance="link"]:where([data-hn-ui-button])::after),
1301
1400
  :global(html[data-ui-input-modality="touch"]
1302
1401
  :scope[data-ui-button-state~="size=xs"]:where([data-hn-ui-button])::after) {
1303
1402
  position: absolute;
@@ -1307,7 +1406,7 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1307
1406
  transform: translate(-50%, -50%);
1308
1407
  content: "";
1309
1408
  }
1310
- :global(:scope[data-ui-button-state~="variant=link"]:where([data-hn-ui-button])) {
1409
+ :global(:scope[data-appearance="link"]:where([data-hn-ui-button])) {
1311
1410
  display: inline !important;
1312
1411
  min-block-size: 0;
1313
1412
  padding: 0 !important;
@@ -1326,24 +1425,24 @@ useComponentHost(() => import('../components/ui-button/ui-button.js'), {
1326
1425
  text-decoration-color var(--ui-motion-fast) var(--ui-motion-ease);
1327
1426
  }
1328
1427
 
1329
- :global(:scope[data-ui-button-state~="variant=link"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1428
+ :global(:scope[data-appearance="link"]:hover:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1330
1429
  color: var(--ui-button-link-hover-text, var(--ui-text-primary));
1331
1430
  text-decoration-color: currentColor;
1332
1431
  background: none;
1333
1432
  transform: none;
1334
1433
  }
1335
1434
 
1336
- :global(:scope[data-ui-button-state~="variant=link"]:active:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1435
+ :global(:scope[data-appearance="link"]:active:not(:disabled, [aria-disabled="true"]):where([data-hn-ui-button])) {
1337
1436
  background: none;
1338
1437
  transform: none;
1339
1438
  }
1340
1439
 
1341
- :global(:scope[data-ui-button-state~="variant=link"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])):where([data-hn-ui-button])) {
1440
+ :global(:scope[data-appearance="link"]:is(:disabled, [aria-disabled="true"]:not([aria-busy="true"])):where([data-hn-ui-button])) {
1342
1441
  background: none;
1343
1442
  border-color: transparent;
1344
1443
  }
1345
1444
 
1346
- :global(:scope[data-ui-button-state~="variant=link"]:focus-visible:where([data-hn-ui-button])) {
1445
+ :global(:scope[data-appearance="link"]:focus-visible:where([data-hn-ui-button])) {
1347
1446
  box-shadow: none;
1348
1447
  /* Fallback keeps the ring if the token is missing: an unresolved var() would void the outline. */
1349
1448
  outline: var(--ui-focus-width) solid var(--ui-focus-ring);
package/vue/UiCard.d.ts CHANGED
@@ -24,7 +24,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
24
24
  type: PropType<"neutral" | "accent" | "info" | "success" | "warning" | "danger" | null>;
25
25
  };
26
26
  variant: {
27
- type: PropType<"outlined" | "subtle" | "elevated" | null>;
27
+ type: PropType<"outlined" | "subtle" | "elevated" | "glass" | null>;
28
28
  };
29
29
  "\0htmlNextInputStatus": {
30
30
  type: PropType<InputBindings>;
@@ -43,7 +43,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
43
43
  type: PropType<"neutral" | "accent" | "info" | "success" | "warning" | "danger" | null>;
44
44
  };
45
45
  variant: {
46
- type: PropType<"outlined" | "subtle" | "elevated" | null>;
46
+ type: PropType<"outlined" | "subtle" | "elevated" | "glass" | null>;
47
47
  };
48
48
  "\0htmlNextInputStatus": {
49
49
  type: PropType<InputBindings>;
package/vue/UiCard.vue CHANGED
@@ -60,8 +60,8 @@ const propValidityContract = {
60
60
  required: false,
61
61
  target: { attribute: 'variant' },
62
62
  description:
63
- 'The surface. outlined is a bordered panel on the page; subtle is a quiet filled one with no border, for supporting details set apart from the flow;\n elevated floats above the page with a shadow, for a view\'s one card, such as sign-in.',
64
- values: ['outlined', 'subtle', 'elevated'],
63
+ 'The surface. outlined is a bordered panel on the page; subtle is a quiet filled one with no border, for supporting details set apart from the flow;\n elevated floats above the page with a shadow, for a view\'s one card, such as sign-in. glass frames an opaque readable content plane with frosted material;\n shared glassiness and surface separation govern its treatment.',
64
+ values: ['outlined', 'subtle', 'elevated', 'glass'],
65
65
  default: 'outlined',
66
66
  },
67
67
  },
@@ -75,7 +75,9 @@ const props = defineProps({
75
75
  'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger' | null
76
76
  >,
77
77
  },
78
- variant: { type: null as unknown as PropType<'outlined' | 'subtle' | 'elevated' | null> },
78
+ variant: {
79
+ type: null as unknown as PropType<'outlined' | 'subtle' | 'elevated' | 'glass' | null>,
80
+ },
79
81
  [BINDING_INPUTS_PROP]: { type: null as unknown as PropType<InputBindings> },
80
82
  })
81
83
  const acceptedProps: Record<string, unknown> = {
@@ -133,11 +135,11 @@ const checkedProps = computed(() => {
133
135
  props['tone'],
134
136
  props[BINDING_INPUTS_PROP],
135
137
  ) as 'neutral' | 'accent' | 'info' | 'success' | 'warning' | 'danger',
136
- variant: propInputs.value<'outlined' | 'subtle' | 'elevated' | null>(
138
+ variant: propInputs.value<'outlined' | 'subtle' | 'elevated' | 'glass' | null>(
137
139
  'variant',
138
140
  props['variant'],
139
141
  props[BINDING_INPUTS_PROP],
140
- ) as 'outlined' | 'subtle' | 'elevated',
142
+ ) as 'outlined' | 'subtle' | 'elevated' | 'glass',
141
143
  })
142
144
  })
143
145
  const inputStatus = (name: string, handlesError: boolean) => {
@@ -300,6 +302,54 @@ const hostState = computed(() =>
300
302
  box-shadow: var(--ui-shadow-lg);
301
303
  }
302
304
 
305
+ :global(:scope[data-ui-card-state~="variant=glass"]:where([data-hn-ui-card])) {
306
+ --_ui-panel-glass: clamp(0, var(--ui-glassiness, 0), 1);
307
+ --_ui-panel-separation: clamp(0, var(--ui-surface-separation, 0), 1);
308
+ --_ui-panel-rim: calc(
309
+ (var(--_ui-panel-separation) + var(--_ui-panel-glass) * 0.25) * 0.65 * 8px
310
+ );
311
+ border-width: calc(var(--ui-border-width) + var(--_ui-panel-rim));
312
+ border-color: transparent;
313
+ background:
314
+ linear-gradient(var(--_ui-card-surface), var(--_ui-card-surface)) padding-box,
315
+ linear-gradient(
316
+ var(--ui-material-glass, var(--ui-surface-raised)),
317
+ var(--ui-material-glass, var(--ui-surface-raised))
318
+ ) border-box,
319
+ var(--_ui-card-surface) padding-box;
320
+ box-shadow:
321
+ var(--ui-shadow-lg),
322
+ inset 0 0 0 var(--ui-border-width) var(--ui-material-edge, var(--ui-border-strong));
323
+ backdrop-filter: blur(calc(var(--_ui-panel-glass) * 0.65 * 18px))
324
+ saturate(calc(1 + var(--_ui-panel-glass) * 0.65 * 0.18));
325
+ -webkit-backdrop-filter: blur(calc(var(--_ui-panel-glass) * 0.65 * 18px))
326
+ saturate(calc(1 + var(--_ui-panel-glass) * 0.65 * 0.18));
327
+ }
328
+ @supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
329
+ :global(:scope[data-ui-card-state~="variant=glass"]:where([data-hn-ui-card])) {
330
+ background: var(--_ui-card-surface);
331
+ }
332
+ }
333
+ @media (prefers-reduced-transparency: reduce) {
334
+ :global(:scope[data-ui-card-state~="variant=glass"]:where([data-hn-ui-card])) {
335
+ background: var(--_ui-card-surface);
336
+ border-width: var(--ui-border-width);
337
+ border-color: var(--ui-border-strong);
338
+ backdrop-filter: none;
339
+ -webkit-backdrop-filter: none;
340
+ }
341
+ }
342
+ @media (forced-colors: active) {
343
+ :global(:scope[data-ui-card-state~="variant=glass"]:where([data-hn-ui-card])) {
344
+ background: Canvas;
345
+ color: CanvasText;
346
+ border: var(--ui-border-width) solid CanvasText;
347
+ box-shadow: none;
348
+ backdrop-filter: none;
349
+ -webkit-backdrop-filter: none;
350
+ }
351
+ }
352
+
303
353
  :global(:scope[data-ui-card-state~="tone=accent"]:where([data-hn-ui-card])) {
304
354
  border-color: color-mix(in srgb, var(--ui-accent) 25%, var(--ui-border-default));
305
355
  --_ui-card-surface: color-mix(in srgb, var(--ui-accent) 6%, var(--ui-surface-default));