From daac8b2e5483551baed50e47e21d8bb62e141cb1 Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 4 Jun 2026 20:49:01 +0200 Subject: [PATCH] feat(temas/color): subtle intent harmonization (slider, default 12%) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Canonical intents (red/green/...) can clash next to a brand color. Replace the harmonize on/off toggle with a slider (0 = pure canonical -> 0.35 strong), default a SUBTLE 12%: intents lean toward the brand enough to feel cohesive but stay recognizable (red is still red). Verified: green seed -> threat #e35013 at 12% (warmer red), pure #e5484d at 0. Also clarified that "La paleta" is the FIXED library (does not derive from the seed; the seed derives the roles) to resolve the recurring confusion. RFC §6.2 notes the subtle-default guidance. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/uix/eidos/COLOR_ENGINE_RFC.md | 5 ++++- web/routes/temas/color/+page.svelte | 25 ++++++++++++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/uix/eidos/COLOR_ENGINE_RFC.md b/src/uix/eidos/COLOR_ENGINE_RFC.md index 8a598d04f..60b809483 100644 --- a/src/uix/eidos/COLOR_ENGINE_RFC.md +++ b/src/uix/eidos/COLOR_ENGINE_RFC.md @@ -326,7 +326,10 @@ expone con un input de color por fila + «auto» para volver a derivado. **Los 6 intents NO se derivan** — son hues canónicos del libro (un error es rojo siempre). `harmonize(color, toward, amount)` (M3 `blend.harmonize`) los empuja hacia -la marca un % si el builder quiere cohesión — opt-in, conserva L y C. +la marca un % si el builder quiere cohesión — opt-in, conserva L y C. Un valor +**sutil (~10-15%)** hace que los intents se sientan de la familia **sin perder su +lectura** (rojo sigue rojo); el builder de `/temas/color` lo usa como default (slider +0 = canónico puro → fuerte). Resuelve el "los intents puros chirrían con la marca". **Caveat del +60°**: la rotación de Material puede caer cerca de un intent según el primary (p. ej. `purple + 60° = H6 ≈ red/threat`). Por eso el tema base afinó su diff --git a/web/routes/temas/color/+page.svelte b/web/routes/temas/color/+page.svelte index 51884eb03..7990887e6 100644 --- a/web/routes/temas/color/+page.svelte +++ b/web/routes/temas/color/+page.svelte @@ -118,7 +118,9 @@ let seedHex = $state('#8e4ec6') let builderVariant = $state('tonal') - let harmonizeIntents = $state(false) + // Subtle by default: intents lean toward the brand enough to feel cohesive but + // stay recognizable (red is still red). 0 = pure canonical. (M3 harmonize.) + let harmonizeAmount = $state(0.12) // Per-role overrides the designer pinned (role → hex). Empty = fully derived. let overrides = $state>({}) @@ -184,11 +186,12 @@ for (const { role, seed } of schemeSeeds) { if (role !== 'neutralVariant') emitRole(parts, role, seed, bg) } - if (harmonizeIntents) { + if (harmonizeAmount > 0) { for (const intent of INTENTS) { if (intent === 'neutral') continue const baseHex = activeScales[CANONICAL_INTENT_SCALES[intent]]?.['9'] - if (baseHex) emitRole(parts, intent, harmonize(parseColor(baseHex), seedOklch, 0.22), bg) + if (baseHex) + emitRole(parts, intent, harmonize(parseColor(baseHex), seedOklch, harmonizeAmount), bg) } } return parts.join(';') @@ -252,8 +255,9 @@ con su pick on-solid (APCA), y aplica el tema a TODA la página en vivo (override de --primitive-{'{role}'}-* en .root → reproyecta toda la jerarquía + el chrome neutral; en una app real sería setCssVariables). La - librería de 31 escalas y los 6 intents canónicos NO cambian — salvo que actives - harmonize intents (los empuja hacia la temperatura del seed). Y puedes + librería de 31 escalas NO cambia. Los 6 intents se armonizan suavemente + hacia la marca (slider; 0 = canónico puro) para que no se sientan desentonados, sin perder su + lectura — rojo sigue siendo rojo. Y puedes fijar cualquier rol con su propio color (el input de cada fila); los demás se siguen derivando del seed.

@@ -276,8 +280,9 @@ {/each}
@@ -332,7 +337,9 @@ Escalas funcionales (1-2 fondos · 3-5 componente · 6-8 bordes · 9 sólido · 10 hover · 11-12 texto). El representativo de cada escala es el paso 9. La paleta la trae el tema; el framework envía estas 31 (valores - Radix exactos, listos para autoría OKLCH). + Radix exactos, listos para autoría OKLCH). Es la librería fija de + referencia — el seed del builder NO la cambia: deriva los roles (arriba), + que son escalas generadas nuevas, no miembros de esta lista.

@@ -829,6 +836,10 @@ color: var(--color-content-secondary); cursor: pointer; } + .builder-harmonize input[type='range'] { + max-inline-size: 120px; + accent-color: var(--color-primary-solid); + } .role-pin { display: inline-flex; align-items: center;