Skip to main content

egui_components_theme/
tokens.rs

1//! Semantic color tokens (light + dark) mirroring `gpui-component`'s
2//! `default-theme.json` gpui-component default preset.
3
4use crate::palette::*;
5use egui::Color32;
6
7/// Semantic color tokens consumed by the components.
8///
9/// Field naming follows `gpui-component`'s `ThemeColor` (e.g. `primary_foreground`
10/// for `primary.foreground` in the upstream JSON), so cross-referencing the
11/// original sources stays easy.
12#[derive(Clone, Copy, Debug)]
13pub struct ThemeColor {
14    // Base surface
15    pub background: Color32,
16    pub foreground: Color32,
17    pub border: Color32,
18    pub ring: Color32,
19    pub overlay: Color32,
20    pub caret: Color32,
21    pub selection_background: Color32,
22
23    // Primary
24    pub primary_background: Color32,
25    pub primary_foreground: Color32,
26    pub primary_hover_background: Color32,
27    pub primary_active_background: Color32,
28
29    // Secondary
30    pub secondary_background: Color32,
31    pub secondary_foreground: Color32,
32    pub secondary_hover_background: Color32,
33    pub secondary_active_background: Color32,
34
35    // Accent (used by ghost / outline hover)
36    pub accent_background: Color32,
37    pub accent_foreground: Color32,
38
39    // Muted (subdued text/surfaces)
40    pub muted_background: Color32,
41    pub muted_foreground: Color32,
42
43    // Danger / Success / Warning / Info
44    pub danger_background: Color32,
45    pub danger_foreground: Color32,
46    pub success_background: Color32,
47    pub success_foreground: Color32,
48    pub warning_background: Color32,
49    pub warning_foreground: Color32,
50    pub info_background: Color32,
51    pub info_foreground: Color32,
52
53    // Inputs
54    pub input_border: Color32,
55
56    // Popover
57    pub popover_background: Color32,
58    pub popover_foreground: Color32,
59
60    // Slider / Switch
61    pub slider_bar_background: Color32,
62    pub slider_thumb_background: Color32,
63    pub switch_background: Color32,
64
65    // Link
66    pub link_foreground: Color32,
67    pub link_hover_foreground: Color32,
68    pub link_active_foreground: Color32,
69}
70
71impl ThemeColor {
72    /// Light preset — matches `Default Light` in `default-theme.json`.
73    pub const fn light() -> Self {
74        Self {
75            background: WHITE,
76            foreground: NEUTRAL.get(950),
77            border: NEUTRAL.get(200),
78            ring: NEUTRAL.get(950),
79            overlay: Color32::from_rgba_premultiplied(0, 0, 0, 0x0d),
80            caret: Color32::from_rgb(0x0a, 0x0a, 0x0a),
81            selection_background: Color32::from_rgb(0x55, 0xa0, 0xfc),
82
83            primary_background: NEUTRAL.get(900),
84            primary_foreground: NEUTRAL.get(50),
85            primary_hover_background: NEUTRAL.get(800),
86            primary_active_background: NEUTRAL.get(950),
87
88            secondary_background: NEUTRAL.get(200),
89            secondary_foreground: NEUTRAL.get(900),
90            secondary_hover_background: NEUTRAL.get(200),
91            secondary_active_background: NEUTRAL.get(300),
92
93            accent_background: NEUTRAL.get(100),
94            accent_foreground: NEUTRAL.get(900),
95
96            muted_background: NEUTRAL.get(100),
97            muted_foreground: NEUTRAL.get(500),
98
99            danger_background: RED.get(500),
100            danger_foreground: NEUTRAL.get(50),
101            success_background: GREEN.get(500),
102            success_foreground: NEUTRAL.get(50),
103            warning_background: YELLOW.get(500),
104            warning_foreground: NEUTRAL.get(50),
105            info_background: CYAN.get(500),
106            info_foreground: NEUTRAL.get(50),
107
108            input_border: NEUTRAL.get(200),
109
110            popover_background: WHITE,
111            popover_foreground: NEUTRAL.get(950),
112
113            slider_bar_background: Color32::from_rgb(0x17, 0x17, 0x17),
114            slider_thumb_background: WHITE,
115            switch_background: Color32::from_rgb(0xd4, 0xd4, 0xd4),
116
117            link_foreground: Color32::from_rgb(0x0a, 0x0a, 0x0a),
118            link_hover_foreground: Color32::from_rgb(0x40, 0x40, 0x40),
119            link_active_foreground: Color32::from_rgb(0x0a, 0x0a, 0x0a),
120        }
121    }
122
123    /// Dark preset — matches `Default Dark` in `default-theme.json`.
124    pub const fn dark() -> Self {
125        Self {
126            background: NEUTRAL.get(950),
127            foreground: NEUTRAL.get(50),
128            border: NEUTRAL.get(800),
129            ring: NEUTRAL.get(300),
130            overlay: Color32::from_rgba_premultiplied(0, 0, 0, 0x33),
131            caret: Color32::from_rgb(0xfa, 0xfa, 0xfa),
132            selection_background: Color32::from_rgb(0x1d, 0x4e, 0xd8),
133
134            primary_background: NEUTRAL.get(50),
135            primary_foreground: NEUTRAL.get(900),
136            primary_hover_background: NEUTRAL.get(100),
137            primary_active_background: NEUTRAL.get(200),
138
139            secondary_background: NEUTRAL.get(800),
140            secondary_foreground: NEUTRAL.get(50),
141            secondary_hover_background: Color32::from_rgb(0x29, 0x29, 0x29),
142            secondary_active_background: Color32::from_rgb(0x21, 0x21, 0x21),
143
144            accent_background: NEUTRAL.get(800),
145            accent_foreground: NEUTRAL.get(50),
146
147            muted_background: NEUTRAL.get(800),
148            muted_foreground: NEUTRAL.get(400),
149
150            danger_background: RED.get(400),
151            danger_foreground: RED.get(600),
152            success_background: GREEN.get(400),
153            success_foreground: GREEN.get(600),
154            warning_background: YELLOW.get(400),
155            warning_foreground: YELLOW.get(600),
156            info_background: CYAN.get(400),
157            info_foreground: CYAN.get(600),
158
159            input_border: Color32::from_rgb(0x2f, 0x2f, 0x2f),
160
161            popover_background: NEUTRAL.get(950),
162            popover_foreground: NEUTRAL.get(50),
163
164            slider_bar_background: Color32::from_rgb(0xfa, 0xfa, 0xfa),
165            slider_thumb_background: Color32::from_rgb(0x0a, 0x0a, 0x0a),
166            switch_background: Color32::from_rgb(0x40, 0x40, 0x40),
167
168            link_foreground: Color32::from_rgb(0xfa, 0xfa, 0xfa),
169            link_hover_foreground: Color32::from_rgb(0xff, 0xff, 0xff),
170            link_active_foreground: Color32::from_rgb(0xd4, 0xd4, 0xd4),
171        }
172    }
173}