@nuxt/ui 3.0.0-alpha.12 → 3.0.0-alpha.13

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 (123) hide show
  1. package/.nuxt/ui/accordion.ts +2 -2
  2. package/.nuxt/ui/alert.ts +46 -36
  3. package/.nuxt/ui/avatar-group.ts +1 -1
  4. package/.nuxt/ui/avatar.ts +3 -3
  5. package/.nuxt/ui/badge.ts +37 -28
  6. package/.nuxt/ui/breadcrumb.ts +5 -5
  7. package/.nuxt/ui/button.ts +42 -42
  8. package/.nuxt/ui/calendar.ts +15 -15
  9. package/.nuxt/ui/card.ts +27 -1
  10. package/.nuxt/ui/carousel.ts +2 -2
  11. package/.nuxt/ui/checkbox.ts +18 -18
  12. package/.nuxt/ui/chip.ts +8 -8
  13. package/.nuxt/ui/color-picker.ts +2 -2
  14. package/.nuxt/ui/command-palette.ts +12 -12
  15. package/.nuxt/ui/container.ts +1 -1
  16. package/.nuxt/ui/context-menu.ts +32 -32
  17. package/.nuxt/ui/drawer.ts +72 -11
  18. package/.nuxt/ui/dropdown-menu.ts +33 -33
  19. package/.nuxt/ui/form-field.ts +6 -6
  20. package/.nuxt/ui/input-menu.ts +41 -41
  21. package/.nuxt/ui/input-number.ts +20 -20
  22. package/.nuxt/ui/input.ts +23 -23
  23. package/.nuxt/ui/kbd.ts +4 -4
  24. package/.nuxt/ui/link.ts +3 -3
  25. package/.nuxt/ui/modal.ts +5 -5
  26. package/.nuxt/ui/navigation-menu.ts +77 -78
  27. package/.nuxt/ui/pin-input.ts +20 -20
  28. package/.nuxt/ui/popover.ts +2 -2
  29. package/.nuxt/ui/progress.ts +17 -17
  30. package/.nuxt/ui/radio-group.ts +20 -20
  31. package/.nuxt/ui/select-menu.ts +33 -32
  32. package/.nuxt/ui/select.ts +31 -31
  33. package/.nuxt/ui/separator.ts +8 -8
  34. package/.nuxt/ui/skeleton.ts +1 -1
  35. package/.nuxt/ui/slideover.ts +4 -4
  36. package/.nuxt/ui/slider.ts +16 -16
  37. package/.nuxt/ui/stepper.ts +18 -18
  38. package/.nuxt/ui/switch.ts +20 -20
  39. package/.nuxt/ui/table.ts +16 -16
  40. package/.nuxt/ui/tabs.ts +33 -33
  41. package/.nuxt/ui/textarea.ts +23 -23
  42. package/.nuxt/ui/toast.ts +42 -32
  43. package/.nuxt/ui/toaster.ts +4 -4
  44. package/.nuxt/ui/tooltip.ts +2 -2
  45. package/.nuxt/ui.css +90 -0
  46. package/README.md +2 -2
  47. package/cli/package.json +1 -1
  48. package/cli/templates.mjs +1 -1
  49. package/dist/client/devtools/200.html +1 -1
  50. package/dist/client/devtools/404.html +1 -1
  51. package/dist/client/devtools/_nuxt/CG6Dc4jp.js +1 -0
  52. package/dist/client/devtools/_nuxt/{DYuJNiSW.js → DrNJgD08.js} +1 -1
  53. package/dist/client/devtools/_nuxt/{DLmPhbaq.js → ElqrUh1r.js} +1 -1
  54. package/dist/client/devtools/_nuxt/builds/latest.json +1 -1
  55. package/dist/client/devtools/_nuxt/builds/meta/255c8d0b-7281-4d74-b4b6-ec96e6721aa0.json +1 -0
  56. package/dist/client/devtools/_nuxt/entry.Hn8drx4g.css +1 -0
  57. package/dist/client/devtools/_nuxt/error-404.Dew7w9Ee.css +1 -0
  58. package/dist/client/devtools/_nuxt/error-500.Dep59i31.css +1 -0
  59. package/dist/client/devtools/_nuxt/mC2e7kOs.js +57 -0
  60. package/dist/client/devtools/index.html +1 -1
  61. package/dist/devtools/runtime/examples/CardExample.vue +3 -3
  62. package/dist/devtools/runtime/examples/CollapsibleExample.vue +1 -1
  63. package/dist/devtools/runtime/examples/ContainerExample.vue +1 -1
  64. package/dist/devtools/runtime/examples/ContextMenuExample.vue +1 -1
  65. package/dist/devtools/runtime/examples/PopoverExample.vue +1 -1
  66. package/dist/devtools/runtime/examples/TooltipExample.vue +1 -1
  67. package/dist/module.cjs +2 -1
  68. package/dist/module.json +1 -1
  69. package/dist/module.mjs +2 -1
  70. package/dist/runtime/components/Alert.vue +13 -10
  71. package/dist/runtime/components/App.vue +3 -3
  72. package/dist/runtime/components/Avatar.vue +1 -1
  73. package/dist/runtime/components/Badge.vue +5 -1
  74. package/dist/runtime/components/Calendar.vue +2 -1
  75. package/dist/runtime/components/Card.vue +6 -2
  76. package/dist/runtime/components/CommandPalette.vue +46 -39
  77. package/dist/runtime/components/ContextMenu.vue +8 -0
  78. package/dist/runtime/components/ContextMenuContent.vue +4 -2
  79. package/dist/runtime/components/Drawer.vue +7 -1
  80. package/dist/runtime/components/DropdownMenu.vue +8 -0
  81. package/dist/runtime/components/DropdownMenuContent.vue +4 -2
  82. package/dist/runtime/components/InputNumber.vue +3 -2
  83. package/dist/runtime/components/Modal.vue +15 -1
  84. package/dist/runtime/components/NavigationMenu.vue +31 -11
  85. package/dist/runtime/components/SelectMenu.vue +62 -60
  86. package/dist/runtime/components/Slideover.vue +15 -1
  87. package/dist/runtime/components/Stepper.vue +1 -1
  88. package/dist/runtime/components/Table.vue +94 -16
  89. package/dist/runtime/components/Textarea.vue +2 -1
  90. package/dist/runtime/components/Toast.vue +26 -14
  91. package/dist/runtime/components/Toaster.vue +2 -2
  92. package/dist/runtime/composables/useToast.d.ts +5 -4
  93. package/dist/runtime/composables/useToast.js +2 -2
  94. package/dist/runtime/index.css +1 -1
  95. package/dist/runtime/locale/az.d.ts +2 -0
  96. package/dist/runtime/locale/az.js +54 -0
  97. package/dist/runtime/locale/bn.d.ts +2 -0
  98. package/dist/runtime/locale/bn.js +54 -0
  99. package/dist/runtime/locale/index.d.ts +3 -0
  100. package/dist/runtime/locale/index.js +3 -0
  101. package/dist/runtime/plugins/colors.js +1 -1
  102. package/dist/runtime/types/index.d.ts +1 -0
  103. package/dist/runtime/types/index.js +1 -0
  104. package/dist/runtime/types/utils.d.ts +5 -0
  105. package/dist/runtime/vue/components/Link.vue +75 -16
  106. package/dist/shared/{ui.ClMXjgLK.cjs → ui.C5FzRWM5.cjs} +471 -364
  107. package/dist/shared/{ui.CENZ17mM.mjs → ui.DCZM2pl8.mjs} +467 -364
  108. package/dist/unplugin.cjs +44 -20
  109. package/dist/unplugin.d.cts +10 -0
  110. package/dist/unplugin.d.mts +10 -0
  111. package/dist/unplugin.d.ts +10 -0
  112. package/dist/unplugin.mjs +43 -19
  113. package/dist/vite.cjs +3 -2
  114. package/dist/vite.d.cts +2 -0
  115. package/dist/vite.d.mts +2 -0
  116. package/dist/vite.d.ts +2 -0
  117. package/dist/vite.mjs +3 -2
  118. package/package.json +60 -33
  119. package/dist/client/devtools/_nuxt/CgoQwOTV.js +0 -57
  120. package/dist/client/devtools/_nuxt/builds/meta/3184ffe2-7577-4441-af98-fe6e81c30e3a.json +0 -1
  121. package/dist/client/devtools/_nuxt/entry.ChJczkiN.css +0 -1
  122. package/dist/client/devtools/_nuxt/error-404.DyY3rYaL.css +0 -1
  123. package/dist/client/devtools/_nuxt/error-500.D_1PCaJh.css +0 -1
@@ -1 +1 @@
1
- <!DOCTYPE html><html data-capo=""><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt_ui__/devtools/_nuxt/entry.ChJczkiN.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/CgoQwOTV.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt_ui__/devtools/_nuxt/error-404.DyY3rYaL.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/DYuJNiSW.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt_ui__/devtools/_nuxt/error-500.D_1PCaJh.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/DLmPhbaq.js"><script type="module" src="/__nuxt_ui__/devtools/_nuxt/CgoQwOTV.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1738000156136,false]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt_ui__/devtools",buildId:"3184ffe2-7577-4441-af98-fe6e81c30e3a",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
1
+ <!DOCTYPE html><html data-capo=""><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/__nuxt_ui__/devtools/_nuxt/entry.Hn8drx4g.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/mC2e7kOs.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/CG6Dc4jp.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt_ui__/devtools/_nuxt/error-404.Dew7w9Ee.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/DrNJgD08.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt_ui__/devtools/_nuxt/error-500.Dep59i31.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt_ui__/devtools/_nuxt/ElqrUh1r.js"><script type="module" src="/__nuxt_ui__/devtools/_nuxt/mC2e7kOs.js" crossorigin></script><script>"use strict";(()=>{const t=window,e=document.documentElement,c=["dark","light"],n=getStorageValue("localStorage","nuxt-color-mode")||"system";let i=n==="system"?u():n;const r=e.getAttribute("data-color-mode-forced");r&&(i=r),l(i),t["__NUXT_COLOR_MODE__"]={preference:n,value:i,getColorScheme:u,addColorScheme:l,removeColorScheme:d};function l(o){const s=""+o+"",a="";e.classList?e.classList.add(s):e.className+=" "+s,a&&e.setAttribute("data-"+a,o)}function d(o){const s=""+o+"",a="";e.classList?e.classList.remove(s):e.className=e.className.replace(new RegExp(s,"g"),""),a&&e.removeAttribute("data-"+a)}function f(o){return t.matchMedia("(prefers-color-scheme"+o+")")}function u(){if(t.matchMedia&&f("").media!=="not all"){for(const o of c)if(f(":"+o).matches)return o}return"light"}})();function getStorageValue(t,e){switch(t){case"localStorage":return window.localStorage.getItem(e);case"sessionStorage":return window.sessionStorage.getItem(e);case"cookie":return getCookie(e);default:return null}}function getCookie(t){const c=("; "+window.document.cookie).split("; "+t+"=");if(c.length===2)return c.pop()?.split(";").shift()}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1739799100668,false]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt_ui__/devtools",buildId:"255c8d0b-7281-4d74-b4b6-ec96e6721aa0",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
@@ -2,11 +2,11 @@
2
2
  <div class="flex flex-col gap-4">
