mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 20:19:34 +01:00
chore(CommandPalette): handle loading state (#221)
This commit is contained in:
@@ -184,6 +184,7 @@ export default defineAppConfig({
|
||||
commandPalette: {
|
||||
default: {
|
||||
icon: 'i-octicon-search-24',
|
||||
loadingIcon: 'i-octicon-sync-24',
|
||||
selectedIcon: 'i-octicon-check-24',
|
||||
empty: {
|
||||
icon: 'i-octicon-search-24'
|
||||
|
||||
@@ -29,7 +29,7 @@ baseProps:
|
||||
|
||||
### Chip
|
||||
|
||||
Use the `chipColor`, `chipVariant` and `chipPosition` props to display a chip on the Avatar.
|
||||
Use the `chip-color`, `chip-variant` and `chip-position` props to display a chip on the Avatar.
|
||||
|
||||
::component-card
|
||||
---
|
||||
|
||||
@@ -113,7 +113,7 @@ Button
|
||||
|
||||
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 `leading` and `trailing` props to set the icon position or the `leadingIcon` and `trailingIcon` props to set a different icon for each position.
|
||||
Use the `leading` and `trailing` props to set the icon position or the `leading-icon` and `trailing-icon` props to set a different icon for each position.
|
||||
|
||||
::component-card
|
||||
---
|
||||
@@ -163,7 +163,7 @@ 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`.
|
||||
Use the `loading-icon` 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
|
||||
---
|
||||
|
||||
@@ -56,7 +56,7 @@ props:
|
||||
|
||||
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 `leading` and `trailing` props to set the icon position or the `leadingIcon` and `trailingIcon` props to set a different icon for each position.
|
||||
Use the `leading` and `trailing` props to set the icon position or the `leading-icon` and `trailing-icon` props to set a different icon for each position.
|
||||
|
||||
::component-card
|
||||
---
|
||||
@@ -94,7 +94,7 @@ 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`.
|
||||
Use the `loading-icon` 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
|
||||
---
|
||||
|
||||
@@ -78,7 +78,7 @@ props:
|
||||
|
||||
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 `trailing-icon` 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
|
||||
---
|
||||
|
||||
@@ -136,9 +136,9 @@ 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 `trailing-icon` 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`.
|
||||
Use the `selected-icon` prop to set a different icon or change it globally in `ui.selectMenu.default.selectedIcon`. Defaults to `i-heroicons-check-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
|
||||
@@ -160,7 +160,7 @@ 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`.
|
||||
Use the `selected-icon` prop to set a different icon or change it globally in `ui.commandPalette.default.selectedIcon`. Defaults to `i-heroicons-check-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
@@ -174,6 +174,24 @@ excludedProps:
|
||||
---
|
||||
::
|
||||
|
||||
### Loading
|
||||
|
||||
Use the `loading` prop to show a loading icon.
|
||||
|
||||
Use the `loading-icon` prop to set a different icon or change it globally in `ui.commandPalette.default.loadingIcon`. Defaults to `i-heroicons-arrow-path-20-solid`.
|
||||
|
||||
::component-card
|
||||
---
|
||||
padding: false
|
||||
baseProps:
|
||||
empty: null
|
||||
props:
|
||||
loading: true
|
||||
excludedProps:
|
||||
- icon
|
||||
---
|
||||
::
|
||||
|
||||
### Placeholder
|
||||
|
||||
Use the `placeholder` prop to change the input placeholder
|
||||
@@ -218,6 +236,8 @@ Use the `empty` prop to display a message when there are no results.
|
||||
|
||||
You can pass an `object` through the `empty` prop or globally through `ui.commandPalette.default.empty`. Here is the default:
|
||||
|
||||
You can also set it to `null` to hide the empty label.
|
||||
|
||||
::component-card
|
||||
---
|
||||
padding: false
|
||||
@@ -299,6 +319,10 @@ const groups = computed(() => {
|
||||
```
|
||||
::
|
||||
|
||||
::alert{icon="i-heroicons-light-bulb"}
|
||||
The `loading` state will automatically be enabled when a `search` function is loading. You can disable this behaviour by setting the `loading-icon` prop to `null` or globally in `ui.commandPalette.default.loadingIcon`.
|
||||
::
|
||||
|
||||
## Themes
|
||||
|
||||
Our theming system provides a lot of flexibility to customize the component. Here is some examples of what you can do.
|
||||
|
||||
@@ -546,6 +546,7 @@ const commandPalette = {
|
||||
},
|
||||
default: {
|
||||
icon: 'i-heroicons-magnifying-glass-20-solid',
|
||||
loadingIcon: 'i-heroicons-arrow-path-20-solid',
|
||||
empty: {
|
||||
icon: 'i-heroicons-magnifying-glass-20-solid',
|
||||
label: 'We couldn\'t find any items.',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
>
|
||||
<div :class="ui.wrapper">
|
||||
<div v-show="searchable" :class="ui.input.wrapper">
|
||||
<UIcon v-if="icon" :name="icon" :class="[ui.input.icon.base, ui.input.icon.size]" aria-hidden="true" />
|
||||
<UIcon v-if="iconName" :name="iconName" :class="iconClass" aria-hidden="true" />
|
||||
<ComboboxInput
|
||||
ref="comboboxInput"
|
||||
:value="query"
|
||||
@@ -74,6 +74,7 @@ import type { Group, Command } from '../../types/command-palette'
|
||||
import UIcon from '../elements/Icon.vue'
|
||||
import UButton from '../elements/Button.vue'
|
||||
import type { Button as ButtonType } from '../../types/button'
|
||||
import { classNames } from '../../utils'
|
||||
import CommandPaletteGroup from './CommandPaletteGroup.vue'
|
||||
import { useAppConfig } from '#imports'
|
||||
// TODO: Remove
|
||||
@@ -112,6 +113,10 @@ export default defineComponent({
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
groups: {
|
||||
type: Array as PropType<Group[]>,
|
||||
default: () => []
|
||||
@@ -120,6 +125,10 @@ export default defineComponent({
|
||||
type: String,
|
||||
default: () => appConfig.ui.commandPalette.default.icon
|
||||
},
|
||||
loadingIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.commandPalette.default.loadingIcon
|
||||
},
|
||||
selectedIcon: {
|
||||
type: String,
|
||||
default: () => appConfig.ui.commandPalette.default.selectedIcon
|
||||
@@ -175,6 +184,7 @@ export default defineComponent({
|
||||
const query = ref('')
|
||||
const comboboxInput = ref<ComponentPublicInstance<HTMLInputElement>>()
|
||||
const comboboxApi = ref(null)
|
||||
const isLoading = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
if (props.autoselect) {
|
||||
@@ -231,10 +241,17 @@ export default defineComponent({
|
||||
|
||||
const debouncedSearch = useDebounceFn(async () => {
|
||||
const searchableGroups = props.groups.filter(group => !!group.search)
|
||||
if (!searchableGroups.length) {
|
||||
return
|
||||
}
|
||||
|
||||
isLoading.value = true
|
||||
|
||||
await Promise.all(searchableGroups.map(async (group) => {
|
||||
searchResults.value[group.key] = await group.search(query.value)
|
||||
}))
|
||||
|
||||
isLoading.value = false
|
||||
}, props.debounce)
|
||||
|
||||
watch(query, () => {
|
||||
@@ -247,6 +264,22 @@ export default defineComponent({
|
||||
}, 0)
|
||||
})
|
||||
|
||||
const iconName = computed(() => {
|
||||
if ((props.loading || isLoading.value) && props.loadingIcon) {
|
||||
return props.loadingIcon
|
||||
}
|
||||
|
||||
return props.icon
|
||||
})
|
||||
|
||||
const iconClass = computed(() => {
|
||||
return classNames(
|
||||
ui.value.input.icon.base,
|
||||
ui.value.input.icon.size,
|
||||
((props.loading || isLoading.value) && props.loadingIcon) && 'animate-spin'
|
||||
)
|
||||
})
|
||||
|
||||
// Methods
|
||||
|
||||
function activateFirstOption () {
|
||||
@@ -292,6 +325,8 @@ export default defineComponent({
|
||||
groups,
|
||||
comboboxInput,
|
||||
query,
|
||||
iconName,
|
||||
iconClass,
|
||||
onSelect,
|
||||
onClear
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user