beta

Color Picker <mv-color-picker>

Muestra de color que abre un popover con cierre ligero (o se muestra en línea): un área de saturación/brillo, sliders de tono y opacidad, un único campo de texto que acepta cualquier color CSS con un selector HEX/RGB/HSL/OKLCH, el cuentagotas, muestras y colores recientes. Cada slider anuncia un nombre de color legible, y el elemento es un campo de formulario cuyo valor es un color CSS.

CategoríaFormularios
TipoWeb Component (<mv-color-picker>)
Estadobeta
Keywordscolor, picker, oklch, hex, hsl, eyedropper, swatches, popover, form-associated, editor

When to use

  • Users choose an arbitrary color in a theme builder, design tool or brand settings page
  • A form field should submit a CSS color, with swatches and recent colors for quick reuse
  • Colors are pasted or typed in any CSS syntax and edited in HEX, RGB, HSL or OKLCH with opacity

Avoid when

  • Shoppers choose a product color among a few fixed variants → use Swatch instead
  • The value is a multi-stop gradient rather than a single color → use Gradient Editor instead

Instalación

node scripts/add.mjs color-picker --out ./src/marvelous

Agente de IA con el servidor MCP de Marvelous UI: install_components({ slugs: ["color-picker"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Archivos copiados (dependencias incluidas): 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.

Uso

Marcado de referencia: parte de él y personalízalo con atributos, data-* y variables CSS:

<div id="cp-demo">
  <style>
    #cp-demo { display: flex; flex-wrap: wrap; gap: 1.5rem; align-items: flex-start; justify-content: center; width: 100%; }
    #cp-demo .cpd-col { display: grid; gap: 1rem; width: 17rem; }
    #cp-demo .cpd-preview { display: grid; place-items: center; height: 9.5rem; border: 1px solid var(--mv-border); border-radius: var(--mv-radius-xl); background: var(--cpd-surface, var(--mv-bg)); transition: background var(--mv-duration-fast); }
    #cp-demo .cpd-ticket { display: grid; gap: .2rem; min-width: 11rem; padding: .9rem 1rem; border-radius: .9rem; background: var(--cpd-brand); color: var(--cpd-ink); font: 600 .95rem/1.25 var(--mv-font-sans); box-shadow: 0 16px 32px -18px var(--cpd-brand); }
    #cp-demo .cpd-ticket small { font: 500 .65rem/1.4 var(--mv-font-mono); opacity: .8; }
    #cp-demo .cpd-form { display: grid; gap: .6rem; padding: .9rem; border: 1px solid var(--mv-border); border-radius: var(--mv-radius-lg); background: var(--mv-surface); }
    #cp-demo .cpd-head { margin: 0; font: 600 .7rem var(--mv-font-sans); letter-spacing: .06em; text-transform: uppercase; color: var(--mv-fg-muted); }
    #cp-demo .cpd-row { display: grid; grid-template-columns: 4.75rem 1fr; align-items: center; gap: .5rem; font-size: .8rem; color: var(--mv-fg-muted); }
    #cp-demo .cpd-row mv-color-picker { width: 100%; }
    #cp-demo .cpd-marks { display: flex; align-items: center; gap: .5rem; font-size: .8rem; color: var(--mv-fg-muted); }
  </style>
  <div class="cpd-col">
    <div class="cpd-preview" id="cp-demo-preview">
      <div class="cpd-ticket">Summer Pass · $49<small id="cp-demo-out"></small></div>
    </div>
    <form class="cpd-form" aria-label="Theme" onsubmit="return false">
      <p class="cpd-head">Theme</p>
      <div class="cpd-row"><label for="cp-demo-brand">Brand</label>
        <mv-color-picker id="cp-demo-brand" name="brand" value="#7C3AED"></mv-color-picker>
      </div>
      <div class="cpd-row"><label for="cp-demo-surface">Surface</label>
        <mv-color-picker id="cp-demo-surface" name="surface" format="oklch" value="oklch(94% 0.03 300 / 0.8)"></mv-color-picker>
      </div>
      <div class="cpd-row"><label for="cp-demo-ink">Text</label>
        <mv-color-picker id="cp-demo-ink" name="ink" value="rgb(255 255 255)" opaque swatches="#FFFFFF, #F8FAFC, #FDE68A, #1E1B4B, #0F172A"></mv-color-picker>
      </div>
      <div class="cpd-marks">Tags
        <mv-color-picker data-variant="swatch" label="Tag Sale" value="#F97316" opaque></mv-color-picker>
        <mv-color-picker data-variant="swatch" label="Tag New" value="#14B8A6" opaque></mv-color-picker>
        <mv-color-picker data-variant="swatch" label="Tag Sold out" value="#64748B" opaque></mv-color-picker>
      </div>
    </form>
  </div>
  <mv-color-picker inline label="Accent" value="#EC4899" no-recent></mv-color-picker>
</div>
<script type="module">
  const $ = (id) => document.getElementById(`cp-demo-${id}`);
  const apply = () => {
    const p = $("preview");
    p.style.setProperty("--cpd-brand", $("brand").value);
    p.style.setProperty("--cpd-surface", $("surface").value);
    p.style.setProperty("--cpd-ink", $("ink").value);
    $("out").textContent = $("brand").value;
  };
  document.getElementById("cp-demo").addEventListener("mv-input", apply);
  customElements.whenDefined("mv-color-picker").then(() => requestAnimationFrame(apply));
</script>

API

Attributes

NameTipoDefaultDescription
valuestring#000000Initial CSS color (hex, rgb(), hsl(), hwb(), oklch(), oklab(), name, var()…). Restored on form reset.
formathex | rgb | hsl | oklchinferred from valueOutput and field format; the user can switch it in the panel.
labelstringColorAccessible name of the well and the panel (falls back to an associated <label>).
swatchesstringComma-separated colors for the swatch row; an empty string hides it.
inlinebooleanPanel rendered in place, with no well or popover; mv-change fires at the end of each gesture.
opaquebooleanHides opacity (alpha is always 1).
no-recentbooleanNeither reads nor saves recent colors (shared localStorage).
placementstringbottom-startPopover placement, flipped and shifted to stay on screen.
name / disabled / readonlyStandard form behavior; readonly still opens the panel to read and copy the value.
data-variantswatchRound swatch only, no text.

Properties

NameTipoDescription
valuestringCSS color in the current format (an oklch value is kept exactly, even outside the sRGB gamut). Setting it does not fire events.
rgba{ r, g, b, a }Channels from 0 to 1.
hexstring“#RRGGBB”, or “#RRGGBBAA” when translucent.
modestringCurrent format (read and write).
isOpenbooleanWhether the popover is open.
stringsobjectOverrides for every visible and announced label, color names included (i18n).

Methods

NameDescription
show() / hide()Opens or closes the popover; closing with a new color fires mv-change.
parseColor(str, el?) / formatColor(rgba, mode, lch?) / mixColors(a, b, t) / colorName(rgba)Module exports: parsing (null when not a color), formatting, sRGB mix, readable name. HSV, HSL and OKLCH conversions are exported too.

Events

NameDescription
mv-inputLive change (drag, keys, typing, swatch). detail: { value, hex, rgba }.
mv-changePopover closed with a new color, or end of a gesture when inline. The color joins the recent ones.
mv-open / mv-closePopover opened and closed.

CSS classes

NameDescription
mv-color-picker-trigger / -chip / -panel / -area / -hue / -alpha / -compare / -fields / -format / -input / -swatchGenerated parts.

CSS variables

NameDefaultDescription
--mv-color-picker-width8.5remWell width.
--mv-color-picker-panel-width17.5remPanel width.
--mv-color-picker-area-height9.5remHeight of the saturation/brightness area.
--mv-color-picker-columns10Swatches per row.

Accessibility

The well is a button (aria-haspopup=dialog, aria-expanded) whose name holds the label, a readable color name and the value. The popover is a named dialog that closes on outside click, Escape, Enter or when focus leaves it, and focus returns to the well. The 2D area is a slider (aria-valuetext “Saturation 80%, brightness 60%, dark violet”) moved with the arrow keys (Shift ×10, Page Up/Down for brightness, Home/End for saturation). Hue and opacity are sliders that also name the color. The format is a native select, the text field accepts any CSS color and its arrow keys nudge the number under the caret; invalid text sets aria-invalid. Swatch groups have one tab stop each and arrow-key navigation, with aria-pressed on the current color. Forced colors keep the color surfaces and switch outlines, thumbs and focus to system colors.

Esta página se tradujo con IA. Informar de un problema de traducción