slint icon indicating copy to clipboard operation
slint copied to clipboard

Color Palette

Open ogoffart opened this issue 3 years ago • 11 comments

The idea would be to have a Palette singleton in the style, similar to the StyleMetrics one.

The palette would have property for each interresting color.

Idea for picking the different color roles:

  • Material style: https://material.io/design/color/the-color-system.html#color-theme-creation
  • QPalette: https://doc.qt.io/qt-5/qpalette.html#ColorRole-enum
  • UIKit: https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors
  • MS Windows: https://docs.microsoft.com/en-us/dotnet/api/system.windows.systemcolors?view=net-5.0

ogoffart avatar Nov 25 '20 09:11 ogoffart

tronical avatar Nov 25 '20 12:11 tronical

  • KDE: https://api.kde.org/frameworks/kconfigwidgets/html/classKColorScheme.html
  • GTK: https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-22/gtk/theme/Adwaita/_colors-public.scss

Another point: do we want to add api such as color.darker() color.lighter() ?

ogoffart avatar Nov 25 '20 12:11 ogoffart

You already have impl InterpolatedPropertyValue for Color for animating colors. If you could expose that as color.mix(another-color, weight) as Sass does, it would even use the same RGB colorspace Sass uses.

With that function in place, you could drastically reduce the number of colors in the Palette and calculate the rest of them, making the theming easier for the end-users.

I think that's a very good idea. The CSS color-mix() function takes that a step further by adding a color space parameter. API wise that might be even better for future support for different color spaces. What do you think?

tronical avatar Dec 21 '21 12:12 tronical

Although more color spaces give more flexibility to a designer, personally I would not miss them. If this color.mix function would be shipped earlier, and Sass users do not miss them, I would postpone their introduction.

At the moment the HSL space used for color.brighten and color.darken are not accessible to the .60 language either, nor the red, green, blue and alpha components of the internal representation, so in the far future I would rather have a consistent way of introducing color spaces all around the language (gradients, animations, constructing from color components, extracting color components).

Coming from #1315 I'm wondering if the palette should perhaps be a model instead of a struct, and the rows are roles.

If the palette was a struct and we'd have a per-widget palette, then that's a substantial amount of bytes spent for each widget when in most cases it would be copied from the global palette.

If the palette were a model, then it would be basically a smart pointer that defaults pointing to the global palette but can be overridden by the user.

tronical avatar Jun 07 '22 08:06 tronical

Yes! And switching themes (dark mode - light mode - accessible mode) could also be implemented by just replacing the global palette. And as I mentioned, in many color schemes, intermediate tones are used by mixing base colors together.

That could be done either on the palette by defining role colors mixed from base colors, or on the widget itself.

Having the palette being of type [Color] is not a bad idea, and then we can have constants in some namespace for the indices.

But another possibility would be to just have special compiler support for this. So not every element would have a palette at runtime. in the implementation widget, one would simply do

FooWidget := Rectangle { 
   background: Colors.button-background;  
}

And when using it we can override some of the palette with

FooWidget {
    palette: { button-background: red;    }  // the other color are "inherited"
}

Where palette is a builtin property.

ogoffart avatar Jun 07 '22 11:06 ogoffart

Ahh, interesting idea - this combines after all. We could use a model in the implementation but hide it behind the syntax you're proposing. Let me see if I understood correctly:

  1. If an element uses Colors.XXX in a binding, then this is translated to resolve to a newly materialised palette property.
  2. The newly materialised palette property is publicly visible
  3. A binding to the palette property with object assignment results in a binding that inherits unset values from the global palette.

tronical avatar Jun 07 '22 11:06 tronical

Where is this "button-background" defined? What happens when I mistype that as "butn-background" somewhere? Is that recognized as an error or will that silently add a new color to the palette?

hunger avatar Jun 20 '22 07:06 hunger

It would be defined in the compiler and typo would be detected

ogoffart avatar Jun 20 '22 11:06 ogoffart

Might we get an additional choice as an interim solution? A grey color scheme with high contrast text and widget outlines would be sufficient until custom colors are implemented.

ghost avatar Apr 14 '23 18:04 ghost

MVP merged in https://github.com/slint-ui/slint/pull/3984

ogoffart avatar Jan 15 '24 18:01 ogoffart