feat: Transiciones hover en Select widget

SelectState ahora incluye:
- hover: HoverTransition para transiciones suaves
- last_time_ms: tracking de tiempo para delta

El color de fondo del botón principal del Select ahora
transiciona suavemente entre normal y hover (lighten 5%).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
reugenio 2025-12-17 01:12:21 +01:00
parent 25728c151c
commit 74e83d2334

View file

@ -2,6 +2,7 @@
//!
//! A dropdown menu for selecting one option from a list.
//! The dropdown opens on click and closes when an option is selected.
//! Supports smooth hover transitions via HoverTransition.
const std = @import("std");
const Context = @import("../core/context.zig").Context;
@ -9,6 +10,7 @@ const Command = @import("../core/command.zig");
const Layout = @import("../core/layout.zig");
const Style = @import("../core/style.zig");
const Input = @import("../core/input.zig");
const animation = @import("../render/animation.zig");
/// Select state (caller-managed)
pub const SelectState = struct {
@ -20,6 +22,10 @@ pub const SelectState = struct {
scroll_offset: usize = 0,
/// Whether this widget has focus
focused: bool = false,
/// Hover transition for smooth effects
hover: animation.HoverTransition = .{},
/// Last frame time for delta calculation
last_time_ms: u64 = 0,
/// Get selected index as optional usize
pub fn selectedIndex(self: SelectState) ?usize {
@ -110,15 +116,22 @@ pub fn selectRect(
const has_focus = ctx.hasFocus(widget_id);
state.focused = has_focus;
// Determine button colors
// Update hover transition
const current_time = ctx.current_time_ms;
const dt_ms: u64 = if (state.last_time_ms > 0 and current_time > state.last_time_ms)
current_time - state.last_time_ms
else
16;
state.last_time_ms = current_time;
state.hover.update(hovered and !config.disabled and !state.open, dt_ms);
// Determine button colors with smooth transition
const bg_color = if (config.disabled)
theme.button_bg.darken(20)
else if (state.open)
theme.button_bg.lighten(10)
else if (hovered)
theme.button_bg.lighten(5)
else
theme.button_bg;
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;