gpui_kit_material/tokens/
shape.rs1use gpui::{Pixels, Styled, px};
3
4pub const RADIUS_NONE: Pixels = px(0.);
14pub const RADIUS_EXTRA_SMALL: Pixels = px(4.);
16pub const RADIUS_SMALL: Pixels = px(8.);
18pub const RADIUS_MEDIUM: Pixels = px(12.);
20pub const RADIUS_LARGE: Pixels = px(16.);
22pub const RADIUS_LARGE_INCREASED: Pixels = px(20.);
24pub const RADIUS_EXTRA_LARGE: Pixels = px(28.);
26pub const RADIUS_EXTRA_LARGE_INCREASED: Pixels = px(32.);
28pub const RADIUS_EXTRA_EXTRA_LARGE: Pixels = px(48.);
30pub const RADIUS_FULL: Pixels = px(1000.);
33
34pub const RADIUS_PILL: Pixels = RADIUS_FULL;
36pub const FIELD_RADIUS: Pixels = RADIUS_EXTRA_SMALL;
38pub const RADIUS_CARD: Pixels = RADIUS_MEDIUM;
40pub const MENU_RADIUS: Pixels = RADIUS_LARGE;
42pub const RADIUS_HERO: Pixels = RADIUS_EXTRA_LARGE;
44
45pub const TILE_RADIUS: Pixels = px(24.);
48pub const TILE_INNER_RADIUS: Pixels = px(6.);
49pub const TILE_GAP: Pixels = px(2.);
50
51pub type OuterCorners = [bool; 4];
54
55pub fn tile_corners<E: Styled>(element: E, outer: OuterCorners) -> E {
58 let radius = |outside: bool| {
59 if outside {
60 TILE_RADIUS
61 } else {
62 TILE_INNER_RADIUS
63 }
64 };
65 element
66 .rounded_tl(radius(outer[0]))
67 .rounded_tr(radius(outer[1]))
68 .rounded_br(radius(outer[2]))
69 .rounded_bl(radius(outer[3]))
70}
71
72pub fn list_corners(index: usize, count: usize) -> OuterCorners {
74 let first = index == 0;
75 let last = index + 1 >= count;
76 [first, first, last, last]
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn vertical_groups_round_only_their_ends() {
85 assert_eq!(list_corners(0, 1), [true; 4]);
86 assert_eq!(list_corners(0, 3), [true, true, false, false]);
87 assert_eq!(list_corners(1, 3), [false; 4]);
88 assert_eq!(list_corners(2, 3), [false, false, true, true]);
89 }
90
91 #[test]
92 fn corner_scale_matches_m3() {
93 let scale = [
94 (RADIUS_NONE, 0.),
95 (RADIUS_EXTRA_SMALL, 4.),
96 (RADIUS_SMALL, 8.),
97 (RADIUS_MEDIUM, 12.),
98 (RADIUS_LARGE, 16.),
99 (RADIUS_LARGE_INCREASED, 20.),
100 (RADIUS_EXTRA_LARGE, 28.),
101 (RADIUS_EXTRA_LARGE_INCREASED, 32.),
102 (RADIUS_EXTRA_EXTRA_LARGE, 48.),
103 ];
104 for (radius, expected) in scale {
105 assert_eq!(radius, px(expected));
106 }
107 let fixture: serde_json::Value =
108 serde_json::from_str(include_str!("../../tests/fixtures/figma-sys-tokens.json"))
109 .unwrap();
110 let reference = &fixture["shape_corner_px"];
111 for (radius, name) in [
112 (RADIUS_NONE, "none"),
113 (RADIUS_EXTRA_SMALL, "extra-small"),
114 (RADIUS_SMALL, "small"),
115 (RADIUS_MEDIUM, "medium"),
116 (RADIUS_LARGE, "large"),
117 (RADIUS_LARGE_INCREASED, "large-increased"),
118 (RADIUS_EXTRA_LARGE, "extra-large"),
119 (RADIUS_EXTRA_LARGE_INCREASED, "extra-large-increased"),
120 (RADIUS_EXTRA_EXTRA_LARGE, "extra-extra-large"),
121 (RADIUS_FULL, "full"),
122 ] {
123 assert_eq!(
124 radius,
125 px(reference[name].as_f64().unwrap() as f32),
126 "{name}"
127 );
128 }
129 assert_eq!(FIELD_RADIUS, px(4.), "M3 text fields use extra-small");
130 assert_eq!(RADIUS_CARD, px(12.), "M3 cards use medium");
131 }
132}