Skip to main content

teksilo_core/styles/
menu_item_style.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! Tier-3 style protocol for `MenuItem`. See `docs/styling-system.md`.
5
6use std::rc::Rc;
7
8use teksilo_tokens::TextRole;
9
10use crate::build_context::BuildContext;
11use crate::signal::Signal;
12use crate::widget_id::WidgetId;
13
14#[derive(Clone, Debug)]
15pub struct MenuItemStyleConfig {
16    pub label: WidgetId,
17    /// Optional leading slot (icon, checkmark, radio dot).
18    pub leading: Option<WidgetId>,
19    /// Optional trailing slot (shortcut chip, submenu chevron).
20    pub trailing: Option<WidgetId>,
21    pub is_hovered: Signal<bool>,
22    pub is_pressed: Signal<bool>,
23    pub is_focused: Signal<bool>,
24    pub is_disabled: Signal<bool>,
25    /// Bound to keyboard-arrow navigation within the parent menu.
26    pub is_highlighted: Signal<bool>,
27}
28
29pub trait MenuItemStyle: 'static {
30    fn make_body(&self, cfg: &MenuItemStyleConfig, ctx: &mut BuildContext) -> WidgetId;
31
32    /// The text role a menu row's label and shortcut take while the row is
33    /// **highlighted** — hovered, or reached by keyboard navigation.
34    /// `None` (the default) keeps the row's own mapping.
35    ///
36    /// The row builds its label before a style ever sees it, so a style
37    /// that fills the highlight with a saturated colour cannot recolour
38    /// the text on top of it. macOS fills a highlighted menu row with the
39    /// accent and flips its label to `selectedMenuItemTextColor` (white),
40    /// so its style returns [`TextRole::OnAccent`]; IntUI and Fluent both
41    /// use a neutral wash and leave this `None`.
42    ///
43    /// Same shape as
44    /// [`ButtonStyle::label_text_role`](crate::styles::ButtonStyle::label_text_role),
45    /// and defaulted for the same reason: an existing style needs no
46    /// change.
47    fn highlighted_label_role(&self) -> Option<TextRole> {
48        None
49    }
50}
51
52pub type SharedMenuItemStyle = Rc<dyn MenuItemStyle>;