slint-ui / slint

Slint is a declarative GUI toolkit to build native user interfaces for Rust, C++, or JavaScript apps.
https://slint.dev
Other
17.53k stars 600 forks source link

Make styling.slint resources accessable #3687

Open FloVanGH opened 1 year ago

FloVanGH commented 1 year ago

For each style (expect qt) we have a styling.slint file with all styling resources that are relevant for the specific style such as brushes and typography. That works well internal for our std-widgets but it's difficult at the moment to create a custom that is consistent with that style or to create a custom style that is based of on that style. What you can do at the moment is to copy paste the styling.sling file in your custom widget library or you have to create your own based on the corresponding design guidelines.

But we could make it easier, if we make the resources of styling.slint accessible per style through a public api.

Example

import { Palette, Typography } from "cupertino-style.slint";

export component MyFancyCupertinoWidget {
      in property <string> text <=> i-text.text;

      Rectangle {
            background: Palette.accent;

            i-text := Text {
                 font-size: Typography.body.font-size;
            }
      }
}
import { Palette, Typography } from "fluent-style.slint";

export component MyFancyCupertinoWidget {
      in property <string> text <=> i-text.text;

      Rectangle {
            background: Palette.accent;

            i-text := Text {
                 font-size: Typography.body.font-size;
            }
      }
}
ogoffart commented 1 year ago

Ideally we should find a way to expose the color palette (see also https://github.com/slint-ui/slint/issues/116 )

Currently, some variable are accessible through the StyleMetrics, but it's undocumented. So yes, we should do something about this.

FloVanGH commented 1 year ago

I think all resources of a style should be provided not only the Palette, because if you want to create a custom widget you want to get access also to stuff like typography settings. I think from user perspective a api similar to my examples would be great. So you can access the resources of a specific style. So you would be able to create a custom widget library that supports also different styles like fluent, cupertino and material and not only one.

ogoffart commented 1 year ago

Yes, of course, it is more than just the Palette. So what we need to do is to find a good interface and export all of that (palette, metrics, typography, ...)

And I don't think we want user to write MyFancyCupertinoWidget but just MyFancyWidget and it should work with all styles.

import { Palette } from "std-widgets.slint";

export component MyFancyWidget {
      Rectangle {
            background: Palette.accent;
      }
}
FloVanGH commented 1 year ago

And I don't think we want user to write MyFancyCupertinoWidget but just MyFancyWidget and it should work with all styles.

It can make sense, because depending on design guidelines you maybe forced to provide different variants per style, because there are to different in look and feel.

An import like this could be difficult:

import { Palette } from "std-widgets.slint";

export component MyFancyWidget {
      Rectangle {
            background: Palette.accent;
      }
}
  1. The Palette, and Typography, .. have different fields per style
  2. You would not be able to create a dedicated variant per style
  3. The use should be able to use specific resource e.g. the specific Palette from cupertino
ogoffart commented 1 year ago

The Palette, and Typography, .. have different fields per style

Yes, our job here is to find a good set of roles for both palette and typography that are common to all styles.

You would not be able to create a dedicated variant per style The use should be able to use specific resource e.g. the specific Palette from cupertino

I agree it also make sense to expose style-specific widgets or globals.. But i feel like a interface common to all styles is more important to get right.


So in other words, i think it is really important to expose the palette and the font in a way common to all style because you can't do cross platform apps without that. (and i think this is what https://github.com/slint-ui/slint/discussions/3685 asks for )

But I also understand the need to have platform-specific (style-specific) things exposed. These are two different things.

FloVanGH commented 1 year ago

Ok then we have two different use cases here.

  1. I want to create custom widgets (maybe cross platform, supports all styles) that doesn't looks foreign to the current style.
import { StyleMetrics } from "std-widgets.slint; 

export component MyFancyWidget {
      in property <string> text <=> i-text.text;

      Rectangle {
            background: StyleMetrics.accent;

            i-text := Text {
                 font-size: StyleMetrics.default-font-size;
            }
      }
}
  1. I want to create custom widgets that are as close as possible to the corresponding design guidelines:
import { Palette, Typography } from "cupertino-style.slint";

export component MyFancyCupertinoWidget {
      in property <string> text <=> i-text.text;

      Rectangle {
            background: Palette.accent;

            i-text := Text {
                 font-size: Typography.body.font-size;
            }
      }
}
import { Palette, Typography } from "fluent-style.slint";

export component MyFancyCupertinoWidget {
      in property <string> text <=> i-text.text;

      Rectangle {
            background: Palette.accent;

            i-text := Text {
                 font-size: Typography.body.font-size;
            }
      }
}

For the second you case wee will need different imports per style, because the globals like Palette of the styles do not necessarily have all the same fields.

ogoffart commented 1 year ago

want to create custom widgets (maybe cross platform, supports all styles) that doesn't looks foreign to the current style

Yes, and not just custom widget, but interface in general. And the point is that the current StyleMetrics API is not documented and also not great. Palette would be a better name for it. (And if that means renaming the current internal palette to CupertinoPalette or StylePalette, so be it)

FloVanGH commented 1 year ago

Proposal

The following solution could be implemented with little effort and would fulfill the requirements of both use cases. The use case to implement custom controls that works with the all styles, what means providing a generic access to the styling resources like brushes but everything that can be generalized between all styles. And the second solution where a user want to create a custom widget that is close as possible to the corresponding design guidelines, what means to give the user access to the complete resources of the corresponding style.

ColorScheme

ColorScheme would be an enum to define the current color scheme e.g. dark and light. It would be replaces the dark-color-scheme bool property. With an enum more color schemes should be extended in the future like high-contrast-theme.

Example

export enum ColorScheme {
    Dark,
    Light,
    // Can be expended in the future e.g. with HighContrast
}

{StyleName}Palette

Each style would provide its own palette like FluentPalette, MaterialPalette and CupertinoPalette. Theses palettes would contain each all brushes of the corresponding style, also the brushes that are unique to the style. All theses palettes should be accessible through the std-widgets.slint import. So the user would be able to create libraries with custom widgets for all styles.

Example

export global CupertinoPalette {
    out property <brush> background;
    out property <brush> accent;
    out property <brush> accent-secondary;
    out property <brush> foreground;
    out property <brush> border;
    out property <brush> surface;
    out property <brush> on-surfe;
    out property <brush> selection;
    out property <brush> focus;

    in-out property <ColorScheme> color-scheme;
}

{StyleName}Typography

Same as {StyleName}Palette but with the typography settings of the styles like font sizes and weights.

Palette

Palette would be a global with all generic brushes that can be provided by all styles like window background. It would be provided by each style with its own settings.

Example

export global Palette {
    out property <brush> background  CupertinoPalette.background;
    out property <brush> accent: CupertinoPalette.accent;
    out property <brush> foreground: CupertinoPalette.foreground;
    out property <brush> border: CupertinoPalette.border;
    out property <brush> surface: CupertinoPalette.surface;
    out property <brush> on-surface: CupertinoPalette.on-surface;
    out property <brush> selection: CupertinoPalette.selection ;
    out property <brush> focus: CupertinoPalette.focus;

    in-out property <ColorScheme> color-scheme <=> CupertinoPalette.color-scheme;
}

Typography

Same as Palette but with the typography settings of the styles like font sizes and weights.

StyleMetrics

StyleMetrics would be replaced by Palette and Typography.

Usage example

import { Palette, Typography } from "std-widgets.slint";

export component MyFancyWidget {
    in property <string> text <=> i-text.text;
    Rectangle {
        background: Palette.surface;

        i-text := Text {
             color: Palette.on-surface;
             font-size: Typography.default.font-size;
        }
    }
}
import { CupertinoPalette, CupertinoTypography, FluentPalette, FluentTypography } from "std-widgets.slint";

export component MyFancyFluentWidget {
    in property <string> text <=> i-text.text;
    Rectangle {
        background: FluentPalette.surface;

        i-text := Text {
             color: FluentPalette.on-surface;
             font-size: FluentTypography.default.font-size;
        }
    }
}

export component MyFancyCupertinoWidget {
    in property <string> text <=> i-text.text;
    Rectangle {
        background: CupertinoPalette.surface;

        i-text := Text {
             color: CupertinoPalette.on-surface;
             font-size: CupertinoTypography.default.font-size;
        }
    }
}

Last words

Later more resources could be provided like spaces, radius, animation settings, ...

tronical commented 1 year ago

All theses palettes should be accessible through the std-widgets.slint import.

Does that mean that regardless of the currently selected style, I can always import { CupertinoPalette } from "std-widgets.slint" ? (I think it makes sense, just want to make sure I understand correctly)

Regarding the names: I think Palette is a good name, in real life it resembles an actual object. Typography however is not an object, it's a style/technique. How about TypeSettings, FontSettings, TypographySettings?

That aside, I'm very much in favor of this approach (and its incremental nature).

ogoffart commented 1 year ago

Thanks a lot for the concreate proposal. IMHO, Cupertino... should not be available from std-widgets.slint

We could offer them from cupertino.slint and fluent.slint. In fact now that we have (soon) the concept of library, we could reserver the @std name and rename our std-widgets to @std/widgets.slint, and have @std/fluent.slint and so on. So you could do

import { FluentButton, FluentPalette } from "@std/fluent.slint";
// You get a fluent looking Button regardless what is the configured style.

// Alternativelyn it could be named without the Fluent prefix (which could be added with `as Fluent ...` if needed
import { Button, Palette as FluentPalette } from "@std/fluent.slint";

But anyway, we have here two different issues.

And I think we all agree we need a Palette and a FontSettings (name to be bikeshed) But the roles in the palette needs to be extended. We need to cover most of the roles that other toolkit export, see list in https://github.com/slint-ui/slint/issues/116 And we of course need what was previously in the StyleMetrics.

One thing is that Qt allow for different palette for enabled and disabled widgets, and for active and inactive window.

For example, we need to have color roles for text selection (background and foreground), and maybe some extra background for button, listview, lineedit and co.

FloVanGH commented 1 year ago

All theses palettes should be accessible through the std-widgets.slint import.

Does that mean that regardless of the currently selected style, I can always import { CupertinoPalette } from "std-widgets.slint" ? (I think it makes sense, just want to make sure I understand correctly)

Yes that was my intention. I used this way because it would already work without providing more import paths. But I saw @ogoffart has also a suggestion.

Regarding the names: I think Palette is a good name, in real life it resembles an actual object. Typography however is not an object, it's a style/technique. How about TypeSettings, FontSettings, TypographySettings?

That aside, I'm very much in favor of this approach (and its incremental nature).

I have started with Typography because we used that name for that stuff in my previous job in WPF 😄. But I'm open for alternatives. I think FontSettings is the most memorable for the users because of font-size, font-weight.

FloVanGH commented 1 year ago

Thanks a lot for the concreate proposal. IMHO, Cupertino... should not be available from std-widgets.slint

We could offer them from cupertino.slint and fluent.slint. In fact now that we have (soon) the concept of library, we could reserver the @std name and rename our std-widgets to @std/widgets.slint, and have @std/fluent.slint and so on. So you could do

This way also my first idea to do it with separate imports. I choose the std-widgets way in my proposal because it would work now. But yeah we should provide with dedicated imports. That would make it later also possible to provide more stuff that is specific to a style, maybe a widget that is only available in a specific style. I think the important part is that a user has always the possibility to access that stuff of all styles, so he can also create custom widget libraries that providing widgets that are specific for all styles. So maybe someone wants to create widgets that looks native to macOS and Windows. But with that imports it would be the case 🙂. I like the idea with @std. Makes it clear and also a user can see that everything that is in std is provided from Slint itself. Would we continue to provide the std-widgets.slint import? Otherwise we need to wait for 2.0 because this would be a really important breaking change. Could we deprecated the old import and remove it with 2.0?

import { FluentButton, FluentPalette } from "@std/fluent.slint";
// You get a fluent looking Button regardless what is the configured style.

// Alternativelyn it could be named without the Fluent prefix (which could be added with `as Fluent ...` if needed
import { Button, Palette as FluentPalette } from "@std/fluent.slint";

But anyway, we have here two different issues.

And I think we all agree we need a Palette and a FontSettings (name to be bikeshed) But the roles in the palette needs to be extended. We need to cover most of the roles that other toolkit export, see list in #116 And we of course need what was previously in the StyleMetrics.

One thing is that Qt allow for different palette for enabled and disabled widgets, and for active and inactive window.

For example, we need to have color roles for text selection (background and foreground), and maybe some extra background for button, listview, lineedit and co.

Yes it really an important topic. And I think we need to provide in Palette as much as possible that can be shared for all styles. I think first step would be to align the property names of the {StyleName}Palettes and using same name patterns also for FontSettings. And then reference all that resources e.g. in Palette that can shared with the same use e.g. the window background color, common foreground color, base accent color, ...

FloVanGH commented 1 year ago

I'm also want to take care of that topic and do an proposal PR with all the stuff to which we agree. As soon there is the time to start with that topic ;-). I think it will be really useful.

therasuldev commented 9 months ago

Hi, can we change color of specific word in sentence ??

tronical commented 9 months ago

That's not supported at the moment. We're tracking this in #2723