Try both styles
Compare sizes, ranges, tooltips, marks and elastic motion.
Need precise increments?
NumberStepper provides buttons and a directly editable number.
Your first slider
Two styles, one configuration
- Pill
- Circle
thumbStyle() changes the handle’s appearance. elastic() independently enables stretching, a spring return and a moving tooltip. Either style can use either motion setting. The pill keeps its height during dragging; only the circle style thickens the rail and enlarges the pressed handle. The circular rail spans the full control width, while handle centers stay half a diameter inside its edges at the minimum and maximum. Numeric readouts use the same rolling-number animation as NumberStepper. The browser’s reduced-motion preference suppresses movement. Touch dragging follows the same bounds and step rules as mouse dragging; vertical page scrolling remains available beside a horizontal track.
Tooltips and readouts
tooltips() shows the active handle’s value during dragging and keyboard changes. Hover alone does not open a tooltip. After a drag, the tooltip remains briefly visible; a keyboard tooltip closes when the handle loses focus. tooltips(false) disables it.
showValue() adds a readout. Use valuePlacement('header') to keep it beside the track label, including sliders with tooltips or pips. For a single handle without tooltips or pips, the default footer placement shows a row below the track; valuePosition('start'|'center'|'end') aligns that footer’s value. For multiple handles, footer places a value beneath each handle. When an enabled tooltip is visible, the header readout fades out and returns afterwards.
A single-handle footer is omitted when tooltips or pips are enabled. Choose
valuePlacement('header') if you want a permanent readout in that combination.tooltips([true, false]). For a custom textual formatter, use RawJs:
tooltips() with prefix(), suffix(), locale() and decimalPlaces().
Optional circular icon button
startIcon() and endIcon() are decorative: they never change the value.
Use the separate iconButton() API when you want a clickable circular button.
It switches to a chosen value and restores the previous value on the next click.
The same API works for volume, brightness, a speed preset or another numeric setting.
Volume: mute and restore
A custom preset on the right
iconButtonPosition() accepts start or end. The button replaces a decorative
icon on its own side; the other side remains independent. Omitting
iconButtonValue() targets the range minimum. iconButtonRestoreValue() supplies
a fallback when the initial value equals the target and no previous value exists.
The default fallback is the middle of the selectable range, or an endpoint when
the middle is the target. Target and restore values follow the configured step
and must be selectable and different. Each field remembers its own previous value,
including subsequent keyboard and drag changes. Disabled fields cannot invoke
the button; it also stays disabled during a drag. Icon buttons support one handle;
range sliders continue to support decorative icons. Normal server validation applies.
Magnetic marks and optional vibration
Marks can be numbers, labelled values or both. Endpoint labels are allowed; dots appear inside the track. Selecting a label changes the value. During dragging, nearby marks attract the handle withindetentDistance() pixels.
A range with two handles
[200, 800]. Use a JSON column with an array model cast for this shape. rangeHandles() requires exactly two values. Multiple handles can also be defined by an array state; the maximum supported count is 128.
minDifference() prevents handles getting too close; maxDifference() limits their distance. Values are ordered unless you explicitly select the unconstrained behavior. rangePadding(10) reserves both ends; rangePadding([10, 20]) reserves different amounts.
Tap enables track selection. Drag enables dragging the filled range. Fixed moves handles together while preserving the interval. Unconstrained permits crossed handles. SmoothSteps is the smooth-step behavior accepted by the underlying constraint solver; the submitted value still follows the configured step. Use Fixed with exactly two handles and Drag. Do not combine Unconstrained with minDifference() or maxDifference().
rangePadding() in numeric units, not percentages. Handle-distance limits and padding use integers. Clear them with minDifference(null), maxDifference(null) or rangePadding(null).
Formatting, size and direction
sm, md or lg. variant('secondary') provides a neutral track accent; color() selects a Filament color and fillColor('#6366f1') supplies your own accent. rtl() reverses horizontal direction. vertical() switches orientation; configure enough height for a vertical field in your layout.
Non-linear scales and pips
[value, step] at a point for a segment’s step.
pipsMode(), pipsDensity(), pipsValues(), steppedPips(), pipsFormatter() and pipsFilter() configure their mode, density, positions, step alignment and custom JavaScript presentation. Step dots are off by default. Up to ten intervals show every step; longer scales show up to eleven evenly distributed dots. They are omitted for vertical controls, continuous scales and scales with more than 100 intervals.
Keyboard and validation
Arrow keys move one step. Shift + Arrow and Page Up/Down uselargeStep(); by default this is at least one step and approximately one tenth of the range. Home/End select the endpoints. RTL reverses left/right keys. Disabled fields cannot change value.
default(). Use required(false) to allow an empty saved value; the visual handle still needs a position, so it displays the minimum until a value is chosen. default(null) keeps the initial saved state empty.
FLEX schema configuration
Schema defaults differ from the direct PHP API:
step is 1, decimal_places is 0, show_value is true, and auto_fill / fill_track are true. For a fractional schema slider, set both step and decimal_places, for example 0.25 and 2. The full schema key reference appears below.Fill, colors and thumb visibility
fillTrack() fills from the minimum to a single handle. For multiple handles, pass one boolean per segment: before the first handle, between every pair, and after the last handle. There must be one more segment than handles.
autoFill() chooses the segments for you: from the minimum for one handle, or between handles for multiple handles. An explicit fillTrack() array takes priority. fillTrack(null)->autoFill(false) removes the fill.
fillColor() overrides color(). Pass a valid CSS color such as #14B8A6 or var(--brand-accent); fillColor(null) returns to the selected Filament color. variant('secondary') uses a neutral accent when no custom fill color is supplied. Light and dark appearances follow the panel theme.
hideThumbUntilInteraction() hides a single handle until hover, focus or dragging. Multiple handles remain visible so users can see the selected intervals. Turn it off with hideThumbUntilInteraction(false).
Scale labels: every pips mode
Pips describe the scale; magneticmarks() are selectable presets. These are separate features and can be combined. All modes below use PipsMode from Filament\Forms\Components\Slider\Enums.
- Count
- Positions
- Values
- Custom labels
pipsDensity() controls spacing between unlabelled scale ticks, as a percentage of track length; smaller values add more ticks. If omitted, it uses 10. steppedPips() aligns requested positions with permitted steps. pipsFormatter() receives the numeric $value and returns its display text. pipsFilter() also receives $value: return -1 to omit a tick, 0 for an unlabelled tick, 1 for a major labelled tick, or 2 for a minor labelled tick. These formatters change presentation only.
For Count, use 2–1001 labelled positions. Steps, Positions and Values: use no more than 1001 configured positions. Keep labels sparse enough to remain readable on small screens. Disable the scale with pipsMode(null); clear custom formatting with pipsFormatter(null) and pipsFilter(null).
Vertical controls and RTL
10rem. The example overrides its height to 14rem. For vertical controls, rtl(true) puts the minimum at the bottom; rtl(false) puts it at the top. For horizontal controls, it puts the minimum on the right or left respectively. rtl(null) follows the panel’s direction for horizontal fields and defaults to a bottom minimum for vertical fields. A larger keyboard increment still respects bounds and handle constraints.
Dynamic configuration and state changes
Use PHP closures for values that depend on another field. If another field affects slider configuration, make that field live so the configuration is refreshed.live() sends committed changes to the server; without it, the value is sent with the form’s next request.
For client-side reactions, the slider dispatches two bubbling value events and can report a managed callback error. Listen on a parent element so you can observe one or several sliders:
updatePreview() and saveSelection() are functions supplied by your application. A browser event does not replace PHP validation or authorize a database write. Error events report failures; they do not indicate a successful save.
Saving numbers and ranges
- Single number
- Multiple values
- Optional value
Use a numeric column for a single value. Match its precision to your configured step.
locale() affects separators and grouping only; it does not translate captions, labels or icon-button text. Accepts tags such as en-US, de-DE and pl_PL. Omitting it keeps plain numbers without grouping. Locale-aware initial rendering requires PHP’s intl extension; enable it for consistent localized output before and after initialization.
decimalPlaces() accepts 0–20 and sets rounding/display precision. It does not define increments: use step() for that. Choose a step compatible with your precision, such as step(0.25)->decimalPlaces(2). Steps are multiples of the step value: with range(1, 10)->step(2), permitted values are 2, 4, 6, 8 and 10. Set bounds and defaults on that same grid. A non-linear segment can have its own step, but submitted values must also pass the field’s configured Laravel step rules.
Without decimalPlaces(), readouts display whole numbers for continuous sliders and use the fractional precision of step() when provided. This display rounding also applies to initial values and accessible value text; it does not round a continuous slider’s stored value. Set decimalPlaces() explicitly when you need a fixed number of decimal places. Custom JavaScript tooltip formatters continue to receive the actual numeric value.
Schema option reference
Use PHP configuration for advanced combinations such as non-linear scales, pips formatters and per-handle tooltip formats. The saved FLEX schema exposes the following slider options; JavaScript functions and PHP closures do not belong in JSON.label, default_value, validation and is_required are field-level properties outside config. Saved schema fields are optional by default; set is_required: true to require a value. This overrides the direct PHP slider’s required default. With is_range: true, the builder supplies an initial pair at approximately 20% and 80% of the scale, respecting the step, unless you supply an array default. The PHP API’s rangeHandles() instead uses the minimum and maximum when no pair is supplied.
When configuring a range through the schema, an explicit auto_fill takes priority over fill_track. Choose one of these keys to keep the intended appearance clear.
Assets and motion
Slider assets load with the rendered field. Elastic motion loads only whenelastic() is enabled; the range/constraint adapter loads for configurations that need it. Rolling digits share the numeric animation module used by NumberStepper. Reusing that module does not require adding a NumberStepper field.
Inactive tabs and closed modals load their slider when activated. When a field is removed, its gesture listeners, observers, pending frames and animations are disposed. Your application does not need to initialize the slider separately. See asset loading for deployment and shared-resource behavior.
Configuration reference
Most PHP configuration methods accept closures for values that depend on the form. Shared field options such as
label(), disabled(), required() and state update callbacks remain available. See the dynamic configuration and state changes examples above.