0

I want to create a follow effect. currently the when i move the slider.thumb the tool tip moves instantly with the slider.thumb. but i want when to create a pulling effect with slight delay.

Here is the Video Showing Desired Effect

this is my current code. & stackblitz link

import * as Slider from '@radix-ui/react-slider'
import { useState } from 'react'

export const InputRange = () => {
    const [value, setValue] = useState(2)

    return (
        <form>
            <Slider.Root
                className="relative flex items-center select-none touch-none w-full h-5 "
                defaultValue={[value]}
                min={1}
                max={30}
                step={1}
                aria-label="Volume"
                onValueChange={(e) => setValue(e[0])}
            >
                <Slider.Track className="bg-slate-200 relative grow rounded-full h-[3px]">
                    <Slider.Range className="absolute bg-black rounded-full h-full" />
                </Slider.Track>
                <Slider.Thumb className="relative group duration-150 block w-6 h-6 bg-black rounded-full active:scale-125 outline-none border-none cursor-pointer " >
                    <h1 className='absolute ease-in-out duration-150 opacity-0 group-active:opacity-100 group-active:-translate-y-12 -translate-x-8 -translate-y-6  px-5 py-2 bg-black text-center rounded-full text-white whitespace-nowrap text-xs font-bold'>{value} {value === 1 ? "night" : "nights"} </h1>
                </Slider.Thumb>
            </Slider.Root>
        </form>
    )
}

I tried to update the position of the tooltip for the radix-ui/react-slider component, but it caused the tooltip to move off the screen when I moved the slider.

const updateTooltipPosition = () => {
        const thumb = thumbRef.current.getBoundingClientRect()
        const tooltip = tooltipRef.current.getBoundingClientRect()
        // console.log(thumb.x );
        const tooltipCenter = tooltip.left + tooltip.width / 2
        console.log(tooltip.left , tooltipCenter)

        tooltipRef.current.style.transform = `translate(${}px, -120%)`
    }

tried using useEffect but did nothing.

  const [value, setValue] = useState(2)
  const tooltipRef = useRef(null)

  useEffect(() => {
    if (tooltipRef.current) {
      const tooltipWidth = tooltipRef.current.offsetWidth
      const thumbPosition = ((value - 1) / 29) * 100 // calculate the position of the thumb
      const tooltipPosition = thumbPosition - tooltipWidth / 2 // adjust for the width of the tooltip
      tooltipRef.current.style.left = `${tooltipPosition}%` // set the left position of the tooltip
    }
  }, [value])

other possible ways i wanted to try like using a library like react-spring, framer motion but don't know how it will solve the issue.

Pushon
  • 15
  • 6

1 Answers1

0
export const InputRange = () => {
  const [value, setValue] = useState(2);
  // Positioning offset state. Default value is when `value = 2`.
  const [offset, setOffset] = useState(14.8812);
  // Tooltip element reference.
  const ref = useRef(null);

  useLayoutEffect(() => {
    // Get the left and right edge coordinates of the tooltip element.
    const { left, right } = ref.current.getBoundingClientRect();
    // If left or right is positive, the tooltip element (or a parent)
    // does not have `display: none`:
    if (left + right > 0) {
      // Get the box of the form, that we'll use as our layout "edge".
      const containerRect = ref.current.closest('form').getBoundingClientRect();

      // Adjust the left and right sides to account for the 
      // `active:scale-125` "extra". `12` is thumb width ÷ 2.
      const limitLeft = containerRect.left - 12 * 0.25;
      const limitRight = containerRect.right + 12 * 0.25;

      // Get the overhang distance of the tooltip from its left and 
      // right edges, relative to the container's (adjusted) left and 
      // right edges, compensating for existing offset and the
      // `active:scale-125`.
      const offsetLeft = offset + (limitLeft - left) / 1.25;
      const offsetRight = offset + (limitRight - right) / 1.25;
      // If there is left overhang, set the offset.
      if (offsetLeft > 0) {
        setOffset(offsetLeft);
      // If there is right overhang, set the offset.
      } else if (offsetRight < 0) {
        setOffset(offsetRight);
      }
    }
  });

  return (
    <form>
      {/* … */}
      <div style={{ transform: `translateX(${offset}px)` }}>
        <h1 className="… -translate-x-1/2 left-1/2 …" ref={ref}>
          {value} {value === 1 ? 'time' : 'times'}{' '}
        </h1>
      </div>
      {/* … */}
    </form>
  );
};

Live example on Stackblitz

Wongjn
  • 8,544
  • 2
  • 8
  • 24
  • There is an issue with a video that I have seen at this [video link](https://streamable.com/n26ssk). The problem is that the tool tip, which is supposed to stay centered when it is moved, is not staying centered. When the tool tip reaches the edge, it creates an effect, but even when it is moved, the center of the tool tip should align with the slider thumb. As seen in the video, when the slider is moved fast, the tool tip should create a lagging behind effect, and when the slider is moving slowly, the tool tip should not lag. – Pushon May 04 '23 at 09:16