diff --git a/src/components/Form/Settings/Slider/Slider.jsx b/src/components/Form/Settings/Slider/Slider.jsx index 49e42329..825f3421 100644 --- a/src/components/Form/Settings/Slider/Slider.jsx +++ b/src/components/Form/Settings/Slider/Slider.jsx @@ -9,7 +9,10 @@ import './Slider.scss'; const SliderComponent = memo((props) => { const [value, setValue] = useState(localStorage.getItem(props.name) || props.default); + const [hoverValue, setHoverValue] = useState(null); + const [hoverPosition, setHoverPosition] = useState(0); const animationRef = useRef(null); + const sliderRef = useRef(null); const handleChange = useCallback( (e) => { @@ -57,7 +60,8 @@ const SliderComponent = memo((props) => { const easeOutCubic = 1 - Math.pow(1 - progress, 3); const currentValue = startValue + (endValue - startValue) * easeOutCubic; - const roundedValue = Math.round(currentValue / (Number(props.step) || 1)) * (Number(props.step) || 1); + const roundedValue = + Math.round(currentValue / (Number(props.step) || 1)) * (Number(props.step) || 1); localStorage.setItem(props.name, roundedValue); setValue(roundedValue); @@ -76,6 +80,30 @@ const SliderComponent = memo((props) => { toast(variables.getMessage('toasts.reset')); }, [value, props]); + const handleMouseMove = useCallback( + (e) => { + if (!sliderRef.current || props.disabled) return; + + const rect = sliderRef.current.getBoundingClientRect(); + const x = e.clientX - rect.left; + const percentage = Math.max(0, Math.min(100, (x / rect.width) * 100)); + + const range = Number(props.max) - Number(props.min); + const rawValue = (percentage / 100) * range + Number(props.min); + const step = Number(props.step) || 1; + const snappedValue = Math.round(rawValue / step) * step; + const clampedValue = Math.max(Number(props.min), Math.min(Number(props.max), snappedValue)); + + setHoverPosition(percentage); + setHoverValue(clampedValue); + }, + [props], + ); + + const handleMouseLeave = useCallback(() => { + setHoverValue(null); + }, []); + const percentage = ((Number(value) - Number(props.min)) / (Number(props.max) - Number(props.min))) * 100; @@ -88,8 +116,9 @@ const SliderComponent = memo((props) => { {variables.getMessage('modals.main.settings.buttons.reset')} -
+
{ aria-valuenow={Number(value)} disabled={props.disabled || false} /> + {hoverValue !== null && !props.disabled && ( + <> +
+
+ {hoverValue} +
+ + )} {props.marks && props.marks.length > 0 && (
{props.marks.map((mark) => ( diff --git a/src/components/Form/Settings/Slider/Slider.scss b/src/components/Form/Settings/Slider/Slider.scss index 252bf342..4fb49f81 100644 --- a/src/components/Form/Settings/Slider/Slider.scss +++ b/src/components/Form/Settings/Slider/Slider.scss @@ -29,6 +29,7 @@ font-weight: 500; text-transform: uppercase; letter-spacing: 0.5px; + transition: all 0.2s ease; @include themed { color: t($link); @@ -36,10 +37,16 @@ &:hover { opacity: 0.8; + transform: scale(1.05); } svg { font-size: 12px; + transition: transform 0.2s ease; + } + + &:hover svg { + transform: rotate(180deg); } } @@ -56,7 +63,7 @@ border-radius: 3px; outline: none; cursor: pointer; - transition: background 0.3s ease; + transition: all 0.2s ease; @include themed { background: linear-gradient( @@ -68,6 +75,11 @@ ); } + &:hover:not(:disabled) { + height: 8px; + filter: brightness(1.1); + } + &::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; @@ -114,7 +126,9 @@ &::-webkit-slider-thumb { @include themed { - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2), 0 0 0 3px t($link); + box-shadow: + 0 2px 6px rgba(0, 0, 0, 0.2), + 0 0 0 3px t($link); } transform: scale(1.15); @@ -122,7 +136,9 @@ &::-moz-range-thumb { @include themed { - box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2), 0 0 0 3px t($link); + box-shadow: + 0 2px 6px rgba(0, 0, 0, 0.2), + 0 0 0 3px t($link); } transform: scale(1.15); @@ -171,4 +187,53 @@ } } } + + .slider-hover-indicator { + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + width: 12px; + height: 12px; + border-radius: 50%; + pointer-events: none; + z-index: 1; + opacity: 0.6; + + @include themed { + background: t($link); + box-shadow: 0 0 8px rgba(t($link), 0.5); + } + } + + .slider-hover-tooltip { + position: absolute; + top: -35px; + transform: translateX(-50%); + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + font-weight: 600; + white-space: nowrap; + pointer-events: none; + z-index: 2; + + @include themed { + background: t($link); + color: t($background); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + } + + &::after { + content: ''; + position: absolute; + top: 100%; + left: 50%; + transform: translateX(-50%); + border: 5px solid transparent; + + @include themed { + border-top-color: t($link); + } + } + } }