Change colour scheme in code (for M3 template)

Making a FR from a question asked in this post (I know @brooke said they’d add it to the list, but always good to have a proper FR :slight_smile: ) :

I want my clients to be able to choose light/dark.

edit why does the preview of my post show a snippet of the linked post but my submitted post only show a link?

edit 2 oooo just to make a liar of me, it changed! It definitely did not show the excerpt originally. I’m not going mad, beep beep!

3 Likes

I am adding my “upvote” to this, as it would be a very easy way to add a “Dark Mode”-setting to an app.

It seems to possible at the moment, by doing some fancy CSS stuff with variables, and what-not, but a simple way of calling something like anvil.set_colour_scheme("Material Dark") would be nice!

2 Likes

@EsbenLorenzen the current way to do this doesn’t need to involve fancy css, instead you might take the Material Light and Material Dark theme color schemes.
Open the app in one color scheme, log the output of app.theme_colors and repeat with the other color scheme.

>>> app.theme_colors
ThemeColors({'Secondary Container': '#E8DEF8', 'Tertiary Container': '#FFD8E4', 'On Background': '#1C1B1F', 'Disabled Container': 'rgba(28, 27, 31, 0.12)', 'On Tertiary': '#FFFFFF', 'Outline': '#79747E', 'On Primary Container': '#21005E', 'Dark Overlay 2': 'rgba(30, 25, 43, 0.12)', 'On Secondary': '#FFFFFF', 'On Secondary Container': '#1E192B', 'Primary Container': '#EADDFF', 'Secondary': '#625B71', 'On Surface Variant': '#49454E', 'Surface Variant': '#E7E0EC', 'Light Overlay 1': 'rgba(255, 255, 255, 0.08)', 'Tertiary': '#7D5260', 'Light Overlay 2': 'rgba(255, 255, 255, 0.12)', 'Primary Overlay 2': 'rgba(103, 80, 164, 0.08)', 'Primary': '#6750A4', 'On Tertiary Container': '#370B1E', 'Primary Overlay 3': 'rgba(103, 80, 164, 0.11)', 'Primary Overlay 1': 'rgba(103, 80, 164, 0.05)', 'On Surface': '#1C1B1F', 'On Disabled': 'rgba(28, 27, 31, 0.38)', 'Error': '#B3261E', 'Background': '#FFFBFE', 'Dark Overlay 1': 'rgba(30, 25, 43, 0.08)', 'Surface': '#FFFBFE', 'On Primary': '#FFFFFF'})

Then create a module with the color scheme dictionary and a single function

DARK = {...}
LIGHT = {...}

def set_theme(dark=False):
    app.theme_colors.update(DARK if dark else LIGHT)

And if you just want something to copy and paste, here’s the module with M3 dark and light themes.

Full Module include themes

from anvil import app

LIGHT = {
    'Secondary Container': '#E8DEF8',
    'Tertiary Container': '#FFD8E4',
    'On Background': '#1C1B1F',
    'Disabled Container': 'rgba(28, 27, 31, 0.12)',
    'On Tertiary': '#FFFFFF',
    'Outline': '#79747E',
    'On Primary Container': '#21005E',
    'Dark Overlay 2': 'rgba(30, 25, 43, 0.12)',
    'On Secondary': '#FFFFFF',
    'On Secondary Container': '#1E192B',
    'Primary Container': '#EADDFF',
    'Secondary': '#625B71',
    'On Surface Variant': '#49454E',
    'Surface Variant': '#E7E0EC',
    'Light Overlay 1': 'rgba(255, 255, 255, 0.08)',
    'Tertiary': '#7D5260',
    'Light Overlay 2': 'rgba(255, 255, 255, 0.12)',
    'Primary Overlay 2': 'rgba(103, 80, 164, 0.08)',
    'Primary': '#6750A4',
    'On Tertiary Container': '#370B1E',
    'Primary Overlay 3': 'rgba(103, 80, 164, 0.11)',
    'Primary Overlay 1': 'rgba(103, 80, 164, 0.05)',
    'On Surface': '#1C1B1F',
    'On Disabled': 'rgba(28, 27, 31, 0.38)',
    'Error': '#B3261E',
    'Background': '#FFFBFE',
    'Dark Overlay 1': 'rgba(30, 25, 43, 0.08)',
    'Surface': '#FFFBFE',
    'On Primary': '#FFFFFF'
}

DARK = {
    'Secondary Container': '#4A4458',
    'Tertiary Container': '#633B48',
    'On Background': '#E6E1E5',
    'Disabled Container': 'rgba(230, 225, 229, 0.12)',
    'On Tertiary': '#492532',
    'Outline': '#938F99',
    'On Primary Container': '#EADDFF',
    'Dark Overlay 2': 'rgba(232, 222, 248, 0.12)',
    'On Secondary': '#332D41',
    'On Secondary Container': '#E8DEF8',
    'Primary Container': '#4F378B',
    'Secondary': '#CCC2DC',
    'On Surface Variant': '#CAC4D0',
    'Surface Variant': '#49454F',
    'Light Overlay 1': 'rgba(232, 222, 248, 0.08)',
    'Tertiary': '#EFB8C8',
    'Light Overlay 2': 'rgba(232, 222, 248, 0.12)',
    'Primary Overlay 2': 'rgba(208, 188, 255, 0.08)',
    'Primary': '#D0BCFF',
    'On Tertiary Container': '#FFD8E4',
    'Primary Overlay 3': 'rgba(208, 188, 255, 0.11)',
    'Primary Overlay 1': 'rgba(208, 188, 255, 0.05)',
    'On Surface': '#E6E1E5',
    'On Disabled': 'rgba(230, 225, 229, 0.38)',
    'Error': '#F2B8B5',
    'Background': '#1C1B1F',
    'Dark Overlay 1': 'rgba(232, 222, 248, 0.08)',
    'Surface': '#1C1B1F',
    'On Primary': '#371E73'
}

def set_theme(dark=False):
    theme = DARK if dark else LIGHT
    app.theme_colors.update(theme)

And a clone
https://anvil.works/build#clone:MUTZN5TYTDATDAS4=Q6RFFNYBYCBDJG23MPIZE6ZC

6 Likes

Brilliant!
I’ll try it out.

Thank you!

1 Like