component

Input Range

A styled wrapper around <input type="range"> that shares the feedback, size, and background vocabulary of the rest of the form surface. The track fills proportionally with the current value so users see the selected amount at a glance.

Feedback

Apply semantic feedback colors to tint the filled track and thumb — useful for tying a slider to a validation state or a themed control group.

---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column" })}>
  <InputRange feedback="neutral" value={40} min={0} max={100} fullWidth />
  <InputRange feedback="primary" value={55} min={0} max={100} fullWidth />
  <InputRange feedback="success" value={70} min={0} max={100} fullWidth />
  <InputRange feedback="danger" value={25} min={0} max={100} fullWidth />
  <InputRange feedback="warning" value={85} min={0} max={100} fullWidth />
</div>

Size

Four sizes scale the track height and thumb diameter together so the control stays proportional inside tight toolbars or prominent settings panels.

---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div class={stack({ gap: "md", direction: "column" })}>
  <InputRange size="xs" value={20} min={0} max={100} fullWidth />
  <InputRange size="sm" value={40} min={0} max={100} fullWidth />
  <InputRange size="md" value={60} min={0} max={100} fullWidth />
  <InputRange size="lg" value={80} min={0} max={100} fullWidth />
</div>

Prefix & Suffix

Use fieldPrefix and fieldSuffix to add labels or a live value readout alongside the track. The native <input> still owns the value — bind it to display the current number. Use labelPosition to place the labels inline with the track (default), or stacked on top or bottom.

Volume
35%
Brightness
72%
0
100
---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---

<div class={stack({ gap: "lg", direction: "column" })}>
  <InputRange value={35} min={0} max={100} fullWidth>
    <span slot="fieldPrefix" class={css({ whiteSpace: "nowrap" })}>
      Volume
    </span>
    <span
      slot="fieldSuffix"
      class={css({ minWidth: "3ch", textAlign: "right" })}
    >
      35%
    </span>
  </InputRange>

  <InputRange value={72} min={0} max={100} fullWidth labelPosition="top">
    <span slot="fieldPrefix" class={css({ whiteSpace: "nowrap" })}>
      Brightness
    </span>
    <span slot="fieldSuffix" class={css({ textAlign: "right" })}>72%</span>
  </InputRange>

  <InputRange value={60} min={0} max={100} fullWidth labelPosition="bottom">
    <span slot="fieldPrefix" class={css({ whiteSpace: "nowrap" })}> 0 </span>
    <span slot="fieldSuffix" class={css({ textAlign: "right" })}>100</span>
  </InputRange>
</div>

Dual Range

Provide valueStart and valueEnd (instead of a single value) to select an interval with two thumbs — ideal for price ranges or bounds. Set minGap to keep a minimum distance between the thumbs. Each thumb is a real native <input type="range">, so keyboard and assistive-tech support come for free.

---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({ gap: "lg", direction: "column" })}
  style="width: 28rem; max-width: 100%"
>
  <InputRange valueStart={200} valueEnd={750} min={0} max={1000} fullWidth />
  <InputRange
    valueStart={30}
    valueEnd={60}
    min={0}
    max={100}
    minGap={10}
    feedback="success"
    showValue="always"
    fullWidth
  />
</div>

Tick Marks

Pass marks to render dots along the track: marks (with a step) auto-generates evenly-spaced marks, or pass an array of { value, label? } to place explicit, labelled marks.

FasterSmarter
---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({ gap: "lg", direction: "column" })}
  style="width: 28rem; max-width: 100%"
>
  <InputRange value={40} min={0} max={100} step={20} marks fullWidth />
  <InputRange
    value={50}
    min={0}
    max={100}
    step={25}
    marks={[
      { value: 0, label: "Faster" },
      { value: 100, label: "Smarter" },
    ]}
    showValue
    fullWidth
  />
</div>

Stepped

appearance="stepped" gives the segmented look — a wider pill thumb, firmer dots, and snap-to-mark defaulted on. Combine with marks and a step.

Faster
Smarter
---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
---

<div
  class={stack({ gap: "lg", direction: "column" })}
  style="width: 28rem; max-width: 100%"
>
  <InputRange
    value={50}
    min={0}
    max={100}
    step={25}
    appearance="stepped"
    marks
    fullWidth
  >
    <span slot="fieldPrefix">Faster</span>
    <span slot="fieldSuffix">Smarter</span>
  </InputRange>
</div>

Snap to Marks

Set snap with an array of marks (and step="any" for fine input resolution) to snap the value to the nearest mark on drag or arrow-key — including unevenly-spaced stops.

0102560100
---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";

const stops = [0, 10, 25, 60, 100];
---

<div
  class={stack({ gap: "lg", direction: "column" })}
  style="width: 28rem; max-width: 100%"
>
  <InputRange
    value={25}
    min={0}
    max={100}
    step="any"
    snap
    marks={stops.map((value) => ({ value, label: String(value) }))}
    fullWidth
  />
