Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Control themes #2769

Closed
kekekeks opened this issue Jul 24, 2019 · 14 comments
Closed

Control themes #2769

kekekeks opened this issue Jul 24, 2019 · 14 comments
Milestone

Comments

@kekekeks
Copy link
Member

The current styling system isn't really suitable for defining controls themes:

  • we don't have a way to properly specify the default theme
  • we don't have a way to completely re-style a control and prevent the current theme selectors from leaking to such re-styled control

So we need a switchable group of styles that can be associated with a control like Style is associated with one in WPF and basically act like WPF's style.

<Button>
    <Button.ControlTheme>
        <ControlTheme BasedOn="{x:StaticResource SomeBaseButtonTheme}">
             <Setter Property="Background" "Value"="Red"/>
             <Style Selector=":pointerover">
               <Setter Property="Background" "Value"="Green"/>
             </Style>
        </ControlTheme>
    </Button.ControlTheme>

</Button>

Such control theme could be switched and manipulated by selectors in our regular CSS-like styles.

A control would announce its default theme by implementing

interface IHaveDefaultControlTheme
{
       Style GetDefaultControlTheme();
}

which would be generated by the XAML compiler based on x:DefaultControlThemeFor in a XAML file in the same assembly:

<ControlTheme x:DefaultControlThemeFor="{x:Type MyControl}">

</ControlTheme>
@robloo
Copy link
Contributor

robloo commented Sep 12, 2019

I don't see this functionality on the roadmap and I know you are working to finish up 0.9 at the moment. Can it be assumed this would be targeted for 1.0? As you mentioned in #2981 it would speed up porting of controls which would then open up the floodgate of fixes and new controls coming over from WPF.

@kekekeks kekekeks added this to the 0.10 milestone Sep 13, 2019
@handicraftsman
Copy link

Would be nice if used with something like reacts contexts - resource dictionaries are not sufficient because they cannot override parent values iiuc.

@danwalmsley
Copy link
Member

danwalmsley commented May 26, 2020

Some High level requirements:

  • Display Modes
    iOS, Windows 10, OSX operating systems Request Light, Dark and HighContrast modes from the application...

Any theme should be able to express:

Default colours (probably Light)
Dark, and HighContrast

If a theme only expresses 1, (it has to be the default) and thats what avalonia falls back to say when HighContrast is asked for.

  • Overriding Display Mode
    Any Control / Layoutable should be able to say:

Im rendered with Default theme, instead of HighContrast...

This is common for parts of apps that express branding, logos, media, etc

or something way of expressing the same thing.

In UWP they have RequestedTheme property and its an enum with Light / Dark... it seems like UWP is limited to just 2 themes at first... however that is not the case.

because the OS has the concept of Light and Dark that enum expresses that.

A MacOSX theme for UWP is possible, but the theme itself should optionaly define the Default, Dark and High contrast themes

@robloo
Copy link
Contributor

robloo commented Nov 1, 2021

This is an API breaking change as I understand it and in #2239 (comment) it's mentioned 0.11 is going to lock down breaking changes considerably. What happens to this if it doesn't make 0.11? Will it never get implemented?

This is a fundamentally important feature as I see it to the styling system. The current CSS like system is quite powerful but this issue needs to get closed to finish it. (Triggers would be nice too but I suppose behaviors exist for that)

Without this change themes and control styles are more complex than they need to be. We need to wrap each controls default style and template into a single parent container "Style".

@danwalmsley
Copy link
Member

@robloo this will get implemented, breaking changes will cause the major revision number to increase by 1.

btw... 0.11 will never be released... the next major version will be 11.0.0

@grokys
Copy link
Member

grokys commented Nov 1, 2021

Work was started on this a while ago on https://github.com/AvaloniaUI/Avalonia/commits/feature/2769-control-themes - just needs to be finished off.

@sgf
Copy link

sgf commented Dec 10, 2021

In the design of Style, the design of XAML is very bad. It is highly redundant and difficult to read.

I suggest adding support for CSS-3 directly. Use various advanced improvements made to CSS styles in the web(sass,less,scss...) .

@robloo
Copy link
Contributor

robloo commented Dec 10, 2021

I suggest adding support for CSS-3 directly. Use various advanced improvements made to CSS styles in the web(sass,less,scss...) .

GTK eventually went that route too. However, I think you should create a new issue for that.