3
3
  <UCard class="w-96">
4
4
  <template #header>
5
- <div class="bg-[var(--ui-bg-accented)]/40 h-8" />
5
+ <div class="bg-(--ui-bg-accented)/40 h-8" />
6
6
  </template>
7
- <div class="bg-[var(--ui-bg-accented)]/40 h-32" />
7
+ <div class="bg-(--ui-bg-accented)/40 h-32" />
8
8
  <template #footer>
9
- <div class="bg-[var(--ui-bg-accented)]/40 h-8" />
9
+ <div class="bg-(--ui-bg-accented)/40 h-8" />
10
10
  </template>
11
11
  </UCard>
12
12
  </div>
@@ -2,7 +2,7 @@
2
2
  <UCollapsible class="w-48">
3
3
  <UButton label="Open Collapse" block />
4
4
  <template #content>
5
- <div class="bg-[var(--ui-bg-accented)]/40 h-60" />
5
+ <div class="bg-(--ui-bg-accented)/40 h-60" />
6
6
  </template>
7
7
  </UCollapsible>
8
8
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
2
  <UContainer>
3
- <div class="bg-[var(--ui-bg-accented)]/40 h-60 aspect-video w-72" />
3
+ <div class="bg-(--ui-bg-accented)/40 h-60 aspect-video w-72" />
4
4
  </UContainer>
5
5
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
2
  <UContextMenu>
3
- <div class="bg-[var(--ui-bg-accented)]/40 h-60 w-72" />
3
+ <div class="bg-(--ui-bg-accented)/40 h-60 w-72" />
4
4
  </UContextMenu>
5
5
  </template>
@@ -2,7 +2,7 @@
2
2
  <UPopover>
3
3
  <UButton label="Open Collapse" />
4
4
  <template #content>
5
- <div class="bg-[var(--ui-bg-accented)]/40 h-24 w-60" />
5
+ <div class="bg-(--ui-bg-accented)/40 h-24 w-60" />
6
6
  </template>
7
7
  </UPopover>
8
8
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
2
  <UTooltip>
3
- <div class="bg-[var(--ui-bg-accented)]/40 size-20" />
3
+ <div class="bg-(--ui-bg-accented)/40 size-20" />
4
4
  </UTooltip>
5
5
  </template>
package/dist/module.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const defu = require('defu');
4
4
  const kit = require('@nuxt/kit');
5
- const templates = require('./shared/ui.ClMXjgLK.cjs');
5
+ const templates = require('./shared/ui.C5FzRWM5.cjs');
6
6
  const devtoolsKit = require('@nuxt/devtools-kit');
7
7
  const sirv = require('sirv');
8
8
  require('get-port-please');
@@ -10,6 +10,7 @@ const scule = require('scule');
10
10
  const fs = require('node:fs');
11
11
  require('../dist/runtime/utils/index.js');
12
12
  require('node:url');
13
+ require('tailwindcss/colors');
13
14
 
14
15
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
16
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
package/dist/module.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "nuxt": ">=3.13.1"
6
6
  },
7
7
  "docs": "https://ui3.nuxt.dev/getting-started/installation/nuxt",
8
- "version": "3.0.0-alpha.12",
8
+ "version": "3.0.0-alpha.13",
9
9
  "builder": {
10
10
  "@nuxt/module-builder": "0.8.4",
11
11
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import defu, { defu as defu$1 } from 'defu';
2
2
  import { defineNuxtModule, createResolver, addVitePlugin, addPlugin, addComponentsDir, addImportsDir, extendPages, hasNuxtModule, installModule } from '@nuxt/kit';
3
- import { d as defaultOptions, r as resolveColors, a as getDefaultUiConfig, b as addTemplates, c as buildTemplates } from './shared/ui.CENZ17mM.mjs';
3
+ import { d as defaultOptions, r as resolveColors, a as getDefaultUiConfig, b as addTemplates, c as buildTemplates } from './shared/ui.DCZM2pl8.mjs';
4
4
  import { addCustomTab } from '@nuxt/devtools-kit';
5
5
  import sirv from 'sirv';
6
6
  import 'get-port-please';
@@ -8,6 +8,7 @@ import { kebabCase, camelCase } from 'scule';
8
8
  import fs from 'node:fs';
9
9
  import '../dist/runtime/utils/index.js';
10
10
  import 'node:url';
11
+ import 'tailwindcss/colors';
11
12
 
12
13
  const devtoolsComponentMeta = {};
13
14
  function extractDevtoolsMeta(code) {
@@ -25,10 +25,11 @@ export interface AlertProps {
25
25
  avatar?: AvatarProps
26
26
  color?: AlertVariants['color']
27
27
  variant?: AlertVariants['variant']
28
+ orientation?: AlertVariants['orientation']
28
29
  /**
29
30
  * Display a list of actions:
30
- * - under the title and description if multiline
31
- * - next to the close button if not multiline
31
+ * - under the title and description when orientation is `vertical`
32
+ * - next to the close button when orientation is `horizontal`
32
33
  * `{ size: 'xs' }`{lang="ts-type"}
33
34
  */
34
35
  actions?: ButtonProps[]
@@ -72,23 +73,25 @@ import UIcon from './Icon.vue'
72
73
  import UAvatar from './Avatar.vue'
73
74
  import UButton from './Button.vue'
74
75
 
75
- const props = defineProps<AlertProps>()
76
+ const props = withDefaults(defineProps<AlertProps>(), {
77
+ orientation: 'vertical'
78
+ })
76
79
  const emits = defineEmits<AlertEmits>()
77
80
  const slots = defineSlots<AlertSlots>()
78
81
 
79
82
  const { t } = useLocale()
80
83
  const appConfig = useAppConfig()
81
84
 
82
- const multiline = computed(() => !!props.title && !!props.description)
83
-
84
85
  const ui = computed(() => alert({
85
86
  color: props.color,
86
- variant: props.variant
87
+ variant: props.variant,
88
+ orientation: props.orientation,
89
+ title: !!props.title || !!slots.title
87
90
  }))
88
91
  </script>
89
92
 
90
93
  <template>
91
- <Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root], multiline })">
94
+ <Primitive :as="as" :data-orientation="orientation" :class="ui.root({ class: [props.class, props.ui?.root] })">
92
95
  <slot name="leading">
93
96
  <UAvatar v-if="avatar" :size="((props.ui?.avatarSize || ui.avatarSize()) as AvatarProps['size'])" v-bind="avatar" :class="ui.avatar({ class: props.ui?.avatar })" />
94
97
  <UIcon v-else-if="icon" :name="icon" :class="ui.icon({ class: props.ui?.icon })" />
@@ -106,15 +109,15 @@ const ui = computed(() => alert({
106
109
  </slot>
107
110
  </div>
108
111
 
109
- <div v-if="multiline && actions?.length" :class="ui.actions({ class: props.ui?.actions, multiline: true })">
112
+ <div v-if="orientation === 'vertical' && actions?.length" :class="ui.actions({ class: props.ui?.actions })">
110
113
  <slot name="actions">
111
114
  <UButton v-for="(action, index) in actions" :key="index" size="xs" v-bind="action" />
112
115
  </slot>
113
116
  </div>
114
117
  </div>
115
118
 
116
- <div v-if="(!multiline && actions?.length) || close" :class="ui.actions({ class: props.ui?.actions, multiline: false })">
117
- <template v-if="!multiline">
119
+ <div v-if="(orientation === 'horizontal' && actions?.length) || close" :class="ui.actions({ class: props.ui?.actions, orientation: 'horizontal' })">
120
+ <template v-if="orientation === 'horizontal' && actions?.length">
118
121
  <slot name="actions">
119
122
  <UButton v-for="(action, index) in actions" :key="index" size="xs" v-bind="action" />
120
123
  </slot>
@@ -47,9 +47,9 @@ provide(localeContextInjectionKey, locale)
47
47
  <slot />
48
48
  </UToaster>
49
49
  <slot v-else />
50
- </TooltipProvider>
51
50
 
52
- <UModalProvider />
53
- <USlideoverProvider />
51
+ <UModalProvider />
52
+ <USlideoverProvider />
53
+ </TooltipProvider>
54
54
  </ConfigProvider>
55
55
  </template>
@@ -46,7 +46,7 @@ import UIcon from './Icon.vue'
46
46
  defineOptions({ inheritAttrs: false })
47
47
 
48
48
  const props = withDefaults(defineProps<AvatarProps>(), { as: 'span' })
49
- const attrs = useAttrs()
49
+ const attrs = useAttrs() as any
50
50
 
51
51
  const fallbackProps = useForwardProps(reactivePick(props, 'delayMs'))
52
52
 
@@ -38,20 +38,24 @@ export interface BadgeSlots {
38
38
  <script setup lang="ts">
39
39
  import { computed } from 'vue'
40
40
  import { Primitive } from 'reka-ui'
41
+ import { useButtonGroup } from '../composables/useButtonGroup'
41
42
  import { useComponentIcons } from '../composables/useComponentIcons'
42
43
  import UIcon from './Icon.vue'
44
+ import UAvatar from './Avatar.vue'
43
45
 
44
46
  const props = withDefaults(defineProps<BadgeProps>(), {
45
47
  as: 'span'
46
48
  })
47
49
  defineSlots<BadgeSlots>()
48
50
 
51
+ const { orientation, size: buttonGroupSize } = useButtonGroup<BadgeProps>(props)
49
52
  const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponentIcons(props)
50
53
 
51
54
  const ui = computed(() => badge({
52
55
  color: props.color,
53
56
  variant: props.variant,
54
- size: props.size
57
+ size: buttonGroupSize.value || props.size,
58
+ buttonGroup: orientation.value
55
59
  }))
56
60
 
57
61
  extendDevtoolsMeta({ defaultProps: { label: 'Badge' } })
@@ -6,6 +6,7 @@ import type { AppConfig } from '@nuxt/schema'
6
6
  import _appConfig from '#build/app.config'
7
7
  import theme from '#build/ui/calendar'
8
8
  import { tv } from '../utils/tv'
9
+ import type { PartialString } from '../types/utils'
9
10
 
10
11
  const appConfigCalendar = _appConfig as AppConfig & { ui: { calendar: Partial<typeof theme> } }
11
12
 
@@ -58,7 +59,7 @@ export interface CalendarProps<R extends boolean, M extends boolean> extends Omi
58
59
  defaultValue?: CalendarModelValue<R, M>
59
60
  modelValue?: CalendarModelValue<R, M>
60
61
  class?: any
61
- ui?: Partial<typeof calendar.slots>
62
+ ui?: PartialString<typeof calendar.slots>
62
63
  }
63
64
 
64
65
  export interface CalendarEmits<R extends boolean, M extends boolean> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import type { VariantProps } from 'tailwind-variants'
2
3
  import type { AppConfig } from '@nuxt/schema'
3
4
  import _appConfig from '#build/app.config'
4
5
  import theme from '#build/ui/card'
@@ -9,12 +10,15 @@ const appConfigCard = _appConfig as AppConfig & { ui: { card: Partial<typeof the
9
10
 
10
11
  const card = tv({ extend: tv(theme), ...(appConfigCard.ui?.card || {}) })
11
12
 
13
+ type CardVariants = VariantProps<typeof card>
14
+
12
15
  export interface CardProps {
13
16
  /**
14
17
  * The element or component this component should render as.
15
18
  * @defaultValue 'div'
16
19
  */
17
20
  as?: any
21
+ variant?: CardVariants['variant']
18
22
  class?: any
19
23
  ui?: Partial<typeof card.slots>
20
24
  }
@@ -29,13 +33,13 @@ extendDevtoolsMeta({ example: 'CardExample' })
29
33
  </script>
30
34
 
31
35
  <script setup lang="ts">
36
+ import { computed } from 'vue'
32
37
  import { Primitive } from 'reka-ui'
33
38
 
34
39
  const props = defineProps<CardProps>()
35
40
  const slots = defineSlots<CardSlots>()
36
41
 
37
- // eslint-disable-next-line vue/no-dupe-keys
38
- const ui = card()
42
+ const ui = computed(() => card({ variant: props.variant }))
39
43
  </script>
40
44
 
41
45
  <template>
@@ -8,14 +8,14 @@ import theme from '#build/ui/command-palette'
8
8
  import type { UseComponentIconsProps } from '../composables/useComponentIcons'
9
9
  import { extendDevtoolsMeta } from '../composables/extendDevtoolsMeta'
10
10
  import { tv } from '../utils/tv'
11
- import type { AvatarProps, ButtonProps, ChipProps, KbdProps, InputProps } from '../types'
11
+ import type { AvatarProps, ButtonProps, ChipProps, KbdProps, InputProps, LinkProps } from '../types'
12
12
  import type { DynamicSlots, PartialString } from '../types/utils'
13
13
 
14
14
  const appConfigCommandPalette = _appConfig as AppConfig & { ui: { commandPalette: Partial<typeof theme> } }
15
15
 
16
16
  const commandPalette = tv({ extend: tv(theme), ...(appConfigCommandPalette.ui?.commandPalette || {}) })
17
17
 
18
- export interface CommandPaletteItem {
18
+ export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'custom'> {
19
19
  prefix?: string
20
20
  label?: string
21
21
  suffix?: string
@@ -136,12 +136,15 @@ import { useAppConfig } from '#imports'
136
136
  import { useLocale } from '../composables/useLocale'
137
137
  import { omit, get } from '../utils'
138
138
  import { highlight } from '../utils/fuse'
139
+ import { pickLinkProps } from '../utils/link'
139
140
  import UIcon from './Icon.vue'
140
141
  import UAvatar from './Avatar.vue'
141
142
  import UButton from './Button.vue'
142
143
  import UChip from './Chip.vue'
143
- import UKbd from './Kbd.vue'
144
+ import ULinkBase from './LinkBase.vue'
145
+ import ULink from './Link.vue'
144
146
  import UInput from './Input.vue'
147
+ import UKbd from './Kbd.vue'
145
148
 
146
149
  const props = withDefaults(defineProps<CommandPaletteProps<G, T>>(), {
147
150
  modelValue: '',
@@ -281,47 +284,51 @@ const groups = computed(() => {
281
284
  :key="`group-${groupIndex}-${index}`"
282
285
  :value="omit(item, ['matches' as any, 'group' as any, 'onSelect', 'labelHtml', 'suffixHtml'])"
283
286
  :disabled="item.disabled"
284
- :class="ui.item({ class: props.ui?.item, active: item.active })"
287
+ as-child
285
288
  @select="item.onSelect"
286
289
  >
287
- <slot :name="item.slot || group.slot || 'item'" :item="item" :index="index">
288
- <slot :name="item.slot ? `${item.slot}-leading` : group.slot ? `${group.slot}-leading` : `item-leading`" :item="item" :index="index">
289
- <UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, loading: true })" />
290
- <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, active: item.active })" />
291
- <UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar, active: item.active })" />
292
- <UChip
293
- v-else-if="item.chip"
294
- :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
295
- inset
296
- standalone
297
- v-bind="item.chip"
298
- :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip, active: item.active })"
299
- />
300
- </slot>
301
-
302
- <span v-if="item.labelHtml || get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`]" :class="ui.itemLabel({ class: props.ui?.itemLabel, active: item.active })">
303
- <slot :name="item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`" :item="item" :index="index">
304
- <span v-if="item.prefix" :class="ui.itemLabelPrefix({ class: props.ui?.itemLabelPrefix })">{{ item.prefix }}</span>
305
-
306
- <span :class="ui.itemLabelBase({ class: props.ui?.itemLabelBase, active: item.active })" v-html="item.labelHtml || get(item, props.labelKey as string)" />
307
-
308
- <span :class="ui.itemLabelSuffix({ class: props.ui?.itemLabelSuffix, active: item.active })" v-html="item.suffixHtml || item.suffix" />
309
- </slot>
310
- </span>
290
+ <ULink v-slot="{ active, ...slotProps }" v-bind="pickLinkProps(item)" custom>
291
+ <ULinkBase v-bind="slotProps" :class="ui.item({ class: props.ui?.item, active: active || item.active })">
292
+ <slot :name="item.slot || group.slot || 'item'" :item="item" :index="index">
293
+ <slot :name="item.slot ? `${item.slot}-leading` : group.slot ? `${group.slot}-leading` : `item-leading`" :item="item" :index="index">
294
+ <UIcon v-if="item.loading" :name="loadingIcon || appConfig.ui.icons.loading" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, loading: true })" />
295
+ <UIcon v-else-if="item.icon" :name="item.icon" :class="ui.itemLeadingIcon({ class: props.ui?.itemLeadingIcon, active: active || item.active })" />
296
+ <UAvatar v-else-if="item.avatar" :size="((props.ui?.itemLeadingAvatarSize || ui.itemLeadingAvatarSize()) as AvatarProps['size'])" v-bind="item.avatar" :class="ui.itemLeadingAvatar({ class: props.ui?.itemLeadingAvatar, active: active || item.active })" />
297
+ <UChip
298
+ v-else-if="item.chip"
299
+ :size="((props.ui?.itemLeadingChipSize || ui.itemLeadingChipSize()) as ChipProps['size'])"
300
+ inset
301
+ standalone
302
+ v-bind="item.chip"
303
+ :class="ui.itemLeadingChip({ class: props.ui?.itemLeadingChip, active: active || item.active })"
304
+ />
305
+ </slot>
306
+
307
+ <span v-if="item.labelHtml || get(item, props.labelKey as string) || !!slots[item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`]" :class="ui.itemLabel({ class: props.ui?.itemLabel, active: active || item.active })">
308
+ <slot :name="item.slot ? `${item.slot}-label` : group.slot ? `${group.slot}-label` : `item-label`" :item="item" :index="index">
309
+ <span v-if="item.prefix" :class="ui.itemLabelPrefix({ class: props.ui?.itemLabelPrefix })">{{ item.prefix }}</span>
310
+
311
+ <span :class="ui.itemLabelBase({ class: props.ui?.itemLabelBase, active: active || item.active })" v-html="item.labelHtml || get(item, props.labelKey as string)" />
312
+
313
+ <span :class="ui.itemLabelSuffix({ class: props.ui?.itemLabelSuffix, active: active || item.active })" v-html="item.suffixHtml || item.suffix" />
314
+ </slot>
315
+ </span>
311
316
 
312
- <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
313
- <slot :name="item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`" :item="item" :index="index">
314
- <span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: props.ui?.itemTrailingKbds })">
315
- <UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
317
+ <span :class="ui.itemTrailing({ class: props.ui?.itemTrailing })">
318
+ <slot :name="item.slot ? `${item.slot}-trailing` : group.slot ? `${group.slot}-trailing` : `item-trailing`" :item="item" :index="index">
319
+ <span v-if="item.kbds?.length" :class="ui.itemTrailingKbds({ class: props.ui?.itemTrailingKbds })">
320
+ <UKbd v-for="(kbd, kbdIndex) in item.kbds" :key="kbdIndex" :size="((props.ui?.itemTrailingKbdsSize || ui.itemTrailingKbdsSize()) as KbdProps['size'])" v-bind="typeof kbd === 'string' ? { value: kbd } : kbd" />
321
+ </span>
322
+ <UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: props.ui?.itemTrailingHighlightedIcon })" />
323
+ </slot>
324
+
325
+ <ListboxItemIndicator as-child>
326
+ <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
327
+ </ListboxItemIndicator>
316
328
  </span>
317
- <UIcon v-else-if="group.highlightedIcon" :name="group.highlightedIcon" :class="ui.itemTrailingHighlightedIcon({ class: props.ui?.itemTrailingHighlightedIcon })" />
318
329
  </slot>
319
-
320
- <ListboxItemIndicator as-child>
321
- <UIcon :name="selectedIcon || appConfig.ui.icons.check" :class="ui.itemTrailingIcon({ class: props.ui?.itemTrailingIcon })" />
322
- </ListboxItemIndicator>
323
- </span>
324
- </slot>
330
+ </ULinkBase>
331
+ </ULink>
325
332
  </ListboxItem>
326
333
  </ListboxGroup>
327
334
  </div>
@@ -51,6 +51,12 @@ export interface ContextMenuProps<T> extends Omit<ContextMenuRootProps, 'dir'> {
51
51
  * @defaultValue appConfig.ui.icons.loading
52
52
  */
53
53
  loadingIcon?: string
54
+ /**
55
+ * The icon displayed when the item is an external link.
56
+ * Set to `false` to hide the external icon.
57
+ * @defaultValue appConfig.ui.icons.external
58
+ */
59
+ externalIcon?: boolean | string
54
60
  /** The content of the menu. */
55
61
  content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'>
56
62
  /**
@@ -152,6 +158,7 @@ import UContextMenuContent from './ContextMenuContent.vue'
152
158
  const props = withDefaults(defineProps<ContextMenuProps<T>>(), {
153
159
  portal: true,
154
160
  modal: true,
161
+ externalIcon: true,
155
162
  labelKey: 'label'
156
163
  })
157
164
  const emits = defineEmits<ContextMenuEmits>()
@@ -182,6 +189,7 @@ const ui = computed(() => contextMenu({
182
189
  :label-key="labelKey"
183
190
  :checked-icon="checkedIcon"
184
191
  :loading-icon="loadingIcon"
192
+ :external-icon="externalIcon"
185
193
  >
186
194
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
187
195
  <slot :name="name" v-bind="slotData" />
@@ -13,6 +13,7 @@ interface ContextMenuContentProps<T> extends Omit<RekaContextMenuContentProps, '
13
13
  labelKey: string
14
14
  checkedIcon?: string
15
15
  loadingIcon?: string
16
+ externalIcon?: boolean | string
16
17
  class?: any
17
18
  ui: typeof _contextMenu
18
19
  uiOverride?: any
@@ -42,7 +43,7 @@ const emits = defineEmits<ContextMenuContentEmits>()
42
43
  const slots = defineSlots<ContextMenuSlots<T>>()
43
44
 
44
45
  const appConfig = useAppConfig()
45
- const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'class', 'ui', 'uiOverride'), emits)
46
+ const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
46
47
  const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuSlots<T>[string]>
47
48
 
48
49
  const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: ContextMenuItem, active?: boolean, index: number }>()
@@ -64,7 +65,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
64
65
  {{ get(item, props.labelKey as string) }}
65
66
  </slot>
66
67
 
67
- <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
68
+ <UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
68
69
  </span>
69
70
 
70
71
  <span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
@@ -112,6 +113,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
112
113
  :label-key="labelKey"
113
114
  :checked-icon="checkedIcon"
114
115
  :loading-icon="loadingIcon"
116
+ :external-icon="externalIcon"
115
117
  v-bind="item.content"
116
118
  >
117
119
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
@@ -19,6 +19,11 @@ export interface DrawerProps extends Pick<DrawerRootProps, 'activeSnapPoint' | '
19
19
  as?: any
20
20
  title?: string
21
21
  description?: string
22
+ /**
23
+ * Whether to inset the drawer from the edges.
24
+ * @defaultValue false
25
+ */
26
+ inset?: boolean
22
27
  /** The content of the drawer. */
23
28
  content?: Omit<DialogContentProps, 'as' | 'asChild' | 'forceMount'>
24
29
  /**
@@ -80,7 +85,8 @@ const rootProps = useForwardPropsEmits(reactivePick(props, 'activeSnapPoint', 'c
80
85
  const contentProps = toRef(() => props.content)
81
86
 
82
87
  const ui = computed(() => drawer({
83
- direction: props.direction
88
+ direction: props.direction,
89
+ inset: props.inset
84
90
  }))
85
91
  </script>
86
92
 
@@ -51,6 +51,12 @@ export interface DropdownMenuProps<T> extends Omit<DropdownMenuRootProps, 'dir'>
51
51
  * @defaultValue appConfig.ui.icons.loading
52
52
  */
53
53
  loadingIcon?: string
54
+ /**
55
+ * The icon displayed when the item is an external link.
56
+ * Set to `false` to hide the external icon.
57
+ * @defaultValue appConfig.ui.icons.external
58
+ */
59
+ externalIcon?: boolean | string
54
60
  /**
55
61
  * The content of the menu.
56
62
  * @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
@@ -149,6 +155,7 @@ import UDropdownMenuContent from './DropdownMenuContent.vue'
149
155
  const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
150
156
  portal: true,
151
157
  modal: true,
158
+ externalIcon: true,
152
159
  labelKey: 'label'
153
160
  })
154
161
  const emits = defineEmits<DropdownMenuEmits>()
@@ -180,6 +187,7 @@ const ui = computed(() => dropdownMenu({
180
187
  :label-key="labelKey"
181
188
  :checked-icon="checkedIcon"
182
189
  :loading-icon="loadingIcon"
190
+ :external-icon="externalIcon"
183
191
  >
184
192
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
185
193
  <slot :name="name" v-bind="slotData" />
@@ -14,6 +14,7 @@ interface DropdownMenuContentProps<T> extends Omit<RekaDropdownMenuContentProps,
14
14
  labelKey: string
15
15
  checkedIcon?: string
16
16
  loadingIcon?: string
17
+ externalIcon?: boolean | string
17
18
  class?: any
18
19
  ui: typeof _dropdownMenu
19
20
  uiOverride?: any
@@ -48,7 +49,7 @@ const emits = defineEmits<DropdownMenuContentEmits>()
48
49
  const slots = defineSlots<DropdownMenuContentSlots<T>>()
49
50
 
50
51
  const appConfig = useAppConfig()
51
- const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'class', 'ui', 'uiOverride'), emits)
52
+ const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
52
53
  const proxySlots = omit(slots, ['default']) as Record<string, DropdownMenuContentSlots<T>[string]>
53
54
 
54
55
  const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: DropdownMenuItem, active?: boolean, index: number }>()
@@ -70,7 +71,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
70
71
  {{ get(item, props.labelKey as string) }}
71
72
  </slot>
72
73
 
73
- <UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
74
+ <UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
74
75
  </span>
75
76
 
76
77
  <span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
@@ -121,6 +122,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
121
122
  :label-key="labelKey"
122
123
  :checked-icon="checkedIcon"
123
124
  :loading-icon="loadingIcon"
125
+ :external-icon="externalIcon"
124
126
  v-bind="item.content"
125
127
  >
126
128
  <template v-for="(_, name) in proxySlots" #[name]="slotData: any">
@@ -6,6 +6,7 @@ import _appConfig from '#build/app.config'
6
6
  import theme from '#build/ui/input-number'
7
7
  import { tv } from '../utils/tv'
8
8
  import type { ButtonProps } from '../types'
9
+ import type { PartialString } from '../types/utils'
9
10
 
10
11
  const appConfigInputNumber = _appConfig as AppConfig & { ui: { inputNumber: Partial<typeof theme> } }
11
12
 
@@ -19,10 +20,8 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
19
20
  * @defaultValue 'div'
20
21
  */
21
22
  as?: any
22
- class?: any
23
23
  /** The placeholder text when the input is empty. */
24
24
  placeholder?: string
25
- ui?: Partial<typeof inputNumber.slots>
26
25
  color?: InputNumberVariants['color']
27
26
  variant?: InputNumberVariants['variant']
28
27
  size?: InputNumberVariants['size']
@@ -60,6 +59,8 @@ export interface InputNumberProps extends Pick<NumberFieldRootProps, 'modelValue
60
59
  * @defaultValue UApp.locale.code
61
60
  */
62
61
  locale?: string
62
+ class?: any
63
+ ui?: PartialString<typeof inputNumber.slots>
63
64
  }
