Klarhimmel UI

Slider

Stable

A single-value slider on the native range input.

npx shadcn add @klarhimmel/slider

When to use

  • Use for

    A rough value on a range where the position says more than the number.

  • Not for

    An exact figure. Use Input type number. A choice among named options. Use Radio group.

  • Pairs with

    Label and a visible output next to it.

Preview

2
slider.tsx
import { Theme } from '@/components/klarhimmel/theme/style';
import { Slider } from '@/components/klarhimmel/ui/slider';

export default function Example() {
  return (
    <Theme theme="brand">
      <div className="flex flex-col gap-1">
        <label htmlFor="guests" className="text-kh-small font-medium">Guests</label>
        <Slider id="guests" min={1} max={8} defaultValue={2} />
      </div>
    </Theme>
  );
}

Install

Import

import { Slider } from '@/components/klarhimmel/ui/slider';
Lands in
components/klarhimmel/ui/slider.tsx, plus cn() and the theme item if they are missing. Import theme.css after Tailwind.
Render in
Render it inside <Theme>, once near the root of your app. Tokens and fonts are scoped to it, so outside it the component is unstyled.

Examples

  • States

    1500 SEK
    import { useState } from 'react';
    import { Slider } from '@/components/klarhimmel/ui/slider';
    
    export default function SliderStates() {
      const [price, setPrice] = useState(1500);
      return (
        <div className="flex w-[min(24rem,calc(100cqw-3rem))] flex-col gap-5">
          <div className="flex flex-col gap-1">
            <div className="flex items-baseline justify-between text-kh-small">
              <label htmlFor="slider-price" className="font-medium text-kh-ink">Maximum price per night</label>
              <output htmlFor="slider-price" className="text-kh-muted">{price} SEK</output>
            </div>
            <Slider id="slider-price" min={500} max={4000} step={100} value={price} onChange={(e) => setPrice(Number(e.target.value))} />
          </div>
          <div className="flex flex-col gap-1">
            <label htmlFor="slider-off" className="text-kh-small font-medium text-kh-muted">Distance (not available)</label>
            <Slider id="slider-off" defaultValue={30} disabled />
          </div>
        </div>
      );
    }
  • Form

    7 of 10
    import { useState } from 'react';
    import { Slider } from '@/components/klarhimmel/ui/slider';
    
    export default function SliderForm() {
      const [v, setV] = useState(7);
      return (
        <div className="flex w-[min(24rem,calc(100cqw-3rem))] flex-col gap-1">
          <div className="flex items-baseline justify-between gap-3 text-kh-small">
            <label htmlFor="sl-rate" className="font-medium text-kh-ink">How was your stay?</label>
            <output htmlFor="sl-rate" className="text-kh-muted">{v} of 10</output>
          </div>
          <Slider id="sl-rate" name="rating" min={0} max={10} value={v} onChange={(e) => setV(Number(e.target.value))} />
        </div>
      );
    }

API reference

PropTypeDefaultDescription
min / max / stepnumber0 / 100 / 1The range and its steps.
value / defaultValuenumber-Controlled or uncontrolled value.
onChangeChangeEventHandler<HTMLInputElement>-Read the number from event.target.value.
aria-labelstring-Needed when no <label htmlFor> names it.
disabledbooleanfalsePrevents interaction.
classNamestring-Extra classes, merged after the component's own.

Accessibility

KeyDoes
Left / DownDecreases by one step
Right / UpIncreases by one step
Page Down / Page UpMoves in larger steps
Home / EndMinimum or maximum

Native range input: the keys and the slider role are the browser's. Always show the current number next to it.

Accessibility