Skip to main content

eui_core/
layout.rs

1//! Round 2 (docs/round-2-contract.md §7): the shared layout NUMBERS
2//! (`catalog/layout.json`, generated as `LAYOUT_CONSTANT_NAMES`/`VALUES`):
3//! one place for the core and every painter.
4
5use crate::generated::catalog as g;
6
7/// A layout constant by name (`windowThreshold`, `mediaAspectRatio`, …).
8pub fn layout_constant(name: &str) -> Option<f64> {
9    let i = g::LAYOUT_CONSTANT_NAMES.iter().position(|n| *n == name)?;
10    g::LAYOUT_CONSTANT_VALUES.get(i)?.parse().ok()
11}
12
13/// Items past which List and Table window.
14pub const WINDOW_THRESHOLD: f64 = 50.0;
15/// Items rendered beyond each viewport edge.
16pub const WINDOW_OVERSCAN: f64 = 5.0;
17/// Percentage points per arrow key on a Resizable handle.
18pub const RESIZE_STEP: f64 = 10.0;
19/// A panel's min (percent) when unset.
20pub const PANEL_MIN: f64 = 10.0;
21/// A Resizable handle's hit area across its hairline (px).
22pub const RESIZE_HANDLE_HIT: f64 = 8.0;
23/// The max-content width of a text field (px).
24pub const FIELD_INTRINSIC_WIDTH: f64 = 160.0;
25/// The max-content width of an Image/Video without a width (px).
26pub const MEDIA_INTRINSIC_WIDTH: f64 = 320.0;
27/// Width / height of an Image without `aspectRatio` or a height; Video's default.
28pub const MEDIA_ASPECT_RATIO: f64 = 1.7777778;
29/// One TreeGuides gutter column (px).
30pub const TREE_GUIDE_COLUMN: f64 = 14.0;
31/// The radius of a TreeGuides elbow's corner (px).
32pub const TREE_GUIDE_RADIUS: f64 = 3.0;
33/// How far a TreeGuides vertical overshoots its row's TOP to bridge a
34/// Section divider (px; paint only, never layout).
35pub const TREE_GUIDE_BRIDGE: f64 = 1.0;
36/// EXP-1259: how long a `loading` Button waits before it shows its pending
37/// state (ms).
38pub const PENDING_DELAY_MS: f64 = 150.0;
39/// The Skeleton's ONE opacity pulse (ms, low → high → low, ease-in-out).
40pub const SKELETON_PULSE_MS: f64 = 1600.0;
41pub const SKELETON_OPACITY_LOW: f64 = 0.45;
42pub const SKELETON_OPACITY_HIGH: f64 = 0.9;
43/// The Skeleton's static opacity under reduce motion.
44pub const SKELETON_REDUCED_OPACITY: f64 = 0.6;
45/// The bottom fade over a SearchList's rows while more sit below (px).
46pub const SEARCH_LIST_FADE: f32 = 24.0;
47/// EXP-1548: the narrowest a Table column without a `width` gets (px); a
48/// table whose columns need more than its box scrolls horizontally.
49pub const TABLE_COLUMN_MIN: f32 = 120.0;
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn the_constants_are_layout_json() {
57        for (name, v) in [("windowThreshold", WINDOW_THRESHOLD), ("windowOverscan", WINDOW_OVERSCAN), ("resizeStep", RESIZE_STEP), ("panelMin", PANEL_MIN), ("resizeHandleHit", RESIZE_HANDLE_HIT), ("fieldIntrinsicWidth", FIELD_INTRINSIC_WIDTH), ("mediaIntrinsicWidth", MEDIA_INTRINSIC_WIDTH), ("mediaAspectRatio", MEDIA_ASPECT_RATIO), ("treeGuideColumn", TREE_GUIDE_COLUMN), ("treeGuideRadius", TREE_GUIDE_RADIUS), ("treeGuideBridge", TREE_GUIDE_BRIDGE), ("pendingDelayMs", PENDING_DELAY_MS), ("skeletonPulseMs", SKELETON_PULSE_MS), ("skeletonOpacityLow", SKELETON_OPACITY_LOW), ("skeletonOpacityHigh", SKELETON_OPACITY_HIGH), ("skeletonReducedOpacity", SKELETON_REDUCED_OPACITY), ("searchListFade", SEARCH_LIST_FADE as f64), ("tableColumnMin", TABLE_COLUMN_MIN as f64)] {
58            assert_eq!(layout_constant(name), Some(v), "{name}");
59        }
60        assert_eq!(g::LAYOUT_CONSTANT_NAMES.len(), 18);
61        let json: serde_json::Value = serde_json::from_str(g::LAYOUT_JSON).unwrap();
62        assert_eq!(json["windowThreshold"], 50);
63    }
64}