Skip to content

Add dark mode support #5658

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*!
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
* Copyright 2011-2024 The Bootstrap Authors
* Licensed under the Creative Commons Attribution 3.0 Unported License.
*/

(() => {
'use strict'

const getStoredTheme = () => localStorage.getItem('theme')
const setStoredTheme = theme => localStorage.setItem('theme', theme)

const getPreferredTheme = () => {
const storedTheme = getStoredTheme()
if (storedTheme) {
return storedTheme
}

return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}

const setTheme = theme => {
if (theme === 'auto') {
document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
} else {
document.documentElement.setAttribute('data-bs-theme', theme)
}
}

setTheme(getPreferredTheme())

const showActiveTheme = (theme, focus = false) => {
const themeSwitcher = document.querySelector('#bd-theme')

if (!themeSwitcher) {
return
}

const themeSwitcherText = document.querySelector('#bd-theme-text')
const activeThemeIcon = document.querySelector('.theme-icon-active use')
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')

document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
element.classList.remove('active')
element.setAttribute('aria-pressed', 'false')
})

btnToActive.classList.add('active')
btnToActive.setAttribute('aria-pressed', 'true')
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)

if (focus) {
themeSwitcher.focus()
}
}

window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
const storedTheme = getStoredTheme()
if (storedTheme !== 'light' && storedTheme !== 'dark') {
setTheme(getPreferredTheme())
}
})

window.addEventListener('DOMContentLoaded', () => {
showActiveTheme(getPreferredTheme())

document.querySelectorAll('[data-bs-theme-value]')
.forEach(toggle => {
toggle.addEventListener('click', () => {
const theme = toggle.getAttribute('data-bs-theme-value')
setStoredTheme(theme)
setTheme(theme)
showActiveTheme(theme, true)
})
})
})
})()


Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{% raw %}{% extends "base.html" %}
{% load i18n %}
{% block bodyclass %}bg-light{% endblock bodyclass %}

{% block css %}{{ block.super }}{% endblock css %}
{% block title %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
{% endraw %}
{%- endif %}{% raw %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE }}">
<html lang="{{ LANGUAGE_CODE }}" data-bs-theme="light">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
Expand All @@ -29,8 +29,13 @@
{%- raw %}
<!-- Latest compiled and minified Bootstrap CSS -->
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css"
integrity="sha512-SbiR/eusphKoMVVXysTKG/7VseWii+Y3FdHrt0EpKgpToZeemhqHeZeLWLhJutz/2ut2Vw1uQEj2MbRF+TVBUA=="
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css"
integrity="sha512-jnSuA4Ss2PkkikSOLtYs8BlYIeeIK1h99ty4YfvRPAlzr377vr3CXDb7sb7eEEBYjDtcYj+AjBH3FLv5uSJuXg=="
crossorigin="anonymous"
referrerpolicy="no-referrer" />
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This need to be installed via npm when using Gulp or Webpack, and imported in project.scss:

@import '~bootstrap-icons/font/bootstrap-icons.css';

integrity="sha512-dPXYcDub/aeb08c63jRq/k6GaKccl256JQy/AnOq7CAnEZ9FzSL9wSbcZkMp4R26vBsMLFYH4kQ67/bbV8XaCQ=="
crossorigin="anonymous"
referrerpolicy="no-referrer" />
{%- endraw %}
Expand Down Expand Up @@ -79,8 +84,8 @@
{% raw %}
<!-- Bootstrap JS -->
<script defer
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/js/bootstrap.min.js"
integrity="sha512-1/RvZTcCDEUjY/CypiMz+iqqtaoQfAITmNSJY17Myp4Ms5mdxPS5UV7iOfdZoxcGhzFbOm6sntTKJppjvuhg4g=="
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/js/bootstrap.bundle.min.js"
integrity="sha512-7Pi/otdlbbCR+LnW+F7PwFcSDJOuUJB3OxtEHbg4vSMvzvJjde4Po1v4BR9Gdc9aXNUNFVUY+SK51wWT8WF0Gg=="
crossorigin="anonymous"
referrerpolicy="no-referrer"></script>
<!-- Your stuff: Third-party javascript libraries go here -->
Expand All @@ -92,16 +97,19 @@
{% if cookiecutter.frontend_pipeline == 'None' %}
{% raw %}
<script defer src="{% static 'js/project.js' %}"></script>
<script defer src="{% static 'js/theme-toggler.js' %}"></script>
{%- endraw %}
{% elif cookiecutter.frontend_pipeline == 'Django Compressor' %}
{% raw %}
{% compress js %}
<script defer src="{% static 'js/project.js' %}"></script>
<script defer src="{% static 'js/theme-toggler.js' %}"></script>
{% endcompress %}
{%- endraw %}
{% elif cookiecutter.frontend_pipeline == 'Gulp' %}
{% raw %}
<script defer src="{% static 'js/project.min.js' %}"></script>
<script defer src="{% static 'js/theme-toggler.js' %}"></script>
Comment on lines 111 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice if theme-toggler.js could be imported by project.js when using Gulp or Webpack. They will take care of bundling it nicely, I think.

{%- endraw %}
{% elif cookiecutter.frontend_pipeline == "Webpack" %}
{% raw %}
Expand All @@ -114,7 +122,7 @@
<body class="{% block bodyclass %}{% endblock bodyclass %}">
{% block body %}
<div class="mb-1">
<nav class="navbar navbar-expand-md navbar-light bg-light">
<nav class="navbar navbar-expand-md bg-body-tertiary shadow-sm">
<div class="container-fluid">
<button class="navbar-toggler navbar-toggler-right"
type="button"
Expand Down Expand Up @@ -155,6 +163,34 @@
<a id="log-in-link" class="nav-link" href="{% url 'account_login' %}">{% translate "Sign In" %}</a>
</li>
{% endif %}
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle"
href="#"
id="themeDropdown"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false">
<i class="bi bi-palette"></i>
</a>
<ul class="dropdown-menu dropdown-menu-end"
aria-labelledby="themeDropdown">
<li>
<button class="dropdown-item" type="button" data-bs-theme-value="light">
<i class="bi bi-sun-fill me-2"></i>Light
</button>
</li>
<li>
<button class="dropdown-item" type="button" data-bs-theme-value="dark">
<i class="bi bi-moon-stars-fill me-2"></i>Dark
</button>
</li>
<li>
<button class="dropdown-item" type="button" data-bs-theme-value="auto">
<i class="bi bi-circle-half me-2"></i>Auto
</button>
</li>
</ul>
</li>
</ul>
</div>
</div>
Expand Down