Skip to main content

teksilo_core/styles/
split_button_style.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! Tier-3 style protocol for `SplitButton`.
5//!
6//! See `docs/styling-system.md`. The trait is object-safe so
7//! `Rc<dyn SplitButtonStyle>` can be stored in a theme slot or attached
8//! per-call via `SplitButton::style(...)`.
9//!
10//! Mirrors [`ButtonStyle`](crate::styles::ButtonStyle): the active style
11//! receives a pre-built `content` subtree (the SplitButton's interactive
12//! row — default-action region │ divider │ chevron region, with its text
13//! already coloured and its tap / menu handlers attached) and arranges the
14//! shared frame chrome (background fill, border, corner radius, min size)
15//! around it. The widget keeps ownership of text-colour resolution and all
16//! event wiring, exactly as `Button` keeps `resolve_text_role`.
17
18use std::rc::Rc;
19
20use crate::build_context::BuildContext;
21use crate::signal::Signal;
22use crate::styles::ButtonVariant;
23use crate::widget_id::WidgetId;
24
25/// Inputs handed to a [`SplitButtonStyle::make_body`] call.
26///
27/// `content` is the pre-built interactive row (the style only frames it; it
28/// never builds the regions or divider itself). The four boolean signals
29/// carry the live interaction state — the style can `.zip` / `.map` them to
30/// drive a reactive background / border. `variant` is the design-language
31/// hint the style may honour or remap (shared with [`ButtonVariant`]).
32#[derive(Clone, Debug)]
33pub struct SplitButtonStyleConfig {
34    /// The assembled, interactive row: main region │ divider │ chevron.
35    pub content: WidgetId,
36    pub is_pressed: Signal<bool>,
37    pub is_hovered: Signal<bool>,
38    pub is_focused: Signal<bool>,
39    pub is_disabled: Signal<bool>,
40    pub variant: ButtonVariant,
41}
42
43/// Style protocol for `SplitButton`. The active style owns the shared frame
44/// chrome (fill, border, corner radius, overall min size) and arranges it
45/// around the pre-built interactive `content` row.
46///
47/// `'static` (no `Send + Sync`) for the same reason as [`ButtonStyle`](crate::styles::ButtonStyle):
48/// the rest of teksilo-core is single-threaded (`Signal` uses `Rc`).
49pub trait SplitButtonStyle: 'static {
50    fn make_body(&self, cfg: &SplitButtonStyleConfig, ctx: &mut BuildContext) -> WidgetId;
51}
52
53/// Shared handle for a `SplitButtonStyle` impl. Cheap to clone; one shared
54/// `Rc` is used per theme slot and per-call override.
55pub type SharedSplitButtonStyle = Rc<dyn SplitButtonStyle>;