mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-24 00:40:34 +01:00
chore(Kbd): new component
This commit is contained in:
@@ -10,10 +10,10 @@ const users = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const actions = [
|
const actions = [
|
||||||
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => alert('New file') },
|
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => alert('New file'), shortcuts: ['⌘', 'N'] },
|
||||||
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => alert('New folder') },
|
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => alert('New folder'), shortcuts: ['⌘', 'F'] },
|
||||||
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => alert('Add hashtag') },
|
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => alert('Add hashtag'), shortcuts: ['⌘', 'H'] },
|
||||||
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => alert('Add label') }
|
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => alert('Add label'), shortcuts: ['⌘', 'L'] }
|
||||||
]
|
]
|
||||||
|
|
||||||
const groups = computed(() => commandPaletteRef.value?.query
|
const groups = computed(() => commandPaletteRef.value?.query
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ const items = [
|
|||||||
}
|
}
|
||||||
}], [{
|
}], [{
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
icon: 'i-heroicons-pencil-square-20-solid'
|
icon: 'i-heroicons-pencil-square-20-solid',
|
||||||
|
shortcuts: ['E']
|
||||||
}, {
|
}, {
|
||||||
label: 'Duplicate',
|
label: 'Duplicate',
|
||||||
icon: 'i-heroicons-document-duplicate-20-solid'
|
icon: 'i-heroicons-document-duplicate-20-solid',
|
||||||
|
shortcuts: ['D']
|
||||||
}], [{
|
}], [{
|
||||||
label: 'Archive',
|
label: 'Archive',
|
||||||
icon: 'i-heroicons-archive-box-20-solid'
|
icon: 'i-heroicons-archive-box-20-solid'
|
||||||
@@ -19,7 +21,8 @@ const items = [
|
|||||||
icon: 'i-heroicons-arrow-right-circle-20-solid'
|
icon: 'i-heroicons-arrow-right-circle-20-solid'
|
||||||
}], [{
|
}], [{
|
||||||
label: 'Delete',
|
label: 'Delete',
|
||||||
icon: 'i-heroicons-trash-20-solid'
|
icon: 'i-heroicons-trash-20-solid',
|
||||||
|
shortcuts: ['⌘', 'D']
|
||||||
}]
|
}]
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
10
docs/components/content/examples/KbdExample.vue
Normal file
10
docs/components/content/examples/KbdExample.vue
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<script setup>
|
||||||
|
const { metaSymbol } = useShortcuts()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center gap-0.5">
|
||||||
|
<UKbd>{{ metaSymbol }}</UKbd>
|
||||||
|
<UKbd>U</UKbd>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<UTooltip text="Tooltip">
|
<UTooltip text="Tooltip example" :shortcuts="['⌘', 'O']">
|
||||||
<UButton color="gray" label="Button" />
|
<UButton color="gray" label="Hover me" />
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
>
|
>
|
||||||
Search
|
Search
|
||||||
|
|
||||||
<div class="hidden lg:flex items-center gap-1 ml-auto -my-1">
|
<div class="hidden lg:flex items-center gap-0.5 ml-auto -my-1">
|
||||||
<Shortcut value="meta" />
|
<UKbd>{{ metaSymbol }}</UKbd>
|
||||||
<Shortcut value="K" />
|
<UKbd>K</UKbd>
|
||||||
</div>
|
</div>
|
||||||
</UButton>
|
</UButton>
|
||||||
</div>
|
</div>
|
||||||
@@ -30,4 +30,5 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const { isSearchModalOpen } = useDocs()
|
const { isSearchModalOpen } = useDocs()
|
||||||
|
const { metaSymbol } = useShortcuts()
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -22,10 +22,12 @@ const items = [
|
|||||||
}
|
}
|
||||||
}], [{
|
}], [{
|
||||||
label: 'Edit',
|
label: 'Edit',
|
||||||
icon: 'i-heroicons-pencil-square-20-solid'
|
icon: 'i-heroicons-pencil-square-20-solid',
|
||||||
|
shortcuts: ['E']
|
||||||
}, {
|
}, {
|
||||||
label: 'Duplicate',
|
label: 'Duplicate',
|
||||||
icon: 'i-heroicons-document-duplicate-20-solid'
|
icon: 'i-heroicons-document-duplicate-20-solid',
|
||||||
|
shortcuts: ['D']
|
||||||
}], [{
|
}], [{
|
||||||
label: 'Archive',
|
label: 'Archive',
|
||||||
icon: 'i-heroicons-archive-box-20-solid'
|
icon: 'i-heroicons-archive-box-20-solid'
|
||||||
@@ -34,7 +36,8 @@ const items = [
|
|||||||
icon: 'i-heroicons-arrow-right-circle-20-solid'
|
icon: 'i-heroicons-arrow-right-circle-20-solid'
|
||||||
}], [{
|
}], [{
|
||||||
label: 'Delete',
|
label: 'Delete',
|
||||||
icon: 'i-heroicons-trash-20-solid'
|
icon: 'i-heroicons-trash-20-solid',
|
||||||
|
shortcuts: ['⌘', 'D']
|
||||||
}]
|
}]
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
48
docs/content/2.elements/5.kbd.md
Normal file
48
docs/content/2.elements/5.kbd.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
github: true
|
||||||
|
title: 'Keyboard Key'
|
||||||
|
navigation:
|
||||||
|
title: 'Kbd'
|
||||||
|
---
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
::component-example
|
||||||
|
#default
|
||||||
|
:kbd-example
|
||||||
|
|
||||||
|
#code
|
||||||
|
```vue
|
||||||
|
<script setup>
|
||||||
|
const { metaSymbol } = useShortcuts()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex items-center gap-0.5">
|
||||||
|
<UKbd>{{ metaSymbol }}</UKbd>
|
||||||
|
<UKbd>U</UKbd>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
::
|
||||||
|
|
||||||
|
### Size
|
||||||
|
|
||||||
|
Use the `size` prop to change the size of the Kbd.
|
||||||
|
|
||||||
|
::component-card
|
||||||
|
---
|
||||||
|
props:
|
||||||
|
size: 'sm'
|
||||||
|
---
|
||||||
|
|
||||||
|
U
|
||||||
|
::
|
||||||
|
|
||||||
|
## Props
|
||||||
|
|
||||||
|
:component-props
|
||||||
|
|
||||||
|
## Preset
|
||||||
|
|
||||||
|
:component-preset
|
||||||
@@ -118,10 +118,10 @@ const users = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const actions = [
|
const actions = [
|
||||||
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => alert('New file') },
|
{ id: 'new-file', label: 'Add new file', icon: 'i-heroicons-document-plus', click: () => alert('New file'), shortcuts: ['⌘', 'N'] },
|
||||||
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => alert('New folder') },
|
{ id: 'new-folder', label: 'Add new folder', icon: 'i-heroicons-folder-plus', click: () => alert('New folder'), shortcuts: ['⌘', 'F'] },
|
||||||
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => alert('Add hashtag') },
|
{ id: 'hashtag', label: 'Add hashtag', icon: 'i-heroicons-hashtag', click: () => alert('Add hashtag'), shortcuts: ['⌘', 'H'] },
|
||||||
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => alert('Add label') }
|
{ id: 'label', label: 'Add label', icon: 'i-heroicons-tag', click: () => alert('Add label'), shortcuts: ['⌘', 'L'] }
|
||||||
]
|
]
|
||||||
|
|
||||||
const groups = computed(() => commandPaletteRef.value?.query
|
const groups = computed(() => commandPaletteRef.value?.query
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ github: true
|
|||||||
#code
|
#code
|
||||||
```vue
|
```vue
|
||||||
<template>
|
<template>
|
||||||
<UTooltip text="Tooltip">
|
<UTooltip text="Tooltip example" :shortcuts="['⌘', 'O']">
|
||||||
<UButton color="gray" label="Button" />
|
<UButton color="gray" label="Hover me" />
|
||||||
</UTooltip>
|
</UTooltip>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ const dropdown = {
|
|||||||
base: 'flex-shrink-0',
|
base: 'flex-shrink-0',
|
||||||
size: '3xs'
|
size: '3xs'
|
||||||
},
|
},
|
||||||
shortcuts: 'hidden md:inline-flex flex-shrink-0 text-xs font-semibold text-gray-500 dark:text-gray-400 ml-auto'
|
shortcuts: 'hidden md:inline-flex flex-shrink-0 gap-0.5 ml-auto'
|
||||||
},
|
},
|
||||||
transition: {
|
transition: {
|
||||||
enterActiveClass: 'transition duration-100 ease-out',
|
enterActiveClass: 'transition duration-100 ease-out',
|
||||||
@@ -195,6 +195,23 @@ const dropdown = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const kbd = {
|
||||||
|
base: 'inline-flex items-center justify-center text-gray-900 dark:text-white',
|
||||||
|
spacing: 'px-1',
|
||||||
|
size: {
|
||||||
|
xs: 'h-4 min-w-[16px] text-[10px]',
|
||||||
|
sm: 'h-5 min-w-[20px] text-[11px]',
|
||||||
|
md: 'h-6 min-w-[24px] text-[12px]'
|
||||||
|
},
|
||||||
|
rounded: 'rounded',
|
||||||
|
font: 'font-medium font-sans',
|
||||||
|
background: 'bg-gray-100 dark:bg-gray-800',
|
||||||
|
ring: 'ring-1 ring-gray-300 dark:ring-gray-700 ring-inset',
|
||||||
|
default: {
|
||||||
|
size: 'sm'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Forms
|
// Forms
|
||||||
|
|
||||||
const input = {
|
const input = {
|
||||||
@@ -494,7 +511,7 @@ const commandPalette = {
|
|||||||
selected: {
|
selected: {
|
||||||
icon: 'h-4 w-4 text-gray-900 dark:text-white flex-shrink-0'
|
icon: 'h-4 w-4 text-gray-900 dark:text-white flex-shrink-0'
|
||||||
},
|
},
|
||||||
shortcuts: 'hidden md:inline-flex flex-shrink-0 text-xs font-semibold text-gray-500 dark:text-gray-400'
|
shortcuts: 'hidden md:inline-flex flex-shrink-0 gap-0.5'
|
||||||
},
|
},
|
||||||
active: 'flex-shrink-0 text-gray-500 dark:text-gray-400',
|
active: 'flex-shrink-0 text-gray-500 dark:text-gray-400',
|
||||||
inactive: 'flex-shrink-0 text-gray-500 dark:text-gray-400'
|
inactive: 'flex-shrink-0 text-gray-500 dark:text-gray-400'
|
||||||
@@ -582,7 +599,7 @@ const tooltip = {
|
|||||||
rounded: 'rounded',
|
rounded: 'rounded',
|
||||||
ring: 'ring-1 ring-gray-200 dark:ring-gray-800',
|
ring: 'ring-1 ring-gray-200 dark:ring-gray-800',
|
||||||
base: 'invisible lg:visible h-6 px-2 py-1 text-xs font-normal truncate',
|
base: 'invisible lg:visible h-6 px-2 py-1 text-xs font-normal truncate',
|
||||||
shortcuts: 'hidden md:inline-flex items-center justify-end flex-shrink-0 gap-0.5 ml-1',
|
shortcuts: 'hidden md:inline-flex flex-shrink-0 gap-0.5',
|
||||||
transition: {
|
transition: {
|
||||||
enterActiveClass: 'transition ease-out duration-200',
|
enterActiveClass: 'transition ease-out duration-200',
|
||||||
enterFromClass: 'opacity-0 translate-y-1',
|
enterFromClass: 'opacity-0 translate-y-1',
|
||||||
@@ -688,6 +705,7 @@ export default {
|
|||||||
button,
|
button,
|
||||||
buttonGroup,
|
buttonGroup,
|
||||||
dropdown,
|
dropdown,
|
||||||
|
kbd,
|
||||||
input,
|
input,
|
||||||
inputGroup,
|
inputGroup,
|
||||||
textarea,
|
textarea,
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<span class="truncate">{{ item.label }}</span>
|
<span class="truncate">{{ item.label }}</span>
|
||||||
|
|
||||||
<span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
|
<span v-if="item.shortcuts?.length" :class="ui.item.shortcuts">
|
||||||
<kbd v-for="shortcut of item.shortcuts" :key="shortcut" class="font-sans">{{ shortcut }}</kbd>
|
<UKbd v-for="shortcut of item.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
</Component>
|
</Component>
|
||||||
@@ -53,7 +53,8 @@ import { defineComponent, ref, computed, onMounted } from 'vue'
|
|||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
import UIcon from '../elements/Icon.vue'
|
import UIcon from '../elements/Icon.vue'
|
||||||
import UAvatar from '../elements/Avatar.vue'
|
import UAvatar from '../elements/Avatar.vue'
|
||||||
import { classNames, omit } from '../../utils'
|
import UKbd from '../elements/Kbd.vue'
|
||||||
|
import { omit } from '../../utils'
|
||||||
import { usePopper } from '../../composables/usePopper'
|
import { usePopper } from '../../composables/usePopper'
|
||||||
import type { Avatar as AvatarType } from '../../types/avatar'
|
import type { Avatar as AvatarType } from '../../types/avatar'
|
||||||
import type { PopperOptions } from '../../types'
|
import type { PopperOptions } from '../../types'
|
||||||
@@ -73,7 +74,8 @@ export default defineComponent({
|
|||||||
MenuItems,
|
MenuItems,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
UIcon,
|
UIcon,
|
||||||
UAvatar
|
UAvatar,
|
||||||
|
UKbd
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
items: {
|
items: {
|
||||||
|
|||||||
44
src/runtime/components/elements/Kbd.vue
Normal file
44
src/runtime/components/elements/Kbd.vue
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<template>
|
||||||
|
<kbd :class="[ui.base, ui.size[size], ui.spacing, ui.rounded, ui.font, ui.background, ui.ring]">
|
||||||
|
<slot />
|
||||||
|
</kbd>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, computed } 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: {
|
||||||
|
size: {
|
||||||
|
type: String,
|
||||||
|
default: () => appConfig.ui.kbd.default.size,
|
||||||
|
validator (value: string) {
|
||||||
|
return Object.keys(appConfig.ui.kbd.size).includes(value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ui: {
|
||||||
|
type: Object as PropType<Partial<typeof appConfig.ui.kbd>>,
|
||||||
|
default: () => appConfig.ui.kbd
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup (props) {
|
||||||
|
// TODO: Remove
|
||||||
|
const appConfig = useAppConfig()
|
||||||
|
|
||||||
|
const ui = computed<Partial<typeof appConfig.ui.kbd>>(() => defu({}, props.ui, appConfig.ui.kbd))
|
||||||
|
|
||||||
|
return {
|
||||||
|
// eslint-disable-next-line vue/no-dupe-keys
|
||||||
|
ui
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
</slot>
|
</slot>
|
||||||
<slot v-else :name="`${group.key}-inactive`" :group="group" :command="command">
|
<slot v-else :name="`${group.key}-inactive`" :group="group" :command="command">
|
||||||
<span v-if="command.shortcuts?.length" :class="ui.group.command.shortcuts">
|
<span v-if="command.shortcuts?.length" :class="ui.group.command.shortcuts">
|
||||||
<kbd v-for="shortcut of command.shortcuts" :key="shortcut" class="font-sans">{{ shortcut }}</kbd>
|
<UKbd v-for="shortcut of command.shortcuts" :key="shortcut">{{ shortcut }}</UKbd>
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="!command.disabled && group.inactive" :class="ui.group.inactive">{{ group.inactive }}</span>
|
<span v-else-if="!command.disabled && group.inactive" :class="ui.group.inactive">{{ group.inactive }}</span>
|
||||||
</slot>
|
</slot>
|
||||||
@@ -61,6 +61,7 @@ import type { PropType } from 'vue'
|
|||||||
import { ComboboxOption } from '@headlessui/vue'
|
import { ComboboxOption } from '@headlessui/vue'
|
||||||
import UIcon from '../elements/Icon.vue'
|
import UIcon from '../elements/Icon.vue'
|
||||||
import UAvatar from '../elements/Avatar.vue'
|
import UAvatar from '../elements/Avatar.vue'
|
||||||
|
import UKbd from '../elements/Kbd.vue'
|
||||||
import type { Group } from '../../types/command-palette'
|
import type { Group } from '../../types/command-palette'
|
||||||
// TODO: Remove
|
// TODO: Remove
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
@@ -72,7 +73,8 @@ export default defineComponent({
|
|||||||
components: {
|
components: {
|
||||||
ComboboxOption,
|
ComboboxOption,
|
||||||
UIcon,
|
UIcon,
|
||||||
UAvatar
|
UAvatar,
|
||||||
|
UKbd
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
group: {
|
group: {
|
||||||
|
|||||||
@@ -12,10 +12,10 @@
|
|||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<span v-if="shortcuts?.length" :class="ui.shortcuts">
|
<span v-if="shortcuts?.length" :class="ui.shortcuts">
|
||||||
<span class="mr-1 text-gray-700 dark:text-gray-200">·</span>
|
<span class="mx-1 text-gray-700 dark:text-gray-200">·</span>
|
||||||
<kbd v-for="shortcut of shortcuts" :key="shortcut" class="flex items-center justify-center font-sans px-1 h-4 min-w-[16px] text-[10px] bg-gray-100 dark:bg-gray-800 rounded text-gray-900 dark:text-white">
|
<UKbd v-for="shortcut of shortcuts" :key="shortcut" size="xs">
|
||||||
{{ shortcut }}
|
{{ shortcut }}
|
||||||
</kbd>
|
</Ukbd>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
@@ -27,6 +27,7 @@
|
|||||||
import { computed, ref, defineComponent } from 'vue'
|
import { computed, ref, defineComponent } from 'vue'
|
||||||
import type { PropType } from 'vue'
|
import type { PropType } from 'vue'
|
||||||
import { defu } from 'defu'
|
import { defu } from 'defu'
|
||||||
|
import UKbd from '../elements/Kbd.vue'
|
||||||
import { usePopper } from '../../composables/usePopper'
|
import { usePopper } from '../../composables/usePopper'
|
||||||
import type { PopperOptions } from '../../types'
|
import type { PopperOptions } from '../../types'
|
||||||
import { useAppConfig } from '#imports'
|
import { useAppConfig } from '#imports'
|
||||||
@@ -37,6 +38,9 @@ import appConfig from '#build/app.config'
|
|||||||
// const appConfig = useAppConfig()
|
// const appConfig = useAppConfig()
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
UKbd
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
text: {
|
text: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|||||||
Reference in New Issue
Block a user