Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const VRangeSlider = genericComponent<VSliderSlots>()({
'v-slider--focused': isFocused.value,
'v-slider--pressed': mousePressed.value,
'v-slider--disabled': disabled.value,
[`v-slider--variant-${props.variant}`]: props.variant !== 'default',
},
rtlClasses.value,
props.class,
Expand Down
5 changes: 5 additions & 0 deletions packages/vuetify/src/components/VSlider/VSlider.sass
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,8 @@

.v-slider__label
margin-inline-end: $slider-label-margin-end

// Pill variant
.v-slider--variant-pill
.v-slider__container
cursor: pointer
1 change: 1 addition & 0 deletions packages/vuetify/src/components/VSlider/VSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const VSlider = genericComponent<VSliderSlots>()({
'v-slider--focused': isFocused.value,
'v-slider--pressed': mousePressed.value,
'v-slider--disabled': disabled.value,
[`v-slider--variant-${props.variant}`]: props.variant !== 'default',
},
rtlClasses.value,
props.class,
Expand Down
45 changes: 42 additions & 3 deletions packages/vuetify/src/components/VSlider/VSliderThumb.sass
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,45 @@
.v-slider-thumb__surface::before
transform: scale(2)

.v-slider-thumb:hover:not(.v-slider-thumb--focused)
.v-slider-thumb__surface::before
opacity: $slider-thumb-hover-opacity
.v-slider--variant-pill
.v-slider-thumb__surface
border-radius: $slider-pill-thumb-border-radius

&::before,
&::after
display: none

&.v-input--horizontal .v-slider-thumb
inset-inline-start: calc(var(--v-slider-thumb-position) - #{$slider-pill-thumb-width} / 2)

> .v-slider-thumb__surface
width: $slider-pill-thumb-width
min-height: $slider-pill-thumb-min-height

&:focus-visible,
&.v-slider-thumb--focused
> .v-slider-thumb__surface
width: $slider-pill-focused-thumb-width
margin-inline-start: calc((#{$slider-pill-thumb-width} - #{$slider-pill-focused-thumb-width}) / 2)

&.v-input--vertical .v-slider-thumb
top: calc(var(--v-slider-thumb-position) - #{$slider-pill-thumb-width} / 2)

> .v-slider-thumb__surface
height: $slider-pill-thumb-width
min-width: $slider-pill-thumb-min-height

&:focus-visible,
&.v-slider-thumb--focused
> .v-slider-thumb__surface
height: $slider-pill-focused-thumb-width
margin-top: calc((#{$slider-pill-thumb-width} - #{$slider-pill-focused-thumb-width}) / 2)

.v-slider-thumb__ripple
display: none

.v-slider-thumb:focus-visible,
.v-slider-thumb--focused
.v-slider-thumb__surface
outline: 3px solid currentColor
outline-offset: 2px
5 changes: 4 additions & 1 deletion packages/vuetify/src/components/VSlider/VSliderThumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const VSliderThumb = genericComponent<VSliderThumbSlots>()({
step,
disabled,
thumbSize,
trackSize,
thumbLabel,
direction,
isReversed,
Expand All @@ -87,10 +88,12 @@ export const VSliderThumb = genericComponent<VSliderThumbSlots>()({
mousePressed,
decimals,
indexFromEnd,
variant,
} = slider

const isHovered = shallowRef(false)
const isHidden = shallowRef(false)
const isPill = computed(() => variant.value === 'pill')

const elevationProps = computed(() => !disabled.value ? elevation.value : undefined)
const { elevationClasses } = useElevation(elevationProps)
Expand Down Expand Up @@ -174,7 +177,7 @@ export const VSliderThumb = genericComponent<VSliderThumbSlots>()({
style={[
{
'--v-slider-thumb-position': positionPercentage,
'--v-slider-thumb-size': convertToUnit(thumbSize.value),
'--v-slider-thumb-size': convertToUnit(isPill.value ? (trackSize.value + 8) : thumbSize.value),
},
props.style,
]}
Expand Down
121 changes: 121 additions & 0 deletions packages/vuetify/src/components/VSlider/VSliderTrack.sass
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,17 @@
touch-action: pan-y

&__background
inset-inline-start: 0
width: 100%
height: var(--v-slider-track-size)

&__fill
inset-inline-start: var(--v-slider-value-start)
width: calc(var(--v-slider-value-stop) - var(--v-slider-value-start))
height: inherit

.v-slider-track__tick
inset-inline-start: var(--v-slider-tick-position)
margin-top: calc(#{$slider-track-active-size} / 2)

@include tools.rtl()
Expand Down Expand Up @@ -136,15 +141,20 @@
touch-action: pan-x

&__background
top: 0
height: 100%
width: var(--v-slider-track-size)

&__fill
top: calc(100% - var(--v-slider-value-stop))
height: calc(var(--v-slider-value-stop) - var(--v-slider-value-start))
width: inherit

.v-slider-track__ticks
height: 100%

.v-slider-track__tick
bottom: var(--v-slider-tick-position)
margin-inline-start: calc(#{$slider-track-active-size} / 2)
transform: translate(calc(var(--v-slider-tick-size) / -2), calc(var(--v-slider-tick-size) / 2))

Expand All @@ -167,3 +177,114 @@

.v-slider-track__background--opacity
opacity: 0.38

// Pill variant
.v-slider--variant-pill
--v-slider-pill-gap: #{$slider-pill-gap}
--v-slider-pill-thumb-width: #{$slider-pill-thumb-width}

.v-slider-track
border-radius: $slider-pill-track-outer-radius

.v-slider-track__background,
.v-slider-track__fill
border-radius: $slider-pill-track-outer-radius

.v-slider-track__background--opacity
opacity: 0.24

&.v-input--horizontal
.v-slider-track
height: var(--v-slider-track-size)

&__background
height: var(--v-slider-track-size)

&__fill
inset-inline-start: calc(var(--v-slider-value-start) + var(--v-slider-pill-thumb-width) / 2 + var(--v-slider-pill-gap))
width: calc(var(--v-slider-value-stop) - var(--v-slider-value-start) - var(--v-slider-pill-thumb-width) - var(--v-slider-pill-gap) * 2)
height: var(--v-slider-track-size)

.v-slider-track__inactive--before
inset-inline-start: 0
width: calc(var(--v-slider-value-start) - var(--v-slider-pill-thumb-width) / 2 - var(--v-slider-pill-gap))
border-radius: $slider-pill-track-outer-radius $slider-pill-track-inner-radius $slider-pill-track-inner-radius $slider-pill-track-outer-radius

~ .v-slider-track__fill
border-top-left-radius: $slider-pill-track-inner-radius
border-bottom-left-radius: $slider-pill-track-inner-radius

.v-slider-track__inactive--after
inset-inline-start: calc(var(--v-slider-value-stop) + var(--v-slider-pill-thumb-width) / 2 + var(--v-slider-pill-gap))
width: calc(100% - var(--v-slider-value-stop) - var(--v-slider-pill-thumb-width) / 2 - var(--v-slider-pill-gap))
border-radius: $slider-pill-track-inner-radius $slider-pill-track-outer-radius $slider-pill-track-outer-radius $slider-pill-track-inner-radius

~ .v-slider-track__fill
border-top-right-radius: $slider-pill-track-inner-radius
border-bottom-right-radius: $slider-pill-track-inner-radius

.v-slider-track__inactive--before,
.v-slider-track__inactive--after
&::before
content: ''
position: absolute
width: $slider-pill-stop-indicator-size
height: $slider-pill-stop-indicator-size
border-radius: $slider-pill-stop-indicator-border-radius
background: currentColor
top: 50%
transform: translateY(-50%)

.v-slider-track__inactive--before::before
left: calc(#{$slider-pill-gap} - #{$slider-pill-stop-indicator-size} / 2)

.v-slider-track__inactive--after::before
right: calc(#{$slider-pill-gap} - #{$slider-pill-stop-indicator-size} / 2)

&.v-input--vertical
.v-slider-track
width: var(--v-slider-track-size)

&__background
width: var(--v-slider-track-size)

&__fill
top: calc(100% - var(--v-slider-value-stop) + var(--v-slider-pill-thumb-width) / 2 + var(--v-slider-pill-gap))
height: calc(var(--v-slider-value-stop) - var(--v-slider-value-start) - var(--v-slider-pill-thumb-width) - var(--v-slider-pill-gap) * 2)
width: var(--v-slider-track-size)

.v-slider-track__inactive--before
top: calc(100% - var(--v-slider-value-start) + var(--v-slider-pill-thumb-width) / 2 + var(--v-slider-pill-gap))
height: calc(var(--v-slider-value-start) - var(--v-slider-pill-thumb-width) / 2 - var(--v-slider-pill-gap))
border-radius: $slider-pill-track-inner-radius $slider-pill-track-inner-radius $slider-pill-track-outer-radius $slider-pill-track-outer-radius

~ .v-slider-track__fill
border-bottom-left-radius: $slider-pill-track-inner-radius
border-bottom-right-radius: $slider-pill-track-inner-radius

.v-slider-track__inactive--after
top: 0
height: calc(100% - var(--v-slider-value-stop) - var(--v-slider-pill-thumb-width) / 2 - var(--v-slider-pill-gap))
border-radius: $slider-pill-track-outer-radius $slider-pill-track-outer-radius $slider-pill-track-inner-radius $slider-pill-track-inner-radius

~ .v-slider-track__fill
border-top-left-radius: $slider-pill-track-inner-radius
border-top-right-radius: $slider-pill-track-inner-radius

.v-slider-track__inactive--before,
.v-slider-track__inactive--after
&::before
content: ''
position: absolute
width: $slider-pill-stop-indicator-size
height: $slider-pill-stop-indicator-size
border-radius: $slider-pill-stop-indicator-border-radius
background: currentColor
left: 50%
transform: translateX(-50%)

.v-slider-track__inactive--before::before
bottom: calc(#{$slider-pill-gap} - #{$slider-pill-stop-indicator-size} / 2)

.v-slider-track__inactive--after::before
top: calc(#{$slider-pill-gap} - #{$slider-pill-stop-indicator-size} / 2)
90 changes: 51 additions & 39 deletions packages/vuetify/src/components/VSlider/VSliderTrack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ export const VSliderTrack = genericComponent<VSliderTrackSlots>()({
trackColor,
trackFillColor,
trackSize,
variant,
vertical,
min,
max,
indexFromEnd,
// indexFromEnd, TODO: understand and restore behavior
} = slider

const isPill = computed(() => variant.value === 'pill')

const { roundedClasses } = useRounded(rounded)

const {
Expand All @@ -72,32 +75,15 @@ export const VSliderTrack = genericComponent<VSliderTrackSlots>()({
backgroundColorStyles: trackColorStyles,
} = useBackgroundColor(trackColor)

const startDir = computed(() => `inset-${vertical.value ? 'block' : 'inline'}-${indexFromEnd.value ? 'end' : 'start'}`)
const endDir = computed(() => vertical.value ? 'height' : 'width')

const backgroundStyles = computed(() => {
return {
[startDir.value]: '0%',
[endDir.value]: '100%',
}
})

const trackFillWidth = computed(() => props.stop - props.start)

const trackFillStyles = computed(() => {
return {
[startDir.value]: convertToUnit(props.start, '%'),
[endDir.value]: convertToUnit(trackFillWidth.value, '%'),
}
})

const computedTicks = computed(() => {
if (!showTicks.value) return []

const ticks = vertical.value ? parsedTicks.value.slice().reverse() : parsedTicks.value

return ticks.map((tick, index) => {
const directionValue = tick.value !== min.value && tick.value !== max.value ? convertToUnit(tick.position, '%') : undefined
const directionValue = tick.value !== min.value && tick.value !== max.value
? convertToUnit(tick.position, '%')
: undefined

return (
<div
Expand All @@ -110,7 +96,7 @@ export const VSliderTrack = genericComponent<VSliderTrackSlots>()({
'v-slider-track__tick--last': tick.value === max.value,
},
]}
style={{ [startDir.value]: directionValue }}
style={{ '--v-slider-tick-position': directionValue }}
>
{
(tick.label || slots['tick-label']) && (
Expand All @@ -136,32 +122,58 @@ export const VSliderTrack = genericComponent<VSliderTrackSlots>()({
{
'--v-slider-track-size': convertToUnit(trackSize.value),
'--v-slider-tick-size': convertToUnit(tickSize.value),
'--v-slider-value-start': convertToUnit(props.start, '%'),
'--v-slider-value-stop': convertToUnit(props.stop, '%'),
},
props.style,
]}
>
<div
class={[
'v-slider-track__background',
trackColorClasses.value,
{
'v-slider-track__background--opacity': !!color.value || !trackFillColor.value,
},
]}
style={{
...backgroundStyles.value,
...trackColorStyles.value,
}}
/>
{ isPill.value ? (
<>
{ props.start > 0 && (
<div
class={[
'v-slider-track__background',
'v-slider-track__inactive--before',
trackColorClasses.value,
{
'v-slider-track__background--opacity': !!color.value || !trackFillColor.value,
},
]}
style={[trackColorStyles.value]}
/>
)}
<div
class={[
'v-slider-track__background',
'v-slider-track__inactive--after',
trackColorClasses.value,
{
'v-slider-track__background--opacity': !!color.value || !trackFillColor.value,
},
]}
style={[trackColorStyles.value]}
/>
</>
) : (
<div
key="default"
class={[
'v-slider-track__background',
trackColorClasses.value,
{
'v-slider-track__background--opacity': !!color.value || !trackFillColor.value,
},
]}
style={[trackColorStyles.value]}
/>
)}
<div
class={[
'v-slider-track__fill',
trackFillColorClasses.value,
]}
style={{
...trackFillStyles.value,
...trackFillColorStyles.value,
}}
style={[trackFillColorStyles.value]}
/>

{ showTicks.value && (
Expand Down
Loading