rosace_theme/
typography.rs1#[derive(Debug, Clone, PartialEq)]
5pub enum FontFamily {
6 System,
8 Monospace,
10 Custom(String),
12}
13
14#[derive(Debug, Clone, Copy, PartialEq)]
16pub enum FontWeight {
17 Thin = 100,
18 Light = 300,
19 Regular = 400,
20 Medium = 500,
21 SemiBold = 600,
22 Bold = 700,
23 ExtraBold = 800,
24 Black = 900,
25}
26
27#[derive(Debug, Clone)]
29pub struct TextStyle {
30 pub family: FontFamily,
31 pub size: f32,
33 pub weight: FontWeight,
34 pub line_height: f32,
36 pub letter_spacing: f32,
38}
39
40impl TextStyle {
41 pub fn new(size: f32, weight: FontWeight) -> Self {
44 Self {
45 family: FontFamily::System,
46 size,
47 weight,
48 line_height: 1.4,
49 letter_spacing: 0.0,
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
60pub struct Typography {
61 pub display_large: TextStyle, pub display_medium: TextStyle, pub display_small: TextStyle, pub headline_large: TextStyle, pub headline_medium: TextStyle, pub headline_small: TextStyle, pub title_large: TextStyle, pub title_medium: TextStyle, pub title_small: TextStyle, pub body_large: TextStyle, pub body_medium: TextStyle, pub body_small: TextStyle, pub label_large: TextStyle, pub label_medium: TextStyle, pub label_small: TextStyle, }
77
78impl Default for Typography {
79 fn default() -> Self {
80 Self {
81 display_large: TextStyle::new(58.0, FontWeight::Regular),
82 display_medium: TextStyle::new(46.0, FontWeight::Regular),
83 display_small: TextStyle::new(37.0, FontWeight::Regular),
84 headline_large: TextStyle::new(33.0, FontWeight::Regular),
85 headline_medium: TextStyle::new(29.0, FontWeight::Regular),
86 headline_small: TextStyle::new(25.0, FontWeight::Regular),
87 title_large: TextStyle::new(23.0, FontWeight::Regular),
88 title_medium: TextStyle::new(17.0, FontWeight::Medium),
89 title_small: TextStyle::new(15.0, FontWeight::Medium),
90 body_large: TextStyle::new(17.0, FontWeight::Regular),
91 body_medium: TextStyle::new(15.0, FontWeight::Regular),
92 body_small: TextStyle::new(13.0, FontWeight::Regular),
93 label_large: TextStyle::new(15.0, FontWeight::Medium),
94 label_medium: TextStyle::new(13.0, FontWeight::Medium),
95 label_small: TextStyle::new(12.0, FontWeight::Medium),
96 }
97 }
98}
99
100#[cfg(test)]
105mod tests {
106 use super::*;
107
108 #[test]
109 fn typography_scale_sizes_are_ordered() {
110 let t = Typography::default();
111 assert!(t.display_large.size > t.headline_large.size,
112 "display_large ({}) should be larger than headline_large ({})",
113 t.display_large.size, t.headline_large.size);
114 assert!(t.headline_large.size > t.body_large.size,
115 "headline_large ({}) should be larger than body_large ({})",
116 t.headline_large.size, t.body_large.size);
117 }
118
119 #[test]
120 fn typography_default_display_large_is_58px() {
121 let t = Typography::default();
122 assert_eq!(t.display_large.size, 58.0);
123 }
124
125 #[test]
126 fn typography_title_medium_is_medium_weight() {
127 let t = Typography::default();
128 assert_eq!(t.title_medium.weight, FontWeight::Medium);
129 }
130
131 #[test]
132 fn typography_default_line_height() {
133 let t = Typography::default();
134 assert!((t.body_large.line_height - 1.4).abs() < 1e-6);
135 }
136
137 #[test]
138 fn font_family_custom_stores_name() {
139 let f = FontFamily::Custom("Inter".to_string());
140 assert_eq!(f, FontFamily::Custom("Inter".to_string()));
141 assert_ne!(f, FontFamily::System);
142 }
143}