Uno.Themes
Uno.Themes copied to clipboard
Lightweight Styling
Instead of having to override the ControlTemplate of any given Material/Cupertino style we should allow for Lightweight Styling
All styles should be refactored to reference resource keys that follow an accepted standard naming scheme.
Proposed naming convention: {design}{?:style-variant}{control-name}{member}{?:visual-state}
Name Part | Description |
---|---|
design |
A prefix for the design system (Material, Cupertino, etc.) |
style-variant |
(Optional) Certain styles have multiple variants. Ex: For Button we have style variants such as: Outlined, Text, Filled |
control-name |
Name of the control type (Button, TextBox, CheckBox, etc.) |
member |
The property that this style should be assigned to (Foreground, Background, BorderBrush, etc.) |
visual-state |
(Optional) Specifies which VisualState that this resource will be applied to (PointerOver, Checked, Disabled, etc.) |
the proposed naming convention is expanded from the current style naming convention: {design}{?:style-variant}{control-name}Style {design}{?:style-variant}{control-name}{member}{?:visual-state}
eg: MaterialFilledButtonStyle MaterialFilledButtonBackground MaterialFilledButtonBackgroundPressed
note: most styles are also aliased with a new key without the {design} prefix, so "MaterialFilledButtonStyle" can also referenced with "FilledButtonStyle" key.
Something to consider here, overriding these resources is going to be tricky. If my Button Style is referencing MaterialFilledButtonBackground, and I override MaterialFilledButtonBackground within my App.xaml, the aliased FilledButtonBackground resource will continue to resolve to the original value of MaterialFilledButtonBackground and not the overridden value. The same issue applies in the other direction. If I were to override FilledButtonBrush in my App.xaml, the MaterialFilledButtonBrush will not resolve to the new overridden value, only usages of the shared key, FilledButtonBrush, are affected by the override.
Right now, the Material styles contain a mishmash of resource references using both the Material specific keys but also the aliased "shared" keys.
<Setter Property="Foreground"
Value="{StaticResource PrimaryBrush}" />
<Setter Property="BorderThickness"
Value="{StaticResource MaterialOutlinedButtonBorderThickness}" />
<Setter Property="BorderBrush"
Value="{StaticResource MaterialOutlinedButtonBorderBrush}" />
We need to figure out how we should be dealing with overrides. Should all Material styles only reference Material-specific resource keys? So, we'd use MaterialPrimaryBrush, MaterialOutlinedButtonBorderThickness, etc. In that case, we would provide aliases for these resources, but you would need to specifically override the resources using the Material prefix in order for the included styles to adapt properly. Overriding MaterialPrimaryBrush from Purple to Red will be reflected in the styles but any place that is directly referencing the aliased shared key of PrimaryBrush will still show Purple.
Otherwise, we get rid of the Material/Cupertino prefixes for resources, remove all the aliases, and they just get redefined in the Uno.Cupertino and Uno.Material libraries. There will have to be some special cases for resources that may be specific to one design system. In this case, we can reference PrimaryBrush, OutlinedButtonBorderThickness , etc. and those keys would also be the ones to override.
I feel like maintaining the design system prefixes are kind of pointless. Unless there are some resources that exist in only one design-system, then those can be specially documented usages with the Material/Cupertino prefix.
Problem with getting rid of the prefix is that it'll be a big breaking change for anyone that is currently using the Material prefixed keys. For the most part, people would most probably be using the shared aliases, but I'm assuming this'd need to be introduced as a new major version.
@francoistanguay @Xiaoy312 @jeromelaban thoughts? @carldebilly this will for sure affect figma as well
Assuming current users don't override styles using Material-prefixed resources (which currently does not work with Uno), we could invert their definitions for the generic ones to be the original styles and the material prefixed ones to be the aliases.
We may also need to consider the scenario about the resolution in the gallery app, which contains both definitions simultaneously (if included at the app.xaml level), but may still resolve properly when using material-prefixed styles.
Yeah I've already inverted the font resources in my branch:
TypographyOverrides.xaml (should be called aliases, not overrides)
For the actual Styles themselves I don't think this is going to be an issue, it's more for the resources that the styles reference. Like for the Typography changes in the above links, I changed all usages of those resources within the styles to the non-prefixed/non-aliased ones.
So either,
- Generic resource keys are the original definition and the styles reference the generic keys directly. So then overriding FilledButtonBackground will be reflected in the FilledButtonStyle. Or,
- The styles reference only the aliased/prefixed resources and you would then need to specify the design system prefix when overriding. So in order for FilledButtonStyle to reflect the Background override, it needs to reference MaterialFilledButtonBackground
My feeling is people should not use prefixed resource keys within the app, same way they should be using the non-prefixed style keys. Only thing that messes things up are apps like Gallery where you need a way to directly reference the proper design system resources.
FYI for the issue of resource aliases not reflecting the overridden values, it seems that this is a known issue and pain point: https://github.com/microsoft/microsoft-ui-xaml/issues/2913
Looking back on this, we should be going with the original design and allowing lightweight styling at a per-control level. Where we would be able to override something like a Brush in the Material style for NavigationViewItem called MaterialNavigationViewItemBackgroundSelected
, rather than needing to locally override the PrimarySelectedBrush
that this alias would be referencing.
Proposal updated and copied to the original post:
Proposed naming convention: {design}{?:style-variant}{control-name}{member}{?:visual-state}
Name Part | Description |
---|---|
design |
A prefix for the design system (Material, Cupertino, etc.) |
style-variant |
(Optional) Certain styles have multiple variants. Ex: For Button we have style variants such as: Outlined, Text, Filled |
control-name |
Name of the control type (Button, TextBox, CheckBox, etc.) |
member |
The property that this style should be assigned to (Foreground, Background, BorderBrush, etc.) |
visual-state |
(Optional) Specifies which VisualState that this resource will be applied to (PointerOver, Checked, Disabled, etc.) |
Closing this epic issue as the only left is https://github.com/unoplatform/Uno.Themes/issues/1063 which is already in progress