Skip to content

Commit

Permalink
Merge pull request #268 from ucsc/feature/ucsc-134/fe-sidebar-menu
Browse files Browse the repository at this point in the history
[UCSC-134] Sidebar Menu
  • Loading branch information
bjcooper authored Oct 16, 2023
2 parents e45e865 + 6ca16f6 commit 9d22b1f
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 9 deletions.
15 changes: 8 additions & 7 deletions patterns/sidebar-with-navigation.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@
* Categories: navigation
*/
?>

<!-- wp:columns -->
<div class="wp-block-columns"><!-- wp:column {"width":"33.33%"} -->
<div class="wp-block-column" style="flex-basis:33.33%"><!-- wp:heading {"level":3,"fontSize":"base"} -->
<h3 class="wp-block-heading has-base-font-size"><strong>Navigation header</strong></h3>
<!-- wp:columns {"className":"ucsc__sidebar-with-navigation"} -->
<div class="wp-block-columns ucsc__sidebar-with-navigation"><!-- wp:column {"width":"33.33%"} -->
<div class="wp-block-column" style="flex-basis:33.33%"><!-- wp:heading {"level":3,"style":{"typography":{"textTransform":"uppercase"}},"fontSize":"base"} -->
<h3 class="wp-block-heading has-base-font-size" style="text-transform:uppercase">Navigation header</h3>
<!-- /wp:heading -->

<!-- wp:navigation { "maxNestingLevel": 1,"overlayMenu":"never","layout":{"type":"flex","orientation":"vertical","justifyContent":"stretch"}} /--></div>
<!-- wp:navigation {"textColor":"ucsc-royal-blue","overlayMenu":"never","overlayTextColor":"ucsc-royal-blue","maxNestingLevel":1,"layout":{"type":"flex","orientation":"vertical","justifyContent":"left"},"fontSize":"base"} /--></div>
<!-- /wp:column -->

<!-- wp:column {"width":"66.66%"} -->
<div class="wp-block-column" style="flex-basis:66.66%"></div>
<div class="wp-block-column" style="flex-basis:66.66%"><!-- wp:heading {"level":1} -->
<h1 class="wp-block-heading">Page title</h1>
<!-- /wp:heading --></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->
141 changes: 141 additions & 0 deletions src/js/block-patterns/sidebar-with-navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
const el = document.querySelectorAll( '.ucsc__sidebar-with-navigation' );

const selectors = {
itemSelector: '.wp-block-navigation-item',
itemExpandedClass: 'ucsc__sidebar-with-navigation--expanded',
linkSelector: 'a.wp-block-navigation-item__content',
toggleSelector: '.wp-block-navigation-submenu__toggle',
submenuWrapperClass: 'wp-block-navigation__submenu-transition-wrapper',
submenuSelector: '.wp-block-navigation__submenu-container',
};

/**
* Show or hide the submenu associated with a given toggle button.
*
* @param {HTMLElement} toggle The actioned submenu toggle button.
*/
const toggleSubmenu = ( toggle ) => {
const item = toggle.closest( selectors.itemSelector );
const submenu = item.querySelector( selectors.submenuSelector );

// Hide
if ( item.classList.contains( selectors.itemExpandedClass ) ) {
item.classList.remove( selectors.itemExpandedClass );
submenu.setAttribute( 'aria-hidden', true );
submenu
.querySelectorAll( selectors.linkSelector )
.forEach( ( subItemLink ) => {
subItemLink.setAttribute( 'tabIndex', -1 );
} );
}
// Show
else {
item.classList.add( selectors.itemExpandedClass );
submenu.setAttribute( 'aria-hidden', false );
submenu
.querySelectorAll( selectors.linkSelector )
.forEach( ( subItemLink ) => {
subItemLink.removeAttribute( 'tabIndex' );
} );
}
};

/**
* Fix toggle button ARIA attributes, which the core block JS sets incorrectly
* since we've disabled accordion behavior.
*/
const fixAriaAttributes = () => {
el.forEach( ( block ) => {
block.querySelectorAll( selectors.itemSelector ).forEach( ( item ) => {
const isExpanded = item.classList.contains(
selectors.itemExpandedClass
);

const toggle = item.querySelector( selectors.toggleSelector );
if ( toggle ) {
toggle.setAttribute( 'aria-expanded', isExpanded );
}

const submenu = item.querySelector( selectors.submenuSelector );
if ( submenu ) {
toggle.setAttribute( 'aria-hidden', ! isExpanded );
}
} );
} );
};

/**
* Bind event listeners.
*/
const bindEvents = () => {
el.forEach( ( block ) => {
block
.querySelectorAll( selectors.toggleSelector )
.forEach( ( toggle ) => {
toggle.addEventListener( 'click', () => {
toggleSubmenu( toggle );
} );
} );

block
.querySelectorAll( '.' + selectors.submenuWrapperClass )
.forEach( ( wrapper ) => {
wrapper.addEventListener( 'transitionend', () => {
fixAriaAttributes();
} );
} );
} );
};

/**
* Set up custom block markup.
*/
const initBlockMarkup = () => {
el.forEach( ( block ) => {
block
.querySelectorAll( selectors.submenuSelector )
.forEach( ( submenu ) => {
// Initialize submenu ARIA attribute.
submenu.setAttribute( 'aria-hidden', true );
submenu
.querySelectorAll( selectors.linkSelector )
.forEach( ( subItemLink ) => {
subItemLink.setAttribute( 'tabIndex', -1 );
} );

// Add a wrapper around submenus in order to do height transitions.
const item = submenu.closest( selectors.itemSelector );
const wrapper = document.createElement( 'div' );
wrapper.classList.add( selectors.submenuWrapperClass );
item.append( wrapper );
wrapper.append( submenu );
} );

// Remove nested submenus and their toggles.
block
.querySelectorAll(
`${ selectors.submenuSelector } ${ selectors.submenuSelector }`
)
.forEach( ( nestedSubmenu ) => {
const item = nestedSubmenu.closest( selectors.itemSelector );
const toggle = item.querySelector( selectors.toggleSelector );
toggle.remove();
nestedSubmenu.remove();
} );
} );
};

/**
* Initialize custom block behaviors.
*/
const init = () => {
if ( ! el.length ) {
return;
}

initBlockMarkup();
bindEvents();
fixAriaAttributes();
};

export default init;
12 changes: 12 additions & 0 deletions src/js/core/block-patterns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* @module block-patterns
* @description clearing house for all block pattern behaviors.
*/

import sidebarWithNavigation from '../block-patterns/sidebar-with-navigation.js';

const init = () => {
sidebarWithNavigation();
};

export default init;
7 changes: 5 additions & 2 deletions src/js/core/ready.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import debounce from 'lodash/debounce';
import { on, ready } from '../utils/events';
import resize from './resize';
import components from './components';
import blockPatterns from './block-patterns';
import viewportDims from './viewport-dims';

const bindEvents = () => {
Expand All @@ -15,14 +16,16 @@ const bindEvents = () => {

const init = () => {
// set initial states

viewportDims();

// initialize global events

bindEvents();

// initialize components
components();

// initialize block pattern behaviors
blockPatterns();
};

/**
Expand Down
167 changes: 167 additions & 0 deletions src/scss/block-patterns/_sidebar-with-navigation.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/* BLOCK PATTERN: Content with left navigation */

.ucsc__sidebar-with-navigation {
flex-direction: column-reverse;

@include media-query($wp-columns-unstack) {
flex-direction: row;
}

// Block
.wp-block-navigation {
margin-top: 0;

.wp-block-navigation-item__content {

&:hover,
&:focus-visible {
text-decoration: underline;
text-decoration-color: var(--wp--preset--color--ucsc-primary-yellow);
text-decoration-skip-ink: auto;
text-decoration-thickness: 0.12rem;
text-underline-offset: 0.12em;
}

&[aria-current="page"] {
font-weight: 700;
}
}

.wp-block-navigation__submenu-container .wp-block-navigation-item__content {

&:focus-visible {
outline-offset: -1px;
}
}

// Navigation menu
> .wp-block-navigation__container {
width: 100%;
gap: 0;

// Top-level menu item
> .wp-block-navigation-item {
width: 100%;
display: grid;
grid-template-columns: 1fr auto;
grid-template-rows: auto 0fr;
grid-template-areas:
"link toggle"
"submenu submenu";
border-top: 1px solid var(--wp--preset--color--light-gray);
transition: grid-template-rows 0.25s ease;

&:last-child {
border-bottom: 1px solid var(--wp--preset--color--light-gray);
}

// Top-level menu link
> .wp-block-navigation-item__content {
grid-area: link;
padding: 12px 0;
display: block;
}

// Submenu toggle button
> .wp-block-navigation-submenu__toggle {
grid-area: toggle;
display: flex;
height: 100%;
min-width: 32px;
align-items: flex-start;
justify-content: flex-end;
color: inherit;
position: relative;

&::before {
content: "";
display: none;
width: 28px;
height: calc(100% - 2px);
position: absolute;
border: 2px solid #000;
border-radius: 3px;
transform: translateX(5px);
}

&::after {
content: "";
display: block;
width: 10px;
height: 10px;
border-width: 1px 1px 0 0;
border-style: solid;
border-color: currentcolor;
transform: translate(-5px, 12px) rotate(-225deg);
transition: transform 0.25s ease;
}

&:hover,
&:focus-visible {
outline: 0 none;

&::after {
border-width: 2px 2px 0 0;
}
}

&:focus-visible {

&::before {
display: block;
}
}

svg {
display: none;
}
}

// Unwrapped submenu prior to JS initialization
> .wp-block-navigation__submenu-container {
display: none;
}

// Submenu transition wrapper
> .wp-block-navigation__submenu-transition-wrapper {
grid-area: submenu;
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 0.25s ease;

// Submenu
> .wp-block-navigation__submenu-container {
position: static;
width: 100%;
background-color: transparent;
border: 0 none;
color: inherit;
height: auto;
opacity: 1;
overflow: hidden;
visibility: visible;

// Hide everything beyond the top two levels of the menu.
.wp-block-navigation-submenu__toggle,
.wp-block-navigation__submenu-container {
display: none;
}
}
}

// Top-level menu item with submenu expanded
&.ucsc__sidebar-with-navigation--expanded {

> .wp-block-navigation-submenu__toggle::after {
transform: translate(-5px, 18px) rotate(-45deg);
}

> .wp-block-navigation__submenu-transition-wrapper {
grid-template-rows: 1fr;
padding-bottom: 12px;
}
}
}
}
}
}
1 change: 1 addition & 0 deletions src/scss/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@
@import "block-patterns/three-columns-text";
@import "block-patterns/grid-with-background-image";
@import "block-patterns/map-contact";
@import "block-patterns/sidebar-with-navigation";

0 comments on commit 9d22b1f

Please sign in to comment.