Skip to content

Limited contextual theming#24947

Closed
viridia wants to merge 1 commit into
bevyengine:mainfrom
viridia:theme_context
Closed

Limited contextual theming#24947
viridia wants to merge 1 commit into
bevyengine:mainfrom
viridia:theme_context

Conversation

@viridia

@viridia viridia commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

This introduces a new capability to feathers themes: limited contextual theming. The ThemeContextualBackgroundColor allows multiple color tokens to be specified; one of these tokens will be used to determine the background color depending on what kind of container the widget is in. Container types are identified by a SurfaceTier component.

This allows widgets to have different coloring in different contexts. The system is intentionally limited to a fixed set of choices and is not intended to be a general mechanism such as CSS variables.

This PR doesn't attempt to define all the tokens for different contexts or assign them; that will be left to subsequent work (since other people are currently working on tweaking the color assignments).

@viridia viridia changed the title Contextual theming Limited contextual theming Jul 11, 2026
@gagnus

gagnus commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Probably better not putting this in until the updated theming is in, then we can standardise the language etc.

@viridia

viridia commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Probably better not putting this in until the updated theming is in, then we can standardise the language etc.

Really? I was thinking this would make your task easier, since you would no longer have to compromise on color assignments.

@gagnus

gagnus commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

The trouble is the theming is in the wrong place in the context of the change to a more "slot" based theme I'm trying to get in.

Ie what you've done is introduce extra tokens, ie:

ThemeContextualBackgroundColor {
            default: tokens::TEXT_INPUT_BG,
            level1: tokens::TEXT_INPUT_BG_L1,
            level2: tokens::TEXT_INPUT_BG_L2,
            float: tokens::TEXT_INPUT_BG_FLOAT,
        }

Where in my system its the mapping of token to slot that you'd want to adjust,

(tokens::TEXT_INPUT_BG, Slot::Neutral3)

So if we changed mine to be more contextual (which I still think is a bad idea, hence leaving to a second pass) you'd do it at the token -> slot mapping level based on the "slot" of the underlying container (neutral0-2 though really neutral2 is the only one you'd want to change it for).

@viridia

viridia commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

I don't think you need to change your design at all. The extra layer of indirection I'm adding mostly lives at the widget level, not the theme level - that is, widgets can decide whether or not they are "layer sensitive" and themes (either your theme generator or the current manually-created theme map) works as they always have done. The only downside is the explosion in the number of tokens, but that ship has already sailed (like, I was never keen on feathers sliders having a "pressed" state, but other people wanted it, so...more tokens).

The problem I am attempt to address is this: the alpha hack for doing adaptive backgrounds works fine in dark themes, but I'm not convinced it will work in light themes (I mean, we haven't tried it, but I'm somewhat skeptical due to the non-linear nature of RGB luminance and alpha blending). It also places heavy restrictions on the design of future themes: if, for example, you decided that you wanted dark input fields on light backgrounds and light input fields on dark backgrounds, the alpha hack wouldn't work.

Contextual theming rids us of this limitation: it lets us pick an arbitrary fill color to be used against any background, with no coupling between the two color choices. This gives us significant flexibility, and gets rid of the requirement for alpha colors entirely (for backgrounds, at least).

If this were CSS, we would of course use CSS variables or something like that. A lot of older React-based theming systems use a provider component:

<ThemeProvider theme="side_panel_colors">
   <div>...etc...</div>
</ThemeProvider>

Where the theme colors apply to all descendent widgets in the provider block. This lets you, for example, have a side panel with different color choices than the rest of the page - buttons on the side panel can look different.

However, CSS is, to say the least, controversial; there are a lot of Bevy users who don't like its complexity. Third-party crates which implement CSS-like styling in Bevy haven't gained much traction AFAIK.

Instead, what I've thrown up here is the bare minimum possible contextual coloring, with a fixed set of background choices.

@viridia

viridia commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Note that a different approach would be to allow any theme token assignments to be overridden at the container level; so for example a "group" entity could change the color assigned to TEXT_INPUT_BG. The downside of this is that it means that every color lookup now requires an ancestor search to check if the color has been overridden or not.

@gagnus

gagnus commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

I think your instinct is right that alpha won't work longer term, which is the main thing my theming work is trying to get rid of. I am worried though that we haven't really tried living with the easier solutions to this before jumping to what is going to end up being quite complicated token explosion. Like I think if we get the theming work in and solidify that neutral0-2 are the container backgrounds we'll work out what happens to neutral3-6 (weak fill to strongest "pressed" fill) as a cohesive solution on each of those backgrounds rather than ad hoc per component, but until we get the theming in it's all a bit up in the air and everything is going to end up more complicated to unify later.

@viridia

viridia commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

we haven't really tried living with the easier solutions

I'm not sure what this means, though. As I mentioned on discord, I don't want to be the boss of art, but I do know what I like, and part of the reason why my skills as a UI developer are sought after (or were, before I retired) is that I am very exacting when it comes to details about specific colors and shades. I quite like Rin's figma designs, it has the right balance of legibility and subtlety for my taste. While I'm not opposed to the idea of alternative designs, I would prefer that changes to the design be driven by purely aesthetic considerations, and not by technical limitations on our side.

@alice-i-cecile alice-i-cecile added the A-UI Graphical user interfaces, styles, layouts, and widgets label Jul 12, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in UI Jul 12, 2026
@alice-i-cecile alice-i-cecile added C-Feature A new feature, making something new possible X-Contentious There are nontrivial implications that should be thought through S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jul 12, 2026
@viridia viridia closed this Jul 13, 2026
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in UI Jul 13, 2026
@viridia

viridia commented Jul 13, 2026

Copy link
Copy Markdown
Contributor Author

Superceded by #24969

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

Labels

A-UI Graphical user interfaces, styles, layouts, and widgets C-Feature A new feature, making something new possible S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Contentious There are nontrivial implications that should be thought through

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants