Propel

Slider

A single-thumb control for picking a number within a range.

Volume
40
Show code
import { Slider } from "@makeplane/propel/components/slider";
import * as React from "react";

export default function BasicDemo() {
  const [value, setValue] = React.useState(40);
  return (
    <Slider
      label="Volume"
      size="md"
      value={value}
      onValueChange={(next) => setValue(next as number)}
      min={0}
      max={100}
      step={1}
    />
  );
}

Installation

import { Slider } from "@makeplane/propel/components/slider";

Usage

import { Slider } from "@makeplane/propel/components/slider";
import * as React from "react";

export default function BasicDemo() {
  const [value, setValue] = React.useState(40);
  return (
    <Slider
      label="Volume"
      size="md"
      value={value}
      onValueChange={(next) => setValue(next as number)}
      min={0}
      max={100}
      step={1}
    />
  );
}

Examples

Sizes

The size axis sets the thumb and hit-area size; the track bar height stays the same.

sm
40
md
40
lg
40
Show code
import { Slider } from "@makeplane/propel/components/slider";

export default function SizesDemo() {
  return (
    <div className="flex flex-col gap-6">
      <Slider label="sm" size="sm" defaultValue={40} min={0} max={100} step={1} />
      <Slider label="md" size="md" defaultValue={40} min={0} max={100} step={1} />
      <Slider label="lg" size="lg" defaultValue={40} min={0} max={100} step={1} />
    </div>
  );
}

Formatted value

Pass format (an Intl.NumberFormatOptions) to control the readout — here a percentage.

Opacity
60%
Show code
import { Slider } from "@makeplane/propel/components/slider";
import * as React from "react";

export default function FormattedValueDemo() {
  const [value, setValue] = React.useState(0.6);
  return (
    <Slider
      label="Opacity"
      size="md"
      value={value}
      onValueChange={(next) => setValue(next as number)}
      min={0}
      max={1}
      step={0.01}
      format={{ style: "percent", maximumFractionDigits: 0 }}
    />
  );
}

Edge-aligned thumb

With thumbAlignment="edge" the thumb stays fully inside the track at the extremes instead of overhanging it.

Progress
25
Show code
import { Slider } from "@makeplane/propel/components/slider";
import * as React from "react";

export default function EdgeAlignedThumbDemo() {
  const [value, setValue] = React.useState(25);
  return (
    <Slider
      label="Progress"
      size="md"
      value={value}
      onValueChange={(next) => setValue(next as number)}
      min={0}
      max={100}
      step={1}
      thumbAlignment="edge"
    />
  );
}

In a form

Wrap the slider in a Field with a name and its value serializes with the surrounding Form.

Volume
40
Show code
import { Button } from "@makeplane/propel/components/button";
import { Field } from "@makeplane/propel/components/field";
import { Form, FormActions, FormBody } from "@makeplane/propel/components/form";
import { Slider } from "@makeplane/propel/components/slider";
import * as React from "react";

export default function InAFormDemo() {
  const [submitted, setSubmitted] = React.useState<{ volume: number } | null>(null);
  return (
    <div className="flex flex-col gap-3">
      <Form<{ volume: number }> onFormSubmit={(values) => setSubmitted(values)}>
        <FormBody layout="single">
          <Field name="volume">
            <Slider label="Volume" size="md" defaultValue={40} min={0} max={100} step={1} />
          </Field>
        </FormBody>
        <FormActions layout="inline">
          <Button stretch="auto" type="submit" variant="primary" size="sm" label="Save" />
        </FormActions>
      </Form>
      <output className="text-body-xs-regular text-secondary">
        {submitted ? `Volume: ${submitted.volume}` : null}
      </output>
    </div>
  );
}

API Reference

Slider

The ready-made slider: a single-thumb control for picking a number within a range. Drive it with value/defaultValue + onValueChange, and bound it with min/max/step. Pass label (visible) or aria-label to name the thumb, and format (an Intl.NumberFormatOptions) to format the readout. size sets the thumb and hit-area size (sm / md / lg). The track bar height and shape are always the same per the design spec. Grafts Base UI Slider behavior onto the elements/slider styled parts (Slider root + SliderLabel + SliderValue + SliderControl + SliderTrack + SliderIndicator + SliderThumb). For multiple thumbs or fully custom layout, graft the elements/slider parts directly.

PropTypeDefaultDescription
size(required)"sm" | "md" | "lg"—Thumb and control size. sm = 12 px thumb, md = 16 px, lg = 20 px.
aria-labelstring—Defines a string value that labels the current element. Accessible name for the thumb. Required when there is no visible label. @see aria-labelledby.
renderReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SliderRootState>—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.
labelstring—Optional visible label rendered above the track (e.g. "Volume"). When omitted, provide an aria-label for the thumb so the control is still named for assistive tech.