Gradient Editor <mv-gradient-editor>

支持表单关联的 CSS 渐变编辑器(linear、radial、conic):色标是实时渐变条上的键盘滑块,可通过点击、Enter 或 + 添加,通过拖出或 Delete 删除,每个色标都有颜色选择器和位置字段。

分类表单
类型Web Component(<mv-gradient-editor>)
状态稳定版
同时安装color-picker, tooltip, segmented
Keywordsgradient, 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/marvelous

使用 Marvelous 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类型DefaultDescription
valuestringInitial CSS gradient (linear, radial or conic; “to right”, deg/turn/rad angles; missing positions follow the CSS rules). Restored on form reset.
labelstringGradientAccessible name of the group (overrides strings.label).
name / disabled / readonlyStandard form behavior; readonly keeps stops focusable but frozen.
data-typelinear | radial | conicSet by the component (for styling).
data-draggingbooleanSet while a stop is dragged.

Properties

Name类型Description
valuestringSerialized gradient, e.g. “linear-gradient(90deg, #7C3AED 0%, #F472B6 100%)”. Also the submitted form value.
typelinear | radial | conicCurrent type (read-only).
anglenumberAngle (linear) or start angle (conic) in degrees, 0 to 359 (read-only).
stops{ pos, color }[]Stops sorted by position, 0 to 100 (read-only).
stringsobjectDefault 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

NameDescription
parseGradient(str) / formatGradient(model)Module exports: parse a CSS gradient into { type, angle, stops } and serialize it back.

Events

NameDescription
mv-inputLive change (drag, typing, color preview). detail: { value, type, angle, stops }.
mv-changeCommitted change: end of a drag, key press, field change, color picker closed, stop added or removed.

CSS classes

NameDescription
mv-gradient-editor-bar / -stop / -angle / -list / -rowGenerated 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 / -reverseGenerated parts: live swatch, angle dial, numeric fields and icon buttons.

CSS variables

NameDefaultDescription
--mv-gradient-editor-width100%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.

本页面由 AI 翻译。报告翻译问题