Home / Coracle / Articles / Native and Light and Dark Theming

Native and Light and Dark Theming

Coracle Drawings can now pull colours from the host page/screen/window and follow the system light/dark (day/night) theme using the background() and nativeColour("colour_key") API.

Native theming is only available on the web renderer at the moment.

Using native colours on the web

For a Coracle Drawing to use a colour from the parent HTML page it needs to be set as the background on an element with an id:

<div id="boid_colour" style="background: #00ff00;visibility: hidden;"></div>

Coracle can then read that colour using: val boidColour = nativeColour("boid_colour").

background() uses a similar method but reads the background colour of the main web body so can be used to make sure Drawings always work well even when CSS/design changes are made (under the hood the WebRenderer calls: window.getComputedStyle(document.body!!).getPropertyValue("background-color"))

To react to light/dark day/night theme changes in realtime the website needs to use media queries for the colour:

<!DOCTYPE html>
<html lang="en">
    <head>
    <style>
        #boid_colour{
            visibility: hidden;
            background: #1d1d1d;
        }

        @media (prefers-color-scheme: light) {
            #boid_colour{
                background: #1d1d1d;
            }
        }

        @media (prefers-color-scheme: dark) {
            #boid_colour{
                background: #efefef;
            }
        }
    </style>
    </head>
    <body>
    <div id="boid_colour"></div>
    ...
    

The Coracle nativeColour("boid_colour") call needs to happen in the draw loop:

fun draw() {
    background()

    val colour = nativeColour("boid_colour")
    stroke(colour, 0.4f)
    ...
    

There will be some overhead doing that call in the main draw loop, under the hood the WebRenderer has some work to do to get the web colour, and the colourConvert(webColour) method involves some String parsing which is relatively expensive:


override fun nativeColour(key: String): Int {
    val element = document.getElementById(key)
    return when {
        element != null -> {
            val webColour = window.getComputedStyle(element,null).getPropertyValue("background-color")
            colourConvert(webColour)
        }
        else -> 0xff00cc
    }
}

Calling colourConvert(webColour) when setting up a Drawing outside the draw loop is preferred, and allows you to decouple all your colours from the compiled Drawing if that's something you need.