64
65
 
65
66
  export interface InputNumberEmits {
@@ -74,7 +74,7 @@ extendDevtoolsMeta({ example: 'ModalExample' })
74
74
 
75
75
  <script setup lang="ts">
76
76
  import { computed, toRef } from 'vue'
77
- import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose, useForwardPropsEmits } from 'reka-ui'
77
+ import { DialogRoot, DialogTrigger, DialogPortal, DialogOverlay, DialogContent, DialogTitle, DialogDescription, DialogClose, VisuallyHidden, useForwardPropsEmits } from 'reka-ui'
78
78
  import { reactivePick } from '@vueuse/core'
79
79
  import { useAppConfig } from '#imports'
80
80
  import { useLocale } from '../composables/useLocale'
@@ -124,6 +124,20 @@ const ui = computed(() => modal({
124
124
  <DialogOverlay v-if="overlay" :class="ui.overlay({ class: props.ui?.overlay })" />
125
125
 
126
126
  <DialogContent :class="ui.content({ class: [!slots.default && props.class, props.ui?.content] })" v-bind="contentProps" v-on="contentEvents">
127
+ <VisuallyHidden v-if="!!slots.content && ((title || !!slots.title) || (description || !!slots.description))">
128
+ <DialogTitle v-if="title || !!slots.title">
129
+ <slot name="title">
130
+ {{ title }}
131
+ </slot>
132
+ </DialogTitle>
133
+
134
+ <DialogDescription v-if="description || !!slots.description">
135
+ <slot name="description">
136
+ {{ description }}
137
+ </slot>
138
+ </DialogDescription>
139
+ </VisuallyHidden>
140
+
127
141
  <slot name="content">
128
142
  <div v-if="!!slots.header || (title || !!slots.title) || (description || !!slots.description) || (close || !!slots.close)" :class="ui.header({ class: props.ui?.header })">
129
143
  <slot name="header">