diff --git a/crates/op-editor-ui/src/widgets/button.rs b/crates/op-editor-ui/src/widgets/button.rs index 032e0e931..f4ed8555c 100644 --- a/crates/op-editor-ui/src/widgets/button.rs +++ b/crates/op-editor-ui/src/widgets/button.rs @@ -1,4 +1,5 @@ -use crate::{Color, Rect, RenderBackend, Theme}; +use crate::widgets::icons::{draw_icon, Icon}; +use crate::{Color, Point2D, Rect, RenderBackend, Theme}; use jian_widgets::components::button::{Button, ButtonVariant}; use jian_widgets::{Density, Tokens}; @@ -77,6 +78,59 @@ pub(crate) fn paint_button_feedback_wash( } } +/// Icon-button background + feedback, centralised on jian Button. `active` paints +/// the solid primary highlight (e.g. the selected toolbar tool); inactive uses the +/// ghost hover/press wash. Returns the icon color to stroke on top — every icon +/// button funnels its hover/active rendering through here instead of hand-rolling it. +pub(crate) fn paint_icon_button_feedback( + backend: &mut dyn RenderBackend, + theme: &Theme, + rect: Rect, + hovered: bool, + pressed: bool, + active: bool, +) -> Color { + if active { + Button { + label: "", + icon_d: None, + variant: ButtonVariant::Primary, + enabled: true, + hovered, + pressed, + font_size: 0.0, + } + .paint(backend, rect, &tokens_from_theme(theme)); + theme.primary_foreground + } else { + paint_ghost_button_feedback(backend, theme, rect, hovered, pressed) + } +} + +/// A complete icon button: hover / pressed / active feedback (centralised on +/// jian Button) PLUS the centred icon glyph — so every toolbar and chrome icon +/// button is a single call instead of hand-rolling `feedback + draw_icon` +/// separately in each widget. `active` paints the solid primary highlight. +#[allow(clippy::too_many_arguments)] +pub(crate) fn paint_icon_button( + backend: &mut dyn RenderBackend, + theme: &Theme, + rect: Rect, + icon: Icon, + hovered: bool, + pressed: bool, + active: bool, + icon_size: f32, + stroke_w: f32, +) { + let color = paint_icon_button_feedback(backend, theme, rect, hovered, pressed, active); + let origin = Point2D::new( + rect.origin.x + (rect.size.x - icon_size) / 2.0, + rect.origin.y + (rect.size.y - icon_size) / 2.0, + ); + draw_icon(backend, icon, origin, icon_size, color, stroke_w); +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/op-editor-ui/src/widgets/toolbar.rs b/crates/op-editor-ui/src/widgets/toolbar.rs index dff3ef7b6..e2f612181 100644 --- a/crates/op-editor-ui/src/widgets/toolbar.rs +++ b/crates/op-editor-ui/src/widgets/toolbar.rs @@ -25,7 +25,6 @@ use op_editor_core::Tool; /// Outer column width (matches the TS app's `w-12` toolbar). pub const TOOLBAR_WIDTH: f32 = 44.0; const BUTTON_SIZE: f32 = 32.0; -const BUTTON_RADIUS: f32 = 8.0; const ICON_SIZE: f32 = 18.0; const STROKE_W: f32 = 1.6; const BUTTON_GAP: f32 = 4.0; @@ -454,29 +453,15 @@ fn paint_button( origin: Point2D::new(x, y), size: Point2D::new(BUTTON_SIZE, BUTTON_SIZE), }; - let icon_color = if active { - cx.backend - .fill_round_rect(button_rect, BUTTON_RADIUS, theme.primary); - theme.primary_foreground - } else { - crate::widgets::button::paint_ghost_button_feedback( - cx.backend, - theme, - button_rect, - hovered, - pressed, - ) - }; - let icon_origin = Point2D::new( - x + (BUTTON_SIZE - ICON_SIZE) / 2.0, - y + (BUTTON_SIZE - ICON_SIZE) / 2.0, - ); - draw_icon( + crate::widgets::button::paint_icon_button( cx.backend, + theme, + button_rect, icon, - icon_origin, + hovered, + pressed, + active, ICON_SIZE, - icon_color, STROKE_W, ); }