mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 17:26:10 -06:00
simplify color mode selection
This commit is contained in:
parent
aba00ca01d
commit
01d1e7adbc
BIN
netbox/project-static/dist/config.js
vendored
BIN
netbox/project-static/dist/config.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/config.js.map
vendored
BIN
netbox/project-static/dist/config.js.map
vendored
Binary file not shown.
BIN
netbox/project-static/dist/lldp.js
vendored
BIN
netbox/project-static/dist/lldp.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/lldp.js.map
vendored
BIN
netbox/project-static/dist/lldp.js.map
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js
vendored
BIN
netbox/project-static/dist/netbox.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js.map
vendored
BIN
netbox/project-static/dist/netbox.js.map
vendored
Binary file not shown.
BIN
netbox/project-static/dist/status.js
vendored
BIN
netbox/project-static/dist/status.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/status.js.map
vendored
BIN
netbox/project-static/dist/status.js.map
vendored
Binary file not shown.
@ -1,72 +1,42 @@
|
|||||||
/**
|
/**
|
||||||
* Set the color mode on the `<html/>` element and in local storage.
|
* Set the color mode on the `<html/>` element.
|
||||||
*
|
*
|
||||||
* @param mode {"dark" | "light"} NetBox Color Mode.
|
* @param mode {"dark" | "light" | "system"} NetBox Color Mode.
|
||||||
* @param inferred {boolean} Value is inferred from browser/system preference.
|
|
||||||
*/
|
*/
|
||||||
function setMode(mode, inferred) {
|
function setMode(mode) {
|
||||||
document.documentElement.setAttribute("data-netbox-color-mode", mode);
|
if (mode === 'system') {
|
||||||
localStorage.setItem("netbox-color-mode", mode);
|
mode = getSystemColorMode();
|
||||||
localStorage.setItem("netbox-color-mode-inferred", inferred);
|
}
|
||||||
|
document.documentElement.setAttribute('data-netbox-color-mode', mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the system color mode (light or dark).
|
||||||
|
*
|
||||||
|
* @return {string} "dark" or "light" based on system preference.
|
||||||
|
*/
|
||||||
|
function getSystemColorMode() {
|
||||||
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine the best initial color mode to use prior to rendering.
|
* Determine the best initial color mode to use prior to rendering.
|
||||||
*/
|
*/
|
||||||
function initMode() {
|
function initMode() {
|
||||||
try {
|
try {
|
||||||
// Browser prefers dark color scheme.
|
// NetBox server-rendered value.
|
||||||
var preferDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
const serverMode = document.documentElement.getAttribute('data-netbox-color-mode');
|
||||||
// Browser prefers light color scheme.
|
|
||||||
var preferLight = window.matchMedia("(prefers-color-scheme: light)").matches;
|
|
||||||
// Client NetBox color-mode override.
|
|
||||||
var clientMode = localStorage.getItem("netbox-color-mode");
|
|
||||||
// NetBox server-rendered value.
|
|
||||||
var serverMode = document.documentElement.getAttribute("data-netbox-color-mode");
|
|
||||||
// Color mode is inferred from browser/system preference and not deterministically set by
|
|
||||||
// the client or server.
|
|
||||||
var inferred = JSON.parse(localStorage.getItem("netbox-color-mode-inferred"));
|
|
||||||
|
|
||||||
if (inferred === true && (serverMode === "light" || serverMode === "dark")) {
|
if (serverMode === 'light' || serverMode === 'dark' || serverMode === 'system') {
|
||||||
// The color mode was previously inferred from browser/system preference, but
|
// If the server mode is set (light, dark, or system), use the server mode.
|
||||||
// the server now has a value, so we should use the server's value.
|
return setMode(serverMode);
|
||||||
return setMode(serverMode, false);
|
|
||||||
}
|
|
||||||
if (clientMode === null && (serverMode === "light" || serverMode === "dark")) {
|
|
||||||
// If the client mode is not set but the server mode is, use the server mode.
|
|
||||||
return setMode(serverMode, false);
|
|
||||||
}
|
|
||||||
if (clientMode !== null && serverMode === "unset") {
|
|
||||||
// The color mode has been set, deterministically or otherwise, and the server
|
|
||||||
// has no preference or has not been set. Use the client mode, but allow it to
|
|
||||||
/// be overridden by the server if/when a server value exists.
|
|
||||||
return setMode(clientMode, true);
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
clientMode !== null &&
|
|
||||||
(serverMode === "light" || serverMode === "dark") &&
|
|
||||||
clientMode !== serverMode
|
|
||||||
) {
|
|
||||||
// If the client mode is set and is different than the server mode (which is also set),
|
|
||||||
// use the client mode over the server mode, as it should be more recent.
|
|
||||||
return setMode(clientMode, false);
|
|
||||||
}
|
|
||||||
if (clientMode === serverMode) {
|
|
||||||
// If the client and server modes match, use that value.
|
|
||||||
return setMode(clientMode, false);
|
|
||||||
}
|
|
||||||
if (preferDark && serverMode === "unset") {
|
|
||||||
// If the server mode is not set but the browser prefers dark mode, use dark mode, but
|
|
||||||
// allow it to be overridden by an explicit preference.
|
|
||||||
return setMode("dark", true);
|
|
||||||
}
|
|
||||||
if (preferLight && serverMode === "unset") {
|
|
||||||
// If the server mode is not set but the browser prefers light mode, use light mode,
|
|
||||||
// but allow it to be overridden by an explicit preference.
|
|
||||||
return setMode("light", true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// In the event of an error, log it to the console and set the mode to light mode.
|
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
return setMode("light", true);
|
|
||||||
};
|
// If server mode is not set, use the system color mode.
|
||||||
|
return setMode('system');
|
||||||
|
} catch (error) {
|
||||||
|
// In the event of an error, log it to the console and set the mode to system mode.
|
||||||
|
console.error(error);
|
||||||
|
return setMode('system');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
import { getElements, isTruthy } from './util';
|
|
||||||
|
|
||||||
const COLOR_MODE_KEY = 'netbox-color-mode';
|
|
||||||
const TEXT_WHEN_DARK = 'Light Mode';
|
|
||||||
const TEXT_WHEN_LIGHT = 'Dark Mode';
|
|
||||||
const ICON_WHEN_DARK = 'mdi-lightbulb-on';
|
|
||||||
const ICON_WHEN_LIGHT = 'mdi-lightbulb';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if a value is a supported color mode string value.
|
|
||||||
*/
|
|
||||||
function isColorMode(value: unknown): value is ColorMode {
|
|
||||||
return value === 'dark' || value === 'light';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the color mode to light or dark.
|
|
||||||
*
|
|
||||||
* @param mode `'light'` or `'dark'`
|
|
||||||
* @returns `true` if the color mode was successfully set, `false` if not.
|
|
||||||
*/
|
|
||||||
function storeColorMode(mode: ColorMode): void {
|
|
||||||
return localStorage.setItem(COLOR_MODE_KEY, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateElements(targetMode: ColorMode): void {
|
|
||||||
document.documentElement.setAttribute(`data-${COLOR_MODE_KEY}`, targetMode);
|
|
||||||
|
|
||||||
for (const text of getElements<HTMLSpanElement>('span.color-mode-text')) {
|
|
||||||
if (targetMode === 'light') {
|
|
||||||
text.innerText = TEXT_WHEN_LIGHT;
|
|
||||||
} else if (targetMode === 'dark') {
|
|
||||||
text.innerText = TEXT_WHEN_DARK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const icon of getElements<HTMLSpanElement>('i.color-mode-icon', 'span.color-mode-icon')) {
|
|
||||||
if (targetMode === 'light') {
|
|
||||||
icon.classList.remove(ICON_WHEN_DARK);
|
|
||||||
icon.classList.add(ICON_WHEN_LIGHT);
|
|
||||||
} else if (targetMode === 'dark') {
|
|
||||||
icon.classList.remove(ICON_WHEN_LIGHT);
|
|
||||||
icon.classList.add(ICON_WHEN_DARK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const elevation of getElements<HTMLObjectElement>('.rack_elevation')) {
|
|
||||||
const svg = elevation.contentDocument?.querySelector('svg') ?? null;
|
|
||||||
if (svg !== null) {
|
|
||||||
svg.setAttribute(`data-${COLOR_MODE_KEY}`, targetMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call all functions necessary to update the color mode across the UI.
|
|
||||||
*
|
|
||||||
* @param mode Target color mode.
|
|
||||||
*/
|
|
||||||
export function setColorMode(mode: ColorMode): void {
|
|
||||||
for (const func of [storeColorMode, updateElements]) {
|
|
||||||
func(mode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle the color mode when a color mode toggle is clicked.
|
|
||||||
*/
|
|
||||||
function handleColorModeToggle(): void {
|
|
||||||
const currentValue = localStorage.getItem(COLOR_MODE_KEY);
|
|
||||||
if (currentValue === 'light') {
|
|
||||||
setColorMode('dark');
|
|
||||||
} else if (currentValue === 'dark') {
|
|
||||||
setColorMode('light');
|
|
||||||
} else {
|
|
||||||
console.warn('Unable to determine the current color mode');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine the user's preference and set it as the color mode.
|
|
||||||
*/
|
|
||||||
function defaultColorMode(): void {
|
|
||||||
// Get the current color mode value from local storage.
|
|
||||||
const currentValue = localStorage.getItem(COLOR_MODE_KEY) as Nullable<ColorMode>;
|
|
||||||
const serverValue = document.documentElement.getAttribute(`data-${COLOR_MODE_KEY}`);
|
|
||||||
|
|
||||||
if (isTruthy(serverValue) && isTruthy(currentValue)) {
|
|
||||||
return setColorMode(currentValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
let preference: ColorModePreference = 'none';
|
|
||||||
|
|
||||||
// Determine if the user prefers dark or light mode.
|
|
||||||
for (const mode of ['dark', 'light']) {
|
|
||||||
if (window.matchMedia(`(prefers-color-scheme: ${mode})`).matches) {
|
|
||||||
preference = mode as ColorModePreference;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isTruthy(currentValue) && !isTruthy(serverValue) && isColorMode(currentValue)) {
|
|
||||||
return setColorMode(currentValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (preference) {
|
|
||||||
case 'dark':
|
|
||||||
return setColorMode('dark');
|
|
||||||
case 'light':
|
|
||||||
return setColorMode('light');
|
|
||||||
case 'none':
|
|
||||||
return setColorMode('light');
|
|
||||||
default:
|
|
||||||
return setColorMode('light');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize color mode toggle buttons and set the default color mode.
|
|
||||||
*/
|
|
||||||
function initColorModeToggle(): void {
|
|
||||||
for (const element of getElements<HTMLButtonElement>('button.color-mode-toggle')) {
|
|
||||||
element.addEventListener('click', handleColorModeToggle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize all color mode elements.
|
|
||||||
*/
|
|
||||||
export function initColorMode(): void {
|
|
||||||
window.addEventListener('load', defaultColorMode);
|
|
||||||
for (const func of [initColorModeToggle]) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ import { initBootstrap } from './bs';
|
|||||||
import { initQuickSearch } from './search';
|
import { initQuickSearch } from './search';
|
||||||
import { initSelect } from './select';
|
import { initSelect } from './select';
|
||||||
import { initButtons } from './buttons';
|
import { initButtons } from './buttons';
|
||||||
import { initColorMode } from './colorMode';
|
|
||||||
import { initMessages } from './messages';
|
import { initMessages } from './messages';
|
||||||
import { initClipboard } from './clipboard';
|
import { initClipboard } from './clipboard';
|
||||||
import { initDateSelector } from './dateSelector';
|
import { initDateSelector } from './dateSelector';
|
||||||
@ -18,7 +17,6 @@ import { initHtmx } from './htmx';
|
|||||||
function initDocument(): void {
|
function initDocument(): void {
|
||||||
for (const init of [
|
for (const init of [
|
||||||
initBootstrap,
|
initBootstrap,
|
||||||
initColorMode,
|
|
||||||
initMessages,
|
initMessages,
|
||||||
initForms,
|
initForms,
|
||||||
initQuickSearch,
|
initQuickSearch,
|
||||||
|
@ -7,13 +7,7 @@
|
|||||||
data-netbox-url-name="{{ request.resolver_match.url_name }}"
|
data-netbox-url-name="{{ request.resolver_match.url_name }}"
|
||||||
data-netbox-base-path="{{ settings.BASE_PATH }}"
|
data-netbox-base-path="{{ settings.BASE_PATH }}"
|
||||||
{% with preferences|get_key:'ui.colormode' as color_mode %}
|
{% with preferences|get_key:'ui.colormode' as color_mode %}
|
||||||
{% if color_mode == 'dark'%}
|
data-netbox-color-mode={{ color_mode }}
|
||||||
data-netbox-color-mode="dark"
|
|
||||||
{% elif color_mode == 'light' %}
|
|
||||||
data-netbox-color-mode="light"
|
|
||||||
{% else %}
|
|
||||||
data-netbox-color-mode="unset"
|
|
||||||
{% endif %}
|
|
||||||
{% endwith %}
|
{% endwith %}
|
||||||
>
|
>
|
||||||
<head>
|
<head>
|
||||||
|
Loading…
Reference in New Issue
Block a user