Skip to main content

teksilo_core/styles/
link_style.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! Tier-3 style protocol for `Link`. See `docs/styling-system.md`.
5//!
6//! The style owns the full visual: the per-state text colour (idle /
7//! hover / pressed / visited / disabled), the underline policy, the
8//! corner radius, and the focus-ring border. The `Link` widget owns
9//! only the interaction state signals and dispatches events — it
10//! passes the resolved text *string* (not a pre-built `TextWidget`)
11//! through the config so the style can build the label with its own
12//! colour binding.
13
14use std::rc::Rc;
15
16use crate::build_context::BuildContext;
17use crate::signal::{Prop, Signal};
18use crate::widget_id::WidgetId;
19
20#[derive(Clone, Debug)]
21pub struct LinkStyleConfig {
22    /// Label text as a reactive `Prop<String>`. The widget converts its
23    /// `LocalizedString` via `.into()` (a `tr!` source yields a bound,
24    /// locale-reactive prop); the style binds it to the label widget.
25    /// `teksilo-core` can't name `LocalizedString` (i18n depends on core,
26    /// not the reverse), so the i18n type is erased to `Prop<String>` here.
27    pub text: Prop<String>,
28    /// `true` while the pointer is over the link.
29    pub is_hovered: Signal<bool>,
30    /// `true` while the link is being pressed (mouse-down or Space/Enter).
31    pub is_pressed: Signal<bool>,
32    /// `true` while the link holds keyboard focus.
33    pub is_focused: Signal<bool>,
34    /// `true` if the link's target has previously been visited. The
35    /// app owns visited-tracking; default `Signal::new(false)` is
36    /// fine for links that don't represent URLs.
37    pub is_visited: Signal<bool>,
38    /// `true` when the widget is effectively disabled (this node or
39    /// any ancestor has its arena `enabled_state` resolved to false).
40    /// Reactive: re-emits when `enabled_when(..., signal)` flips.
41    pub is_disabled: Signal<bool>,
42}
43
44pub trait LinkStyle: 'static {
45    fn make_body(&self, cfg: &LinkStyleConfig, ctx: &mut BuildContext) -> WidgetId;
46}
47
48pub type SharedLinkStyle = Rc<dyn LinkStyle>;