feat(dropdowns): Add nested list support

This commit is contained in:
Lucas Larroche 2022-02-28 01:57:59 +07:00
parent e54d1ee4f7
commit 083d7e7e6a
15 changed files with 517 additions and 370 deletions

View file

@ -2096,15 +2096,17 @@ progress::-moz-progress-bar {
background-position: -200% 0;
}
}
details[role=list] {
/**
* Dropdown ([role="list"])
*/
details[role=list],
li[role=list] {
position: relative;
padding: 0;
border-bottom: none;
}
details[role=list] summary {
margin: 0;
}
details[role=list] summary + ul {
details[role=list] summary + ul,
details[role=list] > ul,
li[role=list] summary + ul,
li[role=list] > ul {
display: flex;
z-index: 99;
position: absolute;
@ -2112,9 +2114,6 @@ details[role=list] summary + ul {
right: 0;
left: 0;
flex-direction: column;
min-width: -webkit-fit-content;
min-width: -moz-fit-content;
min-width: fit-content;
margin: 0;
padding: 0;
border: var(--border-width) solid var(--dropdown-border-color);
@ -2126,37 +2125,83 @@ details[role=list] summary + ul {
color: var(--dropdown-color);
white-space: nowrap;
}
details[role=list] summary + ul li {
details[role=list] summary + ul li,
details[role=list] > ul li,
li[role=list] summary + ul li,
li[role=list] > ul li {
width: 100%;
margin-bottom: 0;
padding: calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);
list-style: none;
}
details[role=list] summary + ul li:first-of-type {
details[role=list] summary + ul li:first-of-type,
details[role=list] > ul li:first-of-type,
li[role=list] summary + ul li:first-of-type,
li[role=list] > ul li:first-of-type {
margin-top: calc(var(--form-element-spacing-vertical) * 0.5);
}
details[role=list] summary + ul li:last-of-type {
details[role=list] summary + ul li:last-of-type,
details[role=list] > ul li:last-of-type,
li[role=list] summary + ul li:last-of-type,
li[role=list] > ul li:last-of-type {
margin-bottom: calc(var(--form-element-spacing-vertical) * 0.5);
}
details[role=list] summary + ul li a {
details[role=list] summary + ul li a,
details[role=list] > ul li a,
li[role=list] summary + ul li a,
li[role=list] > ul li a {
display: block;
margin: calc(var(--form-element-spacing-vertical) * -0.5) calc(var(--form-element-spacing-horizontal) * -1);
padding: calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);
overflow: hidden;
color: var(--dropdown-color);
text-decoration: none;
text-overflow: ellipsis;
}
details[role=list] summary + ul li a:hover {
details[role=list] summary + ul li a:hover,
details[role=list] > ul li a:hover,
li[role=list] summary + ul li a:hover,
li[role=list] > ul li a:hover {
background-color: var(--dropdown-hover-background-color);
}
details[role=list] summary::after {
details[role=list] summary::after,
li[role=list] > a::after {
display: block;
width: 1.5rem;
height: calc(1rem * var(--line-height));
float: right;
transform: rotate(0deg);
background-position: right;
background-size: 1rem auto;
background-repeat: no-repeat;
content: "";
}
details[role=list][disabled] summary, details[role=list].disabled summary {
border-color: var(--form-element-disabled-border-color);
background-color: var(--form-element-disabled-background-color);
opacity: var(--form-element-disabled-opacity);
pointer-events: none;
details[role=list] {
padding: 0;
border-bottom: none;
}
details[role=list] summary {
margin-bottom: 0;
}
details[role=list] summary:not([role=button]) {
height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
details[role=list] summary:not([role=button]):active, details[role=list] summary:not([role=button]):focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
details[role=list] summary:not([role=button]):focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
details[role=list][open] summary {
border-bottom-right-radius: 0;
@ -2175,55 +2220,38 @@ details[role=list][open] summary::before {
cursor: default;
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]) {
height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):active, *:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
nav ul li details[role=list] {
display: inline-block;
margin: calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);
}
nav ul li details[role=list] summary:not([role=button]) {
padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
border-radius: var(--border-radius);
line-height: var(--line-height);
}
nav ul li details[role=list] summary:not([role=button]):focus {
background-color: var(--primary-focus);
}
nav ul li details[role=list] summary:not([role=button]) a {
pointer-events: none;
}
nav ul li details[role=list] summary:not([role=button]) a:focus {
background-color: transparent;
}
nav ul li details[role=list][open] summary {
nav [role=list] summary + ul,
nav [role=list] > ul {
min-width: -webkit-fit-content;
min-width: -moz-fit-content;
min-width: fit-content;
border-radius: var(--border-radius);
}
nav ul li details[role=list][open] summary + ul {
margin-top: calc(var(--nav-link-spacing-horizontal) * 0.5);
border-radius: var(--border-radius);
}
nav ul li details[role=list][open] summary + ul a {
nav [role=list] summary + ul li a,
nav [role=list] > ul li a {
border-radius: 0;
}
nav ul li details[role=list][open] summary[role=button] + ul {
margin-top: var(--nav-link-spacing-horizontal);
nav [role=list][open] summary {
border-radius: var(--border-radius);
}
nav [role=list] summary + ul {
margin-top: 2px;
}
li[role=list]:hover > ul,
li[role=list] a:active ~ ul,
li[role=list] a:focus ~ ul {
display: flex;
}
li[role=list] > ul {
display: none;
margin-top: calc(var(--nav-link-spacing-vertical) + 2px);
-webkit-margin-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
margin-inline-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
}
li[role=list] > a::after {
background-image: var(--icon-chevron);
}
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -2393,15 +2393,17 @@ progress::-moz-progress-bar {
background-position: -200% 0;
}
}
details[role=list] {
/**
* Dropdown ([role="list"])
*/
details[role=list],
li[role=list] {
position: relative;
padding: 0;
border-bottom: none;
}
details[role=list] summary {
margin: 0;
}
details[role=list] summary + ul {
details[role=list] summary + ul,
details[role=list] > ul,
li[role=list] summary + ul,
li[role=list] > ul {
display: flex;
z-index: 99;
position: absolute;
@ -2409,9 +2411,6 @@ details[role=list] summary + ul {
right: 0;
left: 0;
flex-direction: column;
min-width: -webkit-fit-content;
min-width: -moz-fit-content;
min-width: fit-content;
margin: 0;
padding: 0;
border: var(--border-width) solid var(--dropdown-border-color);
@ -2423,37 +2422,83 @@ details[role=list] summary + ul {
color: var(--dropdown-color);
white-space: nowrap;
}
details[role=list] summary + ul li {
details[role=list] summary + ul li,
details[role=list] > ul li,
li[role=list] summary + ul li,
li[role=list] > ul li {
width: 100%;
margin-bottom: 0;
padding: calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);
list-style: none;
}
details[role=list] summary + ul li:first-of-type {
details[role=list] summary + ul li:first-of-type,
details[role=list] > ul li:first-of-type,
li[role=list] summary + ul li:first-of-type,
li[role=list] > ul li:first-of-type {
margin-top: calc(var(--form-element-spacing-vertical) * 0.5);
}
details[role=list] summary + ul li:last-of-type {
details[role=list] summary + ul li:last-of-type,
details[role=list] > ul li:last-of-type,
li[role=list] summary + ul li:last-of-type,
li[role=list] > ul li:last-of-type {
margin-bottom: calc(var(--form-element-spacing-vertical) * 0.5);
}
details[role=list] summary + ul li a {
details[role=list] summary + ul li a,
details[role=list] > ul li a,
li[role=list] summary + ul li a,
li[role=list] > ul li a {
display: block;
margin: calc(var(--form-element-spacing-vertical) * -0.5) calc(var(--form-element-spacing-horizontal) * -1);
padding: calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);
overflow: hidden;
color: var(--dropdown-color);
text-decoration: none;
text-overflow: ellipsis;
}
details[role=list] summary + ul li a:hover {
details[role=list] summary + ul li a:hover,
details[role=list] > ul li a:hover,
li[role=list] summary + ul li a:hover,
li[role=list] > ul li a:hover {
background-color: var(--dropdown-hover-background-color);
}
details[role=list] summary::after {
details[role=list] summary::after,
li[role=list] > a::after {
display: block;
width: 1.5rem;
height: calc(1rem * var(--line-height));
float: right;
transform: rotate(0deg);
background-position: right;
background-size: 1rem auto;
background-repeat: no-repeat;
content: "";
}
details[role=list][disabled] summary, details[role=list].disabled summary {
border-color: var(--form-element-disabled-border-color);
background-color: var(--form-element-disabled-background-color);
opacity: var(--form-element-disabled-opacity);
pointer-events: none;
details[role=list] {
padding: 0;
border-bottom: none;
}
details[role=list] summary {
margin-bottom: 0;
}
details[role=list] summary:not([role=button]) {
height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
details[role=list] summary:not([role=button]):active, details[role=list] summary:not([role=button]):focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
details[role=list] summary:not([role=button]):focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
details[role=list][open] summary {
border-bottom-right-radius: 0;
@ -2472,55 +2517,38 @@ details[role=list][open] summary::before {
cursor: default;
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]) {
height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):active, *:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
nav ul li details[role=list] {
display: inline-block;
margin: calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);
}
nav ul li details[role=list] summary:not([role=button]) {
padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
border-radius: var(--border-radius);
line-height: var(--line-height);
}
nav ul li details[role=list] summary:not([role=button]):focus {
background-color: var(--primary-focus);
}
nav ul li details[role=list] summary:not([role=button]) a {
pointer-events: none;
}
nav ul li details[role=list] summary:not([role=button]) a:focus {
background-color: transparent;
}
nav ul li details[role=list][open] summary {
nav [role=list] summary + ul,
nav [role=list] > ul {
min-width: -webkit-fit-content;
min-width: -moz-fit-content;
min-width: fit-content;
border-radius: var(--border-radius);
}
nav ul li details[role=list][open] summary + ul {
margin-top: calc(var(--nav-link-spacing-horizontal) * 0.5);
border-radius: var(--border-radius);
}
nav ul li details[role=list][open] summary + ul a {
nav [role=list] summary + ul li a,
nav [role=list] > ul li a {
border-radius: 0;
}
nav ul li details[role=list][open] summary[role=button] + ul {
margin-top: var(--nav-link-spacing-horizontal);
nav [role=list][open] summary {
border-radius: var(--border-radius);
}
nav [role=list] summary + ul {
margin-top: 2px;
}
li[role=list]:hover > ul,
li[role=list] a:active ~ ul,
li[role=list] a:focus ~ ul {
display: flex;
}
li[role=list] > ul {
display: none;
margin-top: calc(var(--nav-link-spacing-vertical) + 2px);
-webkit-margin-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
margin-inline-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
}
li[role=list] > a::after {
background-image: var(--icon-chevron);
}
/**

File diff suppressed because one or more lines are too long

View file

@ -2066,15 +2066,17 @@ progress::-moz-progress-bar {
background-position: -200% 0;
}
}
details[role=list] {
/**
* Dropdown ([role="list"])
*/
details[role=list],
li[role=list] {
position: relative;
padding: 0;
border-bottom: none;
}
details[role=list] summary {
margin: 0;
}
details[role=list] summary + ul {
details[role=list] summary + ul,
details[role=list] > ul,
li[role=list] summary + ul,
li[role=list] > ul {
display: flex;
z-index: 99;
position: absolute;
@ -2082,9 +2084,6 @@ details[role=list] summary + ul {
right: 0;
left: 0;
flex-direction: column;
min-width: -webkit-fit-content;
min-width: -moz-fit-content;
min-width: fit-content;
margin: 0;
padding: 0;
border: var(--border-width) solid var(--dropdown-border-color);
@ -2096,37 +2095,83 @@ details[role=list] summary + ul {
color: var(--dropdown-color);
white-space: nowrap;
}
details[role=list] summary + ul li {
details[role=list] summary + ul li,
details[role=list] > ul li,
li[role=list] summary + ul li,
li[role=list] > ul li {
width: 100%;
margin-bottom: 0;
padding: calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);
list-style: none;
}
details[role=list] summary + ul li:first-of-type {
details[role=list] summary + ul li:first-of-type,
details[role=list] > ul li:first-of-type,
li[role=list] summary + ul li:first-of-type,
li[role=list] > ul li:first-of-type {
margin-top: calc(var(--form-element-spacing-vertical) * 0.5);
}
details[role=list] summary + ul li:last-of-type {
details[role=list] summary + ul li:last-of-type,
details[role=list] > ul li:last-of-type,
li[role=list] summary + ul li:last-of-type,
li[role=list] > ul li:last-of-type {
margin-bottom: calc(var(--form-element-spacing-vertical) * 0.5);
}
details[role=list] summary + ul li a {
details[role=list] summary + ul li a,
details[role=list] > ul li a,
li[role=list] summary + ul li a,
li[role=list] > ul li a {
display: block;
margin: calc(var(--form-element-spacing-vertical) * -0.5) calc(var(--form-element-spacing-horizontal) * -1);
padding: calc(var(--form-element-spacing-vertical) * 0.5) var(--form-element-spacing-horizontal);
overflow: hidden;
color: var(--dropdown-color);
text-decoration: none;
text-overflow: ellipsis;
}
details[role=list] summary + ul li a:hover {
details[role=list] summary + ul li a:hover,
details[role=list] > ul li a:hover,
li[role=list] summary + ul li a:hover,
li[role=list] > ul li a:hover {
background-color: var(--dropdown-hover-background-color);
}
details[role=list] summary::after {
details[role=list] summary::after,
li[role=list] > a::after {
display: block;
width: 1.5rem;
height: calc(1rem * var(--line-height));
float: right;
transform: rotate(0deg);
background-position: right;
background-size: 1rem auto;
background-repeat: no-repeat;
content: "";
}
details[role=list][disabled] summary, details[role=list].disabled summary {
border-color: var(--form-element-disabled-border-color);
background-color: var(--form-element-disabled-background-color);
opacity: var(--form-element-disabled-opacity);
pointer-events: none;
details[role=list] {
padding: 0;
border-bottom: none;
}
details[role=list] summary {
margin-bottom: 0;
}
details[role=list] summary:not([role=button]) {
height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
details[role=list] summary:not([role=button]):active, details[role=list] summary:not([role=button]):focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
details[role=list] summary:not([role=button]):focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
details[role=list][open] summary {
border-bottom-right-radius: 0;
@ -2145,55 +2190,38 @@ details[role=list][open] summary::before {
cursor: default;
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]) {
height: calc(1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 + var(--border-width) * 2);
padding: var(--form-element-spacing-vertical) var(--form-element-spacing-horizontal);
border: var(--border-width) solid var(--form-element-border-color);
border-radius: var(--border-radius);
background-color: var(--form-element-background-color);
color: var(--form-element-placeholder-color);
line-height: inherit;
cursor: pointer;
transition: background-color var(--transition), border-color var(--transition), color var(--transition), box-shadow var(--transition);
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):active, *:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):focus {
border-color: var(--form-element-active-border-color);
background-color: var(--form-element-active-background-color);
}
*:not(nav > ul > li):not(nav > aside > ul > li) > details[role=list] summary:not([role=button]):focus {
box-shadow: 0 0 0 var(--outline-width) var(--form-element-focus-color);
}
nav ul li details[role=list] {
display: inline-block;
margin: calc(var(--nav-link-spacing-vertical) * -1) calc(var(--nav-link-spacing-horizontal) * -1);
}
nav ul li details[role=list] summary:not([role=button]) {
padding: var(--nav-link-spacing-vertical) var(--nav-link-spacing-horizontal);
border-radius: var(--border-radius);
line-height: var(--line-height);
}
nav ul li details[role=list] summary:not([role=button]):focus {
background-color: var(--primary-focus);
}
nav ul li details[role=list] summary:not([role=button]) a {
pointer-events: none;
}
nav ul li details[role=list] summary:not([role=button]) a:focus {
background-color: transparent;
}
nav ul li details[role=list][open] summary {
nav [role=list] summary + ul,
nav [role=list] > ul {
min-width: -webkit-fit-content;
min-width: -moz-fit-content;
min-width: fit-content;
border-radius: var(--border-radius);
}
nav ul li details[role=list][open] summary + ul {
margin-top: calc(var(--nav-link-spacing-horizontal) * 0.5);
border-radius: var(--border-radius);
}
nav ul li details[role=list][open] summary + ul a {
nav [role=list] summary + ul li a,
nav [role=list] > ul li a {
border-radius: 0;
}
nav ul li details[role=list][open] summary[role=button] + ul {
margin-top: var(--nav-link-spacing-horizontal);
nav [role=list][open] summary {
border-radius: var(--border-radius);
}
nav [role=list] summary + ul {
margin-top: 2px;
}
li[role=list]:hover > ul,
li[role=list] a:active ~ ul,
li[role=list] a:focus ~ ul {
display: flex;
}
li[role=list] > ul {
display: none;
margin-top: calc(var(--nav-link-spacing-vertical) + 2px);
-webkit-margin-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
margin-inline-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
}
li[role=list] > a::after {
background-image: var(--icon-chevron);
}
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
css/pico.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -23,12 +23,12 @@
<p>Dropdowns are built with <code>&lt;<b>details</b> <i>role</i>=<u>"list"</u>&gt;</code> as a wrapper and <code>&lt;<b>summary</b>&gt;</code> and <code>&lt;<b>ul</b>&gt;</code> as direct childs.</p>
<p>For style consistency with the form elements, dropdowns are styled like a <a href="forms.html">&lt;select&gt;</a> by default.</p>
<article aria-label="Dropdowns as Selects">
<details role="list">x
<details role="list">
<summary aria-haspopup="listbox">Dropdown</summary>
<ul role="listbox">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li><a href="#" onclick="event.preventDefault()">Action</a></li>
<li><a href="#" onclick="event.preventDefault()">Another action</a></li>
<li><a href="#" onclick="event.preventDefault()">Something else here</a></li>
</ul>
</details>
<select required>
@ -58,30 +58,30 @@
</footer>
</article>
<p><code><i>role</i>=<u>"button"</u></code> on the <code>&lt;<b>summary</b>&gt;</code> element can be used to turn the dropdown into a button.</p>
<p><code>&lt;<b>summary</b> <i>role</i>=<u>"button"</u>&gt;</code> transforms the dropdown into a button.</p>
<article aria-label="Dropdowns as Buttons">
<details role="list">
<summary aria-haspopup="listbox" role="button">Dropdown as a button 1</summary>
<ul role="listbox">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li><a href="#" onclick="event.preventDefault()">Action</a></li>
<li><a href="#" onclick="event.preventDefault()">Another action</a></li>
<li><a href="#" onclick="event.preventDefault()">Something else here</a></li>
</ul>
</details>
<details role="list">
<summary aria-haspopup="listbox" role="button" class="secondary">Dropdown as a button 2</summary>
<ul role="listbox">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li><a href="#" onclick="event.preventDefault()">Action</a></li>
<li><a href="#" onclick="event.preventDefault()">Another action</a></li>
<li><a href="#" onclick="event.preventDefault()">Something else here</a></li>
</ul>
</details>
<details role="list">
<summary aria-haspopup="listbox" role="button" class="contrast">Dropdown as a button 3</summary>
<ul role="listbox">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li><a href="#" onclick="event.preventDefault()">Action</a></li>
<li><a href="#" onclick="event.preventDefault()">Another action</a></li>
<li><a href="#" onclick="event.preventDefault()">Something else here</a></li>
</ul>
</details>
<footer class="code">
@ -227,7 +227,7 @@
</footer>
</article>
<p>Dropdowns can be used inside the <a href="navs.html">&lt;nav&gt;</a> component.</p>
<p>Dropdowns can be used inside a <a href="navs.html">&lt;nav&gt;</a> with a nested <code>&lt;<b>details</b> <i>role</i>=<u>"list"</u>&gt;</code></p>
<article aria-label="Dropdowns inside a nav">
<nav>
<ul>
@ -238,11 +238,11 @@
<li><a href="#" onclick="event.preventDefault()">Link</a></li>
<li>
<details role="list" dir="rtl">
<summary aria-haspopup="listbox">Dropdown</summary>
<summary aria-haspopup="listbox" role="button">Dropdown</summary>
<ul role="listbox">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li><a href="#" onclick="event.preventDefault()">Action</a></li>
<li><a href="#" onclick="event.preventDefault()">Another action</a></li>
<li><a href="#" onclick="event.preventDefault()">Something else here</a></li>
</ul>
</details>
</li>
@ -259,7 +259,7 @@
&lt;<b>li</b>&gt;&lt;<b>a</b> <i>href</i>=<u>"#"</u>&gt;Link&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;<b>li</b>&gt;
&lt;<b>details</b> <i>role</i>=<u>"list"</u> <i>dir</i>=<u>"rtl"</u>&gt;
&lt;<b>summary</b> <i>aria-haspopup</i>=<u>"listbox"</u>&gt;Dropdown&lt;/<b>summary</b>&gt;
&lt;<b>summary</b> <i>aria-haspopup</i>=<u>"listbox"</u> <i>rolep</i>=<u>"button"</u>&gt;Dropdown&lt;/<b>summary</b>&gt;
&lt;<b>ul</b> <i>role</i>=<u>"listbox"</u>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b>&gt;Action&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b>&gt;Another action&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
@ -272,7 +272,48 @@
</footer>
</article>
<p>&nbsp;Dropdowns inside a <code>&lt;<b>nav</b>&gt;</code> are still experimental and will probably evolve.</p>
<p>You can also use <code>&lt;<b>li</b> <i>role</i>=<u>"list"</u>&gt;</code> as a nested wrapper to render a list as a dropdown.</p>
<p>&nbsp;This syntax is experimental. In this version, the dropdown menu is triggered on hover.</p>
<article aria-label="Dropdowns inside a nav">
<nav>
<ul>
<li><strong>Brand</strong></li>
</ul>
<ul>
<li><a href="#" onclick="event.preventDefault()">Link</a></li>
<li><a href="#" onclick="event.preventDefault()">Link</a></li>
<li role="list" dir="rtl">
<a href="#" onclick="event.preventDefault()" aria-haspopup="listbox">Dropdown</a>
<ul role="listbox">
<li><a href="#" onclick="event.preventDefault()">Action</a></li>
<li><a href="#" onclick="event.preventDefault()">Another action</a></li>
<li><a href="#" onclick="event.preventDefault()">Something else here</a></li>
</ul>
</li>
</ul>
</nav>
<footer class="code">
<pre><code>&lt;<b>nav</b>&gt;
&lt;<b>ul</b>&gt;
&lt;<b>li</b>&gt;&lt;<b>strong</b>&gt;Brand&lt;/<b>strong</b>&gt;&lt;/<b>li</b>&gt;
&lt;/<b>ul</b>&gt;
&lt;<b>ul</b>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b> <i>href</i>=<u>"#"</u>&gt;Link&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b> <i>href</i>=<u>"#"</u>&gt;Link&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;<b>li</b> <i>role</i>=<u>"list"</u> <i>dir</i>=<u>"rtl"</u>&gt;
&lt;<b>a</b> <i>href</i>=<u>"#"</u> <i>aria-haspopup</i>=<u>"listbox"</u>&gt;Dropdown&lt;/<b>a</b>&gt;
&lt;<b>ul</b> <i>role</i>=<u>"listbox"</u>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b>&gt;Action&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b>&gt;Another action&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;<b>li</b>&gt;&lt;<b>a</b>&gt;Something else here&lt;/<b>a</b>&gt;&lt;/<b>li</b>&gt;
&lt;/<b>ul</b>&gt;
&lt;/<b>li</b>&gt;
&lt;/<b>ul</b>&gt;
&lt;/<b>nav</b>&gt;</code></pre>
</footer>
</article>
</section>
${require('./_footer.html')}

View file

@ -1,12 +1,14 @@
details[role="list"] {
/**
* Dropdown ([role="list"])
*/
// Menu
details[role="list"],
li[role="list"] {
position: relative;
padding: 0;
border-bottom: none;
summary {
margin: 0;
& + ul {
summary + ul,
> ul {
display: flex;
z-index: 99;
position: absolute;
@ -14,7 +16,6 @@ details[role="list"] {
right: 0;
left: 0;
flex-direction: column;
min-width: fit-content;
margin: 0;
padding: 0;
border: var(--border-width) solid var(--dropdown-border-color);
@ -47,8 +48,10 @@ details[role="list"] {
calc(var(--form-element-spacing-horizontal) * -1);
padding: calc(var(--form-element-spacing-vertical) * 0.5)
var(--form-element-spacing-horizontal);
overflow: hidden;
color: var(--dropdown-color);
text-decoration: none;
text-overflow: ellipsis;
&:hover {
background-color: var(--dropdown-hover-background-color);
@ -56,44 +59,33 @@ details[role="list"] {
}
}
}
}
// Marker
// Marker
details[role="list"] summary,
li[role="list"] > a {
&::after {
height: calc(1rem * var(--line-height));
transform: rotate(0deg);
}
}
&[disabled] summary,
&.disabled summary {
border-color: var(--form-element-disabled-border-color);
background-color: var(--form-element-disabled-background-color);
opacity: var(--form-element-disabled-opacity);
pointer-events: none;
}
&[open] summary {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
&::before {
display: block;
z-index: 1;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: transparent;
width: 1.5rem;
height: calc(1rem * var(--line-height));
float: right;
transform: rotate(0deg);
background-position: right;
background-size: 1rem auto;
background-repeat: no-repeat;
content: "";
cursor: default;
}
}
}
// <summary> as a <select>
*:not(nav > ul > li):not(nav > aside > ul > li) {
> details[role="list"] {
// Global dropdown only
details[role="list"] {
padding: 0;
border-bottom: none;
// Style <summary> as <select>
summary {
margin-bottom: 0;
&:not([role="button"]) {
height: calc(
1rem * var(--line-height) + var(--form-element-spacing-vertical) * 2 +
@ -125,52 +117,66 @@ details[role="list"] {
}
}
}
// Close for details[role="list"]
&[open] summary {
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
&::before {
display: block;
z-index: 1;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: transparent;
content: "";
cursor: default;
}
}
}
// Dropdown inside <nav>
nav ul li {
details[role="list"] {
display: inline-block;
margin: calc(var(--nav-link-spacing-vertical) * -1)
calc(var(--nav-link-spacing-horizontal) * -1);
summary:not([role="button"]) {
padding: var(--nav-link-spacing-vertical)
var(--nav-link-spacing-horizontal);
border-radius: var(--border-radius);
line-height: var(--line-height);
&:focus {
background-color: var(--primary-focus);
}
a {
pointer-events: none;
&:focus {
background-color: transparent;
}
}
}
&[open] summary {
// All Dropdowns inside <nav>
nav [role="list"] summary + ul,
nav [role="list"] > ul {
min-width: fit-content;
border-radius: var(--border-radius);
& + ul {
margin-top: calc(var(--nav-link-spacing-horizontal) * 0.5);
border-radius: var(--border-radius);
a {
li a {
border-radius: 0;
}
}
}
&[role="button"] {
& + ul {
margin-top: var(--nav-link-spacing-horizontal);
}
}
// Dropdowns inside <nav> as nested <details>
nav [role="list"] {
&[open] summary {
border-radius: var(--border-radius);
}
summary + ul {
margin-top: 2px;
}
}
// Dropdowns inside a <nav> without using <details>
li[role="list"] {
// Open on hover (for mobile)
// or on active/focus (for keyboard navigation)
&:hover > ul,
a:active ~ ul,
a:focus ~ ul {
display: flex;
}
> ul {
display: none;
margin-top: calc(var(--nav-link-spacing-vertical) + 2px);
margin-inline-start: calc(var(--nav-element-spacing-horizontal) - var(--nav-link-spacing-horizontal));
}
> a::after {
background-image: var(--icon-chevron);
}
}