From a87eb43d44d3aa91044e137634fda9089a4dd2cf Mon Sep 17 00:00:00 2001 From: J-Sek Date: Mon, 8 Sep 2025 11:50:20 +0200 Subject: [PATCH] feat(VTreeview): add `no-data` slot --- packages/docs/src/data/new-in.json | 3 + .../src/examples/v-treeview/slot-no-data.vue | 188 ++++++++++++++++++ .../docs/src/pages/en/components/treeview.md | 6 + .../src/components/VTreeview/VTreeview.tsx | 15 +- 4 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 packages/docs/src/examples/v-treeview/slot-no-data.vue diff --git a/packages/docs/src/data/new-in.json b/packages/docs/src/data/new-in.json index 1557a31166f..02f16141a9d 100644 --- a/packages/docs/src/data/new-in.json +++ b/packages/docs/src/data/new-in.json @@ -279,12 +279,15 @@ "VTreeview": { "props": { "hideActions": "3.9.0", + "hideNoData": "3.10.0", + "noDataText": "3.10.0", "separateRoots": "3.9.0", "indentLines": "3.9.0" }, "slots": { "header": "3.10.0", "footer": "3.11.0", + "no-data": "3.11.0", "toggle": "3.10.0" } }, diff --git a/packages/docs/src/examples/v-treeview/slot-no-data.vue b/packages/docs/src/examples/v-treeview/slot-no-data.vue new file mode 100644 index 00000000000..ece04d95501 --- /dev/null +++ b/packages/docs/src/examples/v-treeview/slot-no-data.vue @@ -0,0 +1,188 @@ + + + + + diff --git a/packages/docs/src/pages/en/components/treeview.md b/packages/docs/src/pages/en/components/treeview.md index 9ca44d6333f..b8559cb99f7 100644 --- a/packages/docs/src/pages/en/components/treeview.md +++ b/packages/docs/src/pages/en/components/treeview.md @@ -136,6 +136,12 @@ Both **append**, and **prepend** slots get additional information about the item +#### No data + +When searching within the treeview, you might want to show custom **no-data** slot to provide context or immediate action. + + + #### Title In this example we use a custom **title** slot to apply a line-through the treeview item's text when selected. diff --git a/packages/vuetify/src/components/VTreeview/VTreeview.tsx b/packages/vuetify/src/components/VTreeview/VTreeview.tsx index d9d5c42f193..23e84de7c07 100644 --- a/packages/vuetify/src/components/VTreeview/VTreeview.tsx +++ b/packages/vuetify/src/components/VTreeview/VTreeview.tsx @@ -1,8 +1,10 @@ // Components import { makeVTreeviewChildrenProps, VTreeviewChildren } from './VTreeviewChildren' import { makeVListProps, useListItems, VList } from '@/components/VList/VList' +import { VListItem } from '@/components/VList/VListItem' // Composables +import { useLocale } from '@/composables' import { provideDefaults } from '@/composables/defaults' import { makeFilterProps, useFilter } from '@/composables/filter' import { useProxiedModel } from '@/composables/proxiedModel' @@ -31,6 +33,11 @@ export const makeVTreeviewProps = propsFactory({ openAll: Boolean, indentLines: [Boolean, String] as PropType, search: String, + hideNoData: Boolean, + noDataText: { + type: String, + default: '$vuetify.noDataText', + }, ...makeFilterProps({ filterKeys: ['title'] }), ...omit(makeVTreeviewChildrenProps(), [ @@ -53,7 +60,9 @@ export const VTreeview = genericComponent( props: { items?: T[] }, - slots: VTreeviewChildrenSlots + slots: VTreeviewChildrenSlots & { + 'no-data': never + } ) => GenericProps>()({ name: 'VTreeview', @@ -69,6 +78,7 @@ export const VTreeview = genericComponent( }, setup (props, { slots, emit }) { + const { t } = useLocale() const { items } = useListItems(props) const activeColor = toRef(() => props.activeColor) const baseColor = toRef(() => props.baseColor) @@ -175,6 +185,9 @@ export const VTreeview = genericComponent( v-model:activated={ activated.value } v-model:selected={ selected.value } > + { visibleIds.value?.size === 0 && !props.hideNoData && ( + slots['no-data']?.() ?? () + )}