Compare commits

...

40 Commits

Author SHA1 Message Date
Benjamin Canac
17a96416f0 chore(release): 2.14.2 2024-03-05 12:21:34 +01:00
renovate[bot]
4378268117 chore(deps): update devdependency @nuxt/ui-pro to v1.0.1-28492961.4d49b9c (#1471)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 21:38:46 +01:00
Benjamin Canac
622aef5ffe docs: limit search results to 42 2024-03-04 19:27:09 +01:00
Benjamin Canac
174af36000 docs: switch to @nuxt/fonts 2024-03-04 18:21:41 +01:00
Benjamin Canac
2d64b50559 fix(RadioGroup): add missing fieldset config
Resolves #1472
2024-03-04 18:06:49 +01:00
Benjamin Canac
272c19de70 fix(Tooltip): arrow not hidden on mobile
Resolves #1470
2024-03-04 16:27:01 +01:00
Alex Thorwaldson
6a1142b403 fix(Dropdown): active/inactive dropdown links (#1407)
Co-authored-by: gangan <44604921+shinGangan@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2024-03-04 16:11:41 +01:00
renovate[bot]
9937951fb7 chore(deps): update all non-major dependencies (#1440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 16:11:05 +01:00
kmilogp
002129c299 fix(Modal): remove overflow-hidden (#1460)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2024-03-04 12:58:56 +01:00
Benjamin Canac
0c2f655a27 docs(Range): revert example as it shows in the docs 2024-03-04 12:47:51 +01:00
renovate[bot]
fb16735dec chore(deps): update devdependency vue-tsc to v2 (#1454)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-03-04 12:33:38 +01:00
Mukund Shah
aa6e523780 docs(Notification): add Notifications props and config (#1449) 2024-03-04 11:56:18 +01:00
David Parys
bfd15c1818 docs(Link): add IntelliSense section (#1442) 2024-03-04 11:55:17 +01:00
Rodion
027d85402b docs(FormGroup): wrong icon name in #help slot (#1451) 2024-03-04 11:54:44 +01:00
roiLeo
99b9467dc2 docs(SelectMenu): invalid anchor to creatable (#1453) 2024-03-04 11:53:52 +01:00
Benjamin Canac
70bf4a7392 fix(Dropdown): improve hover mode on touch devices 2024-03-04 11:47:39 +01:00
Benjamin Canac
b50fbcf760 fix(Popover): improve hover mode on touch devices 2024-03-04 11:47:34 +01:00
Benjamin Canac
b74bf9f666 chore(Tooltip): use mouseenter instead of mouseover 2024-03-04 11:45:01 +01:00
renovate[bot]
c0feca136a chore(deps): update all non-major dependencies (#1430)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-28 17:21:00 +01:00
Benjamin Canac
0a4a9e3d2c fix(HorizontalNavigation): add relative class to icon 2024-02-28 16:26:16 +01:00
Benjamin Canac
0b29dd4ca5 fix(VerticalNavigation): add relative class to icon
Resolves #1245
2024-02-28 16:25:20 +01:00
Benjamin Canac
9cce4456d0 fix(Notification): improve description alignment when no title provided 2024-02-28 12:52:53 +01:00
Benjamin Canac
ca4f06a313 fix(Alert): improve description alignment when no title provided
Resolves #1408
2024-02-28 12:52:43 +01:00
Benjamin Canac
7dd9ee528e docs(date-picker): improve examples responsive 2024-02-28 11:25:59 +01:00
Shoshana Connack
cdf6ff7152 docs(date-picker): include date-fns in installation (#1434) 2024-02-27 14:26:25 +01:00
Benjamin Canac
9c2104d947 docs: remove banner on examples 2024-02-27 09:18:53 +01:00
Benjamin Canac
d1c8026a1e docs(deps): bump @nuxt/ui-pro 2024-02-27 09:18:53 +01:00
Benjamin Canac
14efa81986 chore(deps): refresh lock 2024-02-27 09:18:53 +01:00
renovate[bot]
b3314dc16b chore(deps): update all non-major dependencies (#1406)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-27 09:18:53 +01:00
Benjamin Canac
06135f38ae docs(home): improve lighthouse 2024-02-26 12:56:40 +01:00
Benjamin Canac
dbbab8ded0 chore(CommandPaletteGroup): remove useless role attributes 2024-02-26 12:56:40 +01:00
Romain Hamel
6e77f1d514 fix(Checkbox): label interaction without FormGroup (#1427) 2024-02-26 12:55:30 +01:00
Benjamin Canac
4b6e80e364 fix(SelectMenu): check null model value
Resolves #1421
2024-02-26 11:37:32 +01:00
Benjamin Canac
8a1b112727 docs(deps): bump @nuxt/ui-pro 2024-02-26 11:37:32 +01:00
Benjamin Canac
961f0ae27b docs: update banner 2024-02-26 11:37:32 +01:00
Benjamin Canac
e819656a34 docs: move headlessui links before github 2024-02-26 11:37:32 +01:00
Sébastien Chopin
024e03acc9 docs(breadcrumb): add link to github (#1414) 2024-02-26 11:37:32 +01:00
renovate[bot]
462d7729c9 chore(deps): update devdependency @nuxt/ui-pro to v1.0.0-28478433.ed477f1 (#1405)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-26 11:37:31 +01:00
gangan
df857fd541 chore(renovate): update extends (#1380) 2024-02-26 11:37:31 +01:00
sdezza
9b208bf297 docs(modal): mention how to programatically close (#1423) 2024-02-26 11:24:02 +01:00
43 changed files with 645 additions and 395 deletions

1
.gitignore vendored
View File

@@ -9,3 +9,4 @@ dist
.vercel .vercel
.idea .idea
.env .env
.data

View File

@@ -1,5 +1,23 @@
# Changelog # Changelog
## [2.14.2](https://github.com/nuxt/ui/compare/v2.14.1...v2.14.2) (2024-03-05)
### Bug Fixes
* **Alert:** improve `description` alignment when no title provided ([ca4f06a](https://github.com/nuxt/ui/commit/ca4f06a313314af5813007878a9b6c8f1003c6d1)), closes [#1408](https://github.com/nuxt/ui/issues/1408)
* **Checkbox:** label interaction without `FormGroup` ([#1427](https://github.com/nuxt/ui/issues/1427)) ([6e77f1d](https://github.com/nuxt/ui/commit/6e77f1d5144d7d87b0c76b43ecf3d731166c808b))
* **Dropdown:** active/inactive dropdown links ([#1407](https://github.com/nuxt/ui/issues/1407)) ([6a1142b](https://github.com/nuxt/ui/commit/6a1142b4032150def78c69080df455f7d2a25e7b))
* **Dropdown:** improve `hover` mode on touch devices ([70bf4a7](https://github.com/nuxt/ui/commit/70bf4a73921f47fcd41599874b595a6eed947f5a))
* **HorizontalNavigation:** add `relative` class to icon ([0a4a9e3](https://github.com/nuxt/ui/commit/0a4a9e3d2c4a7584570e4ab7ae6fe8265c960a33))
* **Modal:** remove `overflow-hidden` ([#1460](https://github.com/nuxt/ui/issues/1460)) ([002129c](https://github.com/nuxt/ui/commit/002129c29926df5a816288b916194ab28cf4c8a4))
* **Notification:** improve `description` alignment when no title provided ([9cce445](https://github.com/nuxt/ui/commit/9cce4456d03c52daca4d7347e60cbcd7f501317a))
* **Popover:** improve `hover` mode on touch devices ([b50fbcf](https://github.com/nuxt/ui/commit/b50fbcf760e908579e81f6e57234f2080e2bf035))
* **RadioGroup:** add missing `fieldset` config ([2d64b50](https://github.com/nuxt/ui/commit/2d64b50559946b166c02cfe921e63d746cdc09d4)), closes [#1472](https://github.com/nuxt/ui/issues/1472)
* **SelectMenu:** check `null` model value ([4b6e80e](https://github.com/nuxt/ui/commit/4b6e80e3646e263a83614830d9ec6adb0edf2ede)), closes [#1421](https://github.com/nuxt/ui/issues/1421)
* **Tooltip:** arrow not hidden on mobile ([272c19d](https://github.com/nuxt/ui/commit/272c19de708144b1b132b98a7287254974f4e144)), closes [#1470](https://github.com/nuxt/ui/issues/1470)
* **VerticalNavigation:** add `relative` class to icon ([0b29dd4](https://github.com/nuxt/ui/commit/0b29dd4ca560cac7d151132e086eab17c0498a5c)), closes [#1245](https://github.com/nuxt/ui/issues/1245)
## [2.14.1](https://github.com/nuxt/ui/compare/v2.14.0...v2.14.1) (2024-02-23) ## [2.14.1](https://github.com/nuxt/ui/compare/v2.14.0...v2.14.1) (2024-02-23)

View File

@@ -3,7 +3,7 @@
<div> <div>
<NuxtLoadingIndicator /> <NuxtLoadingIndicator />
<Banner /> <Banner v-if="!$route.path.startsWith('/examples')" />
<Header v-if="!$route.path.startsWith('/examples')" :links="links" /> <Header v-if="!$route.path.startsWith('/examples')" :links="links" />
@@ -14,7 +14,7 @@
<Footer v-if="!$route.path.startsWith('/examples')" /> <Footer v-if="!$route.path.startsWith('/examples')" />
<ClientOnly> <ClientOnly>
<LazyUContentSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" /> <LazyUContentSearch ref="searchRef" :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 42 }" />
</ClientOnly> </ClientOnly>
<UNotifications> <UNotifications>

View File

@@ -1,11 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { isAfter } from 'date-fns'
const id = 'nuxt-ui-banner-1' const id = 'nuxt-ui-banner-1'
const to = '/pro/pricing' const to = '/pro/pricing'
const date = new Date('2024-02-25T20:00:00Z')
const timeAgo = useTimeAgo(date)
const hideBanner = () => { const hideBanner = () => {
localStorage.setItem(id, 'true') localStorage.setItem(id, 'true')
@@ -25,26 +20,12 @@ if (process.server) {
}] }]
}) })
} }
onMounted(() => {
if (isAfter(new Date(), date)) {
hideBanner()
return
}
const interval = setInterval(() => {
if (isAfter(new Date(), date)) {
hideBanner()
clearInterval(interval)
}
}, 1000)
})
</script> </script>
<template> <template>
<div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner"> <div class="relative bg-primary hover:bg-primary/90 transition-[background] backdrop-blur z-50 app-banner">
<UContainer class="py-2"> <UContainer class="py-2">
<NuxtLink v-if="to" :to="to" class="focus:outline-none" tabindex="-1"> <NuxtLink v-if="to" :to="to" class="focus:outline-none" aria-label="Nuxt UI Pro pricing" tabindex="-1">
<span class="absolute inset-0 " aria-hidden="true" /> <span class="absolute inset-0 " aria-hidden="true" />
</NuxtLink> </NuxtLink>
@@ -52,13 +33,14 @@ onMounted(() => {
<div class="lg:flex-1 hidden lg:flex items-center" /> <div class="lg:flex-1 hidden lg:flex items-center" />
<p class="text-sm font-medium text-white dark:text-gray-900"> <p class="text-sm font-medium text-white dark:text-gray-900">
<UIcon name="i-heroicons-gift" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" /> <UIcon name="i-heroicons-rocket-launch" class="w-5 h-5 align-top flex-shrink-0 pointer-events-none mr-2" />
<span class="font-semibold">Nuxt UI Pro v1.0</span> is out with dashboard components! Discount ends <span class="font-semibold">{{ timeAgo }}</span>. <span class="font-semibold">Nuxt UI Pro v1.0</span> is out with dashboard components!
</p> </p>
<div class="flex items-center justify-end lg:flex-1"> <div class="flex items-center justify-end lg:flex-1">
<button <button
class="p-1.5 rounded-md inline-flex hover:bg-primary/90" class="p-1.5 rounded-md inline-flex hover:bg-primary/90"
aria-label="Close banner"
@click.prevent="hideBanner" @click.prevent="hideBanner"
> >
<UIcon name="i-heroicons-x-mark-20-solid" class="w-5 h-5 text-white dark:text-gray-900" /> <UIcon name="i-heroicons-x-mark-20-solid" class="w-5 h-5 text-white dark:text-gray-900" />

View File

@@ -27,8 +27,8 @@ function selectRange (duration: Duration) {
</UButton> </UButton>
<template #panel="{ close }"> <template #panel="{ close }">
<div class="flex items-center divide-x divide-gray-200 dark:divide-gray-800"> <div class="flex items-center sm:divide-x divide-gray-200 dark:divide-gray-800">
<div class="flex flex-col py-4"> <div class="hidden sm:flex flex-col py-4">
<UButton <UButton
v-for="(range, index) in ranges" v-for="(range, index) in ranges"
:key="index" :key="index"
@@ -37,6 +37,7 @@ function selectRange (duration: Duration) {
variant="ghost" variant="ghost"
class="rounded-none px-6" class="rounded-none px-6"
:class="[isRangeSelected(range.duration) ? 'bg-gray-100 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50']" :class="[isRangeSelected(range.duration) ? 'bg-gray-100 dark:bg-gray-800' : 'hover:bg-gray-50 dark:hover:bg-gray-800/50']"
truncate
@click="selectRange(range.duration)" @click="selectRange(range.duration)"
/> />
</div> </div>

View File

@@ -3,5 +3,5 @@ const value = ref(50)
</script> </script>
<template> <template>
<URange v-model="value" name="range" /> <URange v-model="value" />
</template> </template>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { useBreakpoints, breakpointsTailwind } from '@vueuse/core'
import { DatePicker as VCalendarDatePicker } from 'v-calendar' import { DatePicker as VCalendarDatePicker } from 'v-calendar'
// @ts-ignore // @ts-ignore
import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker' import type { DatePickerDate, DatePickerRangeObject } from 'v-calendar/dist/types/src/use/datePicker'
@@ -25,6 +26,10 @@ const date = computed({
} }
}) })
const breakpoints = useBreakpoints(breakpointsTailwind)
const smallerThanSm = breakpoints.smaller('sm')
const attrs = { const attrs = {
transparent: true, transparent: true,
borderless: true, borderless: true,
@@ -35,7 +40,7 @@ const attrs = {
</script> </script>
<template> <template>
<VCalendarDatePicker v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end" v-model.range="date" :columns="2" v-bind="{ ...attrs, ...$attrs }" /> <VCalendarDatePicker v-if="date && (date as DatePickerRangeObject)?.start && (date as DatePickerRangeObject)?.end" v-model.range="date" :columns="smallerThanSm ? 1 : 2" :rows="smallerThanSm ? 2 : 1" v-bind="{ ...attrs, ...$attrs }" />
<VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" /> <VCalendarDatePicker v-else v-model="date" v-bind="{ ...attrs, ...$attrs }" />
</template> </template>

View File

@@ -1,12 +1,12 @@
--- ---
description: Display togglable accordion panels. description: Display togglable accordion panels.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue
- label: Disclosure - label: Disclosure
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/disclosure' to: 'https://headlessui.com/vue/disclosure'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Accordion.vue
--- ---
## Usage ## Usage

View File

@@ -1,6 +1,10 @@
--- ---
title: Breadcrumb title: Breadcrumb
description: A list of links that indicate the current page's location within a navigational hierarchy. description: A list of links that indicate the current page's location within a navigational hierarchy.
links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/Breadcrumb.vue
--- ---
## Usage ## Usage

View File

@@ -2,12 +2,12 @@
title: CommandPalette title: CommandPalette
description: Add a customizable command palette to your app. description: Add a customizable command palette to your app.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/CommandPalette.vue
- label: 'Combobox' - label: 'Combobox'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/combobox' to: 'https://headlessui.com/vue/combobox'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/navigation/CommandPalette.vue
--- ---
## Usage ## Usage

View File

@@ -16,15 +16,15 @@ Let's start by installing the `v-calendar` and `date-fns` dependency:
::code-group ::code-group
```bash [pnpm] ```bash [pnpm]
pnpm add v-calendar@next pnpm add v-calendar@next date-fns
``` ```
```bash [yarn] ```bash [yarn]
yarn add v-calendar@next yarn add v-calendar@next date-fns
``` ```
```bash [npm] ```bash [npm]
npm install v-calendar@next npm install v-calendar@next date-fns
``` ```
:: ::

View File

@@ -1,12 +1,12 @@
--- ---
description: Display a list of actions in a dropdown menu. description: Display a list of actions in a dropdown menu.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Dropdown.vue
- label: Menu - label: Menu
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: https://headlessui.com/vue/menu to: https://headlessui.com/vue/menu
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/elements/Dropdown.vue
--- ---
## Usage ## Usage

View File

@@ -236,7 +236,7 @@ Use the `#help` slot to set the custom content for help.
::component-card ::component-card
--- ---
slots: slots:
help: Here are some examples <UIcon name="i-heroicons-arrow-right-20-solid" /> help: Here are some examples <UIcon name="i-heroicons-information-circle" />
default: <UInput model-value="benjamincanac" placeholder="you@example.com" /> default: <UInput model-value="benjamincanac" placeholder="you@example.com" />
props: props:
label: 'Email' label: 'Email'

View File

@@ -2,12 +2,12 @@
title: InputMenu title: InputMenu
description: Display an autocomplete input with real-time suggestions. description: Display an autocomplete input with real-time suggestions.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/InputMenu.vue
- label: 'Combobox' - label: 'Combobox'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/combobox' to: 'https://headlessui.com/vue/combobox'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/InputMenu.vue
--- ---
## Usage ## Usage

View File

@@ -33,6 +33,18 @@ It also renders an `<a>` tag when a `to` prop is provided, otherwise it defaults
It is used underneath by the [Button](/components/button), [Dropdown](/components/dropdown) and [VerticalNavigation](/components/vertical-navigation) components. It is used underneath by the [Button](/components/button), [Dropdown](/components/dropdown) and [VerticalNavigation](/components/vertical-navigation) components.
## IntelliSense
If you're using VSCode and wish to get autocompletion for the classes `active-class` and `inactive-class`, you can add the following settings to your `.vscode/settings.json`:
```json [.vscode/settings.json]
{
"tailwindCSS.classAttributes": [
"active-class",
"inactive-class"
],
}
```
## Props ## Props
:component-props :component-props

View File

@@ -1,12 +1,12 @@
--- ---
description: Display a modal within your application. description: Display a modal within your application.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Modal.vue
- label: 'Dialog' - label: 'Dialog'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/dialog' to: 'https://headlessui.com/vue/dialog'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Modal.vue
--- ---
## Usage ## Usage
@@ -79,6 +79,8 @@ Then, you can use the `useModal` composable to control your modals within your a
:component-example{component="modal-example-composable"} :component-example{component="modal-example-composable"}
Additionally, you can close the modal within the modal component by calling `modal.close()`.
## Props ## Props
:component-props :component-props

View File

@@ -289,8 +289,14 @@ Slots defined in the `<UNotifications />` component are automatically passed dow
## Props ## Props
:component-props ::tabs
:component-props{label="Notification"}
:component-props{label="Notifications" slug="UNotifications"}
::
## Config ## Config
:component-preset ::tabs
:component-preset{label="Notification"}
:component-preset{label="Notifications" slug="Notifications"}
::

View File

@@ -1,12 +1,12 @@
--- ---
description: Display a non-modal dialog that floats around a trigger element. description: Display a non-modal dialog that floats around a trigger element.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Popover.vue
- label: 'Popover' - label: 'Popover'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/popover' to: 'https://headlessui.com/vue/popover'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Popover.vue
--- ---
## Usage ## Usage

View File

@@ -2,12 +2,12 @@
title: SelectMenu title: SelectMenu
description: Display a select menu with advanced features. description: Display a select menu with advanced features.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/SelectMenu.vue
- label: 'Listbox' - label: 'Listbox'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/listbox' to: 'https://headlessui.com/vue/listbox'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/SelectMenu.vue
--- ---
## Usage ## Usage
@@ -257,7 +257,7 @@ componentProps:
Use the `#option-create` slot to customize the content displayed when the `creatable` prop is `true` and there is no options. You will have access to the `query` property in the slot scope. Use the `#option-create` slot to customize the content displayed when the `creatable` prop is `true` and there is no options. You will have access to the `query` property in the slot scope.
::callout{icon="i-heroicons-light-bulb"} ::callout{icon="i-heroicons-light-bulb"}
An example is available in the [Create option](#create-option) section. An example is available in the [Creatable](#creatable) section.
:: ::
### `empty` ### `empty`

View File

@@ -1,12 +1,12 @@
--- ---
description: Display a dialog that slides in from the edge of the screen. description: Display a dialog that slides in from the edge of the screen.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Slideover.vue
- label: 'Dialog' - label: 'Dialog'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/dialog' to: 'https://headlessui.com/vue/dialog'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/overlays/Slideover.vue
--- ---
## Usage ## Usage

View File

@@ -1,12 +1,12 @@
--- ---
description: Display a toggle field. description: Display a toggle field.
links: links:
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Toggle.vue
- label: 'Switch' - label: 'Switch'
icon: i-simple-icons-headlessui icon: i-simple-icons-headlessui
to: 'https://headlessui.com/vue/switch' to: 'https://headlessui.com/vue/switch'
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/ui/blob/dev/src/runtime/components/forms/Toggle.vue
--- ---
## Usage ## Usage

View File

@@ -16,7 +16,7 @@
<Footer /> <Footer />
<ClientOnly> <ClientOnly>
<LazyUContentSearch :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 1000 }" /> <LazyUContentSearch :files="files" :navigation="navigation" :links="links" :fuse="{ resultLimit: 42 }" />
</ClientOnly> </ClientOnly>
<UNotifications> <UNotifications>

View File

@@ -17,11 +17,10 @@ export default defineNuxtConfig({
].filter(Boolean), ].filter(Boolean),
modules: [ modules: [
'@nuxt/content', '@nuxt/content',
'@nuxt/fonts',
'@nuxt/image', '@nuxt/image',
'nuxt-og-image', 'nuxt-og-image',
module, module,
'@nuxtjs/fontaine',
'@nuxtjs/google-fonts',
'@nuxtjs/plausible', '@nuxtjs/plausible',
'@vueuse/nuxt', '@vueuse/nuxt',
'nuxt-component-meta', 'nuxt-component-meta',

View File

@@ -7,19 +7,18 @@
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/heroicons": "^1.1.20", "@iconify-json/heroicons": "^1.1.20",
"@iconify-json/simple-icons": "^1.1.92", "@iconify-json/simple-icons": "^1.1.94",
"@nuxt/content": "^2.12.0", "@nuxt/content": "^2.12.0",
"@nuxt/devtools": "^1.0.8", "@nuxt/devtools": "^1.0.8",
"@nuxt/eslint-config": "^0.2.0", "@nuxt/eslint-config": "^0.2.0",
"@nuxt/fonts": "^0.0.1",
"@nuxt/image": "^1.3.0", "@nuxt/image": "^1.3.0",
"@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@1.0.0-28476869.809f447", "@nuxt/ui-pro": "npm:@nuxt/ui-pro-edge@1.0.1-28492961.4d49b9c",
"@nuxtjs/fontaine": "^0.4.1",
"@nuxtjs/google-fonts": "^3.1.3",
"@nuxtjs/plausible": "^0.2.4", "@nuxtjs/plausible": "^0.2.4",
"@octokit/rest": "^20.0.2", "@octokit/rest": "^20.0.2",
"@vueuse/nuxt": "^10.8.0", "@vueuse/nuxt": "^10.9.0",
"date-fns": "^3.3.1", "date-fns": "^3.3.1",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"joi": "^17.12.2", "joi": "^17.12.2",
"nuxt": "^3.10.3", "nuxt": "^3.10.3",
"nuxt-cloudflare-analytics": "^1.0.8", "nuxt-cloudflare-analytics": "^1.0.8",

View File

@@ -4,7 +4,7 @@
<ULandingHero :ui="{ base: 'relative z-[1]', container: 'max-w-4xl' }" class="mb-[calc(var(--header-height)*2)]"> <ULandingHero :ui="{ base: 'relative z-[1]', container: 'max-w-4xl' }" class="mb-[calc(var(--header-height)*2)]">
<template #headline> <template #headline>
<UBadge variant="subtle" size="md" class="hover:bg-primary-100 dark:bg-primary-950/100 dark:hover:bg-primary-900 transition-color relative font-medium rounded-full shadow-none"> <UBadge variant="subtle" size="md" class="hover:bg-primary-100 dark:bg-primary-950/100 dark:hover:bg-primary-900 transition-color relative font-medium rounded-full shadow-none">
<NuxtLink :to="`https://github.com/nuxt/ui/releases/tag/v${config.version.split('.').slice(0, -1).join('.')}.0`" target="_blank" class="focus:outline-none" tabindex="-1"> <NuxtLink :to="`https://github.com/nuxt/ui/releases/tag/v${config.version.split('.').slice(0, -1).join('.')}.0`" target="_blank" class="focus:outline-none" aria-label="Go to last relase" tabindex="-1">
<span class="absolute inset-0" aria-hidden="true" /> <span class="absolute inset-0" aria-hidden="true" />
</NuxtLink> </NuxtLink>
@@ -90,6 +90,7 @@
:width="card.image.width" :width="card.image.width"
:height="card.image.height" :height="card.image.height"
:alt="card.title" :alt="card.title"
loading="lazy"
class="object-cover w-full" class="object-cover w-full"
/> />
</ULandingCard> </ULandingCard>
@@ -180,7 +181,7 @@
</template> </template>
<div class="bg-gray-900/5 dark:bg-white/5 ring-1 ring-inset ring-gray-900/10 dark:ring-white/10 rounded-xl lg:-m-4 p-4"> <div class="bg-gray-900/5 dark:bg-white/5 ring-1 ring-inset ring-gray-900/10 dark:ring-white/10 rounded-xl lg:-m-4 p-4">
<video poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg" controls class="rounded-lg"> <video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg" controls class="rounded-lg">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.webm" type="video/webm"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.webm" type="video/webm">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.mp4" type="video/mp4"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.mp4" type="video/mp4">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.ogg" type="video/ogg"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.ogg" type="video/ogg">
@@ -282,7 +283,7 @@
</div> </div>
</template> </template>
<template #docs-surround> <template #content-surround>
<UContentSurround <UContentSurround
:surround="(surround as unknown as ParsedContent[])" :surround="(surround as unknown as ParsedContent[])"
class="w-full gap-4" class="w-full gap-4"
@@ -300,7 +301,7 @@
/> />
</template> </template>
<template #docs-toc> <template #content-toc>
<div class="absolute top-0 left-0 right-0 space-y-3"> <div class="absolute top-0 left-0 right-0 space-y-3">
<UContentToc :links="toc" class="bg-transparent relative max-h-full overflow-hidden top-0" :ui="({ container: { base: '!pt-0 !pb-4' } } as any)" /> <UContentToc :links="toc" class="bg-transparent relative max-h-full overflow-hidden top-0" :ui="({ container: { base: '!pt-0 !pb-4' } } as any)" />
@@ -380,7 +381,7 @@
<template #description> <template #description>
<span v-html="page.pro.landing?.description" /> <span v-html="page.pro.landing?.description" />
</template> </template>
<video poster="https://res.cloudinary.com/nuxt/video/upload/so_14.4/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.jpg" controls> <video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/so_14.4/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.jpg" controls>
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.webm" type="video/webm"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.webm" type="video/webm">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.mp4" type="video/mp4"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.mp4" type="video/mp4">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.ogg" type="video/ogg"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.ogg" type="video/ogg">
@@ -393,7 +394,7 @@
<template #description> <template #description>
<span v-html="page.pro.docs?.description" /> <span v-html="page.pro.docs?.description" />
</template> </template>
<video poster="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.jpg" controls> <video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.jpg" controls>
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.webm" type="video/webm"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.webm" type="video/webm">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.mp4" type="video/mp4"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.mp4" type="video/mp4">
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.ogg" type="video/ogg"> <source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.ogg" type="video/ogg">
@@ -617,7 +618,7 @@ const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
slot: 'page-body', slot: 'page-body',
class: 'inset-x-4 top-4 justify-start' class: 'inset-x-4 top-4 justify-start'
}, isAfterStep(steps.docs + 12) ? { }, isAfterStep(steps.docs + 12) ? {
slot: 'docs-surround', slot: 'content-surround',
class: 'bottom-4 inset-x-4 h-28' class: 'bottom-4 inset-x-4 h-28'
} : { } : {
name: 'UContentSurround', name: 'UContentSurround',
@@ -634,7 +635,7 @@ const docsBlocks = computed(() => [isAfterStep(steps.docs) && {
class: 'right-4 inset-y-4 w-64', class: 'right-4 inset-y-4 w-64',
inactive: isAfterStep(steps.docs + 14), inactive: isAfterStep(steps.docs + 14),
children: [{ children: [{
slot: 'docs-toc', slot: 'content-toc',
class: 'inset-4 overflow-y-auto' class: 'inset-4 overflow-y-auto'
}] }]
} : { } : {
@@ -763,10 +764,12 @@ const navigationLinks = [{
const surround = [{ const surround = [{
title: 'Introduction', title: 'Introduction',
description: 'Fully styled and customizable components for Nuxt.' description: 'Fully styled and customizable components for Nuxt.',
_path: '/'
}, { }, {
title: 'Theming', title: 'Theming',
description: 'Learn how to customize the look and feel of the components.' description: 'Learn how to customize the look and feel of the components.',
_path: '/'
}] }]
const md = ` const md = `

View File

@@ -5,7 +5,7 @@ export default <Partial<Config>>{
theme: { theme: {
extend: { extend: {
fontFamily: { fontFamily: {
sans: ['DM Sans', 'DM Sans fallback', ...defaultTheme.fontFamily.sans] sans: ['DM Sans', ...defaultTheme.fontFamily.sans]
}, },
colors: { colors: {
green: { green: {

View File

@@ -1,6 +1,6 @@
{ {
"name": "@nuxt/ui", "name": "@nuxt/ui",
"version": "2.14.1", "version": "2.14.2",
"repository": "nuxt/ui", "repository": "nuxt/ui",
"homepage": "https://ui.nuxt.com", "homepage": "https://ui.nuxt.com",
"type": "module", "type": "module",
@@ -45,9 +45,9 @@
"@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.10", "@tailwindcss/typography": "^0.5.10",
"@vueuse/core": "^10.8.0", "@vueuse/core": "^10.9.0",
"@vueuse/integrations": "^10.8.0", "@vueuse/integrations": "^10.9.0",
"@vueuse/math": "^10.8.0", "@vueuse/math": "^10.9.0",
"defu": "^6.1.4", "defu": "^6.1.4",
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
"nuxt-icon": "^0.6.8", "nuxt-icon": "^0.6.8",
@@ -63,8 +63,8 @@
"@nuxt/test-utils": "^3.11.0", "@nuxt/test-utils": "^3.11.0",
"@release-it/conventional-changelog": "^8.0.1", "@release-it/conventional-changelog": "^8.0.1",
"@vue/test-utils": "^2.4.4", "@vue/test-utils": "^2.4.4",
"eslint": "^8.56.0", "eslint": "^8.57.0",
"happy-dom": "^13.4.1", "happy-dom": "^13.6.2",
"joi": "^17.12.2", "joi": "^17.12.2",
"nuxt": "^3.10.3", "nuxt": "^3.10.3",
"release-it": "^17.1.1", "release-it": "^17.1.1",
@@ -73,7 +73,7 @@
"valibot": "^0.29.0", "valibot": "^0.29.0",
"vitest": "^1.3.1", "vitest": "^1.3.1",
"vitest-environment-nuxt": "^1.0.0", "vitest-environment-nuxt": "^1.0.0",
"vue-tsc": "^1.8.27", "vue-tsc": "^2.0.4",
"yup": "^1.3.3", "yup": "^1.3.3",
"zod": "^3.22.4" "zod": "^3.22.4"
}, },
@@ -82,6 +82,6 @@
"@nuxt/schema": "3.10.3", "@nuxt/schema": "3.10.3",
"tailwindcss": "3.4.1", "tailwindcss": "3.4.1",
"@headlessui/vue": "1.7.19", "@headlessui/vue": "1.7.19",
"vue": "3.4.19" "vue": "3.4.21"
} }
} }

738
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{ {
"extends": [ "extends": [
"@nuxtjs" "github>nuxt/renovate-config-nuxt"
] ]
} }

View File

@@ -10,7 +10,7 @@
{{ title }} {{ title }}
</slot> </slot>
</p> </p>
<p v-if="description || $slots.description" :class="ui.description"> <p v-if="description || $slots.description" :class="twMerge(ui.description, !(title && $slots.title) && 'mt-0 leading-5')">
<slot name="description" :description="description"> <slot name="description" :description="description">
{{ description }} {{ description }}
</slot> </slot>

View File

@@ -7,7 +7,8 @@
:disabled="disabled" :disabled="disabled"
:class="ui.trigger" :class="ui.trigger"
role="button" role="button"
@mouseover="onMouseOver" @mouseenter="onMouseEnter"
@touchstart.prevent="onTouchStart"
> >
<slot :open="open" :disabled="disabled"> <slot :open="open" :disabled="disabled">
<button :disabled="disabled"> <button :disabled="disabled">
@@ -16,25 +17,25 @@
</slot> </slot>
</HMenuButton> </HMenuButton>
<div v-if="open && items.length" ref="container" :class="[ui.container, ui.width]" :style="containerStyle" @mouseover="onMouseOver"> <div v-if="open && items.length" ref="container" :class="[ui.container, ui.width]" :style="containerStyle">
<Transition appear v-bind="ui.transition"> <Transition appear v-bind="ui.transition">
<div> <div>
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" /> <div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
<HMenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static> <HMenuItems :class="[ui.base, ui.divide, ui.ring, ui.rounded, ui.shadow, ui.background, ui.height]" static>
<div v-for="(subItems, index) of items" :key="index" :class="ui.padding"> <div v-for="(subItems, index) of items" :key="index" :class="ui.padding">
<NuxtLink v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ href, target, rel, navigate, isExternal }" v-bind="getNuxtLinkProps(item)" custom> <NuxtLink v-for="(item, subIndex) of subItems" :key="subIndex" v-slot="{ href, target, rel, navigate, isExternal, isActive }" v-bind="getNuxtLinkProps(item)" custom>
<HMenuItem v-slot="{ active, disabled: itemDisabled, close }" :disabled="item.disabled"> <HMenuItem v-slot="{ active, disabled: itemDisabled, close }" :disabled="item.disabled">
<component <component
:is="!!href ? 'a' : 'button'" :is="!!href ? 'a' : 'button'"
:href="!itemDisabled ? href : undefined" :href="!itemDisabled ? href : undefined"
:rel="rel" :rel="rel"
:target="target" :target="target"
:class="twMerge(twJoin(ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled), item.class)" :class="twMerge(twJoin(ui.item.base, ui.item.padding, ui.item.size, ui.item.rounded, active || isActive ? ui.item.active : ui.item.inactive, itemDisabled && ui.item.disabled), item.class)"
@click="onClick($event, item, { href, navigate, close, isExternal })" @click="onClick($event, item, { href, navigate, close, isExternal })"
> >
<slot :name="item.slot || 'item'" :item="item"> <slot :name="item.slot || 'item'" :item="item">
<UIcon v-if="item.icon" :name="item.icon" :class="twMerge(twJoin(ui.item.icon.base, active ? ui.item.icon.active : ui.item.icon.inactive), item.iconClass)" /> <UIcon v-if="item.icon" :name="item.icon" :class="twMerge(twJoin(ui.item.icon.base, active || isActive ? ui.item.icon.active : ui.item.icon.inactive), item.iconClass)" />
<UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" /> <UAvatar v-else-if="item.avatar" v-bind="{ size: ui.item.avatar.size, ...item.avatar }" :class="ui.item.avatar.base" />
<span :class="twMerge(ui.item.label, item.labelClass)">{{ item.label }}</span> <span :class="twMerge(ui.item.label, item.labelClass)">{{ item.label }}</span>
@@ -181,7 +182,19 @@ export default defineComponent({
} }
}) })
function onMouseOver () { function onTouchStart () {
if (!menuApi.value) {
return
}
if (menuApi.value.menuState === 0) {
menuApi.value.closeMenu()
} else {
menuApi.value.openMenu()
}
}
function onMouseEnter () {
if (props.mode !== 'hover' || !menuApi.value) { if (props.mode !== 'hover' || !menuApi.value) {
return return
} }
@@ -263,7 +276,8 @@ export default defineComponent({
trigger, trigger,
container, container,
containerStyle, containerStyle,
onMouseOver, onTouchStart,
onMouseEnter,
onMouseLeave, onMouseLeave,
onClick, onClick,
getNuxtLinkProps, getNuxtLinkProps,

View File

@@ -39,6 +39,7 @@ import type { Strategy } from '../../types'
import appConfig from '#build/app.config' import appConfig from '#build/app.config'
import { checkbox } from '#ui/ui.config' import { checkbox } from '#ui/ui.config'
import colors from '#ui-colors' import colors from '#ui-colors'
import { useId } from '#app'
const config = mergeConfig<typeof checkbox>(appConfig.ui.strategy, appConfig.ui.checkbox, checkbox) const config = mergeConfig<typeof checkbox>(appConfig.ui.strategy, appConfig.ui.checkbox, checkbox)
@@ -105,7 +106,8 @@ export default defineComponent({
setup (props, { emit }) { setup (props, { emit }) {
const { ui, attrs } = useUI('checkbox', toRef(props, 'ui'), config, toRef(props, 'class')) const { ui, attrs } = useUI('checkbox', toRef(props, 'ui'), config, toRef(props, 'class'))
const { emitFormChange, color, name, inputId } = useFormGroup(props) const { emitFormChange, color, name, inputId: _inputId } = useFormGroup(props)
const inputId = _inputId.value ?? useId()
const toggle = computed({ const toggle = computed({
get () { get () {

View File

@@ -1,6 +1,6 @@
<template> <template>
<div :class="ui.wrapper"> <div :class="ui.wrapper">
<fieldset v-bind="attrs"> <fieldset v-bind="attrs" :class="ui.fieldset">
<legend v-if="legend || $slots.legend" :class="ui.legend"> <legend v-if="legend || $slots.legend" :class="ui.legend">
<slot name="legend"> <slot name="legend">
{{ legend }} {{ legend }}

View File

@@ -362,7 +362,7 @@ export default defineComponent({
} else { } else {
return null return null
} }
} else { } else if (props.modelValue) {
if (props.valueAttribute) { if (props.valueAttribute) {
const option = props.options.find(option => option[props.valueAttribute] === props.modelValue) const option = props.options.find(option => option[props.valueAttribute] === props.modelValue)
return option ? option[props.optionAttribute] : null return option ? option[props.optionAttribute] : null
@@ -370,6 +370,8 @@ export default defineComponent({
return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : props.modelValue[props.optionAttribute] return ['string', 'number'].includes(typeof props.modelValue) ? props.modelValue : props.modelValue[props.optionAttribute]
} }
} }
return null
}) })
const selectClass = computed(() => { const selectClass = computed(() => {

View File

@@ -1,10 +1,10 @@
<template> <template>
<div :class="ui.group.wrapper" role="option"> <div :class="ui.group.wrapper">
<h2 v-if="label" :class="ui.group.label"> <h2 v-if="label" :class="ui.group.label">
{{ label }} {{ label }}
</h2> </h2>
<div :class="ui.group.container" role="listbox" :aria-label="group[groupAttribute]"> <div :class="ui.group.container" :aria-label="group[groupAttribute]">
<HComboboxOption <HComboboxOption
v-for="(command, index) of group.commands" v-for="(command, index) of group.commands"
:key="`${group.key}-${index}`" :key="`${group.key}-${index}`"

View File

@@ -18,7 +18,7 @@
{{ title }} {{ title }}
</slot> </slot>
</p> </p>
<p v-if="(description || $slots.description)" :class="ui.description"> <p v-if="(description || $slots.description)" :class="twMerge(ui.description, !(title && $slots.title) && 'mt-0 leading-5')">
<slot name="description" :description="description"> <slot name="description" :description="description">
{{ description }} {{ description }}
</slot> </slot>

View File

@@ -7,7 +7,8 @@
:disabled="disabled" :disabled="disabled"
:class="ui.trigger" :class="ui.trigger"
role="button" role="button"
@mouseover="onMouseOver" @mouseenter="onMouseEnter"
@touchstart.prevent="onTouchStart"
> >
<slot :open="open" :close="close"> <slot :open="open" :close="close">
<button :disabled="disabled"> <button :disabled="disabled">
@@ -20,7 +21,7 @@
<div v-if="open" :class="[ui.overlay.base, ui.overlay.background]" /> <div v-if="open" :class="[ui.overlay.base, ui.overlay.background]" />
</Transition> </Transition>
<div v-if="open" ref="container" :class="[ui.container, ui.width]" :style="containerStyle" @mouseover="onMouseOver"> <div v-if="open" ref="container" :class="[ui.container, ui.width]" :style="containerStyle">
<Transition appear v-bind="ui.transition"> <Transition appear v-bind="ui.transition">
<div> <div>
<div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" /> <div v-if="popper.arrow" data-popper-arrow :class="Object.values(ui.arrow)" />
@@ -153,7 +154,19 @@ export default defineComponent({
} }
}) })
function onMouseOver () { function onTouchStart () {
if (!popoverApi.value) {
return
}
if (popoverApi.value.popoverState === 0) {
popoverApi.value.closePopover()
} else {
popoverApi.value.togglePopover()
}
}
function onMouseEnter () {
if (props.mode !== 'hover' || !popoverApi.value) { if (props.mode !== 'hover' || !popoverApi.value) {
return return
} }
@@ -223,7 +236,8 @@ export default defineComponent({
trigger, trigger,
container, container,
containerStyle, containerStyle,
onMouseOver, onTouchStart,
onMouseEnter,
onMouseLeave onMouseLeave
} }
} }

View File

@@ -1,5 +1,5 @@
<template> <template>
<div ref="trigger" :class="ui.wrapper" v-bind="attrs" @mouseover="onMouseOver" @mouseleave="onMouseLeave"> <div ref="trigger" :class="ui.wrapper" v-bind="attrs" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave">
<slot :open="open"> <slot :open="open">
Hover Hover
</slot> </slot>
@@ -96,7 +96,7 @@ export default defineComponent({
// Methods // Methods
function onMouseOver () { function onMouseEnter () {
// cancel programmed closing // cancel programmed closing
if (closeTimeout) { if (closeTimeout) {
clearTimeout(closeTimeout) clearTimeout(closeTimeout)
@@ -137,7 +137,7 @@ export default defineComponent({
trigger, trigger,
container, container,
open, open,
onMouseOver, onMouseEnter,
onMouseLeave onMouseLeave
} }
} }

View File

@@ -1,7 +1,8 @@
export default { export default {
wrapper: 'relative flex items-start', wrapper: 'relative flex items-start',
fieldset: '',
legend: 'text-sm font-medium text-gray-700 dark:text-gray-200 mb-1', legend: 'text-sm font-medium text-gray-700 dark:text-gray-200 mb-1',
default: { default: {
color: 'primary' color: 'primary'
} }
} }

View File

@@ -9,7 +9,7 @@ export default {
inactive: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white', inactive: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white',
label: 'truncate relative', label: 'truncate relative',
icon: { icon: {
base: 'flex-shrink-0 w-5 h-5', base: 'flex-shrink-0 w-5 h-5 relative',
active: 'text-gray-700 dark:text-gray-200', active: 'text-gray-700 dark:text-gray-200',
inactive: 'text-gray-400 dark:text-gray-500 group-hover:text-gray-700 dark:group-hover:text-gray-200' inactive: 'text-gray-400 dark:text-gray-500 group-hover:text-gray-700 dark:group-hover:text-gray-200'
}, },

View File

@@ -11,7 +11,7 @@ export default {
inactive: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:before:bg-gray-50 dark:hover:before:bg-gray-800/50', inactive: 'text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-white hover:before:bg-gray-50 dark:hover:before:bg-gray-800/50',
label: 'truncate relative', label: 'truncate relative',
icon: { icon: {
base: 'flex-shrink-0 w-5 h-5', base: 'flex-shrink-0 w-5 h-5 relative',
active: 'text-gray-700 dark:text-gray-200', active: 'text-gray-700 dark:text-gray-200',
inactive: 'text-gray-400 dark:text-gray-500 group-hover:text-gray-700 dark:group-hover:text-gray-200' inactive: 'text-gray-400 dark:text-gray-500 group-hover:text-gray-700 dark:group-hover:text-gray-200'
}, },

View File

@@ -4,7 +4,7 @@ export default {
container: 'flex min-h-full items-end sm:items-center justify-center text-center', container: 'flex min-h-full items-end sm:items-center justify-center text-center',
padding: 'p-4 sm:p-0', padding: 'p-4 sm:p-0',
margin: 'sm:my-8', margin: 'sm:my-8',
base: 'relative text-left rtl:text-right overflow-hidden flex flex-col', base: 'relative text-left rtl:text-right flex flex-col',
overlay: { overlay: {
base: 'fixed inset-0 transition-opacity', base: 'fixed inset-0 transition-opacity',
background: 'bg-gray-200/75 dark:bg-gray-800/75', background: 'bg-gray-200/75 dark:bg-gray-800/75',

View File

@@ -28,5 +28,8 @@ export default {
openDelay: 0, openDelay: 0,
closeDelay: 0 closeDelay: 0
}, },
arrow arrow: {
...arrow,
base: '[@media(pointer:coarse)]:hidden invisible before:visible before:block before:rotate-45 before:z-[-1] before:w-2 before:h-2'
}
} }