Skip to main content

telegram_webapp_sdk/webapp/
theme.rs

1// SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
2// SPDX-License-Identifier: MIT
3
4use js_sys::Reflect;
5use wasm_bindgen::JsValue;
6
7use crate::webapp::TelegramWebApp;
8
9impl TelegramWebApp {
10    /// Returns `WebApp.colorScheme` — `"light"` or `"dark"`.
11    pub fn color_scheme(&self) -> Option<String> {
12        Reflect::get(&self.inner, &"colorScheme".into())
13            .ok()
14            .and_then(|v| v.as_string())
15    }
16
17    /// Returns the current `WebApp.headerColor` value.
18    pub fn header_color(&self) -> Option<String> {
19        Reflect::get(&self.inner, &"headerColor".into())
20            .ok()
21            .and_then(|v| v.as_string())
22    }
23
24    /// Returns the current `WebApp.backgroundColor` value.
25    pub fn background_color(&self) -> Option<String> {
26        Reflect::get(&self.inner, &"backgroundColor".into())
27            .ok()
28            .and_then(|v| v.as_string())
29    }
30
31    /// Returns the current `WebApp.bottomBarColor` value (Bot API 7.10+).
32    pub fn bottom_bar_color(&self) -> Option<String> {
33        Reflect::get(&self.inner, &"bottomBarColor".into())
34            .ok()
35            .and_then(|v| v.as_string())
36    }
37
38    /// Returns the raw `WebApp.version` string (e.g. `"9.6"`).
39    pub fn raw_version(&self) -> Option<String> {
40        Reflect::get(&self.inner, &"version".into())
41            .ok()
42            .and_then(|v| v.as_string())
43    }
44
45    /// Returns the `WebApp.platform` string (e.g. `"tdesktop"`, `"ios"`,
46    /// `"web"`).
47    pub fn platform(&self) -> Option<String> {
48        Reflect::get(&self.inner, &"platform".into())
49            .ok()
50            .and_then(|v| v.as_string())
51    }
52
53    /// Call `WebApp.setHeaderColor(color)`.
54    ///
55    /// # Errors
56    /// Returns [`JsValue`] if the underlying JS call fails.
57    ///
58    /// # Examples
59    /// ```no_run
60    /// # use telegram_webapp_sdk::webapp::TelegramWebApp;
61    /// # let app = TelegramWebApp::instance().unwrap();
62    /// app.set_header_color("#ffffff").unwrap();
63    /// ```
64    pub fn set_header_color(&self, color: &str) -> Result<(), JsValue> {
65        self.call1("setHeaderColor", &color.into())
66    }
67
68    /// Call `WebApp.setBackgroundColor(color)`.
69    ///
70    /// # Errors
71    /// Returns [`JsValue`] if the underlying JS call fails.
72    ///
73    /// # Examples
74    /// ```no_run
75    /// # use telegram_webapp_sdk::webapp::TelegramWebApp;
76    /// # let app = TelegramWebApp::instance().unwrap();
77    /// app.set_background_color("#ffffff").unwrap();
78    /// ```
79    pub fn set_background_color(&self, color: &str) -> Result<(), JsValue> {
80        self.call1("setBackgroundColor", &color.into())
81    }
82
83    /// Call `WebApp.setBottomBarColor(color)`.
84    ///
85    /// # Errors
86    /// Returns [`JsValue`] if the underlying JS call fails.
87    ///
88    /// # Examples
89    /// ```no_run
90    /// # use telegram_webapp_sdk::webapp::TelegramWebApp;
91    /// # let app = TelegramWebApp::instance().unwrap();
92    /// app.set_bottom_bar_color("#ffffff").unwrap();
93    /// ```
94    pub fn set_bottom_bar_color(&self, color: &str) -> Result<(), JsValue> {
95        self.call1("setBottomBarColor", &color.into())
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use js_sys::{Object, Reflect};
102    use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
103    use web_sys::window;
104
105    use crate::webapp::TelegramWebApp;
106
107    wasm_bindgen_test_configure!(run_in_browser);
108
109    fn setup_webapp() -> Object {
110        let win = window().expect("window");
111        let telegram = Object::new();
112        let webapp = Object::new();
113        let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
114        let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
115        webapp
116    }
117
118    #[wasm_bindgen_test]
119    #[allow(dead_code, clippy::unused_unit)]
120    fn property_getters_read_string_values() {
121        let webapp = setup_webapp();
122        let _ = Reflect::set(&webapp, &"colorScheme".into(), &"dark".into());
123        let _ = Reflect::set(&webapp, &"headerColor".into(), &"#111111".into());
124        let _ = Reflect::set(&webapp, &"backgroundColor".into(), &"#222222".into());
125        let _ = Reflect::set(&webapp, &"bottomBarColor".into(), &"#333333".into());
126        let _ = Reflect::set(&webapp, &"version".into(), &"9.6".into());
127        let _ = Reflect::set(&webapp, &"platform".into(), &"tdesktop".into());
128
129        let app = TelegramWebApp::instance().expect("instance");
130        assert_eq!(app.color_scheme().as_deref(), Some("dark"));
131        assert_eq!(app.header_color().as_deref(), Some("#111111"));
132        assert_eq!(app.background_color().as_deref(), Some("#222222"));
133        assert_eq!(app.bottom_bar_color().as_deref(), Some("#333333"));
134        assert_eq!(app.raw_version().as_deref(), Some("9.6"));
135        assert_eq!(app.platform().as_deref(), Some("tdesktop"));
136    }
137
138    #[wasm_bindgen_test]
139    #[allow(dead_code, clippy::unused_unit)]
140    fn property_getters_return_none_when_absent() {
141        let _webapp = setup_webapp();
142        let app = TelegramWebApp::instance().expect("instance");
143        assert!(app.color_scheme().is_none());
144        assert!(app.platform().is_none());
145    }
146}