Skip to content

Commit 1d44014

Browse files
committedSep 24, 2021
8273034: Make javadoc navigation collapsible on small displays
Reviewed-by: jjg
1 parent bb74ae8 commit 1d44014

File tree

10 files changed

+241
-83
lines changed

10 files changed

+241
-83
lines changed
 

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

+2
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ public class HtmlIds {
8989
static final HtmlId METHOD_SUMMARY_TABLE = HtmlId.of("method-summary-table");
9090
static final HtmlId MODULES = HtmlId.of("modules-summary");
9191
static final HtmlId MODULE_DESCRIPTION = HtmlId.of("module-description");
92+
static final HtmlId NAVBAR_SUB_LIST = HtmlId.of("navbar-sub-list");
93+
static final HtmlId NAVBAR_TOGGLE_BUTTON = HtmlId.of("navbar-toggle-button");
9294
static final HtmlId NAVBAR_TOP = HtmlId.of("navbar-top");
9395
static final HtmlId NAVBAR_TOP_FIRSTROW = HtmlId.of("navbar-top-firstrow");
9496
static final HtmlId NESTED_CLASS_SUMMARY = HtmlId.of("nested-class-summary");

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

+38-12
Original file line numberDiff line numberDiff line change
@@ -350,21 +350,28 @@ private void addMainNavLinks(Content tree) {
350350
* Adds the summary links to the sub-navigation.
351351
*
352352
* @param tree the content tree to which the sub-navigation will added
353+
* @param nested whether to create a flat or nested list
353354
*/
354-
private void addSummaryLinks(Content tree) {
355+
private void addSummaryLinks(Content tree, boolean nested) {
355356
switch (documentedPage) {
356357
case MODULE, PACKAGE, CLASS, HELP -> {
357358
List<? extends Content> listContents = subNavLinks.getSubNavLinks()
358359
.stream().map(HtmlTree::LI).toList();
359360
if (!listContents.isEmpty()) {
360-
tree.add(HtmlTree.LI(switch (documentedPage) {
361+
Content label = switch (documentedPage) {
361362
case MODULE -> contents.moduleSubNavLabel;
362363
case PACKAGE -> contents.packageSubNavLabel;
363364
case CLASS -> contents.summaryLabel;
364365
case HELP -> contents.helpSubNavLabel;
365366
default -> Text.EMPTY;
366-
}).add(Entity.NO_BREAK_SPACE));
367-
addListToNav(listContents, tree);
367+
};
368+
if (nested) {
369+
tree.add(HtmlTree.LI(HtmlTree.P(label))
370+
.add(new HtmlTree(TagName.UL).add(listContents)));
371+
} else {
372+
tree.add(HtmlTree.LI(label).add(Entity.NO_BREAK_SPACE));
373+
addListToNav(listContents, tree);
374+
}
368375
}
369376
}
370377
}
@@ -374,8 +381,9 @@ private void addSummaryLinks(Content tree) {
374381
* Adds the detail links to sub-navigation.
375382
*
376383
* @param tree the content tree to which the links will be added
384+
* @param nested whether to create a flat or nested list
377385
*/
378-
private void addDetailLinks(Content tree) {
386+
private void addDetailLinks(Content tree, boolean nested) {
379387
if (documentedPage == PageMode.CLASS) {
380388
List<Content> listContents = new ArrayList<>();
381389
VisibleMemberTable vmt = configuration.getVisibleMemberTable((TypeElement) element);
@@ -394,10 +402,16 @@ private void addDetailLinks(Content tree) {
394402
}
395403
}
396404
if (!listContents.isEmpty()) {
397-
Content li = HtmlTree.LI(contents.detailLabel);
398-
li.add(Entity.NO_BREAK_SPACE);
399-
tree.add(li);
400-
addListToNav(listContents, tree);
405+
if (nested) {
406+
Content li = HtmlTree.LI(HtmlTree.P(contents.detailLabel));
407+
li.add(new HtmlTree(TagName.UL).add(listContents));
408+
tree.add(li);
409+
} else {
410+
Content li = HtmlTree.LI(contents.detailLabel);
411+
li.add(Entity.NO_BREAK_SPACE);
412+
tree.add(li);
413+
addListToNav(listContents, tree);
414+
}
401415
}
402416
}
403417
}
@@ -605,9 +619,17 @@ public Content getContent() {
605619

606620
HtmlTree navDiv = new HtmlTree(TagName.DIV);
607621
Content skipNavLinks = contents.getContent("doclet.Skip_navigation_links");
622+
String toggleNavLinks = configuration.getDocResources().getText("doclet.Toggle_navigation_links");
608623
tree.add(MarkerComments.START_OF_TOP_NAVBAR);
609624
navDiv.setStyle(HtmlStyle.topNav)
610625
.setId(HtmlIds.NAVBAR_TOP)
626+
.add(new HtmlTree(TagName.BUTTON).setId(HtmlIds.NAVBAR_TOGGLE_BUTTON)
627+
.put(HtmlAttr.ARIA_CONTROLS, HtmlIds.NAVBAR_TOP.name())
628+
.put(HtmlAttr.ARIA_EXPANDED, String.valueOf(false))
629+
.put(HtmlAttr.ARIA_LABEL, toggleNavLinks)
630+
.add(HtmlTree.SPAN(HtmlStyle.navBarToggleIcon, HtmlTree.EMPTY))
631+
.add(HtmlTree.SPAN(HtmlStyle.navBarToggleIcon, HtmlTree.EMPTY))
632+
.add(HtmlTree.SPAN(HtmlStyle.navBarToggleIcon, HtmlTree.EMPTY)))
611633
.add(HtmlTree.DIV(HtmlStyle.skipNav,
612634
links.createLink(HtmlIds.SKIP_NAVBAR_TOP, skipNavLinks,
613635
skipNavLinks.toString())));
@@ -622,18 +644,22 @@ public Content getContent() {
622644
.put(HtmlAttr.TITLE, rowListTitle);
623645
addMainNavLinks(navList);
624646
navDiv.add(navList);
647+
HtmlTree ulNavSummaryRight = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavListSmall);
648+
addSummaryLinks(ulNavSummaryRight, true);
649+
addDetailLinks(ulNavSummaryRight, true);
650+
navDiv.add(ulNavSummaryRight);
625651
tree.add(navDiv);
626652

627653
HtmlTree subDiv = new HtmlTree(TagName.DIV).setStyle(HtmlStyle.subNav);
628654

629-
HtmlTree div = new HtmlTree(TagName.DIV);
655+
HtmlTree div = new HtmlTree(TagName.DIV).setId(HtmlIds.NAVBAR_SUB_LIST);
630656
// Add the summary links if present.
631657
HtmlTree ulNavSummary = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavList);
632-
addSummaryLinks(ulNavSummary);
658+
addSummaryLinks(ulNavSummary, false);
633659
div.add(ulNavSummary);
634660
// Add the detail links if present.
635661
HtmlTree ulNavDetail = new HtmlTree(TagName.UL).setStyle(HtmlStyle.subNavList);
636-
addDetailLinks(ulNavDetail);
662+
addDetailLinks(ulNavDetail, false);
637663
div.add(ulNavDetail);
638664
subDiv.add(div);
639665

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlAttr.java

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
public enum HtmlAttr {
3939
ALT,
4040
ARIA_CONTROLS("aria-controls"),
41+
ARIA_EXPANDED("aria-expanded"),
42+
ARIA_LABEL("aria-label"),
4143
ARIA_LABELLEDBY("aria-labelledby"),
4244
ARIA_ORIENTATION("aria-orientation"),
4345
ARIA_SELECTED("aria-selected"),

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java

+10
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ public enum HtmlStyle {
103103
// The etymology of the name is a mystery.
104104
navBarCell1Rev,
105105

106+
/**
107+
* The class for the navigation bar toggle button for smaller displays.
108+
*/
109+
navBarToggleIcon,
110+
106111
/**
107112
* The class for the primary list of navigation links.
108113
*/
@@ -130,6 +135,11 @@ public enum HtmlStyle {
130135
*/
131136
subNavList,
132137

138+
/**
139+
* The class for the list of subsidiary navigation links for smaller displays.
140+
*/
141+
subNavListSmall,
142+
133143
//</editor-fold>
134144

135145
//<editor-fold desc="header (title block)">

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

+29
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,35 @@ function doSearch(request, response) {
291291
response(result);
292292
}
293293
$(function() {
294+
var expanded = false;
295+
var windowWidth;
296+
function collapse() {
297+
if (expanded) {
298+
$("div#navbar-top").removeAttr("style");
299+
$("button#navbar-toggle-button")
300+
.removeClass("expanded")
301+
.attr("aria-expanded", "false");
302+
expanded = false;
303+
}
304+
}
305+
$("button#navbar-toggle-button").click(function (e) {
306+
if (expanded) {
307+
collapse();
308+
} else {
309+
$("div#navbar-top").height($("#navbar-top").prop("scrollHeight"));
310+
$("button#navbar-toggle-button")
311+
.addClass("expanded")
312+
.attr("aria-expanded", "true");
313+
expanded = true;
314+
windowWidth = window.innerWidth;
315+
}
316+
});
317+
$("ul.sub-nav-list-small li a").click(collapse);
318+
$("input#search-input").focus(collapse);
319+
$("main").click(collapse);
320+
$(window).on("orientationchange", collapse).on("resize", function(e) {
321+
if (expanded && windowWidth !== window.innerWidth) collapse();
322+
});
294323
$("#search-input").catcomplete({
295324
minLength: 1,
296325
delay: 300,

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ doclet.Window_Single_Index=Index
7878
doclet.Window_Split_Index={0}-Index
7979
doclet.Help=Help
8080
doclet.Skip_navigation_links=Skip navigation links
81+
doclet.Toggle_navigation_links=Toggle navigation links
8182
doclet.Navigation=Navigation
8283
doclet.navDeprecated=Deprecated
8384
doclet.Window_Deprecated_List=Deprecated List

‎src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css

+145-57
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,17 @@ button {
128128
* Styles for navigation bar.
129129
*/
130130
@media screen {
131-
.flex-box {
131+
div.flex-box {
132132
position:fixed;
133133
display:flex;
134134
flex-direction:column;
135135
height: 100%;
136136
width: 100%;
137137
}
138-
.flex-header {
138+
header.flex-header {
139139
flex: 0 0 auto;
140140
}
141-
.flex-content {
141+
div.flex-content {
142142
flex: 1 1 auto;
143143
overflow-y: auto;
144144
}
@@ -155,6 +155,12 @@ button {
155155
overflow:hidden;
156156
font-size:12px;
157157
}
158+
button#navbar-toggle-button {
159+
display:none;
160+
}
161+
ul.sub-nav-list-small {
162+
display: none;
163+
}
158164
.sub-nav {
159165
background-color:#dee3e9;
160166
float:left;
@@ -165,11 +171,11 @@ button {
165171
.sub-nav div {
166172
clear:left;
167173
float:left;
168-
padding:0 0 5px 6px;
174+
padding:6px;
169175
text-transform:uppercase;
170176
}
171-
.sub-nav .nav-list {
172-
padding-top:5px;
177+
.sub-nav .sub-nav-list {
178+
padding-top:4px;
173179
}
174180
ul.nav-list {
175181
display:block;
@@ -189,28 +195,23 @@ ul.nav-list li {
189195
}
190196
.sub-nav .nav-list-search {
191197
float:right;
192-
margin:0 0 0 0;
193-
padding:5px 6px;
198+
margin:0;
199+
padding:6px;
194200
clear:none;
195-
}
196-
.nav-list-search label {
201+
text-align:right;
197202
position:relative;
198-
right:-16px;
199203
}
200204
ul.sub-nav-list li {
201205
list-style:none;
202206
float:left;
203-
padding-top:10px;
204207
}
205208
.top-nav a:link, .top-nav a:active, .top-nav a:visited {
206-
color:#FFFFFF;
209+
color:#ffffff;
207210
text-decoration:none;
208211
text-transform:uppercase;
209212
}
210213
.top-nav a:hover {
211-
text-decoration:none;
212214
color:#bb7a2a;
213-
text-transform:uppercase;
214215
}
215216
.nav-bar-cell1-rev {
216217
background-color:#F8981D;
@@ -626,23 +627,22 @@ ul.ui-autocomplete li {
626627
background-repeat:no-repeat;
627628
background-position:2px 3px;
628629
padding-left:20px;
629-
position:relative;
630-
right:-18px;
631-
width:400px;
630+
width: 250px;
631+
margin: 0;
632632
}
633633
#reset-button {
634-
background-color: rgb(255,255,255);
634+
background-color: transparent;
635635
background-image:url('resources/x.png');
636-
background-position:center;
637636
background-repeat:no-repeat;
638-
background-size:12px;
639-
border:0 none;
640-
width:16px;
641-
height:16px;
642-
position:relative;
643-
left:-4px;
644-
top:-4px;
645-
font-size:0px;
637+
background-size:contain;
638+
border:0;
639+
border-radius:0;
640+
width:12px;
641+
height:12px;
642+
position:absolute;
643+
right:12px;
644+
top:10px;
645+
font-size:0;
646646
}
647647
.watermark {
648648
color:#545454;
@@ -807,34 +807,113 @@ table.striped > tbody > tr > th {
807807
font-weight: normal;
808808
}
809809
/**
810-
* Tweak font sizes and paddings for small screens.
810+
* Tweak style for small screens.
811811
*/
812-
@media screen and (max-width: 1050px) {
813-
#search-input {
814-
width: 300px;
812+
@media screen and (max-width: 920px) {
813+
header.flex-header {
814+
max-height: 100vh;
815+
overflow-y: auto;
815816
}
816-
}
817-
@media screen and (max-width: 800px) {
818-
#search-input {
819-
width: 200px;
817+
div#navbar-top {
818+
height: 2.8em;
819+
transition: height 0.35s ease;
820+
}
821+
ul.nav-list {
822+
display: block;
823+
width: 40%;
824+
float:left;
825+
clear: left;
826+
margin: 10px 0 0 0;
827+
padding: 0;
828+
}
829+
ul.nav-list li {
830+
float: none;
831+
padding: 6px;
832+
margin-left: 10px;
833+
margin-top: 2px;
834+
}
835+
ul.sub-nav-list-small {
836+
display:block;
837+
height: 100%;
838+
width: 50%;
839+
float: right;
840+
clear: right;
841+
background-color: #dee3e9;
842+
color: #353833;
843+
margin: 6px 0 0 0;
844+
padding: 0;
845+
}
846+
ul.sub-nav-list-small ul {
847+
padding-left: 20px;
820848
}
821-
.top-nav,
822-
.bottom-nav {
823-
font-size: 11px;
824-
padding-top: 6px;
849+
ul.sub-nav-list-small a:link, ul.sub-nav-list-small a:visited {
850+
color:#4A6782;
825851
}
826-
.sub-nav {
827-
font-size: 11px;
852+
ul.sub-nav-list-small a:hover {
853+
color:#bb7a2a;
828854
}
855+
ul.sub-nav-list-small li {
856+
list-style:none;
857+
float:none;
858+
padding: 6px;
859+
margin-top: 1px;
860+
text-transform:uppercase;
861+
}
862+
ul.sub-nav-list-small > li {
863+
margin-left: 10px;
864+
}
865+
ul.sub-nav-list-small li p {
866+
margin: 5px 0;
867+
}
868+
div#navbar-sub-list {
869+
display: none;
870+
}
871+
.top-nav a:link, .top-nav a:active, .top-nav a:visited {
872+
display: block;
873+
}
874+
button#navbar-toggle-button {
875+
width: 3.4em;
876+
height: 2.8em;
877+
background-color: transparent;
878+
display: block;
879+
float: left;
880+
border: 0;
881+
margin: 0 10px;
882+
cursor: pointer;
883+
font-size: 10px;
884+
}
885+
button#navbar-toggle-button .nav-bar-toggle-icon {
886+
display: block;
887+
width: 24px;
888+
height: 3px;
889+
margin: 1px 0 4px 0;
890+
border-radius: 2px;
891+
transition: all 0.1s;
892+
background-color: #ffffff;
893+
}
894+
button#navbar-toggle-button.expanded span.nav-bar-toggle-icon:nth-child(1) {
895+
transform: rotate(45deg);
896+
transform-origin: 10% 10%;
897+
width: 26px;
898+
}
899+
button#navbar-toggle-button.expanded span.nav-bar-toggle-icon:nth-child(2) {
900+
opacity: 0;
901+
}
902+
button#navbar-toggle-button.expanded span.nav-bar-toggle-icon:nth-child(3) {
903+
transform: rotate(-45deg);
904+
transform-origin: 10% 90%;
905+
width: 26px;
906+
}
907+
}
908+
@media screen and (max-width: 800px) {
829909
.about-language {
830910
padding-right: 16px;
831911
}
832-
ul.nav-list li,
833-
.sub-nav .nav-list-search {
834-
padding: 6px;
912+
ul.nav-list li {
913+
margin-left: 5px;
835914
}
836-
ul.sub-nav-list li {
837-
padding-top: 5px;
915+
ul.sub-nav-list-small > li {
916+
margin-left: 5px;
838917
}
839918
main {
840919
padding: 10px;
@@ -847,20 +926,29 @@ table.striped > tbody > tr > th {
847926
-webkit-text-size-adjust: none;
848927
}
849928
}
850-
@media screen and (max-width: 500px) {
929+
@media screen and (max-width: 400px) {
930+
.about-language {
931+
font-size: 10px;
932+
padding-right: 12px;
933+
}
934+
}
935+
@media screen and (max-width: 400px) {
936+
.nav-list-search {
937+
width: 94%;
938+
}
851939
#search-input {
852-
width: 150px;
940+
width: 70%;
853941
}
854-
.top-nav,
855-
.bottom-nav {
856-
font-size: 10px;
942+
}
943+
@media screen and (max-width: 320px) {
944+
.nav-list-search > label {
945+
display: none;
857946
}
858-
.sub-nav {
859-
font-size: 10px;
947+
.nav-list-search {
948+
width: 90%;
860949
}
861-
.about-language {
862-
font-size: 10px;
863-
padding-right: 12px;
950+
#search-input {
951+
width: 80%;
864952
}
865953
}
866954

‎test/langtools/jdk/javadoc/doclet/checkStylesheetClasses/CheckStylesheetClasses.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ void run() throws Exception {
151151
// (a) it is a poorly chosen name
152152
// (b) it does not seem to be used in make/Docs.gmk or anywhere else
153153
removeAll(styleSheetNames, "all-classes-container", "all-packages-container",
154-
"bottom-nav", "clear", "constant-values-container", "deprecated-content",
154+
"clear", "constant-values-container", "deprecated-content", "expanded",
155155
"footer", "hidden", "override-specify-label", "serialized-class-details",
156156
"tab", "table-sub-heading-color");
157157

‎test/langtools/jdk/javadoc/doclet/testPackageSummary/TestPackageSummary.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public void testSummaryLinks() {
5252
checkOutput("pkg/package-summary.html", true,
5353
"""
5454
<div class="sub-nav">
55-
<div>
55+
<div id="navbar-sub-list">
5656
<ul class="sub-nav-list">
5757
<li>Package:&nbsp;</li>
5858
<li>Description&nbsp;|&nbsp;</li>
@@ -63,7 +63,7 @@ public void testSummaryLinks() {
6363
checkOutput("pkg1/package-summary.html", true,
6464
"""
6565
<div class="sub-nav">
66-
<div>
66+
<div id="navbar-sub-list">
6767
<ul class="sub-nav-list">
6868
<li>Package:&nbsp;</li>
6969
<li><a href="#package-description">Description</a>&nbsp;|&nbsp;</li>
@@ -74,7 +74,7 @@ public void testSummaryLinks() {
7474
checkOutput("pkg1/sub/package-summary.html", true,
7575
"""
7676
<div class="sub-nav">
77-
<div>
77+
<div id="navbar-sub-list">
7878
<ul class="sub-nav-list">
7979
<li>Package:&nbsp;</li>
8080
<li>Description&nbsp;|&nbsp;</li>

‎test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -180,18 +180,18 @@ public void test(Path base) {
180180
}""",
181181
"""
182182
#reset-button {
183-
background-color: rgb(255,255,255);
183+
background-color: transparent;
184184
background-image:url('resources/x.png');
185-
background-position:center;
186185
background-repeat:no-repeat;
187-
background-size:12px;
188-
border:0 none;
189-
width:16px;
190-
height:16px;
191-
position:relative;
192-
left:-4px;
193-
top:-4px;
194-
font-size:0px;
186+
background-size:contain;
187+
border:0;
188+
border-radius:0;
189+
width:12px;
190+
height:12px;
191+
position:absolute;
192+
right:12px;
193+
top:10px;
194+
font-size:0;
195195
}""",
196196
"""
197197
.watermark {

0 commit comments

Comments
 (0)
Please sign in to comment.