diff --git a/src/widgets/select.zig b/src/widgets/select.zig index 17908cb..bb9cb41 100644 --- a/src/widgets/select.zig +++ b/src/widgets/select.zig @@ -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;