Skip to main content

teksilo_core/styles/
slider_style.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! Tier-3 style protocol for `Slider`. See `docs/styling-system.md`.
5
6use std::rc::Rc;
7
8use serde::{Deserialize, Serialize};
9
10use crate::build_context::BuildContext;
11use crate::focus::FocusOrigin;
12use crate::signal::Signal;
13use crate::widget_id::WidgetId;
14
15#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
16pub enum SliderVariant {
17    #[default]
18    Continuous,
19    /// Snaps to discrete tick positions; the style typically paints
20    /// the ticks above/below the track.
21    Discrete,
22    /// Two thumbs: the value is a `(low, high)` range. Here for
23    /// completeness; the IntUI default impl does NOT yet wire range
24    /// behaviour — apps that need range sliders write a custom
25    /// impl.
26    Range,
27}
28
29/// Slider orientation. Horizontal is the default; the value
30/// progresses left → right (or right → left in RTL — slider doesn't
31/// flip today, that's a known follow-up).
32#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Default, Serialize, Deserialize)]
33pub enum SliderOrientation {
34    #[default]
35    Horizontal,
36    Vertical,
37}
38
39#[derive(Clone, Debug)]
40pub struct SliderStyleConfig {
41    /// Normalized `0.0..=1.0` thumb position.
42    pub value_normalized: Signal<f32>,
43    pub is_hovered: Signal<bool>,
44    /// `true` while the user is drag-pressing the thumb.
45    pub is_dragging: Signal<bool>,
46    pub is_disabled: Signal<bool>,
47    /// `Some(FocusOrigin::Keyboard)` while the slider has keyboard
48    /// focus; the IntUI default uses this to gate the focus ring on
49    /// the thumb. `Some(Pointer)` and `None` skip the ring.
50    pub focus_origin: Signal<Option<FocusOrigin>>,
51    pub orientation: SliderOrientation,
52    /// `Some(n)` ⇒ Discrete with `n` ticks; `None` ⇒ Continuous.
53    pub tick_count: Option<u32>,
54    pub variant: SliderVariant,
55}
56
57pub trait SliderStyle: 'static {
58    fn make_body(&self, cfg: &SliderStyleConfig, ctx: &mut BuildContext) -> WidgetId;
59
60    /// Diameter, in logical pixels, of the draggable thumb produced by
61    /// `make_body`. The host `Slider` widget uses this to compute the drag
62    /// hit-region and the position→value mapping at event time (when it can
63    /// no longer reach the theme). The default matches the IntUI recipe's
64    /// thumb; a custom style that paints a different thumb size MUST override
65    /// this too, or dragging will map to the wrong pixel boundary.
66    fn thumb_diameter(&self, _cfg: &SliderStyleConfig) -> f32 {
67        14.0
68    }
69}
70
71pub type SharedSliderStyle = Rc<dyn SliderStyle>;