From 4fcda7996236b2c8430af2a7b27a1b153d4280f0 Mon Sep 17 00:00:00 2001 From: morimorimokenpi <52128219+morimorimokenpi@users.noreply.github.com> Date: Wed, 30 Sep 2026 01:56:38 +0900 Subject: [PATCH 1/2] fix(VStepperVertical): allow tooltips in title slots --- .../VStepperVerticalItem.sass | 13 ++-- .../VStepperVertical/VStepperVerticalItem.tsx | 1 + .../VStepperVertical.spec.browser.tsx | 60 +++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 packages/vuetify/src/components/VStepperVertical/__tests__/VStepperVertical.spec.browser.tsx diff --git a/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.sass b/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.sass index 6f85b6c56f6..73803744fa8 100644 --- a/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.sass +++ b/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.sass @@ -33,13 +33,18 @@ &:after display: none - &.v-expansion-panel--disabled, - &:not(.v-stepper-vertical-item--editable) + &.v-expansion-panel--disabled .v-expansion-panel-title pointer-events: none - .v-expansion-panel-title__overlay - opacity: 0 + &:not(.v-stepper-vertical-item--editable) + .v-expansion-panel-title + cursor: default + + &.v-expansion-panel--disabled, + &:not(.v-stepper-vertical-item--editable) + .v-expansion-panel-title__overlay + opacity: 0 .v-stepper-vertical-item__avatar.v-avatar background: tools.theme-color('surface-variant', var(--v-medium-emphasis-opacity)) diff --git a/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.tsx b/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.tsx index be837957bd8..04c4a3f44c6 100644 --- a/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.tsx +++ b/packages/vuetify/src/components/VStepperVertical/VStepperVerticalItem.tsx @@ -135,6 +135,7 @@ export const VStepperVerticalItem = genericComponent( props.class, ]} readonly={ !props.editable } + hover={ props.hover && canEdit.value } style={ props.style } color="" hideActions={ false } diff --git a/packages/vuetify/src/components/VStepperVertical/__tests__/VStepperVertical.spec.browser.tsx b/packages/vuetify/src/components/VStepperVertical/__tests__/VStepperVertical.spec.browser.tsx new file mode 100644 index 00000000000..bb0f2f620fa --- /dev/null +++ b/packages/vuetify/src/components/VStepperVertical/__tests__/VStepperVertical.spec.browser.tsx @@ -0,0 +1,60 @@ +// Components +import { VStepperVertical, VStepperVerticalItem } from '..' +import { VIcon } from '@/components/VIcon' + +// Directives +import vTooltip from '@/directives/tooltip' + +// Utilities +import { render, screen, userEvent } from '@test' +import { defineComponent, shallowRef } from 'vue' + +const TooltipIcon = defineComponent({ + directives: { vTooltip: vTooltip as any }, + + setup () { + return () => ( + + ) + }, +}) + +describe('VStepperVertical', () => { + it('should allow title tooltips without making the item editable', async () => { + const model = shallowRef(1) + + render(() => ( + + + {{ + title: () => ( + <> + Step 1 + + + ), + default: () => 'Step content', + }} + + + + )) + + await userEvent.hover(screen.getByTestId('title-tooltip')) + + await expect.poll(() => screen.queryByCSS('.v-tooltip .v-overlay__content')).toBeVisible() + + const title = screen.getByText('Step 1').closest('button')! + + expect(getComputedStyle(title).cursor).toBe('default') + expect(getComputedStyle(title.querySelector('.v-expansion-panel-title__overlay')!).opacity).toBe('0') + + await userEvent.click(screen.getByText('Step 2')) + + expect(model.value).toBe(1) + }) +}) From 42962bb4ecb671db821f1f0e95be5cc50f85dac5 Mon Sep 17 00:00:00 2001 From: morimorimokenpi <52128219+morimorimokenpi@users.noreply.github.com> Date: Wed, 30 Sep 2026 02:54:31 +0900 Subject: [PATCH 2/2] fix(VStepper): allow tooltips in title slots --- .../src/components/VStepper/VStepperItem.sass | 3 + .../src/components/VStepper/VStepperItem.tsx | 5 +- .../__tests__/VStepper.spec.browser.tsx | 80 +++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 packages/vuetify/src/components/VStepper/__tests__/VStepper.spec.browser.tsx diff --git a/packages/vuetify/src/components/VStepper/VStepperItem.sass b/packages/vuetify/src/components/VStepper/VStepperItem.sass index 8e5d9a4b648..ef5b716ed24 100644 --- a/packages/vuetify/src/components/VStepper/VStepperItem.sass +++ b/packages/vuetify/src/components/VStepper/VStepperItem.sass @@ -41,6 +41,9 @@ &--disabled pointer-events: none + &:not(.v-stepper-item--editable) + cursor: default + .v-stepper--alt-labels & flex-direction: column justify-content: flex-start diff --git a/packages/vuetify/src/components/VStepper/VStepperItem.tsx b/packages/vuetify/src/components/VStepper/VStepperItem.tsx index 2db5090e030..8ee8aee2cdd 100644 --- a/packages/vuetify/src/components/VStepper/VStepperItem.tsx +++ b/packages/vuetify/src/components/VStepper/VStepperItem.tsx @@ -137,18 +137,19 @@ export const VStepperItem = genericComponent()({ { 'v-stepper-item--complete': hasCompleted.value, 'v-stepper-item--disabled': props.disabled, + 'v-stepper-item--editable': canEdit.value, 'v-stepper-item--error': hasError.value, }, group?.selectedClass.value, ]} - disabled={ !props.editable } + disabled={ props.disabled } type="button" v-ripple={[ props.editable && props.ripple, null, null, ]} - onClick={ onClick } + onClick={ isClickable.value ? onClick : undefined } > { isClickable.value && genOverlays(true, 'v-stepper-item') } diff --git a/packages/vuetify/src/components/VStepper/__tests__/VStepper.spec.browser.tsx b/packages/vuetify/src/components/VStepper/__tests__/VStepper.spec.browser.tsx new file mode 100644 index 00000000000..07e4f27e444 --- /dev/null +++ b/packages/vuetify/src/components/VStepper/__tests__/VStepper.spec.browser.tsx @@ -0,0 +1,80 @@ +// Components +import { VStepper } from '..' +import { VIcon } from '@/components/VIcon' + +// Directives +import vTooltip from '@/directives/tooltip' + +// Utilities +import { render, screen, userEvent } from '@test' +import { defineComponent, shallowRef } from 'vue' + +const TooltipIcon = defineComponent({ + directives: { vTooltip: vTooltip as any }, + + setup () { + return () => ( + + ) + }, +}) + +describe('VStepper', () => { + it('should allow title tooltips without making the item editable', async () => { + const model = shallowRef(1) + + render(() => ( + + {{ + title: ({ step }) => step === 1 ? ( + <> + Step 1 + + + ) : Step 2, + }} + + )) + + await userEvent.hover(screen.getByTestId('title-tooltip')) + + await expect.poll(() => screen.queryByCSS('.v-tooltip .v-overlay__content')).toBeVisible() + + const title = screen.getByText('Step 1').closest('button')! + + expect(getComputedStyle(title).cursor).toBe('default') + + await userEvent.click(screen.getByText('Step 2')) + + expect(model.value).toBe(1) + }) + + it('should keep disabled items disabled', () => { + render(() => ( + + )) + + const item = screen.getByText('Disabled step').closest('button')! + + expect(item).toBeDisabled() + expect(getComputedStyle(item).pointerEvents).toBe('none') + }) +})