Skip to main content

Slider

Overview​

The Slider component provides a range slider input for selecting values within a range.

It supports different sizes, colors, and optional value display.


Import​

import { Slider } from '@allxsmith/bestax-bulma';

Usage​

Basic Slider​

A simple range slider.

function example() {
  const [value, setValue] = useState(50);
  return (
    <Block>
      <Slider value={value} onChange={setValue} />
      <Paragraph mt="2">Value: {value}</Paragraph>
    </Block>
  );
}


With Output Display​

Slider showing the current value tooltip.

function example() {
  const [value, setValue] = useState(50);
  return (
    <Block>
      <Slider value={value} onChange={setValue} showOutput color="primary" />
      <Paragraph mt="4">Value: {value}</Paragraph>
    </Block>
  );
}


Color Variants​

Sliders with different color options.

<Block display="flex" flexDirection="column" gap="5">
  <Slider defaultValue={50} color="primary" showOutput />
  <Slider defaultValue={50} color="success" showOutput />
  <Slider defaultValue={50} color="info" showOutput />
  <Slider defaultValue={50} color="warning" showOutput />
  <Slider defaultValue={50} color="danger" showOutput />
</Block>


Size Variants​

Sliders in different sizes.

<Block display="flex" flexDirection="column" gap="5">
  <Block>
    <Paragraph mb="1">Small</Paragraph>
    <Slider defaultValue={50} size="small" color="primary" />
  </Block>
  <Block>
    <Paragraph mb="1">Normal</Paragraph>
    <Slider defaultValue={50} color="primary" />
  </Block>
  <Block>
    <Paragraph mb="1">Medium</Paragraph>
    <Slider defaultValue={50} size="medium" color="primary" />
  </Block>
  <Block>
    <Paragraph mb="1">Large</Paragraph>
    <Slider defaultValue={50} size="large" color="primary" />
  </Block>
</Block>


Rounded and Circle​

Slider with rounded track and circular thumb.

<Block display="flex" flexDirection="column" gap="5">
  <Block>
    <Paragraph mb="1">Rounded</Paragraph>
    <Slider defaultValue={50} isRounded color="info" showOutput />
  </Block>
  <Block>
    <Paragraph mb="1">Circle Thumb</Paragraph>
    <Slider defaultValue={50} isCircle color="success" showOutput />
  </Block>
  <Block>
    <Paragraph mb="1">Both</Paragraph>
    <Slider defaultValue={50} isRounded isCircle color="warning" showOutput />
  </Block>
</Block>


Custom Range​

Slider with custom min, max, and step values.

function example() {
  const [value, setValue] = useState(500);
  return (
    <Block>
      <Slider
        value={value}
        onChange={setValue}
        min={0}
        max={1000}
        step={50}
        showOutput
        color="primary"
      />
      <Paragraph mt="4">Value: ${value}</Paragraph>
    </Block>
  );
}


Custom Output Format​

Slider with formatted output display.

function example() {
  const [value, setValue] = useState(50);
  return (
    <Block>
      <Slider
        value={value}
        onChange={setValue}
        showOutput
        color="success"
        formatOutput={v => `${v}%`}
      />
      <Paragraph mt="4">Progress: {value}%</Paragraph>
    </Block>
  );
}


Disabled Slider​

A disabled slider that cannot be interacted with.

<Slider defaultValue={30} disabled color="primary" />


Context-Aware Rendering​

The Slider component is context-aware: it detects whether it is already inside a Field and adjusts its rendering accordingly. This means you can use it standalone with a label prop (it wraps itself in a Field), or inside a Field (it skips rendering its own).

Default (with label)​

The simplest usage — the component automatically renders its own Field wrapper.

<Slider label="Volume" defaultValue={50} color="primary" />


With Field Wrapper​

When you need manual control over the Field layout (e.g., horizontal forms), wrap the component in Field. The component detects it's inside a Field and skips rendering its own.

function example() {
  return (
    <Field horizontal label="Volume">
      <Field.Body>
        <Field>
          <Slider defaultValue={50} color="primary" />
        </Field>
      </Field.Body>
    </Field>
  );
}


With Field and Control Wrappers​

For full manual composition, wrap in both Field and Control. The component detects the Field context and renders only the slider element.

function example() {
  return (
    <Field horizontal label="Volume">
      <Field.Body>
        <Field>
          <Control iconLeftName="volume-up">
            <Slider defaultValue={50} color="primary" />
          </Control>
        </Field>
      </Field.Body>
    </Field>
  );
}


Controlled vs Uncontrolled​

Controlled Mode​

Use value and onChange to manage state externally:

const [value, setValue] = useState(50);
<Slider value={value} onChange={setValue} />;

Uncontrolled Mode​

Use defaultValue for internal state management:

<Slider defaultValue={50} />

Form Submission​

Slider uses a native <input type="range"> and is HTML-form-compatible. In single-value mode pass a name prop. In range mode use nameLow and nameHigh so each thumb submits as its own field.

ModeProp(s)
Singlename (forwarded to the single <input type="range">)
RangenameLow (low thumb), nameHigh (high thumb) — both render as separate <input type="range"> elements
function SliderRangeFormDemo() {
  const [submitted, setSubmitted] = React.useState('');
  return (
    <form
      onSubmit={e => {
        e.preventDefault();
        const fd = new FormData(e.currentTarget);
        setSubmitted(JSON.stringify(Array.from(fd.entries()), null, 2));
      }}
    >
      <Slider
        range
        nameLow="priceMin"
        nameHigh="priceMax"
        defaultValue={[20, 80]}
        showOutput
      />
      <div style={{ marginTop: '1.5rem' }}>
        <button type="submit" className="button is-primary">
          Submit
        </button>
      </div>
      {submitted && <pre style={{ marginTop: '1rem' }}>{submitted}</pre>}
    </form>
  );
}


