beta
Slosh Slider — <mv-slosh-slider>
A slider whose fill is liquid: the handle stays rigid under your finger while the liquid chases it on a soft spring, bumps into the end stops, tilts and ripples with its velocity. A complete form field (keyboard, ARIA, reset), or a tank when vertical.
| Category | Forms |
|---|---|
| Type | Web Component (<mv-slosh-slider>) |
| Status | beta |
| Keywords | slider, range, liquid, physics, spring, gauge, tank, form-associated, tactile |
When to use
- A playful or tactile product wants a slider whose liquid fill reacts to drag speed
- A level such as volume, water intake or a fill ratio reads well as a vertical tank
- A marketing or onboarding page wants a memorable form control that still submits a value
Avoid when
- A dense settings screen needs a sober slider, two thumbs or labeled tick marks → use Slider instead
- Another expressive style fits better, like a wave, ruler or value bubble → use Range FX instead
- Many sliders appear on one page; the per-slider spring physics adds noise and cost
Install
node scripts/add.mjs slosh-slider --out ./src/marvelousAI agent with the Marvelous UI MCP server: install_components({ slugs: ["slosh-slider"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Files copied (dependencies included): tokens/tokens.css, core/base.css, core/dom.js, core/element.js, core/form.js, core/motion.js, core/observe.js, components/slosh-slider/slosh-slider.js, components/slosh-slider/slosh-slider.css.
Usage
Canonical markup — start from it and customize with attributes, data-* and CSS variables:
<form id="mv-slosh-slider-demo" style="display:grid;grid-template-columns:minmax(0,1fr) auto;gap:2rem 2.5rem;align-items:end;width:100%;max-width:640px">
<div style="display:grid;gap:1.4rem">
<mv-slosh-slider label="Volume" name="volume" value="64" suffix="%"></mv-slosh-slider>
<mv-slosh-slider label="Monthly budget" name="budget" min="0" max="2000" step="50" value="850" prefix="$" slosh="0.85" style="--mv-slosh-slider-color:var(--mv-success);--mv-slosh-slider-color-2:color-mix(in oklch,var(--mv-success),black 15%)"></mv-slosh-slider>
<mv-slosh-slider label="Brightness (classic)" name="brightness" value="30" suffix="%" slosh="0" style="--mv-slosh-slider-height:1.75rem"></mv-slosh-slider>
</div>
<mv-slosh-slider label="Tank" name="water" orientation="vertical" value="70" suffix=" L" max="120" slosh="0.9" style="--mv-slosh-slider-color:var(--mv-info);--mv-slosh-slider-color-2:color-mix(in oklch,var(--mv-info),black 22%)"></mv-slosh-slider>
<div style="grid-column:1/-1;display:flex;gap:.6rem;align-items:center;flex-wrap:wrap">
<button class="mv-button" data-size="sm" type="submit">Submit</button>
<button class="mv-button" data-size="sm" data-variant="outline" type="reset">Reset</button>
<output id="mv-slosh-slider-demo-out" style="font-size:.8rem;color:var(--mv-fg-muted)"></output>
</div>
</form>
<script type="module">
const form = document.getElementById("mv-slosh-slider-demo");
const out = document.getElementById("mv-slosh-slider-demo-out");
form.addEventListener("submit", (e) => {
e.preventDefault();
out.textContent = [...new FormData(form)].map(([k, v]) => `${k} = ${v}`).join(" · ");
});
</script>API
Attributes
| Name | Type | Default | Description |
|---|---|---|---|
label | string | Visible label (and accessible name). | |
name | string | Form field name. | |
value | number | Initial value (also used on reset). | |
min / max / step | number | 0 / 100 / 1 | Bounds and step (the step sets the displayed precision). |
slosh | number | 0.6 | Inverse viscosity: 0 = classic slider, 1 = very fluid liquid (softer, less damped). |
orientation | horizontal | vertical | horizontal | vertical: a tank that fills from the bottom, with a sloshing horizontal surface. |
prefix / suffix | string | Text around the displayed and announced value (e.g. suffix="%"). | |
hide-value | boolean | Hides the displayed value (it is still announced). | |
disabled / required | boolean | Form states (a disabled fieldset is respected). |
Properties
| Name | Type | Description |
|---|---|---|
value | string | Value (a string, like an input). |
valueAsNumber | number | Numeric value. |
Events
| Name | Description |
|---|---|
input | On every change while dragging or using the keyboard. |
change | On release or after a key press. |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-slosh-slider-color / --mv-slosh-slider-color-2 | accent / darkened accent | Liquid gradient. |
--mv-slosh-slider-track | var(--mv-bg-muted) | Tube background. |
--mv-slosh-slider-height | 2.75rem | Thickness of the horizontal tube. |
--mv-slosh-slider-width / --mv-slosh-slider-length | 4.75rem / 12rem | Size of the vertical tank. |
--mv-slosh-slider-radius | full (2xl when vertical) | Tube radius. |
--mv-slosh-slider-ratio | Set by the component: position 0..1, for styling around it. |
Accessibility
role=slider on the tube (focusable), aria-valuemin/max/now and formatted aria-valuetext; ←/→/↑/↓ (Shift ×10), Page↑/↓, Home/End. Form-associated (ElementInternals): submitted value, reset, disabled fieldset, <label for>. The liquid is decorative (SVG aria-hidden). Reduced motion: instant fill, no ripples.