Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(CommandPalette): handle loading state #221

Merged
merged 3 commits into from
May 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/content/1.getting-started/3.theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion docs/content/2.elements/1.avatar.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand Down
4 changes: 2 additions & 2 deletions docs/content/2.elements/3.button.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand Down Expand Up @@ -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
---
Expand Down
4 changes: 2 additions & 2 deletions docs/content/3.forms/1.input.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand Down Expand Up @@ -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
---
Expand Down
2 changes: 1 addition & 1 deletion docs/content/3.forms/3.select.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand Down
4 changes: 2 additions & 2 deletions docs/content/3.forms/4.select-menu.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand Down
26 changes: 25 additions & 1 deletion docs/content/4.navigation/2.command-palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
---
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions src/runtime/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
Expand Down
37 changes: 36 additions & 1 deletion src/runtime/components/navigation/CommandPalette.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -112,6 +113,10 @@ export default defineComponent({
type: Boolean,
default: true
},
loading: {
type: Boolean,
default: false
},
groups: {
type: Array as PropType<Group[]>,
default: () => []
Expand All @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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, () => {
Expand All @@ -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 () {
Expand Down Expand Up @@ -292,6 +325,8 @@ export default defineComponent({
groups,
comboboxInput,
query,
iconName,
iconClass,
onSelect,
onClear
}
Expand Down