Skip to main content

snora/
lib.rs

1//! # snora
2//!
3//! The iced engine for the Snora GUI framework.
4//!
5//! This crate binds [`snora_core`] vocabulary to iced. It exposes a single
6//! entry point, [`render`], a toast lifecycle helper module, and — when
7//! the `widgets` feature is enabled (the default) — a re-exported set of
8//! prefab `iced::Element` builders from the [`snora-widgets`] crate.
9//!
10//! # Layering
11//!
12//! ```text
13//! Your application
14//!         │
15//!         ▼
16//!  snora::render(AppLayout<Element, Message>) -> Element
17//!         │
18//!         ├─► snora-widgets   (optional, prefab UI parts)
19//!         │         │
20//!         │         ▼
21//!         │   snora-design   (optional, design tokens — no iced dependency)
22//!         ▼
23//!  snora-core   (vocabulary: Toast, Dialog, Sheet, SheetSize, …)
24//! ```
25//!
26//! The dependency graph above is strict and the only way crates relate
27//! to each other:
28//!
29//! * `snora-core` has zero iced dependency. It owns the vocabulary
30//!   (what choices exist).
31//! * `snora-design` has zero iced dependency. It owns the opt-in design
32//!   token vocabulary (`Tokens`, `Palette`, contrast utilities).
33//! * `snora-widgets` depends on `snora-core`, `iced`, and (behind the
34//!   `design` feature) `snora-design`. It owns the prefab widget visuals
35//!   and the iced style bridge that turns tokens into `iced::*::Style`.
36//! * `snora` depends on `snora-core` and (optionally) `snora-widgets`
37//!   and `snora-design`. It owns the engine — `render`, the layer
38//!   composition, and the toast lifecycle helpers.
39//!
40//! Applications normally only depend on `snora` and use it as the single
41//! umbrella crate; the workspace split exists so each layer can evolve
42//! at its own pace.
43//!
44//! # A minimal application view
45//!
46//! ```ignore
47//! use iced::{Element, widget::text};
48//! use snora::{AppLayout, render, LayoutDirection};
49//!
50//! fn view(state: &MyState) -> Element<'_, Message> {
51//!     let body: Element<'_, Message> = text("Hello, snora!").into();
52//!
53//!     let layout = AppLayout::new(body)
54//!         .direction(LayoutDirection::Ltr);
55//!
56//!     render(layout)
57//! }
58//! ```
59//!
60//! # Engine-only builds
61//!
62//! Applications that supply 100 % of their UI parts and do not want the
63//! prefab widgets compiled in can opt out:
64//!
65//! ```toml
66//! [dependencies]
67//! snora = { version = "0.25", default-features = false }
68//! ```
69//!
70//! In this configuration `snora-widgets` is not pulled in and the
71//! `snora::widget` module does not exist.
72//!
73//! [`snora-widgets`]: https://docs.rs/snora-widgets
74
75#![warn(missing_docs)]
76#![cfg_attr(docsrs, feature(doc_cfg))]
77
78// ---- Re-export the vocabulary from snora-core --------------------------
79pub use snora_core::{
80    AppLayout, BreadcrumbAction, Crumb, Dialog, Edge, Icon, LayoutDirection, Menu, MenuAction,
81    MenuItem, Sheet, SheetEdge, SheetSize, SideBar, SideBarItem, Tab, TabAction, TabBar, Toast,
82    ToastIntent, ToastLifetime, ToastPosition,
83};
84
85// ---- Engine modules (always present) ----------------------------------
86mod overlay;
87/// The single rendering entry point: [`render`].
88pub mod render;
89/// Toast rendering and lifecycle helpers
90/// ([`subscription`](toast::subscription), [`sweep_expired`](toast::sweep_expired)).
91pub mod toast;
92/// Keyboard dismissal helper: [`keyboard::dismiss_on_escape`].
93pub mod keyboard;
94
95pub use render::render;
96
97// ---- Widget re-exports (feature-gated) --------------------------------
98
99/// Direction-aware row helpers. Re-exported from `snora-widgets`.
100#[cfg(feature = "widgets")]
101pub use snora_widgets::direction;
102
103/// Shared style functions used by the prefab widgets.
104/// Re-exported from `snora-widgets`.
105#[cfg(feature = "widgets")]
106pub use snora_widgets::style;
107
108/// Optional prefab `iced::Element` builders for header / sidebar / footer
109/// / menu / icon. Re-exported from `snora-widgets`.
110///
111/// This module is only available when the `widgets` feature is enabled
112/// (which is the default).
113#[cfg(feature = "widgets")]
114pub mod widget;
115
116/// Convenience re-export of Lucide icon constants. Available when both
117/// `widgets` and `lucide-icons` features are enabled.
118#[cfg(all(feature = "widgets", feature = "lucide-icons"))]
119pub use snora_widgets::lucide;
120
121// ---- Design re-exports (feature-gated) --------------------------------
122
123/// Snora Design token types, iced style bridge, and contrast utilities.
124///
125/// Available when the `design` feature is enabled. Exposes:
126///
127/// * Token vocabulary from [`snora_design`]: [`design::Tokens`],
128///   [`design::Palette`], [`design::Color`], and the full variant /
129///   sub-token set.
130/// * The iced style bridge under [`design::style`]: color conversion,
131///   semantic button styles, and card/container styles.
132/// * Shallow UI primitives: [`design::button`], [`design::card`],
133///   [`design::notice`], [`design::chip`], [`design::progress`].
134/// * Pure-Rust WCAG contrast utilities under [`design::contrast`]:
135///   [`design::contrast::relative_luminance`],
136///   [`design::contrast::contrast_ratio`],
137///   [`design::contrast::composite_over`].
138///
139/// # iced 0.14 focus limitation
140///
141/// Standard `button` / `container` styles in iced 0.14 do not expose
142/// keyboard-focus state. The style bridge maps every status iced does expose
143/// (hover, pressed, disabled); custom focus rings on standard controls are
144/// not deliverable in v0.20 through this path. See RFC-025 and
145/// `docs/src/contributing/semantic-accessibility.md` for detail.
146#[cfg(feature = "design")]
147pub mod design;