1use maruzzella::{
2 default_product_spec, run, text_tab, BottomPanelLayout, ButtonAppearance, ButtonStyle,
3 InputAppearance, MaruzzellaConfig, SurfaceAppearance, SurfaceLevel, TabGroupSpec,
4 TabStripAppearance, TabStripStyle, TextAppearance, TextRole, ThemeSpec, Tone,
5 WorkbenchNodeSpec,
6};
7
8fn main() {
9 let mut product = default_product_spec();
10 product.branding.title = "Semantic Appearance Demo".to_string();
11 product.branding.search_placeholder = "Search semantic appearance demo".to_string();
12 product.branding.status_text = "Panels, buttons, typography, and tabs styled by named roles"
13 .to_string();
14
15 product.layout.left_panel = TabGroupSpec::new(
16 "panel-left",
17 Some("overview"),
18 vec![
19 text_tab(
20 "overview",
21 "panel-left",
22 "Overview",
23 "This panel uses the `primary-panel` appearance id.",
24 false,
25 ),
26 text_tab(
27 "teams",
28 "panel-left",
29 "Teams",
30 "Downstream apps can override the meaning of `primary-panel` in ThemeSpec.",
31 false,
32 ),
33 ],
34 )
35 .with_panel_appearance("primary-panel")
36 .with_panel_header_appearance("panel-header")
37 .with_tab_strip_appearance("side-tabs");
38
39 product.layout.right_panel = TabGroupSpec::new(
40 "panel-right",
41 Some("inspector"),
42 vec![
43 text_tab(
44 "inspector",
45 "panel-right",
46 "Inspector",
47 "This panel uses `secondary-panel` without any raw CSS selectors.",
48 false,
49 ),
50 text_tab(
51 "history",
52 "panel-right",
53 "History",
54 "Buttons, labels, and tab strips resolve through the same semantic registry.",
55 false,
56 ),
57 ],
58 )
59 .with_panel_appearance("secondary-panel")
60 .with_panel_header_appearance("panel-header")
61 .with_tab_strip_appearance("side-tabs");
62
63 product.layout.bottom_panel = TabGroupSpec::new(
64 "panel-bottom",
65 Some("console"),
66 vec![
67 text_tab(
68 "console",
69 "panel-bottom",
70 "Console",
71 "The bottom panel uses a console-specific panel and tab-strip role.",
72 false,
73 )
74 .with_text_appearance("code"),
75 ],
76 )
77 .with_panel_appearance("console-panel")
78 .with_panel_header_appearance("panel-header")
79 .with_tab_strip_appearance("console-tabs")
80 .with_text_appearance("code");
81 product.layout.bottom_panel_layout = BottomPanelLayout::FullWidth;
82
83 product.layout.workbench = WorkbenchNodeSpec::Group(
84 TabGroupSpec::new(
85 "workbench-main",
86 Some("brief"),
87 vec![
88 text_tab(
89 "brief",
90 "workbench-main",
91 "Brief",
92 "The central workbench uses `canvas-panel` plus an `editor-tabs` strip.",
93 false,
94 ),
95 text_tab(
96 "copy",
97 "workbench-main",
98 "Typography",
99 "This example also overrides named text roles such as `title`, `meta`, and `code`.",
100 true,
101 )
102 .with_text_appearance("meta"),
103 ],
104 )
105 .with_panel_appearance("canvas-panel")
106 .with_panel_header_appearance("panel-header")
107 .with_tab_strip_appearance("editor-tabs"),
108 );
109
110 let config = MaruzzellaConfig::new("com.example.semantic-appearance")
111 .with_persistence_id("semantic-appearance-demo")
112 .with_theme(semantic_theme())
113 .with_product(product);
114
115 run(config);
116}
117
118fn semantic_theme() -> ThemeSpec {
119 let mut theme = ThemeSpec::default();
120 theme.typography.font_family = "\"Azeret Mono\", \"Noto Sans\", sans-serif".to_string();
121 theme.typography.mono_font_family = "\"IBM Plex Mono\", monospace".to_string();
122 theme.typography.font_size_base = 14;
123 theme.typography.font_size_ui = 13;
124 theme.typography.font_size_small = 12;
125 theme.typography.font_size_tiny = 11;
126 theme.typography.font_size_title = 28;
127 theme.palette.bg_0 = "#f1efe6".to_string();
128 theme.palette.bg_1 = "#e3dfd3".to_string();
129 theme.palette.workbench = "#f8f6ef".to_string();
130 theme.palette.panel_left = "#d7e1dd".to_string();
131 theme.palette.panel_right = "#e7ddd0".to_string();
132 theme.palette.panel_bottom = "#d9d5df".to_string();
133 theme.palette.border = "#b5b0a3".to_string();
134 theme.palette.border_strong = "#8f8777".to_string();
135 theme.palette.text_0 = "#1f1e1a".to_string();
136 theme.palette.text_1 = "#4b463d".to_string();
137 theme.palette.text_2 = "#6d665a".to_string();
138 theme.palette.accent = "#0f766e".to_string();
139 theme.palette.accent_strong = "#0b5f58".to_string();
140 theme.density.radius_medium = 12;
141 theme.density.radius_large = 16;
142 theme.density.toolbar_height = 46;
143 theme.density.tab_height = 32;
144 theme.density.panel_header_height = 30;
145
146 theme
147 .with_surface_appearance(
148 "primary-panel",
149 SurfaceAppearance::new(Tone::Primary, SurfaceLevel::Raised, TextRole::Body),
150 )
151 .with_surface_appearance(
152 "secondary-panel",
153 SurfaceAppearance::new(Tone::Secondary, SurfaceLevel::Raised, TextRole::Body),
154 )
155 .with_surface_appearance(
156 "console-panel",
157 SurfaceAppearance::new(Tone::Tertiary, SurfaceLevel::Sunken, TextRole::Code),
158 )
159 .with_surface_appearance(
160 "canvas-panel",
161 SurfaceAppearance::new(Tone::Neutral, SurfaceLevel::Sunken, TextRole::Body)
162 .borderless(),
163 )
164 .with_surface_appearance(
165 "panel-header",
166 SurfaceAppearance::new(Tone::Neutral, SurfaceLevel::Flat, TextRole::SectionLabel),
167 )
168 .with_button_appearance(
169 "primary",
170 ButtonAppearance::new(Tone::Accent, ButtonStyle::Solid, TextRole::BodyStrong),
171 )
172 .with_button_appearance(
173 "secondary",
174 ButtonAppearance::new(Tone::Primary, ButtonStyle::Soft, TextRole::Body),
175 )
176 .with_button_appearance(
177 "ghost",
178 ButtonAppearance::new(Tone::Neutral, ButtonStyle::Ghost, TextRole::Body),
179 )
180 .with_input_appearance(
181 "search",
182 InputAppearance::new(Tone::Secondary, SurfaceLevel::Sunken, TextRole::Body),
183 )
184 .with_text_appearance(
185 "title",
186 TextAppearance {
187 role: TextRole::Title,
188 tone: Tone::Accent,
189 },
190 )
191 .with_text_appearance(
192 "meta",
193 TextAppearance {
194 role: TextRole::Meta,
195 tone: Tone::Neutral,
196 },
197 )
198 .with_tab_strip_appearance(
199 "side-tabs",
200 TabStripAppearance::new(Tone::Primary, TabStripStyle::Utility, TextRole::TabLabel),
201 )
202 .with_tab_strip_appearance(
203 "editor-tabs",
204 TabStripAppearance::new(Tone::Neutral, TabStripStyle::Editor, TextRole::TabLabel),
205 )
206 .with_tab_strip_appearance(
207 "console-tabs",
208 TabStripAppearance::new(Tone::Tertiary, TabStripStyle::Console, TextRole::TabLabel),
209 )
210}