bêta

Color Picker <mv-color-picker>

Pastille de couleur qui ouvre un popover fermé par un clic extérieur (ou s’affiche en ligne) : une zone saturation/luminosité, des sliders de teinte et d’opacité, un champ texte unique qui accepte n’importe quelle couleur CSS avec un sélecteur HEX/RGB/HSL/OKLCH, la pipette, des échantillons et les couleurs récentes. Chaque slider annonce un nom de couleur lisible, et l’élément est un champ de formulaire dont la valeur est une couleur CSS.

CatégorieFormulaires
TypeWeb Component (<mv-color-picker>)
Statutbêta
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

Installation

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

Agent IA avec le serveur MCP de Marvelous UI : install_components({ slugs: ["color-picker"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).

Fichiers copiés (dépendances comprises) : 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.

Utilisation

Balisage de référence : partez de celui-ci et personnalisez-le avec les attributs, data-* et les 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

NameTypeDefaultDescription
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

NameTypeDescription
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.

Cette page a été traduite par IA. Signaler un problème de traduction