mdgriffith / style-elements-design-discussion

BSD 3-Clause "New" or "Revised" License
8 stars 0 forks source link

Theming #18

Open mdgriffith opened 7 years ago

mdgriffith commented 7 years ago

Theming would be a potentially appealing feature for style-elements. Let's discuss!

lsjroberts commented 7 years ago

These are just some early thoughts, I haven't yet refactored my app to use style-elements but I imagine doing so will drive out some more ideas.


It is pretty straightforward to do some basic theming in an app (https://ellie-app.com/3s92tcg5tp4a1/3). The downside with this is that there is no guarantee that both theme stylesheets implement the same set of classes.


So to provide that guarantee we could add a function to extend stylesheets.

baseStyleSheet : StyleSheet Styles variation
baseStyleSheet =
    Style.stylesheet
        [ style None []
        , style Hello
            [ Font.size 36
            ]
        ]

redTheme : StyleSheet Styles variation
redTheme =
    Style.extendStyleSheet baseStyleSheet
        [ style Hello
            [ Color.background Color.red
            , Color.text Color.white
            ]
        ]

blueTheme : StyleSheet Styles variation
blueTheme =
    Style.extendStyleSheet baseStyles
        [ style Hello
            [ Color.background Color.blue
            , Color.text Color.white
            , Font.size 48
            ]
        ]

The problem with this approach is that extendStyleSheet would need to manually check the classes used, to ensure the extended list of classes did not include any that were not in the base list.

For example:

type Styles = StyleNotInBase | ...

invalidTheme : StyleSheet Styles variation
invalidTheme =
    Style.extendStyleSheet baseStyleSheet
        [ style StyleNotInBase [] ]

Is that a bit of a fudge? It feels a little brittle.


A Set might be more suitable than a List?

mdgriffith commented 7 years ago

Check out the Style.Sheet module (it's probably badly named as it's not that discoverable).

You can do something like:


type MainStyles
    = Button
    | OtherStyles OtherStyles

type OtherStyles
    = Hello
    | Bye

main =
    stylesheet
        [ style Button
            [ Color.background blue
            ]
        , Sheet.merge greetings
        ]

greetings =
    Sheet.map OtherStyles
        [ style Hello
            [ Color.background blue
            ]
        , style Bye
            [ Color.background blue
            ]
        ]

I haven't really played around with this so I'm not 100% that this is the right way to do it, but it's a few toys to play with

One weird thing this requires is if the greetings and main are in separate files, then the type declarations have to be in separate files as well. So it'd be like

   types
   |      \
   v       v
main  <- greetings
lsjroberts commented 7 years ago

Ah excellent. Yeah that certainly gets most of the way there. I'll have a play with that and see how it feels over the weekend. Thanks :)