1#[macro_export]
30macro_rules! row {
31 ($($child:expr),* $(,)?) => {{
32 #[allow(unused_imports)]
33 use $crate::__ParentElement as _;
34 $crate::flex::Row::new() $(.child($child))*
35 }};
36}
37
38#[macro_export]
42macro_rules! col {
43 ($($child:expr),* $(,)?) => {{
44 #[allow(unused_imports)]
45 use $crate::__ParentElement as _;
46 $crate::flex::Column::new() $(.child($child))*
47 }};
48}
49
50#[macro_export]
52macro_rules! zstack {
53 ($($child:expr),* $(,)?) => {{
54 #[allow(unused_imports)]
55 use $crate::__ParentElement as _;
56 $crate::flex::Stack::new() $(.child($child))*
57 }};
58}
59
60#[macro_export]
62macro_rules! wrap {
63 ($($child:expr),* $(,)?) => {{
64 #[allow(unused_imports)]
65 use $crate::__ParentElement as _;
66 $crate::flex::Wrap::new() $(.child($child))*
67 }};
68}
69
70#[macro_export]
72macro_rules! vstack {
73 ($($child:expr),* $(,)?) => {{
74 #[allow(unused_imports)]
75 use $crate::__ParentElement as _;
76 $crate::layout::Stack::new() $(.child($child))*
77 }};
78}
79
80#[macro_export]
82macro_rules! hstack {
83 ($($child:expr),* $(,)?) => {{
84 #[allow(unused_imports)]
85 use $crate::__ParentElement as _;
86 $crate::layout::Group::new() $(.child($child))*
87 }};
88}
89
90#[macro_export]
92macro_rules! center {
93 ($($child:expr),* $(,)?) => {{
94 #[allow(unused_imports)]
95 use $crate::__ParentElement as _;
96 $crate::layout::Center::new() $(.child($child))*
97 }};
98}
99
100#[macro_export]
102macro_rules! paper {
103 ($($child:expr),* $(,)?) => {{
104 #[allow(unused_imports)]
105 use $crate::__ParentElement as _;
106 $crate::Paper::new() $(.child($child))*
107 }};
108}
109
110#[macro_export]
112macro_rules! card {
113 ($($child:expr),* $(,)?) => {{
114 #[allow(unused_imports)]
115 use $crate::__ParentElement as _;
116 $crate::Card::new() $(.child($child))*
117 }};
118}
119
120#[macro_export]
123macro_rules! modal {
124 ($($child:expr),* $(,)?) => {{
125 #[allow(unused_imports)]
126 use $crate::__ParentElement as _;
127 $crate::Modal::new() $(.child($child))*
128 }};
129}
130
131#[macro_export]
139macro_rules! text {
140 ($fmt:literal, $($arg:tt)*) => { $crate::Text::new(format!($fmt, $($arg)*)) };
141 ($content:expr) => { $crate::Text::new($content) };
142}
143
144#[macro_export]
146macro_rules! title {
147 ($fmt:literal, $($arg:tt)*) => { $crate::Title::new(format!($fmt, $($arg)*)) };
148 ($content:expr) => { $crate::Title::new($content) };
149}
150
151#[macro_export]
153macro_rules! code {
154 ($fmt:literal, $($arg:tt)*) => { $crate::Code::new(format!($fmt, $($arg)*)) };
155 ($content:expr) => { $crate::Code::new($content) };
156}
157
158#[macro_export]
160macro_rules! kbd {
161 ($fmt:literal, $($arg:tt)*) => { $crate::Kbd::new(format!($fmt, $($arg)*)) };
162 ($content:expr) => { $crate::Kbd::new($content) };
163}
164
165#[macro_export]
167macro_rules! button {
168 ($($arg:expr),* $(,)?) => { $crate::Button::new($($arg),*) };
169}
170
171#[macro_export]
173macro_rules! badge {
174 ($($arg:expr),* $(,)?) => { $crate::Badge::new($($arg),*) };
175}
176
177#[macro_export]
193macro_rules! color {
194 (rgb($r:expr, $g:expr, $b:expr $(,)?)) => {
195 $crate::theme::rgb($r, $g, $b)
196 };
197 (rgba($r:expr, $g:expr, $b:expr, $a:expr $(,)?)) => {
198 $crate::theme::rgba($r, $g, $b, $a)
199 };
200 (hsl($h:expr, $s:expr, $l:expr $(,)?)) => {
201 $crate::theme::hsl($h as f32, $s as f32, $l as f32)
202 };
203 (hsla($h:expr, $s:expr, $l:expr, $a:expr $(,)?)) => {
204 $crate::theme::hsla($h as f32, $s as f32, $l as f32, $a)
205 };
206 ($css:literal) => {
207 $crate::theme::css($css).expect("guise: invalid CSS color literal")
208 };
209 ($name:ident) => {
210 $crate::theme::css(stringify!($name)).expect("guise: unknown CSS color name")
211 };
212}
213
214#[macro_export]
249macro_rules! style {
250 ( $($decls:tt)* ) => {
251 |__guise_el| {
252 #[allow(unused_imports)]
253 use $crate::gpui::Styled as _;
254 $crate::__style!(@m __guise_el ; $($decls)*)
255 }
256 };
257}
258
259#[macro_export]
260#[doc(hidden)]
261macro_rules! __style {
262 (@m $el:expr ;) => { $el };
263
264 (@m $el:expr ; background : $v:literal ; $($r:tt)*) => {
266 $crate::__style!(@m $el.bg($crate::theme::css($v).expect("style!: invalid color")) ; $($r)*)
267 };
268 (@m $el:expr ; background : $v:expr ; $($r:tt)*) => {
269 $crate::__style!(@m $el.bg($v) ; $($r)*)
270 };
271 (@m $el:expr ; color : $v:literal ; $($r:tt)*) => {
272 $crate::__style!(@m $el.text_color($crate::theme::css($v).expect("style!: invalid color")) ; $($r)*)
273 };
274 (@m $el:expr ; color : $v:expr ; $($r:tt)*) => {
275 $crate::__style!(@m $el.text_color($v) ; $($r)*)
276 };
277 (@m $el:expr ; border : $v:literal ; $($r:tt)*) => {
278 $crate::__style!(@m $el.border_1().border_color($crate::theme::css($v).expect("style!: invalid color")) ; $($r)*)
279 };
280 (@m $el:expr ; border : $v:expr ; $($r:tt)*) => {
281 $crate::__style!(@m $el.border_1().border_color($v) ; $($r)*)
282 };
283
284 (@m $el:expr ; display : flex ; $($r:tt)*) => { $crate::__style!(@m $el.flex() ; $($r)*) };
286
287 (@m $el:expr ; direction : row ; $($r:tt)*) => { $crate::__style!(@m $el.flex_row() ; $($r)*) };
288 (@m $el:expr ; direction : column ; $($r:tt)*) => { $crate::__style!(@m $el.flex_col() ; $($r)*) };
289 (@m $el:expr ; direction : col ; $($r:tt)*) => { $crate::__style!(@m $el.flex_col() ; $($r)*) };
290
291 (@m $el:expr ; align : start ; $($r:tt)*) => { $crate::__style!(@m $el.items_start() ; $($r)*) };
292 (@m $el:expr ; align : center ; $($r:tt)*) => { $crate::__style!(@m $el.items_center() ; $($r)*) };
293 (@m $el:expr ; align : end ; $($r:tt)*) => { $crate::__style!(@m $el.items_end() ; $($r)*) };
294 (@m $el:expr ; align : stretch ; $($r:tt)*) => { $crate::__style!(@m $el.items_stretch() ; $($r)*) };
295
296 (@m $el:expr ; justify : start ; $($r:tt)*) => { $crate::__style!(@m $el.justify_start() ; $($r)*) };
297 (@m $el:expr ; justify : center ; $($r:tt)*) => { $crate::__style!(@m $el.justify_center() ; $($r)*) };
298 (@m $el:expr ; justify : end ; $($r:tt)*) => { $crate::__style!(@m $el.justify_end() ; $($r)*) };
299 (@m $el:expr ; justify : between ; $($r:tt)*) => { $crate::__style!(@m $el.justify_between() ; $($r)*) };
300 (@m $el:expr ; justify : around ; $($r:tt)*) => { $crate::__style!(@m $el.justify_around() ; $($r)*) };
301 (@m $el:expr ; justify : evenly ; $($r:tt)*) => { $crate::__style!(@m $el.justify_evenly() ; $($r)*) };
302
303 (@m $el:expr ; position : absolute ; $($r:tt)*) => { $crate::__style!(@m $el.absolute() ; $($r)*) };
304 (@m $el:expr ; position : relative ; $($r:tt)*) => { $crate::__style!(@m $el.relative() ; $($r)*) };
305
306 (@m $el:expr ; weight : bold ; $($r:tt)*) => { $crate::__style!(@m $el.font_weight($crate::gpui::FontWeight::BOLD) ; $($r)*) };
307 (@m $el:expr ; weight : semibold ; $($r:tt)*) => { $crate::__style!(@m $el.font_weight($crate::gpui::FontWeight::SEMIBOLD) ; $($r)*) };
308 (@m $el:expr ; weight : medium ; $($r:tt)*) => { $crate::__style!(@m $el.font_weight($crate::gpui::FontWeight::MEDIUM) ; $($r)*) };
309 (@m $el:expr ; weight : normal ; $($r:tt)*) => { $crate::__style!(@m $el.font_weight($crate::gpui::FontWeight::NORMAL) ; $($r)*) };
310
311 (@m $el:expr ; width : full ; $($r:tt)*) => { $crate::__style!(@m $el.w_full() ; $($r)*) };
312 (@m $el:expr ; height : full ; $($r:tt)*) => { $crate::__style!(@m $el.h_full() ; $($r)*) };
313
314 (@m $el:expr ; width : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.w($crate::gpui::px($v as f32)) ; $($r)*) };
316 (@m $el:expr ; height : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.h($crate::gpui::px($v as f32)) ; $($r)*) };
317 (@m $el:expr ; size : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.w($crate::gpui::px($v as f32)).h($crate::gpui::px($v as f32)) ; $($r)*) };
318 (@m $el:expr ; min_width : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.min_w($crate::gpui::px($v as f32)) ; $($r)*) };
319 (@m $el:expr ; min_height : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.min_h($crate::gpui::px($v as f32)) ; $($r)*) };
320
321 (@m $el:expr ; padding : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.p($crate::gpui::px($v as f32)) ; $($r)*) };
322 (@m $el:expr ; px : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.px($crate::gpui::px($v as f32)) ; $($r)*) };
323 (@m $el:expr ; py : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.py($crate::gpui::px($v as f32)) ; $($r)*) };
324 (@m $el:expr ; pt : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.pt($crate::gpui::px($v as f32)) ; $($r)*) };
325 (@m $el:expr ; pr : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.pr($crate::gpui::px($v as f32)) ; $($r)*) };
326 (@m $el:expr ; pb : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.pb($crate::gpui::px($v as f32)) ; $($r)*) };
327 (@m $el:expr ; pl : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.pl($crate::gpui::px($v as f32)) ; $($r)*) };
328
329 (@m $el:expr ; margin : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.m($crate::gpui::px($v as f32)) ; $($r)*) };
330 (@m $el:expr ; mx : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.mx($crate::gpui::px($v as f32)) ; $($r)*) };
331 (@m $el:expr ; my : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.my($crate::gpui::px($v as f32)) ; $($r)*) };
332 (@m $el:expr ; mt : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.mt($crate::gpui::px($v as f32)) ; $($r)*) };
333 (@m $el:expr ; mr : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.mr($crate::gpui::px($v as f32)) ; $($r)*) };
334 (@m $el:expr ; mb : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.mb($crate::gpui::px($v as f32)) ; $($r)*) };
335 (@m $el:expr ; ml : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.ml($crate::gpui::px($v as f32)) ; $($r)*) };
336
337 (@m $el:expr ; radius : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.rounded($crate::gpui::px($v as f32)) ; $($r)*) };
338 (@m $el:expr ; gap : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.gap($crate::gpui::px($v as f32)) ; $($r)*) };
339 (@m $el:expr ; font_size : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.text_size($crate::gpui::px($v as f32)) ; $($r)*) };
340 (@m $el:expr ; opacity : $v:expr ; $($r:tt)*) => { $crate::__style!(@m $el.opacity($v as f32) ; $($r)*) };
341}
342
343#[cfg(test)]
344mod tests {
345 use crate::{Button, ColorName, Text, Variant};
346
347 #[test]
350 fn macros_expand() {
351 let _ = row![Text::new("a"), Button::new("b", "B")];
352 let _ = col![Text::new("a")];
353 let _ = zstack![Text::new("a")];
354 let _ = wrap![Text::new("a")];
355 let _ = vstack![Text::new("a")];
356 let _ = hstack![Text::new("a")];
357 let _ = center![Text::new("a")];
358 let _ = paper![Text::new("a")];
359 let _ = card![Text::new("a")];
360 let _ = modal![Text::new("a")];
361 let _ = card![Text::new("a"), Text::new("b"),].with_border(true);
363 }
364
365 #[test]
366 fn component_macros_expand() {
367 let name = "Ada";
369 let _ = text!("hello");
370 let _ = text!("hello {}", name);
371 let _ = title!("Heading").order(2);
372 let _ = code!("guise::Button");
373 let _ = kbd!("{}", "K");
374 let _ = button!("save", "Save").variant(Variant::Filled);
376 let _ = badge!("New").color(ColorName::Blue);
377 let _ = Button::new("x", "y"); }
379
380 #[test]
381 fn color_macro_matches_constructors() {
382 use crate::theme::{css, hsl, rgb, rgba};
383 assert_eq!(color!(rgb(34, 139, 230)), rgb(34, 139, 230));
384 assert_eq!(color!(rgba(34, 139, 230, 0.5)), rgba(34, 139, 230, 0.5));
385 assert_eq!(color!(hsl(210, 80, 52)), hsl(210.0, 80.0, 52.0));
386 assert_eq!(color!(teal), css("teal").unwrap());
387 assert_eq!(color!("#228be6"), css("#228be6").unwrap());
388 let _ = Button::new("x", "y").color(color!(rgba(112, 72, 232, 1.0)));
390 }
391
392 #[test]
393 fn style_macro_builds() {
394 use crate::StyleExt;
395 let _ = gpui::div().apply(style! {
396 display: flex;
397 direction: column;
398 align: center;
399 justify: between;
400 gap: 8;
401 padding: 12;
402 width: full;
403 height: 200;
404 radius: 8;
405 background: "#11151c";
406 color: color!(rgb(230, 230, 230));
407 border: color!("#2a2f3a");
408 opacity: 0.95;
409 weight: semibold;
410 position: relative;
411 });
412 }
413}