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();
})();