tauri
tauri copied to clipboard
[feat] Change Window theme dynamically at runtime
Describe the problem
As far as I can tell from the docs, concerning the theme of the window, there are JS APIs for only (1) getting the window's current theme, and (2) listening to the system theme change.
I'm trying to set the window's theme to "dark"/"light" as well when the user chooses the "dark"/"light" theme in my app.
Is there a way to dynamically change the theme of the window through JavaScript?
Describe the solution you'd like
A JS API to change the theme of the window.
Alternatives considered
No response
Additional context
No response
did you try https://tauri.app/v1/api/js/window/#theme-2 ?
You can give the user 3 choices for theme. Dark, light, or follow system theme - just like a lot of other apps do. If the user decides not to follow the system theme you can use whichever one the user chooses. Do you have a hard dependency on the window theme itself?
Is there a way to dynamically change the theme of the window through JavaScript?
Currently only when creating the window like
const webview = new WebviewWindow('uniqueLabel', {
url: 'path/to/page.html',
theme: "dark"
});
(same api avail in rust and tauri.conf.json)
did you try https://tauri.app/v1/api/js/window/#theme-2 ?
I'm looking for a dynamic solution in JS and not the initial configuration.
You can give the user 3 choices for theme. Dark, light, or follow system theme - just like a lot of other apps do. If the user decides not to follow the system theme you can use whichever one the user chooses. Do you have a hard dependency on the window theme itself?
For now, all I want is a toggle button where the user can choose either light or dark mode. The problem is, the app window (top bar) always remains the same (light). I was wondering if it was possible to simply apply the theme change for the window something like: windowTheme = windowTheme === "light" ? "dark" : "light"
in JS.
Currently only when creating the window like
const webview = new WebviewWindow('uniqueLabel', { url: 'path/to/page.html', theme: "dark" });
(same api avail in rust and tauri.conf.json)
Thanks for the tip.
I think an API like this in the WindowManager class would be convenient. Is it plausible?
type Theme = 'light' | 'dark';
async setTheme(theme: Theme): Promise<void> {
return invokeTauriCommand({
__tauriModule: 'Window',
message: {
cmd: 'manage',
data: {
label: this.label,
cmd: {
type: 'setTheme',
payload: theme
}
}
}
})
}
import { appWindow } from '@tauri-apps/api/window';
await appWindow.setTheme("dark");
And perhaps the theme()
getter can be renamed to getTheme()
as such:
async getTheme(): Promise<Theme | null> {
return invokeTauriCommand({
__tauriModule: 'Window',
message: {
cmd: 'manage',
data: {
label: this.label,
cmd: {
type: 'getTheme'
}
}
}
})
}
Is it plausible?
As long as all or some of the platforms support changing the theme at runtime, yes! But i think this needs changes in Tao, so i'm going to upstream this issue and see if Amr screams at me 😄
/upstream tauri-apps/tao
Try it: tauri-plugin-theme
@FabianLars Would you be open for any kind of contribution here? I am working on https://github.com/martpie/museeks/pull/759, and I would like to achieve a behavior close to Electron's nativeTheme
(behavior, not necessarily API).
I would really like that issue (and others, related to getting system theme preference manually) to be solved for Tauri 2.0 main release. This issue is just one thing to be solved to have dynamic theme support (system theme + possible override from a Tauri app user config).
Would you be open to an RFC explaining the needed changes? or PRs? I would be happy to contribute code, but getting the behavior right is critical, and this is likely to be a breaking change in behavior, so maybe discussing and documenting the weird edgecases first would be better.
We're always open for contributions!
to be solved for Tauri 2.0 main release
Probably too late for that.
Would you be open to an RFC explaining the needed changes? or PRs?
Sure, we even have a rfc repo https://github.com/tauri-apps/rfcs which sadly never got the attention it deserved. If there's not that much to talk about (i honestly don't know, i thought we just need a setTheme method and can call it a day lol) then a normal issue is fine too imo.
and this is likely to be a breaking change in behavior
I don't see where it'd be breaking (at least where it doesn't count as a bugfix).
In Windows, I use the following method:
use windows_sys::Win32::Graphics::Dwm::*;
use windows_sys::Win32::Foundation::*;
use tauri::{Theme,WebviewWindow};
pub fn set_window_theme(window:&WebviewWindow,theme:Theme) {
unsafe {
let handle = window.hwnd().unwrap().0;
let value: BOOL = if theme == Theme::Dark {1} else {0};
let attribute = DWMWA_USE_IMMERSIVE_DARK_MODE;
DwmSetWindowAttribute(handle, attribute as u32, &value as *const _ as *const _, std::mem::size_of::<BOOL>() as u32);
}
}
checkout this demo for more : Tauri Theme Demo