Skip to content

Theme API 2

Andy Williams edited this page Apr 2, 2024 · 5 revisions

Note

This document is archived as it refers to a design process.

We want to support adding items to app themes without breaking API compatibility. Also to allow people to easily load variations on the standard theme, such as setting primary colour etc.

Current

The current theme consists of a fyne.Theme interface that any theme must implement, and the theme package which has many functions that mirror these features for accessing the current theme.

Future

My proposal is that we completely change the theme interface and push developers to utilise the theme package functions in their app. A new theme API would be "future proof" by using extensible lookups instead of simple methods that return single values. For example:

type Variant uint
type ColorName string
type SizeName string

const (
    DarkTheme Variant = iota
    LightTheme
// potential for adding theme types such as high visibility or monochrome...

    BackgroundColor ColorName = "background"
    TextColor       ColorName = "text"
// etc etc

    PaddingSize SizeName = "padding"
    TextSize    SizeName = "text"
)

type Theme interface {
    Color(ColorName, Variant) color.Color
    Size(SizeName) int
    Font(TextStyle) fyne.Resource
}

An approach like this would allow us to use something like a JSON store or other mapping to store the values. A loaded theme could provide all the values, or delegate to a builtin fallback. Certain APIs such as "ThemeFromJSON" would load from a JSON string or "ThemeFromTheme" could create a new theme in code that overloads the values from the default theme...

Benefits

By taking this approach we can

  • Import themes from Material Design generation app
  • Easily communicate theme details outside of the Go code
  • Support adding new features in the future - the package will add APIs and the lookups will add new values (all of which are API compatible and would default to sensible values if missed)

Drawbacks

This is of course a massive change. All apps that currently provide a custom theme will fail to compile. As SetTheme(Theme) is part of the main App API this probably needs to be a breaking change. To ease the transition we could rename the current Theme interface to OldTheme or similar, and provide a helper to convert, such as theme.OldThemeAdapter(OldTheme) Theme which will do the reverse lookups to avoid developers having to completely re-implement their code.

Other thoughts

As pointed out in @jkvatne work we need to figure out how to add shading and other features so buttons can have clearly differentiated states whether default/high importance etc.