Skip to content

Commit

Permalink
feat!: Add collapsible menu to Header (#1784)
Browse files Browse the repository at this point in the history
Co-authored-by: Vincent Smedinga <v.smedinga@amsterdam.nl>
  • Loading branch information
alimpens and VincentSmedinga authored Dec 20, 2024
1 parent 3505dcc commit 44ce6d8
Show file tree
Hide file tree
Showing 22 changed files with 875 additions and 204 deletions.
12 changes: 7 additions & 5 deletions packages/css/src/components/header/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ Includes the name of the application if it is not the general website.
- It includes the logo of the City or the organization, the site title (except for the general website), and a menu with links to commonly used pages.
- The Header is important because it conveys our corporate identity and is the first thing people see.
Using it consistently helps users recognize and trust the website.
- It is the same on every page of the application.
- The page menu can contain a maximum of 5 items.
- The Header is the same on every page of the application, although full-screen pages may hide it, e.g. a video or a map.
- The inline menu can contain a maximum of 5 items.
The last two will often be ‘Search’ and ‘Menu’.
- Labels should be short to ensure the menu fits on one line, even on medium-wide screens.
- An icon can be added to the end of a link to make its function easier to find.
- The 'Menu' button opens a collapsible menu, which has room for more links.
- On narrow windows, links can move from the inline menu to the collapsible one.
- Labels should be short to help the inline menu fit on a single line whenever possible.
- An icon can be added to the end of a link to make its destination easier to guess.

## References

- A Header is a [landmark](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_landmark_roles) and can be use to group navigation elements.
- A Header is a [landmark](https://www.w3.org/TR/wai-aria-practices-1.1/#aria_landmark_roles) and can be used to group navigation elements.
- [WCAG 3.2.3](https://wcag.com/designers/3-2-3-consistent-navigation/) Consistent Navigation: Navigation menus that appear on multiple pages are consistent.
234 changes: 182 additions & 52 deletions packages/css/src/components/header/header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,83 +4,213 @@
*/

@use "../../common/breakpoint" as *;
@use "../../common/text-rendering" as *;

.ams-header {
/*
* The branding section is created twice: once outside the navigation and once hidden inside it.
* This keeps all navigation in one nav element and lets the menu wrap around the branding section.
* Display grid is used to let both branding sections overlap.
*/
display: grid;
padding-block: var(--ams-header-padding-block);
padding-inline: var(--ams-header-padding-inline);
}

.ams-header__branding {
align-items: center;
align-self: start; // To align the branding section to the top of the header when it wraps
column-gap: var(--ams-header-branding-column-gap);
display: flex;
flex-wrap: wrap;
padding-block: var(--ams-header-padding-block);
row-gap: 1.5rem;
grid-area: 1 / 1; // To allow this section to overlap with the second branding section
}

@media screen and (min-width: $ams-breakpoint-wide) {
column-gap: var(--ams-header-column-gap);
flex-wrap: nowrap;
}
.ams-header__branding--hidden {
opacity: 0%;
user-select: none; // The hidden branding section should not be selectable
}

.ams-header__logo-link {
flex: none;
outline-offset: var(--ams-header-logo-link-outline-offset);
}

.ams-header__links {
display: none;
/* TODO Remove after updating Heading line heights in DES-973. */
.ams-heading.ams-header__brand-name {
line-height: 1.35;
}

.ams-header__navigation {
column-gap: var(--ams-header-navigation-column-gap);
display: flex;
flex-wrap: wrap;
grid-area: 1 / 1; // To allow this section to overlap with the branding section
// This section blocks pointer events initially, so the hidden branding section can't be activated.
// The menu and collapsible menu set it back to auto, to make sure they can be activated.
pointer-events: none;
row-gap: var(--ams-header-navigation-row-gap);
}

@mixin reset-list {
list-style: none;
margin-block: 0;
padding-inline-start: 0;
}

.ams-header__menu {
align-items: center;
column-gap: var(--ams-header-menu-column-gap);
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
margin-inline-start: auto;
pointer-events: auto; // Set pointer events back to auto to allow the menu to be activated
row-gap: var(--ams-header-menu-row-gap);

@media screen and (min-width: $ams-breakpoint-medium) {
display: block;
flex: 10 0 auto;
@include reset-list;
}

// Do not show menu items below the wide breakpoint...
.ams-header__menu-item {
@media screen and (not (min-width: $ams-breakpoint-wide)) {
display: none;
}
}

@media screen and (min-width: $ams-breakpoint-wide) {
order: 3;
// ...unless they're fixed.
.ams-header__menu-item--fixed {
display: revert;
}

@mixin header-menu-action {
color: var(--ams-header-menu-item-color);
font-family: var(--ams-header-menu-item-font-family);
font-size: var(--ams-header-menu-item-font-size);
font-weight: var(--ams-header-menu-item-font-weight);
line-height: var(--ams-header-menu-item-line-height);
outline-offset: var(--ams-header-menu-item-outline-offset);
padding-block: var(--ams-header-menu-item-padding-block);
touch-action: manipulation;
white-space: nowrap;

@include text-rendering;

&:hover {
color: var(--ams-header-menu-item-hover-color);
}
}

.ams-header__menu {
flex: 1;
padding-inline-start: var(--ams-page-menu-column-gap); // TODO Don’t use tokens of another component
text-align: end;
.ams-header__menu-link {
display: inline-block;
text-decoration-line: var(--ams-header-menu-link-text-decoration-line);
text-decoration-thickness: var(--ams-header-menu-link-text-decoration-thickness);
text-underline-offset: var(--ams-header-menu-link-text-underline-offset);

@include header-menu-action;

&:hover {
text-decoration-line: var(--ams-header-menu-link-hover-text-decoration-line);
}
}

.ams-header__mega-menu-button-item--hide-on-wide-window {
@media screen and (min-width: $ams-breakpoint-wide) {
order: 4;
padding-inline-start: 0;
display: none;
}
}

.ams-header__app-name {
flex: 1 1 100%;
@mixin reset-button {
background: none;
border: 0;
margin-block: 0; // [1]
margin-inline: 0; // [1]
padding-inline: 0;

@media screen and (min-width: $ams-breakpoint-wide) {
min-inline-size: 0;
order: 2;

.ams-header__app-name-heading {
display: block;
inline-size: 100%;
line-height: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// [1] Remove the margin in older Safari.
}

.ams-header__mega-menu-button {
column-gap: var(--ams-header-menu-item-column-gap);
cursor: pointer;
display: grid;
grid-auto-flow: column;

@include header-menu-action;
@include reset-button;
}

.ams-header__mega-menu-button[aria-expanded="true"] {
font-weight: var(--ams-header-mega-menu-button-label-open-font-weight);
}

.ams-header__mega-menu-button-label,
.ams-header__mega-menu-button-hidden-label {
grid-area: 1 / 1; // To allow the label and the hidden label to overlap
}

// This hidden label is used to prevent a layout shift when the mega menu is opened
// and the button text becomes bold.
.ams-header__mega-menu-button-hidden-label {
font-weight: var(--ams-header-mega-menu-button-label-open-font-weight);
pointer-events: none;
user-select: none;
visibility: hidden;
}

.ams-header__menu-icon {
line {
stroke: currentColor;
stroke-width: 3px;
transform-origin: center;
transition:
translate 0.1s ease-in-out,
rotate 0.2s ease-in-out,
opacity 0.1s ease-in-out;

@media (prefers-reduced-motion) {
transition: none;
}
}

.ams-header__menu-icon-top {
translate: 0 -7px;
}

.ams-header__menu-icon-bottom {
translate: 0 7px;
}
}

// Temporary – will move to Mega Menu and/or Icon Button
.ams-header__menu-button {
background-color: transparent;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><path fill='%23004699' fill-rule='evenodd' d='M0 3.238h32V7.81H0V3.238zm0 10.476h32v4.572H0v-4.572zM0 24.19h32v4.572H0V24.19z'/></svg>");
background-position: center right;
background-repeat: no-repeat;
background-size: 1.1875rem 1.1875rem;
border: 0;
color: var(--ams-page-menu-item-color);
font-family: var(--ams-page-menu-item-font-family);
font-size: var(--ams-page-menu-item-font-size);
font-weight: var(--ams-page-menu-item-font-weight);
line-height: var(--ams-page-menu-item-line-height);
margin-block: 0;
margin-inline: 0;
padding-inline: 0 1.875rem;
text-align: center;
touch-action: manipulation;
.ams-header__menu-icon--open {
.ams-header__menu-icon-top {
rotate: 45deg;
translate: 0;
}
.ams-header__menu-icon-middle {
opacity: 0%;
}
.ams-header__menu-icon-bottom {
rotate: -45deg;
translate: 0;
}
}

.ams-header__mega-menu {
inline-size: 100%;
pointer-events: auto; // Set pointer events back to auto to allow the mega menu to be activated

// Remove inline padding from Grids that are used in the mega menu.
// The grid inline padding is set on the header element.
& .ams-grid {
padding-inline: 0;
}
}

.ams-header__mega-menu--closed.ams-header__mega-menu--closed {
display: none;
}

.ams-header__grid-cell-narrow-window-only {
@media screen and (min-width: $ams-breakpoint-wide) {
display: none;
}
}
2 changes: 1 addition & 1 deletion packages/css/src/components/logo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The sub-brands are:
- The logo links to the homepage of the website or application.
- If the application is a form, application, or tool without a homepage, the logo links to the page where the form, application, or tool is referred to.

The height of the logo is always 40 pixels.
The logo is 40 pixels tall at its minimum, growing to 56 pixels in wider windows.
This also applies to sub-brand logos.

## Download
Expand Down
1 change: 1 addition & 0 deletions packages/css/src/components/logo/logo.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
.ams-logo {
block-size: var(--ams-logo-block-size);
display: block;
min-block-size: var(--ams-logo-min-block-size);
}

.ams-logo__emblem {
Expand Down
Loading

0 comments on commit 44ce6d8

Please sign in to comment.