Skip to content

shadcn.io is an independent project built on shadcn/ui

Free

With Tooltip Slider for React

A Progress slider starting at 45, with a bubble above the thumb that stays visible and shows the percentage.

Progress labels the track. A bubble above the thumb reads 45% and lines up with it. The bubble is always visible. It is not a tooltip.

Use it when people watch the number while they drag. For a hint that appears on hover only, use a Tooltip. In React, Base UI does not place that bubble.

Preview

Preview width

Installation

Sign in to get your install command
Free with an account. It carries your token, so the CLI installs everything in one go.
Use email insteadNo credit card

Anatomy

Slider anatomy: root, label, value, track, range, thumb

Usage

<div className="flex w-full max-w-md flex-col gap-2">
  <Label>Progress</Label>
  <div className="relative pt-6">
    <Slider
      aria-label="Progress"
      onValueChange={handleValueChange}
      value={value}
    />
    <div
      aria-hidden="true"
      className="absolute -top-2 -translate-x-1/2 rounded bg-primary px-2 py-1 text-primary-foreground text-xs tabular-nums rtl:translate-x-1/2"
      style={{ insetInlineStart: `${value[0]}%` }}
    >
      {value[0]}%
    </div>
  </div>
</div>

FAQ

Is this a Tooltip component?

No. The bubble is a div in a relative pt-6 wrapper, absolute -top-2 with bg-primary and text-primary-foreground. It is always visible and aria-hidden, since the slider already announces its value.

How does the bubble follow the thumb?

Its inline start is set to the value as a percent, and -translate-x-1/2 centers it on that point. It moves on every step, while you drag or use the keys.

How does the readout follow the thumb?

The value lives in state, starting at 45, and goes back to the slider as value. The bubble prints it with a % sign. onValueChange receives the new value, and the handler stores it as an array.

What happens to the bubble at 0% and 100%?

The bubble is placed by the raw percent, so near the ends half of it hangs past the track, and it can sit slightly off the thumb. Clamp the position if that matters in your layout.

How is the slider named?

The Progress text is a visible Label, and the slider gets the same name with aria-label, so screen readers announce what it sets. On Base UI, aria-label is one string on the slider.

What scale is the percent on?

0 to 100, which matches the percent used for the position. min and max set the ends.

API Reference

Label

No extra props in this demo. The rest is on the Label page.

Slider

Sets aria-label="Progress", onValueChange={handleValueChange} and value={value}. The rest is on the Slider page.