feat(style): Mejorar derivePanelPalette con HSL
- Header usa darkenHsl/lightenHsl (preserva tono mejor que RGB) - Selección sin foco usa desaturate + lightenHsl (más elegante) - Nueva función contrastTextColor() para texto automático b/n - Test adicional para contrastTextColor Z-Design ahora produce paletas más armónicas desde color base. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c330492022
commit
b5a4205c29
1 changed files with 39 additions and 9 deletions
|
|
@ -1048,12 +1048,13 @@ fn deriveDarkPalette(base: Color) PanelColorScheme {
|
||||||
.etiquetas = white.darken(30), // ~70% brightness
|
.etiquetas = white.darken(30), // ~70% brightness
|
||||||
.placeholder = gray,
|
.placeholder = gray,
|
||||||
|
|
||||||
// Header: darkened base color
|
// Header: darkened using HSL (preserves hue better than RGB darken)
|
||||||
.header = base.darken(60),
|
.header = base.darkenHsl(50),
|
||||||
|
|
||||||
// Selection: where the base color SHINES
|
// Selection: base color at full strength when focused
|
||||||
.seleccion_fondo_con_focus = base, // Full color!
|
.seleccion_fondo_con_focus = base,
|
||||||
.seleccion_fondo_sin_focus = base.blendTowards(gray, 50), // Muted
|
// Unfocused: desaturated and slightly lightened (HSL-based, more elegant)
|
||||||
|
.seleccion_fondo_sin_focus = base.desaturate(60).lightenHsl(10),
|
||||||
|
|
||||||
// Borders: accent on focus, subtle otherwise
|
// Borders: accent on focus, subtle otherwise
|
||||||
.borde_con_focus = base,
|
.borde_con_focus = base,
|
||||||
|
|
@ -1079,12 +1080,13 @@ fn deriveLightPalette(base: Color) PanelColorScheme {
|
||||||
.etiquetas = black.lighten(40), // ~60% darkness
|
.etiquetas = black.lighten(40), // ~60% darkness
|
||||||
.placeholder = gray,
|
.placeholder = gray,
|
||||||
|
|
||||||
// Header: very light version of base
|
// Header: lightened using HSL (preserves hue better)
|
||||||
.header = base.blendTowards(white, 85),
|
.header = base.lightenHsl(40),
|
||||||
|
|
||||||
// Selection: base color (slightly lightened for readability)
|
// Selection: base color at full strength when focused
|
||||||
.seleccion_fondo_con_focus = base,
|
.seleccion_fondo_con_focus = base,
|
||||||
.seleccion_fondo_sin_focus = base.blendTowards(white, 60),
|
// Unfocused: desaturated and lightened (HSL-based)
|
||||||
|
.seleccion_fondo_sin_focus = base.desaturate(50).lightenHsl(30),
|
||||||
|
|
||||||
// Borders: accent on focus, subtle otherwise
|
// Borders: accent on focus, subtle otherwise
|
||||||
.borde_con_focus = base,
|
.borde_con_focus = base,
|
||||||
|
|
@ -1092,6 +1094,17 @@ fn deriveLightPalette(base: Color) PanelColorScheme {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get appropriate text color (black or white) based on background luminosity.
|
||||||
|
/// Uses the HSL lightness value to determine contrast.
|
||||||
|
pub fn contrastTextColor(background: Color) Color {
|
||||||
|
const hsl = background.toHsl();
|
||||||
|
// If background is light (L > 0.5), use dark text; otherwise use light text
|
||||||
|
return if (hsl.l > 0.5)
|
||||||
|
Color.rgb(20, 20, 25) // Dark text for light backgrounds
|
||||||
|
else
|
||||||
|
Color.rgb(245, 245, 245); // Light text for dark backgrounds
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// Z-Design Tests
|
// Z-Design Tests
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
|
|
@ -1149,3 +1162,20 @@ test "derivePanelPalette light mode" {
|
||||||
try std.testing.expect(palette.fondo_con_focus.g > 245);
|
try std.testing.expect(palette.fondo_con_focus.g > 245);
|
||||||
try std.testing.expect(palette.fondo_con_focus.b > 250);
|
try std.testing.expect(palette.fondo_con_focus.b > 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "contrastTextColor" {
|
||||||
|
// Dark background should get light text
|
||||||
|
const dark_bg = Color.rgb(30, 30, 30);
|
||||||
|
const text_on_dark = contrastTextColor(dark_bg);
|
||||||
|
try std.testing.expect(text_on_dark.r > 200); // Light text
|
||||||
|
|
||||||
|
// Light background should get dark text
|
||||||
|
const light_bg = Color.rgb(240, 240, 240);
|
||||||
|
const text_on_light = contrastTextColor(light_bg);
|
||||||
|
try std.testing.expect(text_on_light.r < 50); // Dark text
|
||||||
|
|
||||||
|
// Mid-gray (128/255 = 0.502 > 0.5) gets dark text
|
||||||
|
const mid_gray = Color.rgb(128, 128, 128);
|
||||||
|
const text_on_mid = contrastTextColor(mid_gray);
|
||||||
|
try std.testing.expect(text_on_mid.r < 50); // Dark text (L = 0.502 > 0.5)
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue