Un explorador de variantes ramificado para cualquier elemento controlado por propiedades personalizadas de CSS (o cualquier estado mediante callbacks): “Generar 4 variantes” hace brotar hijos mutados de la variante aplicada (un slider Spread fija lo atrevidas que son las mutaciones), mostrados como un árbol ordenado de miniaturas en vivo: clones escalados e inertes del objetivo, así que funciona con cualquier componente sin capturas de pantalla. Guarda favoritas, descarta los callejones sin salida en un resumen “3 variantes descartadas”, fija hasta cuatro variantes en una franja Comparar a tamaño real con diferencias etiquetadas (“hue 212 → 18”), cruza dos de ellas parámetro a parámetro y haz checkout de cualquier nodo: el objetivo se interpola hacia él. Árbol horizontal en contenedores anchos, esquema con sangría en los estrechos, con semilla, serializable y con exportación CSS en un clic.
Agente de IA con el servidor MCP de Marvelous UI: install_components({ slugs: ["variant-tree"], target_dir: "<absolute path>/src/marvelous", framework: "react" }).
Id of the element to explore (looked up in the same root; waited for if rendered later). Without it, the first child element is the target.
params
string
Explorable parameters, same syntax as data-vary on the target (which is used when this attribute is absent).
data-vary
string
On the target: “--hue: 0..360; --radius: 0..28px step 2 as corners; --weight: 400|600|800”. Numeric ranges (unit taken from the bounds, optional step, wrap for circular values; a 0..360 hue wraps by default) or discrete sets separated by |. “as <label>” names the parameter in the UI; otherwise the last segment of the property name is used. Plain CSS properties (opacity…) work too.
count
number
4
Children created per generation (1-12).
spread
number (0-1)
0.4
Mutation strength, mirrored by the Spread slider: subtle nudges and neighbor values when low, far jumps when high. At least one parameter always changes, siblings never duplicate each other.
seed
number
Seeds the random generator: the same seed and actions give the same tree (demos, tests, shareable explorations).
label
string
Explore variants
Panel title.
max-previews
number
16
Maximum live clones in the tree. Priority: applied path, pinned, kept, then newest; the others show a cheap bar glyph of their parameters.
layout
auto | horizontal | vertical
auto
Tidy horizontal tree, or indented outline. auto switches to the outline under 520px of component width (ResizeObserver).
Properties
Name
Tipo
Description
params
Param[] | string
Parsed parameters ({ name, label, type: "range", min, max, unit, step, wrap } | { name, label, type: "set", values }). Assign an array or a string to redefine them (restarts the tree).
Serializable tree. Assign a saved array to restore an exploration (can be set before the element is defined).
current
{ id, params, css }
The applied variant, with its CSS declarations ready to paste (read-only).
mutate
(state, rng, spread) => state
Custom mutation for arbitrary state (return a new object or mutate the copy). rng() is the seeded generator.
apply
(state, el) => void
Custom rendering: called on the target and on every preview clone. Replaces the default custom-property writes (no tween).
Methods
Name
Description
generate(n?, { from?, animate? })
Creates n mutated children of the applied node (or from) and returns their ids. animate: false skips the sprout animation (seeding).
checkout(id, { animate? })
Applies a node to the target; numeric parameters tween (hue the short way around), discrete ones switch.
favorite(id?, force?)
Toggles the star (defaults to the applied node).
pin(id?, force?)
Toggles a node in the Compare strip (4 at most, the oldest makes room).
combine(a, b, picks?)
Creates and applies a hybrid child of a: for each differing parameter, the value of a or b (picks: { name: "a" | "b" }, random but mixed when omitted). Returns its id, or null if it would equal a parent.
prune(id?) / restore(id)
Folds a node and its descendants into a stub / unfolds a node or every pruned child of id.
reset(state?)
Starts over from state (default: the target's current computed values).
refresh()
Re-clones the previews (content changes inside the target are also picked up automatically).
Events
Name
Description
mv-generate
New children. detail: { parent, ids, params[] }.
mv-checkout
A node was applied. detail: { id, params }.
mv-combine
A hybrid was created. detail: { id, a, b, params }.
mv-favorite
detail: { id, favorite }.
mv-prune
detail: { id, count }.
Content structure
Name
Description
(content)
Optional: the target itself, when for is not used.
CSS classes
Name
Description
mv-variant-tree-panel / -head / -bar
Generated panel, header (title, status, Copy variables) and toolbar acting on the applied variant.
Scrollable tree canvas, tiles (role treeitem) with their live thumbnail, discarded-variants stub and SVG edges (data-path on the applied path, data-kind="mate" for a hybrid's second parent).
mv-variant-tree-combine / -compare / -chip
Crossover panel, Compare strip and diff chips.
CSS variables
Name
Default
Description
--mv-variant-tree-accent
var(--mv-accent)
Applied node, path and primary actions.
--mv-variant-tree-favorite
var(--mv-warning)
Star of kept variants.
--mv-variant-tree-mate
var(--mv-info)
Side B of a crossover and the hybrid's second edge.
--mv-variant-tree-thumb-bg
var(--mv-bg-subtle)
Background behind the clones.
--mv-variant-tree-bg
var(--mv-surface)
Panel background.
--mv-variant-tree-max-height
42rem
Height of the tree view before it scrolls.
Accessibility
The tree is a real role="tree": each tile is a treeitem with aria-level, aria-setsize, aria-posinset, aria-expanded and aria-selected (the applied variant), named by its parameter summary (“Variant 3 · hue 18, radius 12px · kept · in comparison, slot 1”). Roving tabindex: Up/Down/Home/End browse in reading order, Right/Left expand, collapse or move to child/parent, Enter or Space applies, F keeps, P compares, G generates from the focused node, Delete discards (focus moves to the stub, which Enter restores). Thumbnails are aria-hidden and inert clones (ids, names and labels stripped, never focusable). Applying, generating, keeping, comparing, combining and copying are announced in a polite live region; the Spread slider has an aria-valuetext (“Moderate, 45%”); unavailable actions stay focusable with aria-disabled and explain why when used. Diff chips read “hue 212 becomes 18”. Focus rings everywhere. Reduced motion (OS or data-motion="reduce"): no sprout, bloom, edge growth or glide, and the target switches instantly instead of tweening.