Skip to content

Commit 49f51f9

Browse files
committed
8370612: Simplify implementation of dark theme
8371021: Tab order in theme picker is broken Reviewed-by: jlamperth, liach
1 parent c0b82ff commit 49f51f9

File tree

9 files changed

+114
-419
lines changed

9 files changed

+114
-419
lines changed

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Navigation.java

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -500,14 +500,28 @@ private void addHelpLink(Content target) {
500500
private void addThemeSwitcher(Content target) {
501501
var selectTheme = contents.getContent("doclet.theme.select_theme");
502502
target.add(HtmlTree.LI(HtmlTree.BUTTON(HtmlIds.THEME_BUTTON)
503-
.add(HtmlTree.IMG(pathToRoot.resolve(DocPaths.RESOURCE_FILES).resolve(DocPaths.SUN_SVG),
504-
selectTheme.toString()).addStyle(HtmlIds.THEME_LIGHT.name()))
505-
.add(HtmlTree.IMG(pathToRoot.resolve(DocPaths.RESOURCE_FILES).resolve(DocPaths.MOON_SVG),
506-
selectTheme.toString()).addStyle(HtmlIds.THEME_DARK.name()))
507503
.put(HtmlAttr.ARIA_LABEL, selectTheme.toString())
508504
.put(HtmlAttr.TITLE, selectTheme.toString())));
509505
}
510506

507+
private void addThemePanel(Content target) {
508+
var selectTheme = contents.getContent("doclet.theme.select_theme");
509+
target.add(HtmlTree.DIV(HtmlIds.THEME_PANEL)
510+
.add(HtmlTree.DIV(selectTheme))
511+
.add(HtmlTree.DIV(HtmlTree.LABEL(HtmlIds.THEME_LIGHT.name(), Text.EMPTY)
512+
.add(HtmlTree.INPUT(HtmlAttr.InputType.RADIO, HtmlIds.THEME_LIGHT)
513+
.put(HtmlAttr.NAME, "theme").put(HtmlAttr.VALUE, HtmlIds.THEME_LIGHT.name()))
514+
.add(HtmlTree.SPAN(contents.getContent("doclet.theme.light"))))
515+
.add(HtmlTree.LABEL(HtmlIds.THEME_DARK.name(), Text.EMPTY)
516+
.add(HtmlTree.INPUT(HtmlAttr.InputType.RADIO, HtmlIds.THEME_DARK)
517+
.put(HtmlAttr.NAME, "theme").put(HtmlAttr.VALUE, HtmlIds.THEME_DARK.name()))
518+
.add(HtmlTree.SPAN(contents.getContent("doclet.theme.dark"))))
519+
.add(HtmlTree.LABEL(HtmlIds.THEME_OS.name(), Text.EMPTY)
520+
.add(HtmlTree.INPUT(HtmlAttr.InputType.RADIO, HtmlIds.THEME_OS)
521+
.put(HtmlAttr.NAME, "theme").put(HtmlAttr.VALUE, HtmlIds.THEME_OS.name()))
522+
.add(HtmlTree.SPAN(contents.getContent("doclet.theme.system"))))));
523+
}
524+
511525
private void addSearch(Content target) {
512526
var resources = configuration.getDocResources();
513527
var inputText = HtmlTree.INPUT(HtmlAttr.InputType.TEXT, HtmlIds.SEARCH_INPUT)
@@ -557,6 +571,7 @@ public Content getContent() {
557571
.put(HtmlAttr.TITLE, rowListTitle);
558572
addMainNavLinks(navList);
559573
navContent.add(navList);
574+
addThemePanel(navContent);
560575
var aboutDiv = HtmlTree.DIV(HtmlStyles.aboutLanguage, aboutContent);
561576
navContent.add(aboutDiv);
562577
navigationBar.add(HtmlTree.DIV(HtmlStyles.topNav, navContent).setId(HtmlIds.NAVBAR_TOP));
@@ -574,22 +589,6 @@ public Content getContent() {
574589
breadcrumbNav.addAll(subNavLinks, HtmlTree::LI);
575590
subNavContent.addUnchecked(breadcrumbNav);
576591

577-
var selectTheme = contents.getContent("doclet.theme.select_theme");
578-
subNavContent.add(HtmlTree.DIV(HtmlIds.THEME_PANEL)
579-
.add(HtmlTree.DIV(selectTheme))
580-
.add(HtmlTree.DIV(HtmlTree.LABEL(HtmlIds.THEME_LIGHT.name(), Text.EMPTY)
581-
.add(HtmlTree.INPUT(HtmlAttr.InputType.RADIO, HtmlIds.THEME_LIGHT)
582-
.put(HtmlAttr.NAME, "theme").put(HtmlAttr.VALUE, HtmlIds.THEME_LIGHT.name()))
583-
.add(HtmlTree.SPAN(contents.getContent("doclet.theme.light"))))
584-
.add(HtmlTree.LABEL(HtmlIds.THEME_DARK.name(), Text.EMPTY)
585-
.add(HtmlTree.INPUT(HtmlAttr.InputType.RADIO, HtmlIds.THEME_DARK)
586-
.put(HtmlAttr.NAME, "theme").put(HtmlAttr.VALUE, HtmlIds.THEME_DARK.name()))
587-
.add(HtmlTree.SPAN(contents.getContent("doclet.theme.dark"))))
588-
.add(HtmlTree.LABEL(HtmlIds.THEME_OS.name(), Text.EMPTY)
589-
.add(HtmlTree.INPUT(HtmlAttr.InputType.RADIO, HtmlIds.THEME_OS)
590-
.put(HtmlAttr.NAME, "theme").put(HtmlAttr.VALUE, HtmlIds.THEME_OS.name()))
591-
.add(HtmlTree.SPAN(contents.getContent("doclet.theme.system"))))));
592-
593592
if (options.createIndex() && documentedPage != PageMode.SEARCH) {
594593
addSearch(subNavContent);
595594
}

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/highlight.css

Lines changed: 1 addition & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
/* ignored */
6666
}
6767

68-
body.theme-dark {
68+
:root[data-theme="theme-dark"] {
6969
.hljs-title.function_,
7070
.hljs-template-variable {
7171
color: #66bcce;
@@ -126,127 +126,3 @@ body.theme-dark {
126126
/* ignored */
127127
}
128128
}
129-
130-
@media (prefers-color-scheme: dark) {
131-
.hljs-title.function_,
132-
.hljs-template-variable {
133-
color: #66bcce;
134-
}
135-
.hljs-code,
136-
.hljs-comment,
137-
.hljs-quote {
138-
color:#9d9d9d;
139-
font-style: italic;
140-
}
141-
.hljs-meta {
142-
color: #836F00;
143-
}
144-
.hljs-symbol,
145-
.hljs-template-tag,
146-
.hljs-keyword,
147-
.hljs-literal,
148-
.hljs-name,
149-
.hljs-built_in,
150-
.hljs-char.escape_ {
151-
color: #88aece;
152-
}
153-
.hljs-variable,
154-
.hljs-property,
155-
.hljs-attr,
156-
.hljs-section {
157-
color: #c59bc1;
158-
}
159-
.hljs-attribute {
160-
color: #c59bc1;
161-
}
162-
.hljs-regexp,
163-
.hljs-number {
164-
color: #cfe374;
165-
}
166-
.hljs-link {
167-
color: #b5bd68;
168-
}
169-
.hljs-string {
170-
color: #b5bd68;
171-
}
172-
.hljs-doctag {
173-
text-decoration: underline;
174-
}
175-
.hljs-emphasis {
176-
font-style: italic;
177-
}
178-
.hljs-strong {
179-
font-weight: bold;
180-
}
181-
.hljs-subst,
182-
.hljs-title,
183-
.hljs-params,
184-
.hljs-bullet,
185-
.hljs-formula,
186-
.hljs-tag,
187-
.hljs-type {
188-
/* ignored */
189-
}
190-
191-
body.theme-light {
192-
.hljs-title.function_,
193-
.hljs-template-variable {
194-
color: #00738F;
195-
}
196-
.hljs-code,
197-
.hljs-comment,
198-
.hljs-quote {
199-
color: #6e6e71;
200-
font-style: italic;
201-
}
202-
.hljs-meta {
203-
color: #836F00;
204-
}
205-
.hljs-symbol,
206-
.hljs-template-tag,
207-
.hljs-keyword,
208-
.hljs-literal,
209-
.hljs-name,
210-
.hljs-built_in,
211-
.hljs-char.escape_ {
212-
color: #0C40C2;
213-
}
214-
.hljs-variable,
215-
.hljs-property,
216-
.hljs-attr,
217-
.hljs-section {
218-
color: #841191;
219-
}
220-
.hljs-attribute {
221-
color: #164ad9;
222-
}
223-
.hljs-regexp,
224-
.hljs-number {
225-
color: #104BEB;
226-
}
227-
.hljs-link {
228-
color: #47688a;
229-
}
230-
.hljs-string {
231-
color: #008313;
232-
}
233-
.hljs-doctag {
234-
text-decoration: underline;
235-
}
236-
.hljs-emphasis {
237-
font-style: italic;
238-
}
239-
.hljs-strong {
240-
font-weight: bold;
241-
}
242-
.hljs-subst,
243-
.hljs-title,
244-
.hljs-params,
245-
.hljs-bullet,
246-
.hljs-formula,
247-
.hljs-tag,
248-
.hljs-type {
249-
/* ignored */
250-
}
251-
}
252-
}

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ const sortAsc = "sort-asc";
1717
const sortDesc = "sort-desc";
1818
const tableTab = "table-tab";
1919
const activeTableTab = "active-table-tab";
20-
const THEMES = Object.freeze(["theme-light", "theme-dark", "theme-os"]);
20+
const THEME_LIGHT = "theme-light";
21+
const THEME_DARK = "theme-dark";
22+
const THEME_OS = "theme-os";
2123

2224
const linkIcon = "##REPLACE:doclet.Link_icon##";
2325
const linkToSection = "##REPLACE:doclet.Link_to_section##";
@@ -320,12 +322,21 @@ function makeFilterWidget(sidebar, updateToc) {
320322
return sidebar;
321323
}
322324

325+
const osDarkTheme = window.matchMedia("(prefers-color-scheme: dark)");
326+
osDarkTheme.addEventListener("change", e => {
327+
if (getTheme() === THEME_OS) {
328+
setTheme(THEME_OS);
329+
}
330+
});
323331
function getTheme() {
324-
return localStorage.getItem('theme') || THEMES[0];
332+
return localStorage.getItem("theme") || THEME_LIGHT;
333+
}
334+
function setTheme(theme) {
335+
var value = theme !== THEME_OS ? theme : osDarkTheme.matches ? THEME_DARK : THEME_LIGHT;
336+
document.documentElement.setAttribute("data-theme", value);
325337
}
326-
327338
function initTheme() {
328-
document.body.classList.add(getTheme());
339+
setTheme(getTheme());
329340
}
330341

331342
function setTopMargin() {
@@ -347,7 +358,6 @@ document.addEventListener("readystatechange", (e) => {
347358

348359
document.addEventListener("DOMContentLoaded", function(e) {
349360
setTopMargin();
350-
const subnav = document.querySelector("ol.sub-nav-list");
351361
const keymap = new Map();
352362
const searchInput = document.getElementById("search-input")
353363
|| document.getElementById("page-search-input");
@@ -360,10 +370,9 @@ document.addEventListener("DOMContentLoaded", function(e) {
360370
keymap.set(".", filterInput);
361371
}
362372
// Clone TOC sidebar to header for mobile navigation
363-
const navbar = document.querySelector("div#navbar-top");
364373
const sidebar = document.querySelector(".main-grid nav.toc");
365374
const main = document.querySelector(".main-grid main");
366-
const mainnav = navbar.querySelector("ul.nav-list");
375+
const mainnav = document.querySelector("div#navbar-top ul.nav-list");
367376
const toggleButton = document.querySelector("button#navbar-toggle-button");
368377
const tocMenu = sidebar ? sidebar.cloneNode(true) : null;
369378
const themeButton = document.querySelector("button#theme-button");
@@ -401,19 +410,22 @@ document.addEventListener("DOMContentLoaded", function(e) {
401410
}
402411
input.addEventListener("change", e => {
403412
setTheme(e.target.value);
413+
localStorage.setItem("theme", e.target.value);
404414
})
405415
});
406-
function setTheme(theme) {
407-
THEMES.forEach(t => {
408-
if (t !== theme) document.body.classList.remove(t);
409-
});
410-
document.body.classList.add(theme);
411-
localStorage.setItem("theme", theme);
412-
document.getElementById(theme).checked = true;
413-
}
416+
themePanel.addEventListener("focusout", e => {
417+
if (e.relatedTarget && !themePanel.contains(e.relatedTarget) && !themeButton.contains(e.relatedTarget)) {
418+
closeThemePanel();
419+
}
420+
});
421+
themePanel.addEventListener("keydown", e => {
422+
if (e.key === "Escape" || e.key === "Enter") {
423+
closeThemePanel();
424+
}
425+
});
414426
makeFilterWidget(sidebar, updateToc);
415427
if (tocMenu) {
416-
navbar.appendChild(tocMenu);
428+
document.querySelector("div#navbar-top").appendChild(tocMenu);
417429
makeFilterWidget(tocMenu, updateToc);
418430
var menuInput = tocMenu.querySelector("input.filter-input");
419431
}
@@ -473,7 +485,7 @@ document.addEventListener("DOMContentLoaded", function(e) {
473485
expanded = true;
474486
mainnav.style.display = "block";
475487
mainnav.style.removeProperty("height");
476-
var maxHeight = window.innerHeight - subnav.offsetTop + 4;
488+
var maxHeight = window.innerHeight - document.querySelector("div.sub-nav").offsetTop;
477489
var expandedHeight = Math.min(maxHeight, mainnav.scrollHeight + 10);
478490
if (tocMenu) {
479491
tocMenu.style.display = "flex";

0 commit comments

Comments
 (0)