Overview
By default SDS uses light-mode only, but dark-mode support can be controlled by setting html attributes using javascript.
Basic usage
Displaying Dark/Light mode
Dark/Light mode can be enabled by setting the appropriate data-ds-theme
value on the root html
element:
<html data-ds-theme="light">
...
</html>
// Alternatively you can omit/remove the data-ds-theme attribute
<html>
...
</html>
Toggling the current theme
The following sds component, combined with the example javascript will allow users to toggle the theme or fallback to the current OS theme:
<label class="ds-switch --theme --hide-label">
<input type="checkbox">
<div>Dark Mode</div>
</label>
<label class="ds-switch --theme --hide-label --small">
<input type="checkbox">
<div>Dark Mode</div>
</label>
The following javascript will firstly check local storage for a ‘ds:theme’ setting. If no setting exists it will fall back to using the OS theme. It will also set all html theme toggles on the page to the correct state and listen for any click events.
////////////////////
// Theme controls
////////////////////
// Import the sds color object - needed for changing chart colors
import { dsColor } from "https://assets.soracom.io/js/sds/latest/color.js";
if (typeof window.Chart !== "undefined") {
Chart.register(ChartDataLabels);
}
// Check if a specific theme is set in localStorage, otherwise use the system setting
let currentTheme =
localStorage["ds:theme"] ||
(window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
window.onload = () => {
// Set the html data-attribute to match the current theme
if (currentTheme) {
document.documentElement.dataset.dsTheme = currentTheme;
// Update any charts
setChartTheme(currentTheme);
}
// Reveal the page (in case it's invisible initially)
document.body.style.opacity = "1";
};
// Enable theme toggle controls and keep them in sync
let themeToggles = document.querySelectorAll(
'[class*="ds-switch"][class*="--theme"] input'
);
if (themeToggles.length > 0) {
for (const toggle of themeToggles) {
// Set the initial state of the theme-toggle component to match the current theme
setAllThemeToggles(currentTheme);
// Change the current theme when the toggle is clicked
toggle.addEventListener("click", function (e) {
let targetTheme = toggle.checked ? "dark" : "light";
// Set the theme
document.documentElement.dataset.dsTheme = targetTheme;
// Save the setting to local storage
localStorage["ds:theme"] = targetTheme;
// Update all toggles to be the same
setAllThemeToggles(targetTheme);
// Change any chart text colors
setChartTheme(targetTheme);
});
}
}
function setAllThemeToggles(theme) {
for (const toggle of themeToggles) {
toggle.checked = theme === "dark";
}
}
function setChartTheme(theme) {
var textColor =
theme === "dark" ? dsColor.inkBright.rgb : dsColor.inkShade.rgb;
if (typeof window.Chart !== "undefined") {
Chart.helpers.each(Chart.instances, function (instance) {
instance.options.scales.x.ticks.color = textColor;
instance.options.scales.y.ticks.color = textColor;
instance.options.plugins.datalabels.color = textColor;
instance.options.plugins.legend.labels.color = textColor;
instance.update();
});
}
}
Initial loading state
It’s recommended adding the following style element to the html head of the page for a better initial page loading experience. This allows the theme script above to reveal the page once the correct theme has been determined, and prevents an initial flash of dark or light colors.
<html>
<head>
<style>
/* Hide the page content, it will be revealed via script when fully loaded */
body { opacity: 0; }
/* Set background color if the user OS is in dark mode */
@media (prefers-color-scheme: dark) {
body { background-color: var(--color-ink-900); }
}
</style>
</head>
...
</html>