From 3ea232817be6a70d1e887f2244f060f789e5d4e5 Mon Sep 17 00:00:00 2001 From: Sai Sridhar Date: Sun, 28 Jun 2026 16:15:10 +0530 Subject: [PATCH 1/5] feat(VAlert): add duration prop for auto-dismissal (#20409) --- .../src/examples/v-alert/prop-duration.vue | 25 +++++++++++++++++ .../docs/src/pages/en/components/alerts.md | 6 ++++ .../vuetify/src/components/VAlert/VAlert.tsx | 28 ++++++++++++++++++- 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 packages/docs/src/examples/v-alert/prop-duration.vue diff --git a/packages/docs/src/examples/v-alert/prop-duration.vue b/packages/docs/src/examples/v-alert/prop-duration.vue new file mode 100644 index 00000000000..d480a826e80 --- /dev/null +++ b/packages/docs/src/examples/v-alert/prop-duration.vue @@ -0,0 +1,25 @@ + + + diff --git a/packages/docs/src/pages/en/components/alerts.md b/packages/docs/src/pages/en/components/alerts.md index 97701b717a5..7959420d393 100644 --- a/packages/docs/src/pages/en/components/alerts.md +++ b/packages/docs/src/pages/en/components/alerts.md @@ -131,6 +131,12 @@ The **closable** prop adds a [v-icon](/components/icons) on the far right, after +#### Duration + +The **duration** prop causes the alert to automatically dismiss itself after the specified number of milliseconds. Set to `-1` (the default) to disable auto-dismiss. Combine with **closable** to give users both auto-dismiss and manual control. + + + The close icon automatically applies a default `aria-label` and is configurable by using the **close-label** prop or changing **close** value in your locale. ::: info diff --git a/packages/vuetify/src/components/VAlert/VAlert.tsx b/packages/vuetify/src/components/VAlert/VAlert.tsx index 42672ddc0e0..b30684c40d7 100644 --- a/packages/vuetify/src/components/VAlert/VAlert.tsx +++ b/packages/vuetify/src/components/VAlert/VAlert.tsx @@ -25,7 +25,7 @@ import { makeThemeProps, provideTheme } from '@/composables/theme' import { genOverlays, makeVariantProps, useVariant } from '@/composables/variant' // Utilities -import { toRef } from 'vue' +import { onMounted, onScopeDispose, toRef, watch } from 'vue' import { genericComponent, propsFactory } from '@/util' // Types @@ -57,6 +57,10 @@ export const makeVAlertProps = propsFactory({ type: String, default: '$vuetify.close', }, + duration: { + type: [Number, String], + default: -1, + }, icon: { type: [Boolean, String, Function, Object] as PropType, default: null, @@ -107,6 +111,28 @@ export const VAlert = genericComponent()({ setup (props, { emit, slots }) { const isActive = useProxiedModel(props, 'modelValue') + + let dismissTimer = -1 + function clearDismissTimer () { + if (dismissTimer !== -1) { + window.clearTimeout(dismissTimer) + dismissTimer = -1 + } + } + function scheduleDismiss () { + clearDismissTimer() + const ms = Number(props.duration) + if (ms > 0 && isActive.value) { + dismissTimer = window.setTimeout(() => { + isActive.value = false + dismissTimer = -1 + }, ms) + } + } + onMounted(scheduleDismiss) + watch(() => [props.duration, isActive.value], scheduleDismiss) + onScopeDispose(clearDismissTimer) + const icon = toRef(() => { if (props.icon === false) return undefined if (!props.type) return props.icon From 08caf01d3a6e9c2e4887e938be0848c073e20dbe Mon Sep 17 00:00:00 2001 From: Sai Sridhar Date: Sun, 28 Jun 2026 16:24:02 +0530 Subject: [PATCH 2/5] fix(VAlert): fix attribute order and self-closing in duration example --- packages/docs/src/examples/v-alert/prop-duration.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/src/examples/v-alert/prop-duration.vue b/packages/docs/src/examples/v-alert/prop-duration.vue index d480a826e80..32a6e4866eb 100644 --- a/packages/docs/src/examples/v-alert/prop-duration.vue +++ b/packages/docs/src/examples/v-alert/prop-duration.vue @@ -11,10 +11,10 @@ v-else v-model="visible" type="info" - closable :duration="3000" text="This alert will automatically dismiss after 3 seconds." - /> + closable + > From d692e8b122e3ae2ef40c75391fbbfaf93a193f51 Mon Sep 17 00:00:00 2001 From: Sai Sridhar Date: Sun, 28 Jun 2026 16:34:03 +0530 Subject: [PATCH 3/5] fix(VAlert): fix attribute order in duration example --- packages/docs/src/examples/v-alert/prop-duration.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/docs/src/examples/v-alert/prop-duration.vue b/packages/docs/src/examples/v-alert/prop-duration.vue index 32a6e4866eb..b8b3f14ccae 100644 --- a/packages/docs/src/examples/v-alert/prop-duration.vue +++ b/packages/docs/src/examples/v-alert/prop-duration.vue @@ -10,10 +10,10 @@ From 943967542aa2be840f06ef47415b578fb82cc9c1 Mon Sep 17 00:00:00 2001 From: Sai Sridhar Date: Sun, 28 Jun 2026 16:40:36 +0530 Subject: [PATCH 4/5] fix(VAlert): put closable last per vue/attributes-order rule --- packages/docs/src/examples/v-alert/prop-duration.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docs/src/examples/v-alert/prop-duration.vue b/packages/docs/src/examples/v-alert/prop-duration.vue index b8b3f14ccae..4d7ee8f6d50 100644 --- a/packages/docs/src/examples/v-alert/prop-duration.vue +++ b/packages/docs/src/examples/v-alert/prop-duration.vue @@ -10,10 +10,10 @@ From 2a2eac88af096d97cdec9b40f9f581e77b323647 Mon Sep 17 00:00:00 2001 From: Sai Sridhar Date: Sun, 28 Jun 2026 16:53:02 +0530 Subject: [PATCH 5/5] feat(VSkeletonLoader): add chip-group and timeline-item types (#20451, #20695) --- .../VSkeletonLoader/VSkeletonLoader.sass | 21 +++++++++++++++++++ .../VSkeletonLoader/VSkeletonLoader.tsx | 4 ++++ 2 files changed, 25 insertions(+) diff --git a/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.sass b/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.sass index d75b6de9aaa..e0c3e81f4f9 100644 --- a/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.sass +++ b/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.sass @@ -103,6 +103,27 @@ height: $skeleton-loader-chip-height max-width: $skeleton-loader-chip-width + &__chip-group + flex-wrap: wrap + + .v-skeleton-loader__chip + flex: 0 0 auto + + &__timeline-item, + &__timeline-item-two, + &__timeline-item-three + flex-wrap: nowrap + align-items: flex-start + + > .v-skeleton-loader__avatar + flex: 0 0 auto + align-self: center + + > .v-skeleton-loader__heading, + > .v-skeleton-loader__sentences, + > .v-skeleton-loader__paragraph + flex: 1 1 auto + + .v-skeleton-loader__bone flex: 1 1 auto margin-inline-start: 0 diff --git a/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.tsx b/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.tsx index 17e9477de10..12a33414d06 100644 --- a/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.tsx +++ b/packages/vuetify/src/components/VSkeletonLoader/VSkeletonLoader.tsx @@ -28,6 +28,7 @@ export const rootTypes = { card: 'image, heading', 'card-avatar': 'image, list-item-avatar', chip: 'chip', + 'chip-group': 'chip@5', 'date-picker': 'list-item, heading, divider, date-picker-options, date-picker-days, actions', 'date-picker-options': 'text, avatar@2', 'date-picker-days': 'avatar@28', @@ -52,6 +53,9 @@ export const rootTypes = { 'table-row': 'text@6', 'table-tfoot': 'text@2, avatar@2', text: 'text', + 'timeline-item': 'avatar, heading', + 'timeline-item-two': 'avatar, sentences', + 'timeline-item-three': 'avatar, paragraph', } as const function genBone (type: string, children: VSkeletonBones = []) {