Range FX <mv-range-fx>

하나의 접근성 모델 위에 만든 표현력 있는 슬라이더입니다. 드래그하면 트랙이 물결치는 파도가 되거나(wave), 값 말풍선이 튀어나와 속도에 따라 기울거나(bubble), 고정된 바늘 아래로 눈금자가 관성을 가지고 스크롤되거나(ruler), 액체 캡이 늘어나거나(fluid), 라벨이 트랙 안에 있다가 채움 영역 아래에서 색이 반전됩니다(inline).

작동 방식

하나의 접근성 모델 위에 만든 표현력 있는 슬라이더: 드래그하면 트랙이 물결처럼 일렁이고(wave), 값 말풍선이 튀어나와 속도에 따라 기울며(bubble), 고정된 바늘 아래에서 눈금자가 관성으로 스크롤되고(ruler), 액체 캡이 늘어나거나(fluid), 라벨이 트랙 안에 있다가 채워진 부분 아래에서 색이 반전됩니다(inline). 폼 연동(form-associated)을 지원합니다.

카테고리기본 요소
유형Web Component (<mv-range-fx>)
상태안정
Keywordsslider, range, wave, bubble, ruler, fluid, inline-label, spring, velocity, form-associated

When to use

  • A showcase or creative tool needs a slider with personality, such as a rippling wave, tilting bubble or liquid cap
  • A value is picked on a ruler that scrolls under a fixed needle, like a measurement or tuning control
  • The label and value must live inside the track to save space

Avoid when

  • Dual thumbs, ticks, labeled marks or a sober look for dense forms are needed → use Slider instead
  • The fill should slosh like liquid with inertia, or the control should look like a vertical tank → use Slosh Slider instead

설치

node scripts/add.mjs range-fx --out ./src/marvelous

Marvelous UI MCP 서버를 사용하는 AI 에이전트: install_components({ slugs: ["range-fx"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

복사되는 파일(의존성 포함): tokens/tokens.css, core/base.css, core/canvas.js, core/dom.js, core/element.js, core/form.js, core/motion.js, core/observe.js, components/range-fx/range-fx.js, components/range-fx/range-fx.css.

사용법

기본 마크업입니다. 여기서 시작해 속성, data-*, CSS 변수로 커스터마이즈하세요:

<form id="rfx-demo" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(17rem,1fr));gap:1.25rem;width:min(100%,46rem)">
  <section style="display:grid;gap:.5rem;padding:1.125rem 1.25rem 1.25rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
    <small style="color:var(--mv-fg-subtle);font-weight:500">wave</small>
    <mv-range-fx variant="wave" label="Volume" name="volume" value="62" value-suffix="%"></mv-range-fx>
  </section>
  <section style="display:grid;gap:.5rem;padding:1.125rem 1.25rem 1.25rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
    <small style="color:var(--mv-fg-subtle);font-weight:500">bubble</small>
    <mv-range-fx variant="bubble" label="Monthly budget" name="budget" min="0" max="2000" step="50" value="850" value-prefix="$"></mv-range-fx>
  </section>
  <section style="grid-column:1/-1;display:grid;gap:.5rem;padding:1.125rem 1.25rem 1rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
    <small style="color:var(--mv-fg-subtle);font-weight:500">ruler: flick the ruler and it settles on the nearest tick</small>
    <mv-range-fx variant="ruler" label="Weight" name="weight" min="70" max="330" step="0.5" major="10" value="151.5" value-suffix=" lb"></mv-range-fx>
  </section>
  <section style="display:grid;gap:.625rem;padding:1.125rem 1.25rem 1.25rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
    <small style="color:var(--mv-fg-subtle);font-weight:500">fluid</small>
    <mv-range-fx variant="fluid" label="Brightness" name="brightness" value="70" value-suffix="%"></mv-range-fx>
  </section>
  <section style="display:grid;gap:.625rem;padding:1.125rem 1.25rem 1.25rem;border:1px solid var(--mv-border);border-radius:var(--mv-radius-xl);background:var(--mv-surface)">
    <small style="color:var(--mv-fg-subtle);font-weight:500">inline</small>
    <mv-range-fx variant="inline" label="Layer opacity" name="opacity" value="40" value-suffix="%"></mv-range-fx>
  </section>
</form>
<script type="module">
  document.getElementById("rfx-demo").addEventListener("submit", (e) => e.preventDefault());
</script>

API

Attributes

Name유형DefaultDescription
variantwave | bubble | ruler | fluid | inlinewaveRendering and velocity-driven effect.
min / max / stepnumber0 / 100 / 1Bounds and step (step decimals are respected, e.g. 0.5).
valuenumberInitial value, restored on form reset.
namestringForm field name.
labelstringVisible label (above, or inside the track for fluid/inline) and accessible name. Otherwise use aria-label / aria-labelledby.
value-prefix / value-suffixstringText around the formatted value (Intl).
large-stepnumber10% of the rangeStep for PageUp/PageDown and Shift+Arrow.
majornumber10ruler: a labeled major tick every N steps.
stopsnumber10inline: number of intervals marked with dots (hidden under the text).
disabled / readonly / requiredbooleanStandard states.

Properties

Name유형Description
value / valueAsNumberstring / numberCurrent value; setting it animates the slider.
formatter(value) => stringCustom formatting (display and aria-valuetext).
form / labels / validityVia ElementInternals.

Methods

NameDescription
focus()Focuses the slider.

Events

NameDescription
mv-inputOn every value change (drag, wheel, keyboard). detail: { value }.
mv-changeEnd of interaction (release, ruler stop, key press).

CSS classes

NameDescription
mv-range-fx-head / -label / -valueLabel + value header.
mv-range-fx-controlFocusable role="slider" element.
mv-range-fx-thumb / -wave / -bubble / -needle / -scale / -fill / -cap / -bar / -stops / -textVariant-specific parts.

CSS variables

NameDefaultDescription
--mv-range-fx-colorvar(--mv-accent)Color of the fill, wave and needle.
--mv-range-fx-tick-gap10pxruler: gap between two ticks.
--mv-range-fx-bubble-bg / -fgbubble: bubble colors.

Accessibility

role="slider" on the control area, with aria-valuenow/min/max, a formatted aria-valuetext (prefix/suffix) and a name taken from the label. Keyboard: arrows (±step, reversed in RTL), Shift+Arrow and PageUp/PageDown (large step), Home/End. All decorations are aria-hidden. Reduced motion: springs, ripple and inertia are disabled and the value jumps into place. Forced colors: tracks in GrayText, the filled part and the needle in Highlight, the text over the fill in HighlightText. The ruler scale is a canvas drawn with the theme colors.

이 페이지는 AI로 번역되었습니다. 번역 문제 신고