mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-15 20:48:12 +01:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a01e0279a9 | ||
|
|
ccbf3e78b1 | ||
|
|
dcc0a6b3a9 | ||
|
|
bb4cd0b1b9 | ||
|
|
ae02f23a8c | ||
|
|
8caa78819a | ||
|
|
6fd5a70ac9 | ||
|
|
cfcd2f1371 | ||
|
|
c47f5e6a68 | ||
|
|
37f1a1b5ad | ||
|
|
0c2a5d98cf | ||
|
|
aabf1dd9eb | ||
|
|
c7c78cb47b | ||
|
|
3335a6a32c |
@@ -2,6 +2,15 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
### [2.0.3](https://github.com/nuxtlabs/ui/compare/v2.0.2...v2.0.3) (2023-05-15)
|
||||
|
||||
### [2.0.2](https://github.com/nuxtlabs/ui/compare/v2.0.1...v2.0.2) (2023-05-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **LinkCustom:** handle `button` when no `to` prop ([c7c78cb](https://github.com/nuxtlabs/ui/commit/c7c78cb47b00963c8a9ea0c0599fbc7e128cff66))
|
||||
|
||||
### [2.0.1](https://github.com/nuxtlabs/ui/compare/v2.0.0...v2.0.1) (2023-05-11)
|
||||
|
||||
|
||||
|
||||
@@ -1,38 +1,48 @@
|
||||
import type { RouterConfig } from '@nuxt/schema'
|
||||
// https://router.vuejs.org/api/interfaces/routeroptions.html
|
||||
export default <RouterConfig> {
|
||||
scrollBehavior (to, _form, savedPosition) {
|
||||
if (history.state.stop) { return }
|
||||
|
||||
if (history.state.smooth) {
|
||||
return {
|
||||
el: history.state.smooth,
|
||||
behavior: 'smooth'
|
||||
}
|
||||
}
|
||||
function findHashPosition (hash): { el: any, behavior: ScrollBehavior, top: number } {
|
||||
const el = document.querySelector(hash)
|
||||
// vue-router does not incorporate scroll-margin-top on its own.
|
||||
if (el) {
|
||||
const top = parseFloat(getComputedStyle(el).scrollMarginTop)
|
||||
|
||||
if (to.hash) {
|
||||
const el = document.querySelector(to.hash) as any
|
||||
|
||||
if (!el) { return }
|
||||
|
||||
const { marginTop } = getComputedStyle(el)
|
||||
|
||||
const marginTopValue = parseInt(marginTop)
|
||||
|
||||
const offset = (document.querySelector(to.hash) as any).offsetTop - marginTopValue
|
||||
|
||||
return {
|
||||
top: offset,
|
||||
behavior: 'smooth'
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll to top of window
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
} else {
|
||||
return { top: 0 }
|
||||
return {
|
||||
el: hash,
|
||||
behavior: 'smooth',
|
||||
top
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://router.vuejs.org/api/#routeroptions
|
||||
export default <RouterConfig>{
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
const nuxtApp = useNuxtApp()
|
||||
|
||||
// If history back
|
||||
if (savedPosition) {
|
||||
// Handle Suspense resolution
|
||||
return new Promise((resolve) => {
|
||||
nuxtApp.hooks.hookOnce('page:finish', () => {
|
||||
setTimeout(() => resolve(savedPosition), 50)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Scroll to heading on click
|
||||
if (to.hash) {
|
||||
return new Promise((resolve) => {
|
||||
if (to.path === from.path) {
|
||||
setTimeout(() => resolve(findHashPosition(to.hash)), 50)
|
||||
} else {
|
||||
nuxtApp.hooks.hookOnce('page:finish', () => {
|
||||
setTimeout(() => resolve(findHashPosition(to.hash)), 50)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Scroll to top of window
|
||||
return { top: 0 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<kbd class="inline-flex items-center justify-center font-sans font-semibold px-1 h-5 min-w-[20px] text-[11px] rounded !my-0 align-text-top ring-1 ring-gray-300 dark:ring-gray-700">
|
||||
<ClientOnly>
|
||||
{{ shortcut }}
|
||||
</ClientOnly>
|
||||
</kbd>
|
||||
<UKbd class="!my-0 align-text-top">
|
||||
{{ shortcut }}
|
||||
</UKbd>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
|
||||
const people = [
|
||||
{ id: 1, label: 'Wade Cooper' },
|
||||
@@ -19,9 +19,9 @@ const selected = ref([])
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="open">
|
||||
<UModal v-model="isOpen">
|
||||
<UCommandPalette
|
||||
v-model="selected"
|
||||
multiple
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
<script setup>
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
const isOpen = ref(false)
|
||||
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||
|
||||
function openContextMenu () {
|
||||
const top = unref(y)
|
||||
function onContextMenu () {
|
||||
const top = unref(y) - unref(windowY)
|
||||
const left = unref(x)
|
||||
|
||||
virtualElement.value.getBoundingClientRect = () => ({
|
||||
@@ -20,8 +21,8 @@ function openContextMenu () {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full" @contextmenu.prevent="openContextMenu">
|
||||
<Placeholder class="h-20 w-full flex items-center justify-center">
|
||||
<div class="w-full" @contextmenu.prevent="onContextMenu">
|
||||
<Placeholder class="h-96 select-none w-full flex items-center justify-center">
|
||||
Right click here
|
||||
</Placeholder>
|
||||
|
||||
|
||||
@@ -5,6 +5,6 @@ const { metaSymbol } = useShortcuts()
|
||||
<template>
|
||||
<div class="flex items-center gap-0.5">
|
||||
<UKbd>{{ metaSymbol }}</UKbd>
|
||||
<UKbd>U</UKbd>
|
||||
<UKbd>K</UKbd>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="open">
|
||||
<UModal v-model="isOpen">
|
||||
<div class="p-4">
|
||||
<Placeholder class="h-48" />
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="open">
|
||||
<UModal v-model="isOpen">
|
||||
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<Placeholder class="h-8" />
|
||||
|
||||
9
docs/components/content/examples/SkeletonExample.vue
Normal file
9
docs/components/content/examples/SkeletonExample.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<div class="flex items-center space-x-4">
|
||||
<USkeleton class="h-12 w-12" :ui="{ rounded: 'rounded-full' }" />
|
||||
<div class="space-y-2">
|
||||
<USkeleton class="h-4 w-[250px]" />
|
||||
<USkeleton class="h-4 w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,12 +1,12 @@
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="open">
|
||||
<USlideover v-model="isOpen">
|
||||
<div class="p-4 h-full">
|
||||
<Placeholder class="w-full h-full" />
|
||||
</div>
|
||||
|
||||
33
docs/content/1.getting-started/1.index.md
Normal file
33
docs/content/1.getting-started/1.index.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: 'Components library as a Nuxt module using TailwindCSS and HeadlessUI.'
|
||||
---
|
||||
|
||||
This module has been developed by the [NuxtLabs](https://nuxtlabs.com/) team for [Volta](https://volta.net) and [Nuxt Studio](https://nuxt.studio/), its goal is to provide everything related to UI when building a Nuxt app. This includes components, icons, colors, dark mode but also keyboard shortcuts.
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
[Volta](https://volta.net/) entire UI is built with this module alongside the 50+ keyboard shortcuts defined.
|
||||
::
|
||||
|
||||
## Features
|
||||
|
||||
- Fully styled and customizable components
|
||||
- HMR support through Nuxt App Config
|
||||
- Dark mode support
|
||||
- Keyboard shortcuts
|
||||
- Bundled icons
|
||||
- Fully typed
|
||||
|
||||
## Credits
|
||||
|
||||
- [nuxt/nuxt](https://github.com/nuxt/nuxt)
|
||||
- [nuxt-modules/color-mode](https://github.com/nuxt-modules/color-mode)
|
||||
- [nuxt-modules/tailwindcss](https://github.com/nuxt-modules/tailwindcss)
|
||||
- [tailwindlabs/tailwindcss](https://github.com/tailwindlabs/tailwindcss)
|
||||
- [tailwindlabs/headlessui](https://github.com/tailwindlabs/headlessui)
|
||||
- [vueuse/vueuse](https://github.com/vueuse/vueuse)
|
||||
- [egoist/tailwindcss-icons](https://github.com/egoist/tailwindcss-icons)
|
||||
|
||||
::alert{icon="i-heroicons-exclamation-triangle"}
|
||||
This documentation is still a work in progress and will be updated regularly.
|
||||
::
|
||||
@@ -1,11 +1,8 @@
|
||||
---
|
||||
title: 'nuxthq/ui'
|
||||
description: 'Components library as a Nuxt module using TailwindCSS and HeadlessUI.'
|
||||
navigation:
|
||||
title: Installation
|
||||
description: 'Learn how to install and configure the module in your Nuxt app.'
|
||||
---
|
||||
|
||||
## Installation
|
||||
## Overview
|
||||
|
||||
1. Install `@nuxthq/ui` dependency to your project:
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
navigation: false
|
||||
---
|
||||
|
||||
## Overview
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
navigation: false
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
## Composables
|
||||
|
||||
## `defineShortcuts`
|
||||
|
||||
## `useShortcuts`
|
||||
167
docs/content/1.getting-started/3.theming.md
Normal file
167
docs/content/1.getting-started/3.theming.md
Normal file
@@ -0,0 +1,167 @@
|
||||
---
|
||||
description: 'Learn how to customize the look and feel of the components.'
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This module relies on Nuxt [App Config](https://nuxt.com/docs/guide/directory-structure/app-config#app-config-file) file to customize the look and feel of the components at runtime with HMR (hot-module-replacement).
|
||||
|
||||
## Colors
|
||||
|
||||
Components are based on a `primary` and a `gray` color. You can change them in your `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
primary: 'sky',
|
||||
gray: 'cool'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
As this module uses TailwindCSS under the hood, you can use any of the [TailwindCSS colors](https://tailwindcss.com/docs/customizing-colors#color-palette-reference) or your own custom colors. By default, the `primary` color is `sky` and the `gray` color is `cool`.
|
||||
|
||||
To provide dynamic colors that can be changed at runtime, this module uses CSS variables. As TailwindCSS already has a `gray` color, the module automatically renames it to `cool` to avoid conflicts (`coolGray` was renamed to `gray` when Tailwind CSS v3.0 was released).
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
Try to change the `primary` and `gray` colors in the navbar and see the colors change live.
|
||||
::
|
||||
|
||||
Components that have a `color` prop like [Avatar](/elements/avatar), [Badge](/elements/badge) and [Button](/elements/button) will use the `primary` color by default but will handle all the colors defined in your `tailwind.config.ts` or the default TailwindCSS colors.
|
||||
|
||||
## Components
|
||||
|
||||
Components are styled with TailwindCSS but classes are all defined in the default [app.config.ts](https://github.com/nuxtlabs/ui/blob/dev/src/runtime/app.config.ts) file. You can override them in your `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
container: {
|
||||
constrained: 'max-w-5xl'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Each component has a `ui` prop that allows you to customize everything specifically.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UContainer :ui="{ constrained: 'max-w-2xl' }">
|
||||
<slot />
|
||||
</UContainer>
|
||||
</template>
|
||||
```
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
You can find the default classes for each component under the `Preset` section.
|
||||
::
|
||||
|
||||
Some component props like `size`, `color`, `variant`, etc. have a default value that you can override in your `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
button: {
|
||||
default: {
|
||||
size: 'md',
|
||||
color: 'gray',
|
||||
variant: 'ghost'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Icons
|
||||
|
||||
You can use any icon (100,000+) from [Iconify](https://iconify.design/).
|
||||
|
||||
Some components have an `icon` prop that allows you to add an icon to the component.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UButton icon="i-heroicons-magnifying-glass" />
|
||||
</template>
|
||||
```
|
||||
|
||||
You can also use the [Icon](/elements/icon) component to add an icon anywhere in your app by following this pattern: `i-{collection_name}-{icon_name}`.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UIcon name="i-heroicons-moon" />
|
||||
</template>
|
||||
```
|
||||
|
||||
By default, the module uses [Heroicons](https://heroicons.com/) but you can change it from the module options in your `nuxt.config.ts`.
|
||||
|
||||
```ts [nuxt.config.ts]
|
||||
export default defineNuxtConfig({
|
||||
ui: {
|
||||
icons: ['mdi', 'simple-icons']
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
Search the icon you want to use on https://icones.js.org built by [@antfu](https://github.com/antfu).
|
||||
::
|
||||
|
||||
Unlike the official [nuxt-icon](https://github.com/nuxt-modules/icon/) module, this module will not fetch any icon from the web and will only bundle the icons you use in your app thanks to [egoist/tailwindcss-icons](https://github.com/egoist/tailwindcss-icons).
|
||||
|
||||
However, you will need to install the icon packages you want to use.
|
||||
|
||||
```sh
|
||||
yarn add --dev @iconify/json-{collection_name}
|
||||
```
|
||||
|
||||
You can easily replace all the default icons of the components in your `app.config.ts`.
|
||||
|
||||
```ts [app.config.ts]
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
button: {
|
||||
default: {
|
||||
loadingIcon: 'i-octicon-sync-24'
|
||||
}
|
||||
},
|
||||
input: {
|
||||
default: {
|
||||
loadingIcon: 'i-octicon-sync-24'
|
||||
}
|
||||
},
|
||||
select: {
|
||||
default: {
|
||||
trailingIcon: 'i-octicon-chevron-down-24'
|
||||
}
|
||||
},
|
||||
selectMenu: {
|
||||
default: {
|
||||
selectedIcon: 'i-octicon-check-24'
|
||||
}
|
||||
},
|
||||
notification: {
|
||||
default: {
|
||||
close: {
|
||||
icon: 'i-octicon-x-24'
|
||||
}
|
||||
}
|
||||
},
|
||||
commandPalette: {
|
||||
default: {
|
||||
icon: 'i-octicon-search-24',
|
||||
selectedIcon: 'i-octicon-check-24',
|
||||
empty: {
|
||||
icon: 'i-octicon-search-24'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Dark mode
|
||||
|
||||
All the components are styled with dark mode in mind.
|
||||
|
||||
Thanks to [TailwindCSS dark mode](https://tailwindcss.com/docs/dark-mode#toggling-dark-mode-manually) `class` strategy and the [@nuxtjs/color-mode](https://github.com/nuxt-modules/color-mode) module, you literally have nothing to do.
|
||||
63
docs/content/1.getting-started/4.shortcuts.md
Normal file
63
docs/content/1.getting-started/4.shortcuts.md
Normal file
@@ -0,0 +1,63 @@
|
||||
---
|
||||
description: 'Learn how to display and define keyboard shortcuts in your app.'
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Some components like [Dropdown](/elements/dropdown), [Command Palette](/navigation/command-palette) and [Tooltip](/overlays/tooltip) support the display of keyboard shortcuts.
|
||||
|
||||
```vue
|
||||
<UDropdown :items="[{ label: 'Edit', shortcuts: ['E'] }]" />
|
||||
```
|
||||
|
||||
Shortcuts are displayed and styled through the [Kbd](/elements/kbd) component.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div class="flex items-center gap-0.5">
|
||||
<UKbd>⌘</UKbd>
|
||||
<UKbd>K</UKbd>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
You will have a preview of how shortcuts are rendered in each component page.
|
||||
::
|
||||
|
||||
## `defineShortcuts`
|
||||
|
||||
This module provides a `defineShortcuts` composable that allows you to define keyboard shortcuts in your app really easily.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UModal v-model="isOpen" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const isOpen = ref(false)
|
||||
|
||||
defineShortcuts({
|
||||
meta_k: {
|
||||
usingInput: true,
|
||||
handler: () => {
|
||||
isOpen.value = !isOpen.value
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## `useShortcuts`
|
||||
|
||||
To display shortcuts in your app according to the user's OS, you can use the `useShortcuts` composable.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const { metaSymbol } = useShortcuts()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UKbd>{{ metaSymbol }}</UKbd>
|
||||
</template>
|
||||
```
|
||||
@@ -37,7 +37,7 @@ props:
|
||||
Button
|
||||
::
|
||||
|
||||
Besides all the colors from the `ui.colors` object, you can also use the `white` and `gray` and `black` colors with their pre-defined variants.
|
||||
Besides all the colors from the `ui.colors` object, you can also use the `white`, `gray` and `black` colors with their pre-defined variants.
|
||||
|
||||
#### White
|
||||
|
||||
@@ -161,6 +161,8 @@ Button
|
||||
|
||||
Use the `loading` prop to show a loading icon and disable the Button.
|
||||
|
||||
Use the `loadingIcon` prop to set a different icon or change it globally in `ui.button.default.loadingIcon`. Defaults to `i-heroicons-arrow-path-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
props:
|
||||
|
||||
20
docs/content/2.elements/5.icon.md
Normal file
20
docs/content/2.elements/5.icon.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
github: true
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
::component-card
|
||||
---
|
||||
props:
|
||||
name: 'i-heroicons-light-bulb'
|
||||
---
|
||||
::
|
||||
|
||||
::alert{icon="i-heroicons-exclamation-triangle"}
|
||||
When playing with the `name` prop above, you won't be able to use any icon you want as icons are bundled on build as explained in the [theming section](/getting-started/theming#icons).
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
@@ -7,6 +7,27 @@ navigation:
|
||||
|
||||
## Usage
|
||||
|
||||
Use the default slot to set the text of the Kbd.
|
||||
|
||||
::component-card
|
||||
---
|
||||
code: K
|
||||
---
|
||||
|
||||
K
|
||||
::
|
||||
|
||||
You can also use the `value` prop:
|
||||
|
||||
::component-card
|
||||
---
|
||||
props:
|
||||
value: K
|
||||
---
|
||||
::
|
||||
|
||||
As explained in the [Shortcuts](/getting-started/shortcuts) page, you can use the `metaSymbol` property of the `useShortcuts` composable to display the meta key according to the user's OS.
|
||||
|
||||
::component-example
|
||||
#default
|
||||
:kbd-example
|
||||
@@ -20,7 +41,7 @@ const { metaSymbol } = useShortcuts()
|
||||
<template>
|
||||
<div class="flex items-center gap-0.5">
|
||||
<UKbd>{{ metaSymbol }}</UKbd>
|
||||
<UKbd>U</UKbd>
|
||||
<UKbd>K</UKbd>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
@@ -34,6 +55,7 @@ Use the `size` prop to change the size of the Kbd.
|
||||
---
|
||||
props:
|
||||
size: 'sm'
|
||||
code: 'U'
|
||||
---
|
||||
|
||||
U
|
||||
@@ -24,6 +24,33 @@ props:
|
||||
---
|
||||
::
|
||||
|
||||
### Placeholder
|
||||
|
||||
Use the `placeholder` prop to set a placeholder text.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'input'
|
||||
props:
|
||||
placeholder: 'Search...'
|
||||
---
|
||||
::
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` prop to change the style of the Input.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'input'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
appearance: 'white'
|
||||
---
|
||||
::
|
||||
|
||||
### Icon
|
||||
|
||||
Use any icon from [Iconify](https://icones.js.org) by setting the `icon` prop by using this pattern: `i-{collection_name}-{icon_name}`.
|
||||
@@ -34,15 +61,14 @@ Use the `leading` and `trailing` props to set the icon position or the `leadingI
|
||||
---
|
||||
baseProps:
|
||||
name: 'input'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
icon: 'i-heroicons-magnifying-glass-20-solid'
|
||||
appearance: 'white'
|
||||
size: 'sm'
|
||||
trailing: false
|
||||
placeholder: 'Search...'
|
||||
excludedProps:
|
||||
- icon
|
||||
- placeholder
|
||||
---
|
||||
::
|
||||
|
||||
@@ -67,6 +93,8 @@ excludedProps:
|
||||
|
||||
Use the `loading` prop to show a loading icon and disable the Input.
|
||||
|
||||
Use the `loadingIcon` prop to set a different icon or change it globally in `ui.input.default.loadingIcon`. Defaults to `i-heroicons-arrow-path-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
|
||||
@@ -11,6 +11,61 @@ baseProps:
|
||||
---
|
||||
::
|
||||
|
||||
### Size
|
||||
|
||||
Use the `size` prop to change the size of the Textarea.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'textarea'
|
||||
props:
|
||||
size: 'sm'
|
||||
---
|
||||
::
|
||||
|
||||
### Placeholder
|
||||
|
||||
Use the `placeholder` prop to set a placeholder text.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'textarea'
|
||||
props:
|
||||
placeholder: 'Search...'
|
||||
---
|
||||
::
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` prop to change the style of the Textarea.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'textarea'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
appearance: 'white'
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the Textarea.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'input'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
appearance: 'white'
|
||||
disabled: true
|
||||
---
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -8,11 +8,109 @@ github: true
|
||||
---
|
||||
baseProps:
|
||||
name: 'select'
|
||||
modelValue: 'Canada'
|
||||
modelValue: 'United States'
|
||||
props:
|
||||
options:
|
||||
- 'United States'
|
||||
- 'Canada'
|
||||
- 'Mexico'
|
||||
excludedProps:
|
||||
- options
|
||||
---
|
||||
::
|
||||
|
||||
### Size
|
||||
|
||||
Use the `size` prop to change the size of the Input.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'select'
|
||||
options:
|
||||
- 'United States'
|
||||
- 'Canada'
|
||||
- 'Mexico'
|
||||
props:
|
||||
size: 'sm'
|
||||
---
|
||||
::
|
||||
|
||||
### Placeholder
|
||||
|
||||
Use the `placeholder` prop to set a placeholder text.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'select'
|
||||
options:
|
||||
- 'United States'
|
||||
- 'Canada'
|
||||
- 'Mexico'
|
||||
props:
|
||||
placeholder: 'Search...'
|
||||
---
|
||||
::
|
||||
|
||||
### Appearance
|
||||
|
||||
Use the `appearance` prop to change the style of the Select.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'select'
|
||||
options:
|
||||
- 'United States'
|
||||
- 'Canada'
|
||||
- 'Mexico'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
appearance: 'white'
|
||||
---
|
||||
::
|
||||
|
||||
### Icon
|
||||
|
||||
Use any icon from [Iconify](https://icones.js.org) by setting the `icon` prop by using this pattern: `i-{collection_name}-{icon_name}`.
|
||||
|
||||
Use the `trailingIcon` prop to set a different icon or change it globally in `ui.select.default.trailingIcon`. Defaults to `i-heroicons-chevron-down-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'select'
|
||||
options:
|
||||
- 'United States'
|
||||
- 'Canada'
|
||||
- 'Mexico'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
icon: 'i-heroicons-magnifying-glass-20-solid'
|
||||
appearance: 'white'
|
||||
size: 'sm'
|
||||
excludedProps:
|
||||
- icon
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the Input.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'select'
|
||||
options:
|
||||
- 'United States'
|
||||
- 'Canada'
|
||||
- 'Mexico'
|
||||
placeholder: 'Search...'
|
||||
props:
|
||||
appearance: 'white'
|
||||
disabled: true
|
||||
---
|
||||
::
|
||||
|
||||
|
||||
@@ -7,6 +7,10 @@ headlessui:
|
||||
|
||||
## Usage
|
||||
|
||||
The SelectMenu component renders by default a [Select](/forms/select) component and is based on the `ui.select` preset. You can use most of the Select props to configure the display if you don't want to override the default slot such as [size](/forms/select#size), [placeholder](/forms/select#placeholder), [appearance](/forms/select#appearance), [icon](/forms/select#icon), [disabled](/forms/select#disabled), etc.
|
||||
|
||||
Like the Select component, you can use the `options` prop to pass an array of strings or objects.
|
||||
|
||||
::component-example
|
||||
#default
|
||||
:select-menu-example-basic{class="max-w-[12rem] w-full"}
|
||||
@@ -25,7 +29,7 @@ const selected = ref(people[0])
|
||||
```
|
||||
::
|
||||
|
||||
You can use multiple values but you have to override the `#label` slot and handle the display yourself.
|
||||
You can use the `multiple` prop to select multiple values but you have to override the `#label` slot and handle the display yourself.
|
||||
|
||||
::component-example
|
||||
#default
|
||||
@@ -76,7 +80,7 @@ const selected = ref(people[3])
|
||||
```
|
||||
::
|
||||
|
||||
You can pass an array of objects to `options` and either compare on the whole object or use the `by` prop to compare on a specific key.
|
||||
You can pass an array of objects to `options` and either compare on the whole object or use the `by` prop to compare on a specific key. You can configure which field will be used to display the label through the `optionAttribute` prop that defaults to `label`.
|
||||
|
||||
::component-example
|
||||
#default
|
||||
@@ -131,6 +135,10 @@ const selected = ref(people[0])
|
||||
|
||||
Use any icon from [Iconify](https://icones.js.org) by setting the `icon` prop by using this pattern: `i-{collection_name}-{icon_name}`.
|
||||
|
||||
Use the `trailingIcon` prop to set a different icon or change it globally in `ui.select.default.trailingIcon`. Defaults to `i-heroicons-chevron-down-20-solid`.
|
||||
|
||||
Use the `selectedIcon` prop to set a different icon or change it globally in `ui.selectMenu.default.selectedIcon`. Defaults to `i-heroicons-check-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
@@ -161,21 +169,6 @@ props:
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the SelectMenu.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
class: 'max-w-[12rem] w-full'
|
||||
placeholder: 'Select a person'
|
||||
options: ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
|
||||
props:
|
||||
disabled: true
|
||||
---
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
@@ -5,6 +5,65 @@ github: true
|
||||
## Usage
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'checkbox'
|
||||
---
|
||||
::
|
||||
|
||||
### Label
|
||||
|
||||
Use the `label` prop to display a label on the right.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'checkbox1'
|
||||
props:
|
||||
label: 'Label'
|
||||
---
|
||||
::
|
||||
|
||||
### Required
|
||||
|
||||
Use the `required` prop to display a red star next to the label.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'checkbox2'
|
||||
props:
|
||||
label: 'Label'
|
||||
required: true
|
||||
---
|
||||
::
|
||||
|
||||
### Help
|
||||
|
||||
Use the `help` prop to display some text under the Checkbox.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'checkbox3'
|
||||
props:
|
||||
label: 'Label'
|
||||
help: 'Please check this box'
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the Checkbox.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'checkbox4'
|
||||
modelValue: true
|
||||
props:
|
||||
disabled: true
|
||||
---
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
@@ -5,6 +5,65 @@ github: true
|
||||
## Usage
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'radio'
|
||||
---
|
||||
::
|
||||
|
||||
### Label
|
||||
|
||||
Use the `label` prop to display a label on the right.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'radio1'
|
||||
props:
|
||||
label: 'Label'
|
||||
---
|
||||
::
|
||||
|
||||
### Required
|
||||
|
||||
Use the `required` prop to display a red star next to the label.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'radio2'
|
||||
props:
|
||||
label: 'Label'
|
||||
required: true
|
||||
---
|
||||
::
|
||||
|
||||
### Help
|
||||
|
||||
Use the `help` prop to display some text under the Radio.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'radio3'
|
||||
props:
|
||||
label: 'Label'
|
||||
help: 'Please choose one'
|
||||
---
|
||||
::
|
||||
|
||||
### Disabled
|
||||
|
||||
Use the `disabled` prop to disable the Radio.
|
||||
|
||||
::component-card
|
||||
---
|
||||
baseProps:
|
||||
name: 'radio4'
|
||||
value: true
|
||||
props:
|
||||
disabled: true
|
||||
---
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
@@ -57,7 +57,7 @@ You can put a `CommandPalette` anywhere you want but it's most commonly used ins
|
||||
#code
|
||||
```vue
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
|
||||
const people = [
|
||||
{ id: 1, label: 'Wade Cooper' },
|
||||
@@ -77,9 +77,9 @@ const selected = ref([])
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="open">
|
||||
<UModal v-model="isOpen">
|
||||
<UCommandPalette
|
||||
v-model="selected"
|
||||
multiple
|
||||
@@ -159,6 +159,8 @@ function onSelect (option) {
|
||||
|
||||
Use any icon from [Iconify](https://icones.js.org) by setting the `icon` prop by using this pattern: `i-{collection_name}-{icon_name}`.
|
||||
|
||||
Use the `selectedIcon` prop to set a different icon or change it globally in `ui.commandPalette.default.selectedIcon`. Defaults to `i-heroicons-check-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
padding: false
|
||||
@@ -230,6 +232,35 @@ excludedProps:
|
||||
---
|
||||
::
|
||||
|
||||
## Full-text search
|
||||
|
||||
The CommandPalette component takes care of the full-text search for you with [Fuse.js](https://fusejs.io). You can pass all the options of Fuse.js through the `fuse` prop.
|
||||
|
||||
When searching for a command, the component will look for a `label` property on the command by default. You can customize this behaviour by overriding the `commandAttribute` prop. This will also affect the display of the command.
|
||||
|
||||
You can also highlight the matches in the command by setting the `fuse.fuseOptions.includeMatches` to `true`. The CommandPalette component automatically takes care of the highlighting for you.
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<UCommandPalette
|
||||
command-attribute="title"
|
||||
:fuse="{
|
||||
fuseOptions: {
|
||||
ignoreLocation: true,
|
||||
includeMatches: true,
|
||||
threshold: 0,
|
||||
keys: ['title', 'description', 'children.children.value', 'children.children.children.value']
|
||||
},
|
||||
resultLimit: 10
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
Try it yourself in this documentation's search by pressing :badge-shortcut{value="meta"} :badge-shortcut{value="K" class="ml-1"}.
|
||||
::
|
||||
|
||||
## Themes
|
||||
|
||||
Our theming system provides a lot of flexibility to customize the component. Here is some examples of what you can do.
|
||||
|
||||
@@ -14,14 +14,14 @@ headlessui:
|
||||
#code
|
||||
```vue
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="open">
|
||||
<UModal v-model="isOpen">
|
||||
<!-- Content -->
|
||||
</UModal>
|
||||
</div>
|
||||
@@ -38,14 +38,14 @@ You can put a [Card](/layout/card) component inside your Modal to handle forms a
|
||||
#code
|
||||
```vue
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<UModal v-model="open">
|
||||
<UModal v-model="isOpen">
|
||||
<UCard :ui="{ divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
|
||||
<template #header>
|
||||
<!-- Content -->
|
||||
|
||||
@@ -13,14 +13,14 @@ headlessui:
|
||||
#code
|
||||
```vue
|
||||
<script setup>
|
||||
const open = ref(false)
|
||||
const isOpen = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<UButton label="Open" @click="open = true" />
|
||||
<UButton label="Open" @click="isOpen = true" />
|
||||
|
||||
<USlideover v-model="open">
|
||||
<USlideover v-model="isOpen">
|
||||
<!-- Content -->
|
||||
</USlideover>
|
||||
</div>
|
||||
|
||||
@@ -11,12 +11,13 @@ github: true
|
||||
```vue
|
||||
<script setup>
|
||||
const { x, y } = useMouse()
|
||||
const { y: windowY } = useWindowScroll()
|
||||
|
||||
const isOpen = ref(false)
|
||||
const virtualElement = ref({ getBoundingClientRect: () => ({}) })
|
||||
|
||||
function openContextMenu () {
|
||||
const top = unref(y)
|
||||
function onContextMenu () {
|
||||
const top = unref(y) - unref(windowY)
|
||||
const left = unref(x)
|
||||
|
||||
virtualElement.value.getBoundingClientRect = () => ({
|
||||
@@ -31,7 +32,7 @@ function openContextMenu () {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div @contextmenu.prevent="openContextMenu">
|
||||
<div @contextmenu.prevent="onContextMenu">
|
||||
<UContextMenu v-model="isOpen" :virtual-element="virtualElement">
|
||||
<!-- Content -->
|
||||
</UContextMenu>
|
||||
|
||||
33
docs/content/6.layout/3.skeleton.md
Normal file
33
docs/content/6.layout/3.skeleton.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
github: true
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
Use to show a placeholder while content is loading.
|
||||
|
||||
::component-example
|
||||
#default
|
||||
:skeleton-example
|
||||
|
||||
#code
|
||||
```vue
|
||||
<template>
|
||||
<div class="flex items-center space-x-4">
|
||||
<USkeleton class="h-12 w-12 rounded-full" />
|
||||
<div class="space-y-2">
|
||||
<USkeleton class="h-4 w-[250px]" />
|
||||
<USkeleton class="h-4 w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
::
|
||||
|
||||
## Props
|
||||
|
||||
:component-props
|
||||
|
||||
## Preset
|
||||
|
||||
:component-preset
|
||||
@@ -3,5 +3,5 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
await navigateTo('/getting-started/installation')
|
||||
await navigateTo('/getting-started')
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Config } from 'tailwindcss'
|
||||
import defaultTheme from 'tailwindcss/defaultTheme'
|
||||
|
||||
export default <Partial<Config>> {
|
||||
darkMode: 'class',
|
||||
content: [
|
||||
'docs/content/**/*.md'
|
||||
],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@nuxthq/ui",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.3",
|
||||
"repository": "https://github.com/nuxtlabs/ui",
|
||||
"license": "MIT",
|
||||
"exports": {
|
||||
|
||||
@@ -390,8 +390,7 @@ const selectMenu = {
|
||||
placement: 'bottom-end'
|
||||
},
|
||||
default: {
|
||||
selectedIcon: 'i-heroicons-check-20-solid',
|
||||
trailingIcon: 'i-heroicons-chevron-down-20-solid'
|
||||
selectedIcon: 'i-heroicons-check-20-solid'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,6 +457,12 @@ const container = {
|
||||
constrained: 'max-w-7xl'
|
||||
}
|
||||
|
||||
const skeleton = {
|
||||
base: 'animate-pulse',
|
||||
background: 'bg-gray-100 dark:bg-gray-800',
|
||||
rounded: 'rounded-md'
|
||||
}
|
||||
|
||||
// Navigation
|
||||
|
||||
const verticalNavigation = {
|
||||
@@ -739,6 +744,7 @@ export default {
|
||||
toggle,
|
||||
card,
|
||||
container,
|
||||
skeleton,
|
||||
verticalNavigation,
|
||||
commandPalette,
|
||||
modal,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<kbd :class="[ui.base, ui.size[size], ui.padding, ui.rounded, ui.font, ui.background, ui.ring]">
|
||||
<slot />
|
||||
<slot>{{ value }}</slot>
|
||||
</kbd>
|
||||
</template>
|
||||
|
||||
@@ -17,6 +17,10 @@ import appConfig from '#build/app.config'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.kbd.default.size,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
<template>
|
||||
<button v-if="!$attrs.to" v-bind="$attrs" :class="inactiveClass">
|
||||
<slot />
|
||||
</button>
|
||||
<NuxtLink
|
||||
v-else
|
||||
v-slot="{ href, navigate, exact, isActive, isExactActive }"
|
||||
custom
|
||||
>
|
||||
|
||||
@@ -161,7 +161,7 @@ export default defineComponent({
|
||||
},
|
||||
trailingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.selectMenu.default.trailingIcon
|
||||
default: () => appConfig.ui.select.default.trailingIcon
|
||||
},
|
||||
selectedIcon: {
|
||||
type: String,
|
||||
|
||||
35
src/runtime/components/layout/Skeleton.vue
Normal file
35
src/runtime/components/layout/Skeleton.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div :class="[ui.base, ui.background, ui.rounded]" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { defu } from 'defu'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
// @ts-expect-error
|
||||
import appConfig from '#build/app.config'
|
||||
|
||||
// const appConfig = useAppConfig()
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
ui: {
|
||||
type: Object as PropType<Partial<typeof appConfig.ui.skeleton>>,
|
||||
default: () => appConfig.ui.skeleton
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
// TODO: Remove
|
||||
const appConfig = useAppConfig()
|
||||
|
||||
const ui = computed<Partial<typeof appConfig.ui.skeleton>>(() => defu({}, props.ui, appConfig.ui.skeleton))
|
||||
|
||||
return {
|
||||
// eslint-disable-next-line vue/no-dupe-keys
|
||||
ui
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user