Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit 40a8e3c

Browse files
committed
Support dark mode and theme switching
1 parent adc3fc1 commit 40a8e3c

File tree

12 files changed

+690
-98
lines changed

12 files changed

+690
-98
lines changed

.node/package-lock.json

+340
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.node/package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
"not dead"
66
],
77
"scripts": {
8-
"watch": "postcss -w ../Assets/**/*.css -o ../Resources/all.min.css --config ./postcss.config.js"
8+
"watch": "concurrently \"postcss -w ../Assets/**/*.css -o ../Sources/swift-doc/Resources/all.min.css --config ./postcss.config.js\" \"tsc -w\"",
9+
"build": "tsc && postcss ../Assets/**/*.css -o ../Sources/swift-doc/Resources/all.min.css --config ./postcss.config.js"
910
},
10-
"dependencies": {
11+
"devDependencies": {
12+
"concurrently": "^5.2.0",
1113
"cssnano": "^4.1.10",
1214
"postcss-cli": "^7.1.0",
13-
"postcss-preset-env": "^6.7.0"
15+
"postcss-preset-env": "^6.7.0",
16+
"typescript": "~3.9.7"
1417
}
1518
}

.node/tsconfig.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"files": ["../Assets/ts/theme-switching.ts"],
3+
"compilerOptions": {
4+
"outFile": "../Sources/swift-doc/Resources/all.js"
5+
}
6+
}

Assets/css/all.css

+113-85
Original file line numberDiff line numberDiff line change
@@ -74,92 +74,89 @@
7474
}
7575
}
7676

