Gradient Editor <mv-gradient-editor>
폼과 연동되는 CSS 그라디언트 편집기(linear, radial, conic): 색상 정지점은 실시간 바 위의 키보드 슬라이더이며, 클릭, Enter, +로 추가하고, 바깥으로 끌어내거나 Delete로 제거하며, 각 정지점에는 색상 선택기와 위치 필드가 있습니다.
| 카테고리 | 폼 |
|---|---|
| 유형 | Web Component (<mv-gradient-editor>) |
| 상태 | 안정 |
| 함께 설치되는 항목 | color-picker, tooltip, segmented |
| Keywords | gradient, color-stops, linear-gradient, conic, radial, angle, inspector, form-associated, editor, safe-rewrite |
When to use
- A theme or design tool lets users build linear, radial or conic CSS gradients with draggable stops
- A form must submit a CSS gradient string edited visually with per-stop colors and an angle
Avoid when
- Only one flat color is needed → use Color Picker instead
- Users pick among a few predefined gradients rather than editing stops → use Swatch instead
설치
node scripts/add.mjs gradient-editor --out ./src/marvelousMarvelous UI MCP 서버를 사용하는 AI 에이전트: install_components({ slugs: ["gradient-editor"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
복사되는 파일(의존성 포함): tokens/tokens.css, core/base.css, core/canvas.js, core/dom.js, core/element.js, core/focus.js, core/form.js, core/position.js, components/color-picker/color-picker.js, components/color-picker/color-picker.css, components/tooltip/tooltip.js, components/tooltip/tooltip.css, components/segmented/segmented.js, components/segmented/segmented.css, components/gradient-editor/gradient-editor.js, components/gradient-editor/gradient-editor.css.
사용법
빠른 시작, 동작하는 가장 작은 마크업:
<mv-gradient-editor name="background" value="linear-gradient(90deg, #7C3AED 0%, #F472B6 100%)"></mv-gradient-editor>기본 마크업입니다. 여기서 시작해 속성, data-*, CSS 변수로 커스터마이즈하세요:
<div id="ge-demo">
<style>
#ge-demo { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: center; justify-content: center; width: 100%; }
#ge-demo .ge-art { display: grid; gap: .75rem; width: 17rem; }
#ge-demo .ge-stage { display: grid; place-items: center; height: 15rem; border-radius: var(--mv-radius-xl); border: 1px solid var(--mv-border); background: var(--mv-bg-muted); }
#ge-demo .ge-ticket { display: grid; align-content: space-between; width: 12rem; height: 12rem; padding: 1rem; border-radius: 1.25rem; color: #fff; text-shadow: 0 1px 6px oklch(0 0 0 / .3); box-shadow: 0 18px 40px -18px oklch(0.25 0.12 280 / .75); }
#ge-demo .ge-ticket small { font: 600 .65rem var(--mv-font-sans); letter-spacing: .08em; text-transform: uppercase; opacity: .85; }
#ge-demo .ge-ticket strong { font: 700 1.35rem/1.1 var(--mv-font-sans); }
#ge-demo .ge-css { margin: 0; padding: .6rem .75rem; border-radius: var(--mv-radius-md); border: 1px solid var(--mv-border); background: var(--mv-surface); color: var(--mv-fg-muted); font: 500 .68rem/1.5 var(--mv-font-mono); overflow-wrap: anywhere; }
#ge-demo form { display: grid; gap: .75rem; width: 18rem; padding: .875rem; border: 1px solid var(--mv-border); border-radius: var(--mv-radius-lg); background: var(--mv-surface); box-shadow: var(--mv-shadow-sm); }
#ge-demo .ge-title { margin: 0; font: 600 .8rem var(--mv-font-sans); color: var(--mv-fg); }
</style>
<div class="ge-art">
<div class="ge-stage">
<div class="ge-ticket" id="ge-demo-ticket"><small>Pass · Sep 24</small><strong>Lisbon Design Week</strong></div>
</div>
<p class="ge-css" id="ge-demo-css"></p>
</div>
<form id="ge-demo-form" aria-labelledby="ge-demo-title">
<p class="ge-title" id="ge-demo-title">Ticket background</p>
<mv-gradient-editor id="ge-demo-editor" name="background" label="Ticket background" value="linear-gradient(135deg, #0EA5E9 0%, #6366F1 48%, #EC4899 100%)"></mv-gradient-editor>
</form>
</div>
<script type="module">
const editor = document.getElementById("ge-demo-editor");
const paint = () => {
document.getElementById("ge-demo-ticket").style.background = editor.value;
document.getElementById("ge-demo-css").textContent = `background: ${editor.value};`;
};
editor.addEventListener("mv-input", paint);
editor.addEventListener("mv-change", paint);
customElements.whenDefined("mv-gradient-editor").then(() => requestAnimationFrame(paint));
</script>API
Attributes
| Name | 유형 | Default | Description |
|---|---|---|---|
value | string | Initial CSS gradient (linear, radial or conic; “to right”, deg/turn/rad angles; missing positions follow the CSS rules). Restored on form reset. | |
label | string | Gradient | Accessible name of the group (overrides strings.label). |
name / disabled / readonly | Standard form behavior; readonly keeps stops focusable but frozen. | ||
data-type | linear | radial | conic | Set by the component (for styling). | |
data-dragging | boolean | Set while a stop is dragged. |
Properties
| Name | 유형 | Description |
|---|---|---|
value | string | Serialized gradient, e.g. “linear-gradient(90deg, #7C3AED 0%, #F472B6 100%)”. Also the submitted form value. |
type | linear | radial | conic | Current type (read-only). |
angle | number | Angle (linear) or start angle (conic) in degrees, 0 to 359 (read-only). |
stops | { pos, color }[] | Stops sorted by position, 0 to 100 (read-only). |
strings | object | Default texts, for translation: label, type, linear, radial, conic, angle, start, reverse, stops, add, stop, stopRole, stopValue, color, position, remove, added, removed ({n}, {pos}, {color}, {count} placeholders). Assignable before the element is defined. |
Methods
| Name | Description |
|---|---|
parseGradient(str) / formatGradient(model) | Module exports: parse a CSS gradient into { type, angle, stops } and serialize it back. |
Events
| Name | Description |
|---|---|
mv-input | Live change (drag, typing, color preview). detail: { value, type, angle, stops }. |
mv-change | Committed change: end of a drag, key press, field change, color picker closed, stop added or removed. |
CSS classes
| Name | Description |
|---|---|
mv-gradient-editor-bar / -stop / -angle / -list / -row | Generated parts: the stop track, the stop sliders, the angle row, the stops list and one row per stop. |
mv-gradient-editor-preview / -dial / -field / -remove / -add / -reverse | Generated parts: live swatch, angle dial, numeric fields and icon buttons. |
CSS variables
| Name | Default | Description |
|---|---|---|
--mv-gradient-editor-width | 100% | Width. |
Accessibility
Named role="group"; the type is a radio group. Each stop on the bar is a role="slider" (0 to 100, roledescription “color stop”) named “Stop n” with an aria-valuetext of “40%, #7C3AED”, in visual order. Arrow keys move it (Shift ×10), Page Up/Down ×10, Home/End to the ends; + or Insert adds a stop halfway to its neighbor, Delete/Backspace removes it and moves focus to the neighbor, Enter/Space opens its color picker. Additions and removals are announced in a polite live region. Escape cancels a drag. The angle is a labelled spinbutton (Up/Down, Shift ×15, Page Up/Down ×45); the dial next to it is a pointer shortcut hidden from assistive tech. The list repeats each stop with its color well, a position spinbutton and a “Remove stop n” button (disabled at two stops). Hover effects only apply to fine pointers, motion follows reduced motion through the duration tokens, and forced colors keep the gradient visible with system-color outlines. The value is submitted with the form and restored on reset.