diff --git a/docs/app/components/content/examples/context-menu/ContextMenuColorItemsExample.vue b/docs/app/components/content/examples/context-menu/ContextMenuColorItemsExample.vue new file mode 100644 index 00000000..807367a9 --- /dev/null +++ b/docs/app/components/content/examples/context-menu/ContextMenuColorItemsExample.vue @@ -0,0 +1,33 @@ + + + diff --git a/docs/app/components/content/examples/dropdown-menu/DropdownMenuColorItemsExample.vue b/docs/app/components/content/examples/dropdown-menu/DropdownMenuColorItemsExample.vue new file mode 100644 index 00000000..5e3f8273 --- /dev/null +++ b/docs/app/components/content/examples/dropdown-menu/DropdownMenuColorItemsExample.vue @@ -0,0 +1,35 @@ + + + diff --git a/docs/content/3.components/context-menu.md b/docs/content/3.components/context-menu.md index 190397ee..c1cec659 100644 --- a/docs/content/3.components/context-menu.md +++ b/docs/content/3.components/context-menu.md @@ -20,9 +20,11 @@ Use the `items` prop as an array of objects with the following properties: - `label?: string`{lang="ts-type"} - `icon?: string`{lang="ts-type"} +- `color?: string`{lang="ts-type"} - `avatar?: AvatarProps`{lang="ts-type"} - `kbds?: string[] | KbdProps[]`{lang="ts-type"} - [`type?: "link" | "label" | "separator" | "checkbox"`{lang="ts-type"}](#with-checkbox-items) +- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items) - [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items) - `disabled?: boolean`{lang="ts-type"} - `class?: any`{lang="ts-type"} @@ -191,6 +193,16 @@ name: 'context-menu-checkbox-items-example' To ensure reactivity for the `checked` state of items, it's recommended to wrap your `items` array inside a `computed`. :: +### With color items + +You can use the `color` property to highlight certain items with a color. + +::component-example +--- +name: 'context-menu-color-items-example' +--- +:: + ### With custom slot Use the `slot` property to customize a specific item. diff --git a/docs/content/3.components/dropdown-menu.md b/docs/content/3.components/dropdown-menu.md index 14137faf..25e8b910 100644 --- a/docs/content/3.components/dropdown-menu.md +++ b/docs/content/3.components/dropdown-menu.md @@ -20,9 +20,11 @@ Use the `items` prop as an array of objects with the following properties: - `label?: string`{lang="ts-type"} - `icon?: string`{lang="ts-type"} +- `color?: string`{lang="ts-type"} - `avatar?: AvatarProps`{lang="ts-type"} - `kbds?: string[] | KbdProps[]`{lang="ts-type"} - [`type?: "link" | "label" | "separator" | "checkbox"`{lang="ts-type"}](#with-checkbox-items) +- [`color?: "error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"`{lang="ts-type"}](#with-color-items) - [`checked?: boolean`{lang="ts-type"}](#with-checkbox-items) - `disabled?: boolean`{lang="ts-type"} - `class?: any`{lang="ts-type"} @@ -273,6 +275,16 @@ name: 'dropdown-menu-checkbox-items-example' To ensure reactivity for the `checked` state of items, it's recommended to wrap your `items` array inside a `computed`. :: +### With color items + +You can use the `color` property to highlight certain items with a color. + +::component-example +--- +name: 'dropdown-menu-color-items-example' +--- +:: + ### Control open state You can control the open state by using the `default-open` prop or the `v-model:open` directive. diff --git a/playground/app/pages/components/context-menu.vue b/playground/app/pages/components/context-menu.vue index 3afa2ed1..b811a9a7 100644 --- a/playground/app/pages/components/context-menu.vue +++ b/playground/app/pages/components/context-menu.vue @@ -86,6 +86,12 @@ const items = computed(() => [ }] ]) +const itemsWithColor = computed(() => Object.keys(theme.variants.color).map(color => ({ + color: (color as keyof typeof theme.variants.color), + icon: 'i-heroicons-swatch', + label: color +}))) + const sizes = Object.keys(theme.variants.size) const size = ref('md' as const) @@ -104,5 +110,11 @@ defineShortcuts(extractShortcuts(items.value)) Right click here + + +
+ Color right click here +
+
diff --git a/playground/app/pages/components/dropdown-menu.vue b/playground/app/pages/components/dropdown-menu.vue index 20f5a924..c5d6320f 100644 --- a/playground/app/pages/components/dropdown-menu.vue +++ b/playground/app/pages/components/dropdown-menu.vue @@ -122,6 +122,12 @@ const items = computed(() => [ }] ]) +const itemsWithColor = computed(() => Object.keys(theme.variants.color).map(color => ({ + color: (color as keyof typeof theme.variants.color), + icon: 'i-heroicons-swatch', + label: color +}))) + const sizes = Object.keys(theme.variants.size) const size = ref('md' as const) @@ -141,6 +147,14 @@ defineShortcuts(extractShortcuts(items.value)) + + + + + + diff --git a/src/runtime/components/ContextMenu.vue b/src/runtime/components/ContextMenu.vue index fa74aa64..035beddf 100644 --- a/src/runtime/components/ContextMenu.vue +++ b/src/runtime/components/ContextMenu.vue @@ -12,9 +12,12 @@ const appConfig = _appConfig as AppConfig & { ui: { contextMenu: Partial + export interface ContextMenuItem extends Omit { label?: string icon?: string + color?: ContextMenuVariants['color'] avatar?: AvatarProps content?: Omit kbds?: KbdProps['value'][] | KbdProps[] @@ -34,8 +37,6 @@ export interface ContextMenuItem extends Omit - export interface ContextMenuProps extends Omit { size?: ContextMenuVariants['size'] items?: T[] | T[][] diff --git a/src/runtime/components/ContextMenuContent.vue b/src/runtime/components/ContextMenuContent.vue index f9efb73b..7b78f76c 100644 --- a/src/runtime/components/ContextMenuContent.vue +++ b/src/runtime/components/ContextMenuContent.vue @@ -52,8 +52,8 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 - - + + @@ -62,19 +62,19 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 {{ get(item, props.labelKey as string) }} - + - + - + @@ -94,7 +94,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 type="button" :disabled="item.disabled" :text-value="get(item, props.labelKey as string)" - :class="ui.item({ class: uiOverride?.item })" + :class="ui.item({ class: uiOverride?.item, color: item?.color })" > @@ -122,7 +122,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 :checked="item.checked" :disabled="item.disabled" :text-value="get(item, props.labelKey as string)" - :class="ui.item({ class: [uiOverride?.item, item.class] })" + :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })" @update:checked="item.onUpdateChecked" @select="item.onSelect" > @@ -136,7 +136,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 @select="item.onSelect" > - + diff --git a/src/runtime/components/DropdownMenu.vue b/src/runtime/components/DropdownMenu.vue index 9e669564..cd8e5b0a 100644 --- a/src/runtime/components/DropdownMenu.vue +++ b/src/runtime/components/DropdownMenu.vue @@ -12,9 +12,12 @@ const appConfig = _appConfig as AppConfig & { ui: { dropdownMenu: Partial + export interface DropdownMenuItem extends Omit { label?: string icon?: string + color?: DropdownMenuVariants['color'] avatar?: AvatarProps content?: Omit kbds?: KbdProps['value'][] | KbdProps[] @@ -34,8 +37,6 @@ export interface DropdownMenuItem extends Omit - export interface DropdownMenuProps extends Omit { size?: DropdownMenuVariants['size'] items?: T[] | T[][] diff --git a/src/runtime/components/DropdownMenuContent.vue b/src/runtime/components/DropdownMenuContent.vue index 6ed7d2e5..fa2a2d19 100644 --- a/src/runtime/components/DropdownMenuContent.vue +++ b/src/runtime/components/DropdownMenuContent.vue @@ -58,8 +58,8 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 - - + + @@ -68,19 +68,19 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 {{ get(item, props.labelKey as string) }} - + - + - + @@ -100,7 +100,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 type="button" :disabled="item.disabled" :text-value="get(item, props.labelKey as string)" - :class="ui.item({ class: uiOverride?.item })" + :class="ui.item({ class: uiOverride?.item, color: item?.color })" > @@ -131,7 +131,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 :checked="item.checked" :disabled="item.disabled" :text-value="get(item, props.labelKey as string)" - :class="ui.item({ class: [uiOverride?.item, item.class] })" + :class="ui.item({ class: [uiOverride?.item, item.class], color: item?.color })" @update:checked="item.onUpdateChecked" @select="item.onSelect" > @@ -145,7 +145,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0 @select="item.onSelect" > - + diff --git a/src/theme/context-menu.ts b/src/theme/context-menu.ts index 45322c45..b0756515 100644 --- a/src/theme/context-menu.ts +++ b/src/theme/context-menu.ts @@ -18,6 +18,10 @@ export default (options: Required) => ({ itemLabelExternalIcon: 'inline-block size-3 align-top text-[var(--ui-text-dimmed)]' }, variants: { + color: { + ...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, ''])), + neutral: '' + }, active: { true: { item: 'text-[var(--ui-text-highlighted)] before:bg-[var(--ui-bg-elevated)]', @@ -81,6 +85,21 @@ export default (options: Required) => ({ } } }, + compoundVariants: [...(options.theme.colors || []).map((color: string) => ({ + color, + active: false, + class: { + item: `text-[var(--ui-${color})] data-highlighted:text-[var(--ui-${color})] data-highlighted:before:bg-[var(--ui-${color})]/10 data-[state=open]:before:bg-[var(--ui-${color})]/10`, + itemLeadingIcon: `text-[var(--ui-${color})]/75 group-data-highlighted:text-[var(--ui-${color})] group-data-[state=open]:text-[var(--ui-${color})]` + } + })), ...(options.theme.colors || []).map((color: string) => ({ + color, + active: true, + class: { + item: `text-[var(--ui-${color})] before:bg-[var(--ui-${color})]/10`, + itemLeadingIcon: `text-[var(--ui-${color})]` + } + }))], defaultVariants: { size: 'md' } diff --git a/src/theme/dropdown-menu.ts b/src/theme/dropdown-menu.ts index 62b27a24..7dd7fd2a 100644 --- a/src/theme/dropdown-menu.ts +++ b/src/theme/dropdown-menu.ts @@ -19,6 +19,10 @@ export default (options: Required) => ({ itemLabelExternalIcon: 'inline-block size-3 align-top text-[var(--ui-text-dimmed)]' }, variants: { + color: { + ...Object.fromEntries((options.theme.colors || []).map((color: string) => [color, ''])), + neutral: '' + }, active: { true: { item: 'text-[var(--ui-text-highlighted)] before:bg-[var(--ui-bg-elevated)]', @@ -82,6 +86,21 @@ export default (options: Required) => ({ } } }, + compoundVariants: [...(options.theme.colors || []).map((color: string) => ({ + color, + active: false, + class: { + item: `text-[var(--ui-${color})] data-highlighted:text-[var(--ui-${color})] data-highlighted:before:bg-[var(--ui-${color})]/10 data-[state=open]:before:bg-[var(--ui-${color})]/10`, + itemLeadingIcon: `text-[var(--ui-${color})]/75 group-data-highlighted:text-[var(--ui-${color})] group-data-[state=open]:text-[var(--ui-${color})]` + } + })), ...(options.theme.colors || []).map((color: string) => ({ + color, + active: true, + class: { + item: `text-[var(--ui-${color})] before:bg-[var(--ui-${color})]/10`, + itemLeadingIcon: `text-[var(--ui-${color})]` + } + }))], defaultVariants: { size: 'md' } diff --git a/test/components/ContextMenu.spec.ts b/test/components/ContextMenu.spec.ts index d7659fbd..99c1c015 100644 --- a/test/components/ContextMenu.spec.ts +++ b/test/components/ContextMenu.spec.ts @@ -23,6 +23,7 @@ describe('ContextMenu', () => { }], [{ label: 'Show Sidebar', + color: 'primary', kbds: ['meta', 'S'] }, { label: 'Show Toolbar', diff --git a/test/components/DropdownMenu.spec.ts b/test/components/DropdownMenu.spec.ts index bb622ace..3e1841b6 100644 --- a/test/components/DropdownMenu.spec.ts +++ b/test/components/DropdownMenu.spec.ts @@ -79,6 +79,7 @@ describe('DropdownMenu', () => { disabled: true }], [{ label: 'Logout', + color: 'error', icon: 'i-heroicons-arrow-right-start-on-rectangle', kbds: ['shift', 'meta', 'q'] }] diff --git a/test/components/__snapshots__/DropdownMenu-vue.spec.ts.snap b/test/components/__snapshots__/DropdownMenu-vue.spec.ts.snap index 6fc6070e..8e7b9974 100644 --- a/test/components/__snapshots__/DropdownMenu-vue.spec.ts.snap +++ b/test/components/__snapshots__/DropdownMenu-vue.spec.ts.snap @@ -27,7 +27,7 @@ exports[`DropdownMenu > renders with arrow correctly 1`] = `
GitHubSupport
-
@@ -65,7 +65,7 @@ exports[`DropdownMenu > renders with class correctly 1`] = `
GitHubSupport
-
@@ -103,7 +103,7 @@ exports[`DropdownMenu > renders with custom slot correctly 1`] = `
GitHubSupport
-
@@ -141,7 +141,7 @@ exports[`DropdownMenu > renders with default slot correctly 1`] = `
GitHubSupport
-
@@ -179,7 +179,7 @@ exports[`DropdownMenu > renders with disabled correctly 1`] = `
GitHubSupport
-
@@ -211,7 +211,7 @@ exports[`DropdownMenu > renders with item slot correctly 1`] = `
Item slotItem slot
-
+
@@ -247,7 +247,7 @@ exports[`DropdownMenu > renders with item-label slot correctly 1`] = `
Item label slotItem label slot
-
@@ -285,7 +285,7 @@ exports[`DropdownMenu > renders with item-leading slot correctly 1`] = `
Item leading slotGitHubItem leading slotSupport
-
@@ -317,7 +317,7 @@ exports[`DropdownMenu > renders with item-trailing slot correctly 1`] = `
GitHubItem trailing slotSupportItem trailing slot
-
+
@@ -353,7 +353,7 @@ exports[`DropdownMenu > renders with items correctly 1`] = `
GitHubSupport
-
@@ -393,7 +393,7 @@ exports[`DropdownMenu > renders with labelKey correctly 1`] = `
i-simple-icons-githubi-heroicons-lifebuoy
-
@@ -431,7 +431,7 @@ exports[`DropdownMenu > renders with size lg correctly 1`] = `
GitHubSupport
-
@@ -469,7 +469,7 @@ exports[`DropdownMenu > renders with size md correctly 1`] = `
GitHubSupport
-
@@ -507,7 +507,7 @@ exports[`DropdownMenu > renders with size sm correctly 1`] = `
GitHubSupport
-
@@ -545,7 +545,7 @@ exports[`DropdownMenu > renders with size xl correctly 1`] = `
GitHubSupport
-
@@ -583,7 +583,7 @@ exports[`DropdownMenu > renders with size xs correctly 1`] = `
GitHubSupport
-
@@ -621,7 +621,7 @@ exports[`DropdownMenu > renders with ui correctly 1`] = `
GitHubSupport
-
diff --git a/test/components/__snapshots__/DropdownMenu.spec.ts.snap b/test/components/__snapshots__/DropdownMenu.spec.ts.snap index 80866fe6..5d153ec1 100644 --- a/test/components/__snapshots__/DropdownMenu.spec.ts.snap +++ b/test/components/__snapshots__/DropdownMenu.spec.ts.snap @@ -29,7 +29,7 @@ exports[`DropdownMenu > renders with arrow correctly 1`] = `
GitHubSupport
-
@@ -69,7 +69,7 @@ exports[`DropdownMenu > renders with class correctly 1`] = `
GitHubSupport
-
@@ -109,7 +109,7 @@ exports[`DropdownMenu > renders with custom slot correctly 1`] = `
GitHubSupport
-
@@ -149,7 +149,7 @@ exports[`DropdownMenu > renders with default slot correctly 1`] = `
GitHubSupport
-
@@ -189,7 +189,7 @@ exports[`DropdownMenu > renders with disabled correctly 1`] = `
GitHubSupport
-
@@ -221,7 +221,7 @@ exports[`DropdownMenu > renders with item slot correctly 1`] = `
Item slotItem slot
-
+
@@ -259,7 +259,7 @@ exports[`DropdownMenu > renders with item-label slot correctly 1`] = `
Item label slotItem label slot
-
@@ -299,7 +299,7 @@ exports[`DropdownMenu > renders with item-leading slot correctly 1`] = `
Item leading slotGitHubItem leading slotSupport
-
@@ -331,7 +331,7 @@ exports[`DropdownMenu > renders with item-trailing slot correctly 1`] = `
GitHubItem trailing slotSupportItem trailing slot
-
+
@@ -369,7 +369,7 @@ exports[`DropdownMenu > renders with items correctly 1`] = `
GitHubSupport
-
@@ -411,7 +411,7 @@ exports[`DropdownMenu > renders with labelKey correctly 1`] = `
i-simple-icons-githubi-heroicons-lifebuoy
-
@@ -451,7 +451,7 @@ exports[`DropdownMenu > renders with size lg correctly 1`] = `
GitHubSupport
-
@@ -491,7 +491,7 @@ exports[`DropdownMenu > renders with size md correctly 1`] = `
GitHubSupport
-
@@ -531,7 +531,7 @@ exports[`DropdownMenu > renders with size sm correctly 1`] = `
GitHubSupport
-
@@ -571,7 +571,7 @@ exports[`DropdownMenu > renders with size xl correctly 1`] = `
GitHubSupport
-
@@ -611,7 +611,7 @@ exports[`DropdownMenu > renders with size xs correctly 1`] = `
GitHubSupport
-
@@ -651,7 +651,7 @@ exports[`DropdownMenu > renders with ui correctly 1`] = `
GitHubSupport
-