77-
/*
78-
@media (prefers-color-scheme: dark) {
79-
:root {
80-
--system-red: rgb(255, 69, 58);
81-
--system-orange: rgb(255, 159, 10);
82-
--system-yellow: rgb(255, 214, 10);
83-
--system-green: rgb(48, 209, 88);
84-
--system-teal: rgb(100, 210, 255);
85-
--system-blue: rgb(10, 132, 255);
86-
--system-indigo: rgb(94, 92, 230);
87-
--system-purple: rgb(191, 90, 242);
88-
--system-pink: rgb(255, 55, 95);
89-
--system-gray: rgb(142, 142, 147);
90-
--system-gray2: rgb(99, 99, 102);
91-
--system-gray3: rgb(72, 72, 74);
92-
--system-gray4: rgb(58, 58, 60);
93-
--system-gray5: rgb(44, 44, 46);
94-
--system-gray6: rgb(28, 28, 30);
95-
96-
--label: rgb(255, 255, 255);
97-
--secondary-label: rgb(235, 235, 245);
98-
--tertiary-label: rgb(235, 235, 245);
99-
--quaternary-label: rgb(235, 235, 245);
100-
--placeholder-text: rgb(235, 235, 245);
101-
--link: rgb(9, 132, 255);
102-
--separator: rgb(44, 44, 46);
103-
--opaque-separator: rgb(56, 56, 58);
104-
--system-fill: rgb(120, 120, 128);
105-
--secondary-system-fill: rgb(120, 120, 128);
106-
--tertiary-system-fill: rgb(118, 118, 128);
107-
--quaternary-system-fill: rgb(118, 118, 128);
108-
--system-background: rgb(0, 0, 0);
109-
--secondary-system-background: rgb(28, 28, 30);
110-
--tertiary-system-background: rgb(44, 44, 46);
111-
--system-grouped-background: rgb(0, 0, 0);
112-
--secondary-system-grouped-background: rgb(28, 28, 30);
113-
--tertiary-system-grouped-background: rgb(44, 44, 46);
114-
}
77+
.dark-theme {
78+
--system-red: rgb(255, 69, 58);
79+
--system-orange: rgb(255, 159, 10);
80+
--system-yellow: rgb(255, 214, 10);
81+
--system-green: rgb(48, 209, 88);
82+
--system-teal: rgb(100, 210, 255);
83+
--system-blue: rgb(10, 132, 255);
84+
--system-indigo: rgb(94, 92, 230);
85+
--system-purple: rgb(191, 90, 242);
86+
--system-pink: rgb(255, 55, 95);
87+
--system-gray: rgb(142, 142, 147);
88+
--system-gray2: rgb(99, 99, 102);
89+
--system-gray3: rgb(72, 72, 74);
90+
--system-gray4: rgb(58, 58, 60);
91+
--system-gray5: rgb(44, 44, 46);
92+
--system-gray6: rgb(28, 28, 30);
93+
94+
--label: rgb(255, 255, 255);
95+
--secondary-label: rgb(235, 235, 245);
96+
--tertiary-label: rgb(235, 235, 245);
97+
--quaternary-label: rgb(235, 235, 245);
98+
--placeholder-text: rgb(235, 235, 245);
99+
--link: rgb(9, 132, 255);
100+
--separator: rgb(44, 44, 46);
101+
--opaque-separator: rgb(56, 56, 58);
102+
--system-fill: rgb(120, 120, 128);
103+
--secondary-system-fill: rgb(120, 120, 128);
104+
--tertiary-system-fill: rgb(118, 118, 128);
105+
--quaternary-system-fill: rgb(118, 118, 128);
106+
--system-background: rgb(0, 0, 0);
107+
--secondary-system-background: rgb(28, 28, 30);
108+
--tertiary-system-background: rgb(44, 44, 46);
109+
--system-grouped-background: rgb(0, 0, 0);
110+
--secondary-system-grouped-background: rgb(28, 28, 30);
111+
--tertiary-system-grouped-background: rgb(44, 44, 46);
112+
}
115113

116-
@supports (color: color(display-p3 1 1 1)) {
117-
:root {
118-
--system-red: color(display-p3 1 0.4118 0.3804);
119-
--system-orange: color(display-p3 1 0.702 0.251);
120-
--system-yellow: color(display-p3 1 0.8314 0.149);
121-
--system-green: color(display-p3 0.1882 0.8588 0.3569);
122-
--system-teal: color(display-p3 0.4392 0.8431 1);
123-
--system-blue: color(display-p3 0.251 0.6118 1);
124-
--system-indigo: color(display-p3 0.4902 0.4784 1);
125-
--system-purple: color(display-p3 0.8549 0.5608 1);
126-
--system-pink: color(display-p3 1 0.3922 0.5098);
127-
--system-gray: color(display-p3 0.6824 0.6824 0.698);
128-
--system-gray2: color(display-p3 0.4863 0.4863 0.502);
129-
--system-gray3: color(display-p3 0.3294 0.3294 0.3373);
130-
--system-gray4: color(display-p3 0.2667 0.2667 0.2745);
131-
--system-gray5: color(display-p3 0.2118 0.2118 0.2196);
132-
--system-gray6: color(display-p3 0.1412 0.1412 0.149);
133-
134-
--label: color(display-p3 1 1 1);
135-
--secondary-label: color(display-p3 0.9216 0.9216 0.9608);
136-
--tertiary-label: color(display-p3 0.9216 0.9216 0.9608);
137-
--quaternary-label: color(display-p3 0.9216 0.9216 0.9608);
138-
--placeholder-text: color(display-p3 0.9216 0.9216 0.9608);
139-
--link: color(display-p3 0.03529 0.5176 1);
140-
--separator: color(display-p3 0.2118 0.2118 0.2196);
141-
--opaque-separator: color(display-p3 0.2196 0.2196 0.2275);
142-
--system-fill: color(display-p3 0.4706 0.4706 0.502);
143-
--secondary-system-fill: color(display-p3 0.4706 0.4706 0.502);
144-
--tertiary-system-fill: color(display-p3 0.4627 0.4627 0.502);
145-
--quaternary-system-fill: color(display-p3 0.4627 0.4627 0.502);
146-
--system-background: color(display-p3 0 0 0);
147-
--secondary-system-background: color(
148-
display-p3 0.1412 0.1412 0.149
149-
);
150-
--tertiary-system-background: color(
151-
display-p3 0.2118 0.2118 0.2196
152-
);
153-
--system-grouped-background: color(display-p3 0 0 0);
154-
--secondary-system-grouped-background: color(
155-
display-p3 0.1412 0.1412 0.149
156-
);
157-
--tertiary-system-grouped-background: color(
158-
display-p3 0.2118 0.2118 0.2196
159-
);
160-
}
161-
}
162-
} */
114+
@supports (color: color(display-p3 1 1 1)) {
115+
.dark-theme {
116+
--system-red: color(display-p3 1 0.4118 0.3804);
117+
--system-orange: color(display-p3 1 0.702 0.251);
118+
--system-yellow: color(display-p3 1 0.8314 0.149);
119+
--system-green: color(display-p3 0.1882 0.8588 0.3569);
120+
--system-teal: color(display-p3 0.4392 0.8431 1);
121+
--system-blue: color(display-p3 0.251 0.6118 1);
122+
--system-indigo: color(display-p3 0.4902 0.4784 1);
123+
--system-purple: color(display-p3 0.8549 0.5608 1);
124+
--system-pink: color(display-p3 1 0.3922 0.5098);
125+
--system-gray: color(display-p3 0.6824 0.6824 0.698);
126+
--system-gray2: color(display-p3 0.4863 0.4863 0.502);
127+
--system-gray3: color(display-p3 0.3294 0.3294 0.3373);
128+
--system-gray4: color(display-p3 0.2667 0.2667 0.2745);
129+
--system-gray5: color(display-p3 0.2118 0.2118 0.2196);
130+
--system-gray6: color(display-p3 0.1412 0.1412 0.149);
131+
132+
--label: color(display-p3 1 1 1);
133+
--secondary-label: color(display-p3 0.9216 0.9216 0.9608);
134+
--tertiary-label: color(display-p3 0.9216 0.9216 0.9608);
135+
--quaternary-label: color(display-p3 0.9216 0.9216 0.9608);
136+
--placeholder-text: color(display-p3 0.9216 0.9216 0.9608);
137+
--link: color(display-p3 0.03529 0.5176 1);
138+
--separator: color(display-p3 0.2118 0.2118 0.2196);
139+
--opaque-separator: color(display-p3 0.2196 0.2196 0.2275);
140+
--system-fill: color(display-p3 0.4706 0.4706 0.502);
141+
--secondary-system-fill: color(display-p3 0.4706 0.4706 0.502);
142+
--tertiary-system-fill: color(display-p3 0.4627 0.4627 0.502);
143+
--quaternary-system-fill: color(display-p3 0.4627 0.4627 0.502);
144+
--system-background: color(display-p3 0 0 0);
145+
--secondary-system-background: color(
146+
display-p3 0.1412 0.1412 0.149
147+
);
148+
--tertiary-system-background: color(
149+
display-p3 0.2118 0.2118 0.2196
150+
);
151+
--system-grouped-background: color(display-p3 0 0 0);
152+
--secondary-system-grouped-background: color(
153+
display-p3 0.1412 0.1412 0.149
154+
);
155+
--tertiary-system-grouped-background: color(
156+
display-p3 0.2118 0.2118 0.2196
157+
);
158+
}
159+
}
163160