Accessibility​

  • Uses native <input type="range"> element
  • Has aria-valuenow, aria-valuemin, and aria-valuemax attributes
  • Fully keyboard accessible with arrow keys
  • Focus states clearly visible


Additional Resources​

Pro Tip

Use the formatOutput prop to display values with units like percentages, currencies, or custom formats.


Props​

PropTypeDefaultDescription
rangefalse | truefalseEnables range mode with two thumbs. Must be false or omitted for single-value mode.
valuenumber | [number, number]—Controlled slider value.
defaultValuenumber | [number, number]0Default value for uncontrolled usage. Initial value for uncontrolled mode.
onChange(value: number) => void | (value: [number, number]) => void—Callback when the value changes.
minDistancenever | number0Minimum distance between thumbs in range mode. Not applicable in single-value mode.
ariaLabelstring | [string, string]—ARIA label(s) for the slider thumb(s). Accessible label for the slider input.
nameLowstring—Form field name for the low thumb. Use this in range mode so each thumb submits with its own name.
nameHighstring—Form field name for the high thumb.
minnumber0Minimum slider value (default: 0).
maxnumber100Maximum slider value (default: 100).
stepnumber1Step increment (default: 1).
size'small' | 'medium' | 'large'—Size variant. Size of the slider.
color'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'—Color variant. Color of the slider.
isRoundedbooleanfalseUse rounded track ends. Whether the slider thumb is rounded.
isCirclebooleanfalseWhether the slider thumb is circular.
showOutputbooleanfalseWhether to show a tooltip with the current value (maps to tooltip 'auto').
tooltip'auto' | 'always' | 'hidden'—Controls tooltip visibility on the thumb. Tooltip display mode (overrides showOutput).
ticksbooleanfalseShows tick marks along the track. Whether to display tick marks at each step.
marksSliderMark[]—Custom labeled marks along the track. Each mark has { value: number; label?: ReactNode }. Custom tick mark positions and labels.
orientation'horizontal' | 'vertical''horizontal'Slider orientation (default: 'horizontal').
scale(value: number) => number—Function to scale the displayed value. Non-linear scale function for displayed values.
getAriaValueText(value: number) => string—Function to generate the aria-valuetext attribute. Custom aria-valuetext formatter.
formatOutput(value: number) => string—Format function for output display. Custom formatter for the tooltip output.
labelReact.ReactNode—Field label, rendered above the widget.
labelSize'small' | 'normal' | 'medium' | 'large'—Size for the label (used in horizontal layouts).
labelPropsReact.LabelHTMLAttributes<HTMLLabelElement> & { [key: string]: unknown; }—Props for the label element.
horizontalbooleanfalseHorizontal field layout.
messageReact.ReactNode—Help/validation message below the input.
messageColor'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'—Bulma color for the message.
fieldClassNamestring—Additional CSS classes for the Field wrapper.
childrenReact.ReactNode—Content rendered inside the component.
disabledbooleanfalseWhether the slider is disabled.
classNamestring—Additional CSS classes.
refReact.Ref<HTMLElement>—Ref forwarded to the input element.
...All standard <input> attributes and Bulma helper props—See Helper Props

CSS & Sass Variables​

Slider registers these variables on its own .slider element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.

CSS VariableSass VariableDefault
--bulma-slider-track-height$slider-track-height0.5rem
--bulma-slider-track-height-small$slider-track-height-small0.375rem
--bulma-slider-track-height-medium$slider-track-height-medium0.625rem
--bulma-slider-track-height-large$slider-track-height-large0.75rem
--bulma-slider-thumb-size$slider-thumb-size1.25rem
--bulma-slider-thumb-size-small$slider-thumb-size-small1rem
--bulma-slider-thumb-size-medium$slider-thumb-size-medium1.5rem
--bulma-slider-thumb-size-large$slider-thumb-size-large1.75rem
--bulma-slider-track-color$slider-track-colorvar(--bulma-border)
--bulma-slider-fill-color$slider-fill-colorvar(--bulma-primary)
--bulma-slider-thumb-color$slider-thumb-colorvar(--bulma-scheme-main)
--bulma-slider-thumb-border$slider-thumb-bordervar(--bulma-border)
--bulma-slider-thumb-shadow$slider-thumb-shadow0 2px 4px rgba(0, 0, 0, 0.1)
--bulma-slider-radius$slider-radiusvar(--bulma-radius)
--bulma-slider-disabled-opacity$slider-disabled-opacity0.5
--bulma-slider-transition-duration$slider-transition-durationvar(--bulma-duration)
--bulma-slider-output-background$slider-output-backgroundvar(--bulma-slider-fill-color)
--bulma-slider-output-color$slider-output-colorvar(--bulma-scheme-main)
--bulma-slider-output-font-size$slider-output-font-sizevar(--bulma-size-small)
--bulma-slider-output-font-weight$slider-output-font-weightvar(--bulma-weight-medium)
--bulma-slider-tick-width$slider-tick-width2px
--bulma-slider-tick-height$slider-tick-height1rem
--bulma-slider-tick-color$slider-tick-colorvar(--bulma-grey-light)
--bulma-slider-tick-opacity$slider-tick-opacity0.5
--bulma-slider-tick-label-font-size$slider-tick-label-font-size0.75rem
--bulma-slider-tick-label-color$slider-tick-label-colorvar(--bulma-text-light)
--bulma-slider-vertical-height$slider-vertical-height200px