</div>

Custom Styling

The passThrough prop provides escape hatches for each slot: style accepts a Panda CSS SystemStyleObject and props forwards arbitrary HTML attributes to the corresponding element.

Wrapped in a surface via passThrough

Squared thumb via passThrough

Forwarded ARIA attributes

Opacity
50%
---
import InputRange from "../InputRange.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---

<div class={stack({ gap: "xl", direction: "column" })}>
  <div>
    <h3>Wrapped in a surface via passThrough</h3>
    <InputRange
      value={40}
      min={0}
      max={100}
      fullWidth
      passThrough={{
        root: {
          style: {
            background: "neutral.surface.hill",
            borderRadius: "md",
            padding: "md",
          },
        },
      }}
    />
  </div>

  <div>
    <h3>Squared thumb via passThrough</h3>
    <InputRange
      value={65}
      min={0}
      max={100}
      fullWidth
      passThrough={{
        input: {
          style: {
            "&::-webkit-slider-thumb": { borderRadius: "xs" },
            "&::-moz-range-thumb": { borderRadius: "xs" },
          },
        },
      }}
    />
  </div>

  <div>
    <h3>Forwarded ARIA attributes</h3>
    <InputRange
      value={50}
      min={0}
      max={100}
      fullWidth
      labelPosition="top"
      passThrough={{
        input: {
          props: {
            "aria-label": "Opacity",
            "data-testid": "opacity-slider",
          },
        },
      }}
    >
      <span slot="fieldPrefix" class={css({ fontWeight: "medium" })}>
        Opacity
      </span>
      <span slot="fieldSuffix" class={css({ textAlign: "right" })}>50%</span>
    </InputRange>
  </div>
</div>
props · 22 shown · 22 total
appearance
"continuous""stepped"
default "continuous"

Visual treatment of the track and thumb. `continuous` is the default smooth slider; `stepped` renders a wider pill thumb, emphasises tick dots, and defaults `snap` on for the segmented look.

background
"surface.peak""surface.hill""surface.base""surface.valley""surface.ground""transparent"
default "transparent"

Surface background token applied to the root wrapper.

border
"none""bold""default""muted""accent"
default "none"

Border style inherited from the panel token set.

element binding svelte
HTMLInputElementnull

No description yet.

feedback
"primary""neutral""success""warning""danger""inherit"
default "primary"

Semantic feedback color scheme that tints the filled track and thumb. One of `neutral`, `primary`, `success` (green), `danger` (red), or `warning` (orange).

fieldPrefix slot svelte
Snippet

No description yet.

fieldSuffix slot svelte
Snippet

No description yet.

fullWidth
boolean
default false

Stretch the root to fill its container.

hasPrefix
boolean

Whether a prefix label/readout slot is present, used to lay out the track row accordingly.

hasSuffix
boolean

Whether a suffix label/readout slot is present, used to lay out the track row accordingly.

labelPosition
"bottom""top""inline"
default "inline"

Where to place `fieldPrefix` and `fieldSuffix` relative to the track: `inline` on the same row, `top` stacked above, or `bottom` stacked below.

marks
booleanInputRangeMark[]

Tick marks along the track. `true` auto-generates evenly-spaced marks from `step`; an array places explicit (optionally labelled) marks.

minGap
number
default 0

Minimum distance (in value units) kept between the two thumbs in dual mode.

mode
"single""dual"

Selection mode. `single` is one thumb (drive with `value`); `dual` is a two-thumb interval (drive with `valueStart`/`valueEnd`). Inferred as `dual` when either dual value is provided.

origin
number"start""center"
default "start"

Where the single-thumb fill originates: `"start"` (default), `"center"` (for signed ranges), or a specific value.

passThrough
InputRangePassThrough< RootElementAttributes, InputElementAttributes, PrefixElementAttributes, SuffixElementAttributes >

Per-slot style and attribute override bag, letting consumers customize any slot of the input-range.

showValue
boolean"active""always""hover""thumb"

Show a value tooltip above the thumb. `true`/`"hover"` reveal it while pointing anywhere on the row or while focused; `"active"` only while dragging or keyboard-adjusting the thumb; `"thumb"` also while the pointer hovers the thumb itself; `"always"` keeps it visible.

size
"sm""md""lg""xs"
default "md"

Size variant that scales the track height and thumb diameter together. One of `xs`, `sm`, `md`, or `lg`.

snap
boolean

Snap the value to the nearest mark on input. Requires `marks`. Defaults on when `appearance="stepped"`.

value svelte
numberstring

No description yet.

valueEnd
nullstringnumber

Upper-bound value of a dual-thumb range. Providing this (or `valueStart`) switches the component to dual mode.

valueStart
nullstringnumber

Lower-bound value of a dual-thumb range. Providing this (or `valueEnd`) switches the component to dual mode.

Plus all standard <input> HTML attributes.

Type

  • Components
  • Blocks