164161
:root {
165162
--large-title: 600 32pt / 39pt sans-serif;
@@ -474,6 +471,10 @@ select {
474471
outline: 0;
475472
z-index: 9;
476473
}
474+
475+
& option {
476+
color: #3c3c43;
477+
}
477478
}
478479

479480
input[type="file"] {
@@ -674,6 +675,8 @@ body {
674675
& > header {
675676
font: var(--title-1);
676677
padding: 0.5em 0;
678+
display: flex;
679+
align-items: center;
677680

678681
& a {
679682
color: var(--label);
@@ -690,6 +693,31 @@ body {
690693
color: var(--secondary-label);
691694
letter-spacing: 0.1ch;
692695
}
696+
& label {
697+
padding-bottom: 4px;
698+
font: var(--caption-1);
699+
}
700+
& .theme-select-container {
701+
display: flex;
702+
flex-direction: column;
703+
}
704+
& select {
705+
color: var(--secondary-label);
706+
font: var(--caption-1);
707+
width: auto;
708+
border: 1px solid var(--label);
709+
710+
/* Simple down-pointing rectangle positioned on the right side of the input */
711+
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%238a8a8a%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.2-5.5-12.8z%22%2F%3E%3C%2Fsvg%3E');
712+
background-repeat: no-repeat, repeat;
713+
background-position: right .7em top 50%, 0 0;
714+
background-size: .65em auto, 100%;
715+
padding-right: 1.8em;
716+
}
717+
& .spacer {
718+
flex-grow: 1;
719+
}
720+
693721
}
694722

695723
& > footer {

Assets/ts/theme-switching.ts

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
type ThemeChoice = "light" | "dark" | "auto";
2+
const themeQuery = window.matchMedia('(prefers-color-scheme: dark)');
3+
const localStorageKey = "picked-theme";
4+
let autoTheme = false;
5+
6+
// load initial theme before load event to prevent flashing of background color on navigation
7+
let initialTheme = window.localStorage.getItem(localStorageKey) ?? "auto";
8+
setPickedTheme(initialTheme as ThemeChoice);
9+
10+
window.addEventListener("load", () => {
11+
const themeSwitcher = window.document.getElementById("theme-switcher") as HTMLSelectElement;
12+
13+
themeSwitcher.addEventListener("change", (themePickedEvent: Event) => {
14+
const newValue = (themePickedEvent.target as HTMLSelectElement).value
15+
setPickedTheme(newValue as ThemeChoice);
16+
});
17+
18+
themeQuery.addEventListener?.("change", (systemThemeChangeEvent) => {
19+
const systemTheme = systemThemeChangeEvent.matches ? "dark" : "light";
20+
updateDropdownLabel(systemTheme);
21+
if (autoTheme) {
22+
applyTheme(systemTheme);
23+
}
24+
})
25+
26+
setInitialTheme(themeSwitcher);
27+
checkThemingSupport();
28+
})
29+
30+
/**
31+
* Sets the correct theme based on what's in storage, and updates the theme switcher dropdown with the correct initial value.
32+
*/
33+
function setInitialTheme(themeSwitcher: HTMLSelectElement) {
34+
let initialTheme = window.localStorage.getItem(localStorageKey) ?? "auto";
35+
themeSwitcher.value = initialTheme;
36+
setPickedTheme(initialTheme as ThemeChoice);
37+
const systemTheme = themeQuery.matches ? "dark" : "light";
38+
updateDropdownLabel(systemTheme);
39+
}
40+
41+
/**
42+
* Updates the styles of the page to reflect a new theme
43+
*/
44+
function applyTheme(newTheme: "light" | "dark") {
45+
const otherTheme = newTheme == "light" ? "dark" : "light";
46+
window.document.documentElement.classList.remove(`${otherTheme}-theme`);
47+
window.document.documentElement.classList.add(`${newTheme}-theme`);
48+
}
49+
50+
/**
51+
* Saves a newly picked theme to storage and applies the theme.
52+
* If the new theme is "auto", the correct theme will be applied based on the system settings.
53+
*/
54+
function setPickedTheme(newTheme: ThemeChoice) {
55+
window.localStorage.setItem(localStorageKey, newTheme);
56+
autoTheme = newTheme === "auto";
57+
if (newTheme === "auto") {
58+
const systemTheme = themeQuery.matches ? "dark" : "light";
59+
applyTheme(systemTheme);
60+
} else {
61+
applyTheme(newTheme);
62+
}
63+
}
64+
65+
/**
66+
* Updates the "Auto" choice of the theme dropdown to reflect the current system theme - either "Auto (light)" or "Auto (dark)"
67+
*/
68+
function updateDropdownLabel(systemTheme: "light" | "dark") {
69+
window.document.getElementById('theme-option-auto').innerText = `Auto (${systemTheme})`;
70+
}
71+
72+
/**
73+
* Checks whether color-scheme is a supported feature of the browser.
74+
* If it is not, removes the auto option from the dropdown.
75+
*/
76+
function checkThemingSupport() {
77+
const darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
78+
const lightQuery = window.matchMedia('(prefers-color-scheme: light)');
79+
// If neither query matches, we know that the browser doesn't support theming.
80+
if (!darkQuery.matches && !lightQuery.matches) {
81+
const themeOptionAuto = window.document.getElementById('theme-option-auto');
82+
// IE doesn't support element.remove()
83+
themeOptionAuto.parentNode.removeChild(themeOptionAuto);
84+
}
85+
// If the browser does not support css properties, we do not allow theme switching.
86+
const customProperty = getComputedStyle(document.body).getPropertyValue("--body");
87+
if (!customProperty) {
88+
(document.querySelector(".theme-select-container") as HTMLDivElement).style.display = 'none';
89+
}
90+
}

Package.resolved

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@
5151
"repositoryURL": "https://github.com/SwiftDocOrg/swift-cmark.git",
5252
"state": {
5353
"branch": null,
54-
"revision": "2a766030bee955b4806044fd7aca1b6884475138",
55-
"version": "0.28.3+20200110.2a76603"
54+
"revision": "1168665f6b36be747ffe6b7b90bc54cfc17f42b7",
55+
"version": "0.28.3+20200207.1168665"
5656
}
5757
},
5858
{

Package.swift

+4
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ let package = Package(
4343
.product(name: "SwiftSyntaxHighlighter", package: "SwiftSyntaxHighlighter"),
4444
.product(name: "Logging", package: "swift-log"),
4545
.product(name: "LoggingGitHubActions", package: "LoggingGitHubActions")
46+
],
47+
resources: [
48+
.copy("Resources/all.js"),
49+
.copy("Resources/all.min.css"),
4650
]
4751
),
4852
.target(

Resources/all.min.css

-1
This file was deleted.

0 commit comments

Comments
 (0)