1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Behavior for the pieces of the system that need it. Everything else is
// CSS and semantic HTML on purpose — a design system that only works with
// JavaScript running is a component library with extra steps.
(function () {
"use strict";
var STORAGE_KEY = "gl-theme";
function readStored() {
try {
return localStorage.getItem(STORAGE_KEY);
} catch (error) {
return null;
}
}
function writeStored(value) {
try {
localStorage.setItem(STORAGE_KEY, value);
} catch (error) {
/* Nothing to do — the media query still gives a sensible default. */
}
}
function systemPrefersDark() {
return window.matchMedia("(prefers-color-scheme: dark)").matches;
}
function currentTheme() {
var explicit = document.documentElement.getAttribute("data-theme");
if (explicit) return explicit;
return systemPrefersDark() ? "dark" : "light";
}
function paintToggle(theme) {
document.querySelectorAll("[data-theme-toggle]").forEach(function (toggle) {
var next = theme === "dark" ? "light" : "dark";
toggle.setAttribute("aria-label", "Switch to the " + next + " theme");
toggle.setAttribute("title", "Switch to the " + next + " theme");
var label = toggle.querySelector("[data-theme-label]");
if (label) label.textContent = "Switch to the " + next + " theme";
});
}
function setUpTheme() {
paintToggle(currentTheme());
document.addEventListener("click", function (event) {
var toggle = event.target.closest("[data-theme-toggle]");
if (!toggle) return;
var next = currentTheme() === "dark" ? "light" : "dark";
document.documentElement.setAttribute("data-theme", next);
writeStored(next);
paintToggle(next);
});
// Follow the OS while the reader has not made an explicit choice.
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", function () {
if (!readStored()) paintToggle(currentTheme());
});
}
// Tabs, wired to the WAI-ARIA authoring practices: arrows move, Home/End
// jump, and only the selected tab stays in the tab order.
function setUpTabs() {
document.querySelectorAll("[data-tabs]").forEach(function (root) {
var tabs = Array.prototype.slice.call(root.querySelectorAll('[role="tab"]'));
if (!tabs.length) return;
function select(tab, focus) {
tabs.forEach(function (candidate) {
var selected = candidate === tab;
candidate.setAttribute("aria-selected", String(selected));
candidate.tabIndex = selected ? 0 : -1;
var panel = document.getElementById(candidate.getAttribute("aria-controls"));
if (panel) panel.hidden = !selected;
});
if (focus) tab.focus();
}
root.addEventListener("click", function (event) {
var tab = event.target.closest('[role="tab"]');
if (tab) select(tab, false);
});
root.addEventListener("keydown", function (event) {
var index = tabs.indexOf(document.activeElement);
if (index === -1) return;
var next = null;
if (event.key === "ArrowRight") next = tabs[(index + 1) % tabs.length];
else if (event.key === "ArrowLeft") next = tabs[(index - 1 + tabs.length) % tabs.length];
else if (event.key === "Home") next = tabs[0];
else if (event.key === "End") next = tabs[tabs.length - 1];
if (next) {
event.preventDefault();
select(next, true);
}
});
select(tabs.filter(function (tab) {
return tab.getAttribute("aria-selected") === "true";
})[0] || tabs[0], false);
});
}
function setUpNavToggle() {
document.addEventListener("click", function (event) {
var toggle = event.target.closest("[data-nav-toggle]");
if (!toggle) return;
var sidebar = toggle.closest("[data-sidebar]");
var collapsed = sidebar.dataset.collapsed !== "false";
sidebar.dataset.collapsed = String(!collapsed);
toggle.setAttribute("aria-expanded", String(collapsed));
});
}
setUpTheme();
setUpTabs();
setUpNavToggle();
})();