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-labelstringDefines 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.
labelstringOptional 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.