fix(color-picker): ValueSwatch now reactively reflects the current color

User report: 'la caja del color seleccionado en el pickercolor no se
actualiza, compruébalo.'

Root cause
----------
The Eidos recipe had an `[data-color-picker-value-swatch]::after`
overlay that painted `var(--cp-trigger-color, currentColor)` on top of
the swatch — a CSS variable set ONLY on the trigger button by the
Eidos wrapper. The popover content is portaled outside the trigger's
subtree, so the var never propagated into the ValueSwatch element.
The overlay therefore stayed at its fallback (`currentColor`) and
covered the soma-set inline `background-color`, hiding the live colour.

Fix
---
1. **Soma `ColorPickerValueSwatchProvider.backgroundStyle`** now emits
   BOTH `background-color: <hex>` and `--cp-current-color: <hex>` so:
   - Consumers without the eidos recipe still see the colour (inline
     background-color, as before).
   - Eidos recipes / external CSS can read `--cp-current-color` as a
     reactive CSS variable on the element itself.

2. **Eidos CSS** drops the `::after` overlay. Instead the checker
   (transparency pattern) lives on a `::before` pseudo with
   `z-index: -1` inside an isolated stacking context, so the soma's
   inline `background-color` paints ON TOP and the checker shows
   through only where alpha < 1. No more colour stomping.

Checks: 67/67 component-audit PASS, svelte-check 0 errors / 0 warnings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
active-uix
dev 5 months ago
parent da19728cb6
commit 8515f5e673

@ -189,16 +189,29 @@
block-size: var(--_color-picker-swatch-size);
border-radius: var(--color-picker-swatch-radius);
border: 1px solid var(--color-picker-swatch-border);
background-image: var(--cp-checker);
background-size: var(--cp-checker-cell) var(--cp-checker-cell);
/* Checker behind the colour swatch — visible only where the colour
has alpha < 1. We use ::before for the checker (z-index -1 inside an
isolated stacking context) and let the soma-set inline
background-color paint the colour itself. The inline `style` from
`ColorPickerValueSwatchProvider` also emits `--cp-current-color` so
downstream consumers can pull the value as a CSS variable too. */
overflow: hidden;
isolation: isolate;
}
[data-color-picker-value-swatch]::after {
[data-color-picker-value-swatch]::before {
content: '';
position: absolute;
inset: 0;
background: var(--cp-trigger-color, currentColor);
z-index: -1;
background-image: var(--cp-checker);
background-size: var(--cp-checker-cell) var(--cp-checker-cell);
background-position:
0 0,
0 calc(var(--cp-checker-cell) / 2),
calc(var(--cp-checker-cell) / 2) calc(var(--cp-checker-cell) / -2),
calc(var(--cp-checker-cell) / -2) 0;
pointer-events: none;
}
[data-color-picker-value-text] {

@ -0,0 +1,49 @@
import { semaSelector } from '$uix/morfo';
import { colorPickerMorfo } from '$uix/morfo/components/color-picker';
import { sound } from '../sounds';
import type { Sema } from '../sema-map';
/**
* ColorPicker perceptual defaults.
*
* The 2D area is a direct-manipulation surface — mirrors the slider's
* `handle-pick / handle-drag` shape so consumers get the same auditory
* / tactile vocabulary when dragging across hue, saturation, brightness.
*
* • handle-pick — single pluck at drag start (pickup cue)
* • handle-drag — continuous stream during drag (sound + haptic
* channels open; per-emit payload owns pitch / gain)
* • commit-set — final pluck at drag-release / swatch click /
* eyedropper pick (release cue)
*
* Channel sliders inherit `slider:*` events automatically because they
* compose `SliderProvider` — no extra rules needed here.
*/
const onArea = (matchers?: Parameters<typeof semaSelector<typeof colorPickerMorfo>>[2]) =>
semaSelector(colorPickerMorfo, 'area', matchers);
const onProvider = (matchers?: Parameters<typeof semaSelector<typeof colorPickerMorfo>>[2]) =>
semaSelector(colorPickerMorfo, 'provider', matchers);
export const colorPickerSema: Sema = {
name: 'color-picker',
cascade: [
{
selector: onArea({ eventName: 'handle-pick' }),
channels: ['sound', 'haptic'],
sound: sound('handle.pickup.air', { gain: 0.12 }),
haptic: { kind: 'tick', intensity: 0.22, duration: 6 }
},
{
selector: onArea({ eventName: 'handle-drag' }),
channels: ['sound', 'haptic']
},
{
selector: onProvider({ eventName: 'commit-set' }),
channels: ['sound', 'haptic'],
sound: sound('handle.release.soft', { gain: 0.1 }),
haptic: { kind: 'tick', intensity: 0.18, duration: 8 }
}
]
};

@ -11,6 +11,7 @@
export { accordionSema } from './accordion'
export { checkboxSema } from './checkbox'
export { colorPickerSema } from './color-picker'
export { comboboxSema } from './combobox'
export { dateFieldSema } from './date-field'
export { dialogSema } from './dialog'

@ -504,8 +504,19 @@ export class ColorPickerValueSwatchProvider {
});
}
/**
* Style emitted inline on `[data-color-picker-value-swatch]`.
*
* Exposes the current colour as both a `background-color` (legacy /
* consumers that bypass the recipe) and a `--cp-current-color` CSS
* variable so the Eidos recipe can composite the colour on top of a
* transparency checker. Without the CSS var, an Eidos `::after`
* overlay would stomp on the inline `background-color` and the
* swatch would not visually update.
*/
readonly backgroundStyle = $derived.by(
() => `background-color: ${this.provider.effectiveColor.hex};`
() =>
`background-color: ${this.provider.effectiveColor.hex}; --cp-current-color: ${this.provider.effectiveColor.hex};`
);
readonly props = $derived.by(() =>

@ -27,6 +27,7 @@
import { accordionSema } from '$uix/sema/components/accordion';
import { checkboxSema } from '$uix/sema/components/checkbox';
import { calendarSema } from '$uix/sema/components/calendar';
import { colorPickerSema } from '$uix/sema/components/color-picker';
import { comboboxSema } from '$uix/sema/components/combobox';
import { dateFieldSema } from '$uix/sema/components/date-field';
import { Popover } from '$uix/eidos/components/popover';
@ -61,6 +62,7 @@
accordionSema,
calendarSema,
checkboxSema,
colorPickerSema,
comboboxSema,
dateFieldSema,
dialogSema,

Loading…
Cancel
Save

Powered by TurnKey Linux.