Skip to content

Theme plugin system#8153

Draft
AdrienZianne wants to merge 83 commits into
emilk:mainfrom
AdrienZianne:theme_plugin
Draft

Theme plugin system#8153
AdrienZianne wants to merge 83 commits into
emilk:mainfrom
AdrienZianne:theme_plugin

Conversation

@AdrienZianne

@AdrienZianne AdrienZianne commented May 12, 2026

Copy link
Copy Markdown
Contributor

What it does

Addition of a new system of theme plugins which allow the user to use different rules engine to compute the style for the available specialised widget style.

How to use

Create a engine implementing the trait ThemePlugin and ThemeStyle<S: StyleStruct> and implement the necessary methods, then register this way (example for ButtonStyle):
ui.add_theme::<ButtonStyle>(&mycustomengine);

Now all button will call the ThemeStyle<ButtonStyle> method to compute the correct style and later use the cached value to avoid the costly computation.

If no valid ThemeStyle<S> or engine is available then it fallback to the default style.

@github-actions

github-actions Bot commented May 12, 2026

Copy link
Copy Markdown

Preview available at https://egui-pr-preview.github.io/pr/8153-themeplugin
Note that it might take a couple seconds for the update to show up after the preview_build workflow has completed.

View snapshot changes at kitdiff

@lucasmerlin lucasmerlin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's trying to do a bit too much at once for now. We should try to start with a super minimal api.

The way it's set up with the single ThemePlugin that can be active at a time breaks extensibility. Say someone makes a EguiMaterial theme crate, and someone else makes a EguiSwitch component crate, and you want to use both in your project.

The way it's now, one would have to make a whole new ThemePlugin struct that wraps the EguiMaterialThemePlugin and adds support for the EguiSwitchStyle (since the rust orphan rules would prevent you from adding something like:
impl ThemeStyle<EguiSwitchStyle> for MeterialThemePlugin {.

So I would suggest we simplify the registration api to instead be per widget type. You could still have a single struct that impls the styles of all the different widget kinds, but they should be added indivudually. (Of course any theme plugin could offer a helper fn that registers them all).
Something like this:

let theme = EguiMaterialTheme::new();
let switch_theme = EguiSwitchTheme::new();
ctx.add_theme::<ButtonStyle>(theme);
ctx.add_theme::<SwitchStyle>(switch_theme);

Both of these would be active at the same time, and there can only ever be a single registered theme per type.

Theme switching could still be implemented either by reregistering the different style types with different configs or by something internal to the theme plugin.

Caching could be reduced to some CachingThemePlugin that wraps some other plugin, so if someone doesn't want / need caching they could skip it.

Comment thread crates/egui/src/context.rs Outdated
Comment on lines +1998 to +2001
/// Change the current theme used by the system to compute the style
pub fn switch_theme(&self, theme_id: &impl ToString) {
self.write(|ctx| ctx.theme.set_current_theme(theme_id));
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a seperate api for this or could this be handled via classes? E.g. a dark_mode class on the root Ui to set the theme to dark mode. (Could even allow changing the theme within a part of the ui, by setting a different theme class there).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caching could be reduced to some CachingThemePlugin that wraps some other plugin, so if someone doesn't want / need caching they could skip it.

Why not use a flag in the ThemePlugin implementation ? That way if we don't find it in the cache, we compute the style and store it only if it's wanted.

Do we need a separate api for this or could this be handled via classes? E.g. a dark_mode class on the root Ui to set the theme to dark mode.

This is an idea, but we need to differentiate "theme" classes from regular classes. I also think that if many people design and share their own themes, their gonna need to share the same keyword like root and selected. Maybe I should create an enum with these keywords and one that take a Classname as a value.

Otherwise the change in how the theme are registered already allow to switch the theme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants