tauri icon indicating copy to clipboard operation
tauri copied to clipboard

[feat] Change Window theme dynamically at runtime

Open Kakamotobi opened this issue 2 years ago • 7 comments

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

Kakamotobi avatar Sep 25 '22 06:09 Kakamotobi

did you try https://tauri.app/v1/api/js/window/#theme-2 ?

amrbashir avatar Sep 30 '22 12:09 amrbashir

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?

astudentinearth avatar Sep 30 '22 14:09 astudentinearth

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)

FabianLars avatar Sep 30 '22 14:09 FabianLars

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.

Kakamotobi avatar Oct 07 '22 07:10 Kakamotobi

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'
        }
      }
    }
  })
}

Kakamotobi avatar Oct 07 '22 12:10 Kakamotobi

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 😄

FabianLars avatar Oct 07 '22 12:10 FabianLars

/upstream tauri-apps/tao

FabianLars avatar Oct 07 '22 12:10 FabianLars

Try it: tauri-plugin-theme

wyhaya avatar Sep 29 '23 11:09 wyhaya

@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.

martpie avatar Mar 21 '24 12:03 martpie

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).

FabianLars avatar Mar 21 '24 13:03 FabianLars

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

selastingeorge avatar Mar 23 '24 13:03 selastingeorge