feat(widgets): Add focus_border_color to text_input and select

Z-Design V2: Allow panels to specify custom focus ring color.
- TextInputConfig.focus_border_color: overrides theme.primary
- SelectConfig.focus_border_color: same pattern
- Uses Command.focusRingColor() instead of focusRing()

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
R.Eugenio 2025-12-30 20:09:08 +01:00
parent dd249d2b2d
commit ded8946702
2 changed files with 14 additions and 6 deletions

View file

@ -48,6 +48,8 @@ pub const SelectConfig = struct {
padding: u32 = 4, padding: u32 = 4,
/// Corner radius (default 3 for fancy mode) /// Corner radius (default 3 for fancy mode)
corner_radius: u8 = 3, corner_radius: u8 = 3,
/// Override focus border color (Z-Design: color del panel). If null, uses theme.primary.
focus_border_color: ?Style.Color = null,
}; };
/// Select result /// Select result
@ -134,15 +136,17 @@ pub fn selectRect(
else else
state.hover.blend(theme.button_bg, theme.button_bg.lighten(5)); state.hover.blend(theme.button_bg, theme.button_bg.lighten(5));
const border_color = if (has_focus or state.open) theme.primary else theme.border; // Z-Design V2: focus_border_color permite color de focus personalizado por panel
const focus_color = config.focus_border_color orelse theme.primary;
const border_color = if (has_focus or state.open) focus_color else theme.border;
// Draw main button background based on render mode // Draw main button background based on render mode
if (Style.isFancy() and config.corner_radius > 0) { if (Style.isFancy() and config.corner_radius > 0) {
ctx.pushCommand(Command.roundedRect(bounds.x, bounds.y, bounds.w, bounds.h, bg_color, config.corner_radius)); ctx.pushCommand(Command.roundedRect(bounds.x, bounds.y, bounds.w, bounds.h, bg_color, config.corner_radius));
ctx.pushCommand(Command.roundedRectOutline(bounds.x, bounds.y, bounds.w, bounds.h, border_color, config.corner_radius)); ctx.pushCommand(Command.roundedRectOutline(bounds.x, bounds.y, bounds.w, bounds.h, border_color, config.corner_radius));
// Draw focus ring when focused (not when dropdown is open) // Draw focus ring when focused (Z-Design V2: usa color del panel)
if (has_focus and !state.open) { if (has_focus and !state.open) {
ctx.pushCommand(Command.focusRing(bounds.x, bounds.y, bounds.w, bounds.h, config.corner_radius)); ctx.pushCommand(Command.focusRingColor(bounds.x, bounds.y, bounds.w, bounds.h, config.corner_radius, focus_color.withAlpha(180)));
} }
} else { } else {
ctx.pushCommand(Command.rect(bounds.x, bounds.y, bounds.w, bounds.h, bg_color)); ctx.pushCommand(Command.rect(bounds.x, bounds.y, bounds.w, bounds.h, bg_color));

View file

@ -217,6 +217,8 @@ pub const TextInputConfig = struct {
text_color: ?Style.Color = null, text_color: ?Style.Color = null,
/// Override border color (for validation feedback). If null, uses theme default. /// Override border color (for validation feedback). If null, uses theme default.
border_color: ?Style.Color = null, border_color: ?Style.Color = null,
/// Override focus border color (Z-Design: color del panel). If null, uses theme.primary.
focus_border_color: ?Style.Color = null,
/// Override placeholder color. If null, uses theme default. /// Override placeholder color. If null, uses theme default.
placeholder_color: ?Style.Color = null, placeholder_color: ?Style.Color = null,
/// Corner radius (default 3 for fancy mode) /// Corner radius (default 3 for fancy mode)
@ -286,7 +288,9 @@ pub fn textInputRect(
const theme = Style.currentTheme().*; const theme = Style.currentTheme().*;
// Use override colors if provided, otherwise use theme defaults // Use override colors if provided, otherwise use theme defaults
const bg_color = config.bg_color orelse (if (has_focus) theme.input_bg.lighten(5) else theme.input_bg); const bg_color = config.bg_color orelse (if (has_focus) theme.input_bg.lighten(5) else theme.input_bg);
const border_color = config.border_color orelse (if (has_focus) theme.primary else theme.input_border); // Z-Design V2: focus_border_color permite color de focus personalizado por panel
const focus_color = config.focus_border_color orelse theme.primary;
const border_color = config.border_color orelse (if (has_focus) focus_color else theme.input_border);
const text_color = config.text_color orelse theme.input_fg; const text_color = config.text_color orelse theme.input_fg;
const placeholder_color = config.placeholder_color orelse theme.secondary; const placeholder_color = config.placeholder_color orelse theme.secondary;
@ -295,9 +299,9 @@ pub fn textInputRect(
// Fancy mode: rounded corners // Fancy mode: rounded corners
ctx.pushCommand(Command.roundedRect(bounds.x, bounds.y, bounds.w, bounds.h, bg_color, config.corner_radius)); ctx.pushCommand(Command.roundedRect(bounds.x, bounds.y, bounds.w, bounds.h, bg_color, config.corner_radius));
ctx.pushCommand(Command.roundedRectOutline(bounds.x, bounds.y, bounds.w, bounds.h, border_color, config.corner_radius)); ctx.pushCommand(Command.roundedRectOutline(bounds.x, bounds.y, bounds.w, bounds.h, border_color, config.corner_radius));
// Draw focus ring when focused // Draw focus ring when focused (Z-Design V2: usa color del panel)
if (has_focus) { if (has_focus) {
ctx.pushCommand(Command.focusRing(bounds.x, bounds.y, bounds.w, bounds.h, config.corner_radius)); ctx.pushCommand(Command.focusRingColor(bounds.x, bounds.y, bounds.w, bounds.h, config.corner_radius, focus_color.withAlpha(180)));
} }
} else { } else {
// Simple mode: square corners // Simple mode: square corners