From d5faffe8b29d72b67e0c0e967fe3dacdccd7156a Mon Sep 17 00:00:00 2001 From: J-Sek Date: Sun, 19 Oct 2025 00:26:46 +0200 Subject: [PATCH] feat(VTabs): add `inset` prop --- .../vuetify/src/components/VTabs/VTabs.sass | 53 +++++++++++++++++++ .../vuetify/src/components/VTabs/VTabs.tsx | 10 +++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/packages/vuetify/src/components/VTabs/VTabs.sass b/packages/vuetify/src/components/VTabs/VTabs.sass index 22172d619d4..2658e9d42f2 100644 --- a/packages/vuetify/src/components/VTabs/VTabs.sass +++ b/packages/vuetify/src/components/VTabs/VTabs.sass @@ -47,6 +47,59 @@ .v-tab:last-child margin-inline-end: 0 + .v-tabs--inset + --v-tabs-inset-radius: 18px + --v-tabs-inset-padding: 4px + + background: rgba(var(--v-theme-on-surface), 0.06) + box-shadow: inset 0 0 0 2px rgba(var(--v-border-color), var(--v-border-opacity)) + max-width: max-content + border-radius: calc(var(--v-tabs-inset-radius) + var(--v-tabs-inset-padding)) + + .v-tab + min-width: 0 + margin: var(--v-tabs-inset-padding) + transition-property: box-shadow, transform, opacity, background, color + border-radius: var(--v-tabs-inset-radius) + + &:focus-visible + outline: 2px solid rgb(var(--v-border-color)) + outline-offset: 2px + + &:after + opacity: 0 + + .v-tab__slider + inset: 0 + border-radius: var(--v-tabs-inset-radius) + z-index: -1 + width: auto + + .v-tab--selected + /* TODO: set text-* class */ + color: rgb(var(--v-theme-surface)) + + &.v-tabs--horizontal + height: calc(var(--v-tabs-height) + var(--v-tabs-inset-padding) * 2) + --v-tabs-inset-tab-radius: calc(var(--v-tabs-outer-radius) - var(--v-tabs-inset-padding) + 4px) + + &.v-tabs--horizontal .v-tab__slider + height: auto + + &.v-tabs--vertical .v-tab__slider + height: calc(100% - 2 * var(--v-slider-padding)) + + .v-slide-group__content + padding-inline: var(--v-slider-padding) + + .v-btn__overlay + display: none + + &.v-tabs--vertical .v-tab + grid-template-columns: max-content 1fr max-content + > .v-btn__content + justify-content: start + @media #{map.get(settings.$display-breakpoints, 'md-and-down')} .v-tabs.v-slide-group--is-overflowing.v-slide-group--horizontal:not(.v-slide-group--has-affixes) .v-tab:first-child diff --git a/packages/vuetify/src/components/VTabs/VTabs.tsx b/packages/vuetify/src/components/VTabs/VTabs.tsx index a7a997d7e4e..6e25b0cadc0 100644 --- a/packages/vuetify/src/components/VTabs/VTabs.tsx +++ b/packages/vuetify/src/components/VTabs/VTabs.tsx @@ -71,6 +71,9 @@ export const makeVTabsProps = propsFactory({ default: undefined, }, hideSlider: Boolean, + inset: Boolean, + insetPadding: [String, Number], + insetRadius: [String, Number], sliderColor: String, ...pick(makeVTabProps(), ['spaced']), @@ -130,6 +133,7 @@ export const VTabs = genericComponent( { 'v-tabs--fixed-tabs': props.fixedTabs, 'v-tabs--grow': props.grow, + 'v-tabs--inset': props.inset, 'v-tabs--stacked': props.stacked, }, densityClasses.value, @@ -137,7 +141,11 @@ export const VTabs = genericComponent( props.class, ]} style={[ - { '--v-tabs-height': convertToUnit(props.height) }, + { + '--v-tabs-height': convertToUnit(props.height), + '--v-tabs-inset-padding': props.inset ? convertToUnit(props.insetPadding) : undefined, + '--v-tabs-inset-radius': props.inset ? convertToUnit(props.insetRadius) : undefined, + }, backgroundColorStyles.value, props.style, ]}