Skip to content
Open
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/docs/2.components/command-palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Each group contains an `items` array of objects that define the commands. Each i
- `suffix?: string`{lang="ts-type"}
- `icon?: IconComponent`{lang="ts-type"}
- `avatar?: AvatarProps`{lang="ts-type"}
- `color?: AvatarProps['color']`{lang="ts-type"}
- `chip?: ChipProps`{lang="ts-type"}
- `kbds?: string[] | KbdProps[]`{lang="ts-type"}
- `active?: boolean`{lang="ts-type"}
Expand Down
5 changes: 5 additions & 0 deletions src/runtime/components/CommandPalette.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export interface CommandPaletteItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
*/
icon?: IconComponent
avatar?: AvatarProps
/**
* Default `color` for the item's leading `B24Avatar`. Overridden by `avatar.color` when set.
*/
color?: AvatarProps['color']
chip?: ChipProps
kbds?: KbdProps['value'][] | KbdProps[]
active?: boolean
Expand Down Expand Up @@ -537,6 +541,7 @@ function onSelect(e: Event, item: T) {
<B24Avatar
v-else-if="item.avatar"
:size="((item.b24ui?.itemLeadingAvatarSize || props.b24ui?.itemLeadingAvatarSize || b24ui.itemLeadingAvatarSize()) as AvatarProps['size'])"
:color="item.color"
v-bind="item.avatar"
data-slot="itemLeadingAvatar"
:class="b24ui.itemLeadingAvatar({ class: [props.b24ui?.itemLeadingAvatar, item.b24ui?.itemLeadingAvatar], active: active || item.active })"
Expand Down
1 change: 1 addition & 0 deletions test/components/CommandPalette.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ describe('CommandPalette', () => {
['with as', { props: { ...props, as: 'section' } }],
['with class', { props: { ...props, class: 'divide-(--ui-color-accent-main-success)' } }],
['with b24ui', { props: { ...props, b24ui: { input: '[&>input]:h-10' } } }],
['with item color', { props: { groups: [{ id: 'team', label: 'Team', items: [{ label: 'Engineer', avatar: { src: 'https://github.com/bitrix24.png' }, color: 'air-primary' as const }, { label: 'Designer', avatar: { src: 'https://github.com/bitrix24.png' }, color: 'air-primary-success' as const }] }] } }],
// Slots
['with empty slot', { props, slots: { empty: () => 'Empty slot' } }],
['with item slot', { props, slots: { item: () => 'Item slot' } }],
Expand Down
24 changes: 24 additions & 0 deletions test/components/__snapshots__/CommandPalette-vue.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,30 @@ exports[`CommandPalette > renders with icon correctly 1`] = `
</div>"
`;

exports[`CommandPalette > renders with item color correctly 1`] = `
"<div dir="ltr" data-slot="root" class="flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-color-divider-default)">
<div data-slot="root" class="isolate relative inline-flex items-center ps-[40px] pe-[44px]">
<!--v-if--><input type="text" placeholder="Enter command or search…" data-slot="input" class="w-full py-0 border-0 focus:outline-none disabled:cursor-not-allowed disabled:pointer-events-auto disabled:select-none disabled:opacity-30 disabled:resize-none appearance-none transition-colors duration-300 ease-linear text-(--ui-color-base-1) placeholder:text-(--ui-color-design-plain-na-content-secondary) hover:text-(--ui-color-base-1) focus:text-(--ui-color-base-1) active:text-(--ui-color-base-1) font-[family-name:var(--ui-font-family-primary)] font-(--ui-font-weight-regular) align-middle text-ellipsis whitespace-nowrap group-not-only:not-first:after:content-[''] group-not-only:not-first:after:absolute group-not-only:not-first:after:top-[7px] group-not-only:not-first:after:bottom-[6px] group-not-only:not-first:after:left-0 group-not-only:not-first:after:w-px group-not-only:not-first:after:bg-current/30 h-[34px] gap-1.5 text-(length:--ui-font-size-lg)/[normal] style-filled rounded-(--ui-border-radius-sm) px-0 ring-0 focus-visible:ring-0 style-transparent-bg md:text-(length:--ui-font-size-lg)/[normal]" autocomplete="off" aria-disabled="false" value=""><span data-slot="leading" class="absolute inset-y-0 start-0 flex items-center px-2"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true" data-slot="icon" class="shrink-0 text-(--b24ui-icon-color) size-4.5"><path fill="currentColor" fill-rule="evenodd" d="M14.05 15.886a6.37 6.37 0 1 1 1.836-1.837l3.311 3.311a1 1 0 0 1 0 1.414l-.422.423a1 1 0 0 1-1.414 0zm1.058-5.328a4.55 4.55 0 1 1-9.098 0 4.55 4.55 0 0 1 9.099 0" clip-rule="evenodd"></path></svg></span>
<!--v-if-->
</div>
<div data-slot="content" class="relative overflow-hidden flex flex-col" role="listbox" tabindex="-1" aria-orientation="vertical" aria-multiselectable="false" data-orientation="vertical">
<div role="presentation" data-slot="viewport" class="relative scroll-py-1 overflow-y-auto scrollbar-thin flex-1 focus:outline-none">
<div role="group" aria-labelledby="reka-listbox-group-v-0" data-slot="group" class="p-1 isolate">
<div id="reka-listbox-group-v-0" data-slot="label" class="text-label p-[6px] text-(length:--ui-font-size-xs) gap-[6px]">Team</div><button type="button" data-reka-collection-item="" id="reka-listbox-item-v-1" role="option" tabindex="-1" aria-selected="false" data-state="unchecked" data-slot="item" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-(--ui-border-radius-sm) data-disabled:cursor-not-allowed data-disabled:opacity-30 p-[6px] text-(length:--ui-font-size-md) gap-[6px] text-legend data-highlighted:not-data-disabled:text-legend data-highlighted:not-data-disabled:before:bg-(--ui-color-bg-content-secondary) transition-colors before:transition-colors"><span data-slot="root" class="air-secondary-accent inline-flex items-center justify-center select-none rounded-full align-middle bg-(--b24ui-background) ring ring-(--b24ui-border-color) style-filled size-5 text-(length:--ui-font-size-4xs)/(--ui-font-line-height-reset) font-(--ui-font-weight-regular) shrink-0"><img src="https://github.com/bitrix24.png" width="20" height="20" data-slot="image" class="h-full w-full rounded-[inherit] object-cover"></span><span data-slot="itemWrapper" class="flex-1 flex flex-col text-start min-w-0 overflow-hidden"><span data-slot="itemLabel" class="truncate space-x-1 text-label"><!--v-if--><span data-slot="itemLabelBase" class="text-label [&amp;>mark]:text-(--ui-color-black-base) [&amp;>mark]:bg-(--ui-color-collab-accent-less-1)">Engineer</span>
<!--v-if--></span>
<!--v-if--></span><span data-slot="itemTrailing" class="ms-auto inline-flex items-center gap-[6px]"><!--v-if--><!--v-if--></span>
</button><button type="button" data-reka-collection-item="" id="reka-listbox-item-v-2" role="option" tabindex="-1" aria-selected="false" data-state="unchecked" data-slot="item" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-(--ui-border-radius-sm) data-disabled:cursor-not-allowed data-disabled:opacity-30 p-[6px] text-(length:--ui-font-size-md) gap-[6px] text-legend data-highlighted:not-data-disabled:text-legend data-highlighted:not-data-disabled:before:bg-(--ui-color-bg-content-secondary) transition-colors before:transition-colors"><span data-slot="root" class="air-secondary-accent inline-flex items-center justify-center select-none rounded-full align-middle bg-(--b24ui-background) ring ring-(--b24ui-border-color) style-filled-success size-5 text-(length:--ui-font-size-4xs)/(--ui-font-line-height-reset) font-(--ui-font-weight-regular) shrink-0"><img src="https://github.com/bitrix24.png" width="20" height="20" data-slot="image" class="h-full w-full rounded-[inherit] object-cover"></span><span data-slot="itemWrapper" class="flex-1 flex flex-col text-start min-w-0 overflow-hidden"><span data-slot="itemLabel" class="truncate space-x-1 text-label"><!--v-if--><span data-slot="itemLabelBase" class="text-label [&amp;>mark]:text-(--ui-color-black-base) [&amp;>mark]:bg-(--ui-color-collab-accent-less-1)">Designer</span>
<!--v-if--></span>
<!--v-if--></span><span data-slot="itemTrailing" class="ms-auto inline-flex items-center gap-[6px]"><!--v-if--><!--v-if--></span>
</button>
</div>
</div>
</div>
<!--v-if-->
<!--v-if-->
</div>"
`;

exports[`CommandPalette > renders with item slot correctly 1`] = `
"<div dir="ltr" data-slot="root" class="flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-color-divider-default)">
<div data-slot="root" class="isolate relative inline-flex items-center ps-[40px] pe-[44px]">
Expand Down
24 changes: 24 additions & 0 deletions test/components/__snapshots__/CommandPalette.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,30 @@ exports[`CommandPalette > renders with icon correctly 1`] = `
</div>"
`;

exports[`CommandPalette > renders with item color correctly 1`] = `
"<div dir="ltr" data-slot="root" class="flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-color-divider-default)">
<div data-slot="root" class="isolate relative inline-flex items-center ps-[40px] pe-[44px]">
<!--v-if--><input type="text" placeholder="Enter command or search…" data-slot="input" class="w-full py-0 border-0 focus:outline-none disabled:cursor-not-allowed disabled:pointer-events-auto disabled:select-none disabled:opacity-30 disabled:resize-none appearance-none transition-colors duration-300 ease-linear text-(--ui-color-base-1) placeholder:text-(--ui-color-design-plain-na-content-secondary) hover:text-(--ui-color-base-1) focus:text-(--ui-color-base-1) active:text-(--ui-color-base-1) font-[family-name:var(--ui-font-family-primary)] font-(--ui-font-weight-regular) align-middle text-ellipsis whitespace-nowrap group-not-only:not-first:after:content-[''] group-not-only:not-first:after:absolute group-not-only:not-first:after:top-[7px] group-not-only:not-first:after:bottom-[6px] group-not-only:not-first:after:left-0 group-not-only:not-first:after:w-px group-not-only:not-first:after:bg-current/30 h-[34px] gap-1.5 text-(length:--ui-font-size-lg)/[normal] style-filled rounded-(--ui-border-radius-sm) px-0 ring-0 focus-visible:ring-0 style-transparent-bg md:text-(length:--ui-font-size-lg)/[normal]" autocomplete="off" aria-disabled="false" value="" aria-activedescendant="reka-listbox-item-v-0-0-1"><span data-slot="leading" class="absolute inset-y-0 start-0 flex items-center px-2"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true" data-slot="icon" class="shrink-0 text-(--b24ui-icon-color) size-4.5"><path fill="currentColor" fill-rule="evenodd" d="M14.05 15.886a6.37 6.37 0 1 1 1.836-1.837l3.311 3.311a1 1 0 0 1 0 1.414l-.422.423a1 1 0 0 1-1.414 0zm1.058-5.328a4.55 4.55 0 1 1-9.098 0 4.55 4.55 0 0 1 9.099 0" clip-rule="evenodd"></path></svg></span>
<!--v-if-->
</div>
<div data-slot="content" class="relative overflow-hidden flex flex-col" role="listbox" tabindex="-1" aria-orientation="vertical" aria-multiselectable="false" data-orientation="vertical">
<div role="presentation" data-slot="viewport" class="relative scroll-py-1 overflow-y-auto scrollbar-thin flex-1 focus:outline-none">
<div role="group" aria-labelledby="reka-listbox-group-v-0-0-0" data-slot="group" class="p-1 isolate">
<div id="reka-listbox-group-v-0-0-0" data-slot="label" class="text-label p-[6px] text-(length:--ui-font-size-xs) gap-[6px]">Team</div><button type="button" data-reka-collection-item="" id="reka-listbox-item-v-0-0-1" role="option" tabindex="-1" aria-selected="false" data-state="unchecked" data-slot="item" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-(--ui-border-radius-sm) data-disabled:cursor-not-allowed data-disabled:opacity-30 p-[6px] text-(length:--ui-font-size-md) gap-[6px] text-legend data-highlighted:not-data-disabled:text-legend data-highlighted:not-data-disabled:before:bg-(--ui-color-bg-content-secondary) transition-colors before:transition-colors" data-highlighted=""><span data-slot="root" class="air-secondary-accent inline-flex items-center justify-center select-none rounded-full align-middle bg-(--b24ui-background) ring ring-(--b24ui-border-color) style-filled size-5 text-(length:--ui-font-size-4xs)/(--ui-font-line-height-reset) font-(--ui-font-weight-regular) shrink-0"><img src="https://github.com/bitrix24.png" width="20" height="20" data-slot="image" class="h-full w-full rounded-[inherit] object-cover"></span><span data-slot="itemWrapper" class="flex-1 flex flex-col text-start min-w-0 overflow-hidden"><span data-slot="itemLabel" class="truncate space-x-1 text-label"><!--v-if--><span data-slot="itemLabelBase" class="text-label [&amp;>mark]:text-(--ui-color-black-base) [&amp;>mark]:bg-(--ui-color-collab-accent-less-1)">Engineer</span>
<!--v-if--></span>
<!--v-if--></span><span data-slot="itemTrailing" class="ms-auto inline-flex items-center gap-[6px]"><!--v-if--><!--v-if--></span>
</button><button type="button" data-reka-collection-item="" id="reka-listbox-item-v-0-0-2" role="option" tabindex="-1" aria-selected="false" data-state="unchecked" data-slot="item" class="group relative w-full flex items-center select-none outline-none before:absolute before:z-[-1] before:inset-px before:rounded-(--ui-border-radius-sm) data-disabled:cursor-not-allowed data-disabled:opacity-30 p-[6px] text-(length:--ui-font-size-md) gap-[6px] text-legend data-highlighted:not-data-disabled:text-legend data-highlighted:not-data-disabled:before:bg-(--ui-color-bg-content-secondary) transition-colors before:transition-colors"><span data-slot="root" class="air-secondary-accent inline-flex items-center justify-center select-none rounded-full align-middle bg-(--b24ui-background) ring ring-(--b24ui-border-color) style-filled-success size-5 text-(length:--ui-font-size-4xs)/(--ui-font-line-height-reset) font-(--ui-font-weight-regular) shrink-0"><img src="https://github.com/bitrix24.png" width="20" height="20" data-slot="image" class="h-full w-full rounded-[inherit] object-cover"></span><span data-slot="itemWrapper" class="flex-1 flex flex-col text-start min-w-0 overflow-hidden"><span data-slot="itemLabel" class="truncate space-x-1 text-label"><!--v-if--><span data-slot="itemLabelBase" class="text-label [&amp;>mark]:text-(--ui-color-black-base) [&amp;>mark]:bg-(--ui-color-collab-accent-less-1)">Designer</span>
<!--v-if--></span>
<!--v-if--></span><span data-slot="itemTrailing" class="ms-auto inline-flex items-center gap-[6px]"><!--v-if--><!--v-if--></span>
</button>
</div>
</div>
</div>
<!--v-if-->
<!--v-if-->
</div>"
`;

exports[`CommandPalette > renders with item slot correctly 1`] = `
"<div dir="ltr" data-slot="root" class="flex flex-col min-h-0 min-w-0 divide-y divide-(--ui-color-divider-default)">
<div data-slot="root" class="isolate relative inline-flex items-center ps-[40px] pe-[44px]">
Expand Down