fret_ui/resizable_panel_group/style.rs
1use fret_core::{Color, Px};
2
3use crate::Theme;
4
5#[derive(Debug, Clone)]
6pub struct ResizablePanelGroupStyle {
7 /// Layout gap between panels in logical px.
8 ///
9 /// This does **not** need to match `hit_thickness`: it is common to keep the visual/layout gap
10 /// small (or zero) while using a larger hit area for usability.
11 pub gap: Px,
12 /// Thickness of the handle region in logical px.
13 ///
14 /// This region is used for hit-testing (and can be larger than `gap`).
15 pub hit_thickness: Px,
16 /// Visual thickness in *device* pixels (converted using the current scale factor).
17 pub paint_device_px: f32,
18 pub handle_color: Color,
19 pub handle_alpha: f32,
20 pub handle_hover_alpha: f32,
21 pub handle_drag_alpha: f32,
22}
23
24impl Default for ResizablePanelGroupStyle {
25 fn default() -> Self {
26 Self {
27 gap: Px(0.0),
28 hit_thickness: Px(6.0),
29 paint_device_px: 1.0,
30 handle_color: Color {
31 r: 1.0,
32 g: 1.0,
33 b: 1.0,
34 a: 1.0,
35 },
36 // Align with shadcn/ui: the handle line should use the border color at full opacity.
37 // Contrast remains subtle because the `border` token is intentionally low-contrast.
38 handle_alpha: 1.0,
39 handle_hover_alpha: 1.0,
40 handle_drag_alpha: 1.0,
41 }
42 }
43}
44
45impl ResizablePanelGroupStyle {
46 pub fn from_theme(theme: &Theme) -> Self {
47 let handle_color = theme
48 .color_by_key("border")
49 .or_else(|| theme.color_by_key("input"))
50 .unwrap_or(theme.snapshot().colors.panel_border);
51
52 Self {
53 // Note: this runtime crate intentionally avoids reading component-layer extension tokens
54 // (e.g. `component.*`). Component libraries should resolve their own chrome and pass an
55 // explicit `ResizablePanelGroupStyle` when needed.
56 gap: Px(0.0),
57 hit_thickness: Px(6.0),
58 paint_device_px: 1.0,
59 handle_color,
60 ..Default::default()
61 }
62 }
63}