WPF styling with triggers was pretty intuitive and easy to read. UWP muddied things up a bit for beginners with the VisualStateManager (It also meant hardcoded string states in code-behind which I don't prefer). I'm not a huge fan of pseudoclasses here in Avalonia either but they are more powerful than just triggers on standard properties and work similar in my mind to UWPs VisualStates.

Regardless, XAML styling is fairly straightforward once you get used to it and is far more powerful in Avalonia. The only issue is there is no container for them and you end up with lots of fragments for one control's default style. That is what I hope this issue fixes.

@sgf
Copy link

sgf commented Dec 10, 2021

I suggest adding support for CSS-3 directly. Use various advanced improvements made to CSS styles in the web(sass,less,scss...) .

GTK eventually went that route too. However, I think you should create a new issue for that.

Someone has already raised it, and I have already expressed support in this issue.
#3686

As for which one is better,
the shorter the better,
the smaller the number of typing characters, the better,
and the smaller space in view of the same function, the better.

<Style Selector="TabControl">
    <Setter Property="Background" Value="#F0F0F0"/>
    <Setter Property="Height" Value="120"/>
</Style>
TabControl{
Background:#F0F0F0;
Height:120;
}

@robloo
Copy link
Contributor

robloo commented Dec 10, 2021

I won't argue which one is better. Each has preferences for certain reasons. I will say XAML isn't difficult. This issue is for something different than a full CSS/JSON styling system though.

@maxkatz6
Copy link
Member

@sgf I would suggest to keep css-related discussion in #3686 issue. CSS doesn't even tries to solve problem of this ticket.

@maxkatz6
Copy link
Member

And more about this specific ticket, why it's not trivial to implement right now.
In proposal XAML compiler should wire default theme with controls in the same assembly. But in reality we don't have (and we shouldn't have) one default theme. User should be able to completely drop old or fluent theme and apply their own. So control shouldn't know about any specific theme, but expect one to be applied. So "IHaveDefaultControlTheme" interface isn't practical.

@maxkatz6
Copy link
Member

Stepping back, why we need it at all, is to simplify control restyling.
Easy to imagine situation, where developer included some custom/default theme, which defined many properties and states (pointerover, pressed...) for simple button. But then developer wants to create new independed button style, which will have very special styling. Developer will need to revert all of these styles related to simple button in order to have exactly what they need.

Basically CSS has exactly the same problem for default controls. They have "scoped css" (as we do have scoped styles), but you can't replace these styles with another, without defining new ones on top of old ones (or technically you can remove style include, but...).

@maxkatz6
Copy link
Member

And returning to this proposal, as for me I see something like this as a solution:

Define "default" theme for button:
FluentButton.axaml

<ResourceDictionary>
   <ControlTheme Type="Button" x:Key="FluentButtonStyle">
       <Style Selector="Button">
           <Setter Property="Template" Value=" ... " />
       </Style>
       <Style Selector="Button:pointerover">
           <!-- -->
       </Style>
   </ControlTheme>
</ResourceDictionary>

Apply default theme globally:
FluentThemeDefinitions.axaml

<Styles>
   <Style Selector="Button">
      <Setter Property="ControlTheme" Value="{StaticResource FluentButtonStyle}" />
   </Style>
</Styles>

Develop will be able to completly ignore default theme and implement their own in the same way, OR they can base on it:
MySuperTheme.axaml

<Styles>
   <Style Selector="Button">
      <Setter Property="ControlTheme">
        <ControlTheme Type="Button" BasedOn="{StaticResource FluentButtonStyle}">
          <Setter Property="Height" Value="66" />
        </ControlTheme>
     </Setter>
   </Style>

   <!-- Or create a new one which will not be based on any other theme -->
   <Style Selector="Button.special-button">
      <Setter Property="ControlTheme">
        <ControlTheme Type="Button">
          <Setter Property="Height" Value="22" />
        </ControlTheme>
     </Setter>
   </Style>

   <!-- And old style global styles will work too -->
   <Style Selector="Button">
       <!-- Will be applied to every button  -->
   </Style>
</Styles>

Questions/problems:

  1. We probably have to allow any selector inside of ControlTheme, even unrelated to Button, but potentially related to its content. Can we scope it in this way?
  2. ControlTheme=null must be allowed: avoid breaking changes (there are developers without fluent/default theme) and allow old way styling existed before
  3. Setting ControlTheme inside of a style essentially modifies application styles while they are executing, which possibly can cause undefined behavior (set control theme inside of another control theme which will set it again to the first theme...hello stack overflow).

@AvaloniaUI AvaloniaUI locked and limited conversation to collaborators Dec 10, 2021
@maxkatz6 maxkatz6 converted this issue into discussion #7120 Dec 10, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests

7 participants