Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions themes/osi/assets/scss/_6_components.mobile-menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,14 @@
}

@media only screen and (max-width: #{$break-nav - 0.06}) {
// stays outside .open-the-menu: the panel keeps painting for .3s after that
// class is dropped, and would cover the logo for those frames without this
// stack while open: overlay (2) < white bar (3) < logo and buttons (4)
.header--blog-name {
position: relative;
z-index: 4;
}

.open-the-menu {
overflow: hidden;

Expand Down Expand Up @@ -198,12 +206,6 @@
position: static;
}

// stack while open: overlay (2) < white bar (3) < logo and buttons (4)
.header--blog-name {
position: relative;
z-index: 4;
}

// white bar behind the fixed logo row: the open menu scrolls beneath it
.header--inner::before {
background-color: $Nwhite;
Expand Down
42 changes: 39 additions & 3 deletions themes/osi/assets/scss/_6_components.navigation--subnav.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
$chevronDown: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 8" fill="none" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 1.5 6 6.5 11 1.5"/></svg>') no-repeat center / contain;

.menu-item.menu-item-has-children a {
padding-right: 30px;
}
Expand Down Expand Up @@ -375,10 +377,30 @@

& > a {
padding-right: .5em;

// masked so the chevron takes the link's colour; empty content keeps it out of
// the accessible name, and aria-expanded carries the open state
&::after {
background-color: currentColor;
content: '';
display: inline-block;
height: .45em;
margin-left: .45em;
mask: $chevronDown;
transition: transform .2s ease;
vertical-align: middle;
width: .7em;
-webkit-mask: $chevronDown;
}
}

&:hover > a::after,
&.is-open > a::after {
transform: rotate(180deg);
}

// offsets/padding align the full-bleed panel with the header content; closing
// freezes it solid for .2s so switches never cross-fade (dim would flash through)
// freezes it solid for .2s so the dim veil never flashes through two panels
& > ul.sub-menu {
box-shadow: 0 14px 18px -10px rgba(#{$Ndarkest_RGB}, 0.2);
display: grid;
Expand All @@ -400,6 +422,7 @@

.megamenu-header {
grid-column: 1 / -1;
grid-row: 1;
margin-bottom: 1.25rem;

.megamenu-eyebrow {
Expand Down Expand Up @@ -458,8 +481,8 @@
grid-column: 1 / -2;
}

// spans 30 rows: links must never auto-place under the card, and
// 1 / -1 cannot span implicit grid rows
// spans past the explicit rows: the card is taller than the links, and a span
// that ends inside the grid would share its height out across their rows
.megamenu-featured {
border-left: 1px solid $Nlight;
grid-column: 3;
Expand All @@ -472,10 +495,12 @@
}

.megamenu-featured--image {
aspect-ratio: 16 / 9;
border-radius: 8px;
display: block;
height: auto;
margin-bottom: .75rem;
object-fit: cover;
width: 100%;
}

Expand All @@ -499,6 +524,17 @@
}
}

// panels appear instantly whenever one is open: fading the incoming panel while
// the outgoing one snaps away leaves a frame with neither of them painted
.header-main.is-nav-open & > ul.sub-menu {
transition: none;
}

// separate rule, as above: an unparseable :has() would drop the JS one too
.header-main:has(.menu-item.megamenu:hover) & > ul.sub-menu {
transition: none;
}

// keyboard open is JS-driven (.is-open); :focus-within here would defeat Escape
&:hover > ul.sub-menu,
&.is-open > ul.sub-menu {
Expand Down
15 changes: 14 additions & 1 deletion themes/osi/assets/scss/_6_components.navigation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,25 @@ footer {
}
}

.open-the-menu .nav-main--cta {
.nav-main .nav-main--cta {
background-color: $brandColor1;
border-radius: 999px;
bottom: 24px;
color: $Nwhite;
display: block;
font-weight: $baseWeightBold;
left: $smallPadding;
// fades with the panel rather than appearing with it: display cannot transition,
// so the button used to land at full opacity while the panel was still arriving
opacity: 0;
padding: .9em;
pointer-events: none;
position: fixed;
right: $smallPadding;
text-align: center;
text-decoration: none;
transition: opacity .3s, visibility 0s linear .3s;
visibility: hidden;
z-index: 5;

&:hover, &:focus {
Expand All @@ -216,6 +222,13 @@ footer {
}
}

.open-the-menu .nav-main .nav-main--cta {
opacity: 1;
pointer-events: auto;
transition: opacity .3s, visibility 0s;
visibility: visible;
}

.nav-main--menu {
height: 0 !important;
padding: 0;
Expand Down
68 changes: 67 additions & 1 deletion themes/osi/inc/class-osi-megamenu-walker.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,71 @@ class OSI_Megamenu_Walker extends Walker_Nav_Menu {
*/
private $current_featured = null;

/**
* Direct-child counts keyed by menu item ID.
*
* @var array
*/
private $child_counts = array();

/**
* Zero-based position of the next item within the panel being rendered.
*
* @var integer
*/
private $panel_index = 0;

/**
* Walk the tree, counting each item's children first.
*
* @param array $elements Menu items to walk.
* @param integer $max_depth Depth limit.
* @param mixed ...$args Arguments passed through to the element handlers.
*
* @return string
*/
public function walk( $elements, $max_depth, ...$args ) { // phpcs:ignore Squiz.Commenting.FunctionComment.ScalarTypeHintMissing,Squiz.Commenting.FunctionComment.TypeHintMissing -- typing params on a Walker override is a fatal signature mismatch; parent is untyped.
$this->child_counts = array_count_values( array_column( $elements, 'menu_item_parent' ) );

add_filter( 'nav_menu_item_attributes', array( $this, 'add_panel_placement' ), 10, 4 );

try {
return parent::walk( $elements, $max_depth, ...$args );
} finally {
remove_filter( 'nav_menu_item_attributes', array( $this, 'add_panel_placement' ), 10 );
}
}

/**
* Place a panel item in its column, filling column one before column two.
*
* Auto-placement cannot do this: the featured card has to span past the explicit rows
* to stay out of their sizing, and column flow would then fill that whole span before
* wrapping (@see T51ENG-2081).
*
* @param array $atts HTML attributes for the menu item's li.
* @param WP_Post $menu_item Menu item data object.
* @param stdClass $args An object of wp_nav_menu() arguments.
* @param integer $depth Depth of menu item.
*
* @return array
*/
public function add_panel_placement( array $atts, WP_Post $menu_item, stdClass $args, int $depth ): array {
if ( 1 !== $depth || null === $this->current_parent || 'primary_navigation' !== ( $args->theme_location ?? '' ) ) {
return $atts;
}

// two columns, matching grid-template-columns in _6_components.navigation--subnav.scss.
$rows = (int) ceil( $this->child_counts[ $this->current_parent->ID ] / 2 );
$column = intdiv( $this->panel_index, $rows ) + 1;
$row = ( $this->panel_index % $rows ) + 2;
++$this->panel_index;

$atts['style'] = ltrim( rtrim( $atts['style'] ?? '', '; ' ) . ';grid-column:' . $column . ';grid-row:' . $row, ';' );

return $atts;
}

/**
* Start element output; remembers the current top-level item.
*
Expand All @@ -43,6 +108,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) {
$is_panel = $this->has_children && in_array( 'megamenu', (array) $item->classes, true );
$this->current_parent = $is_panel ? $item : null;
$this->current_featured = $is_panel ? osi_megamenu_featured( $item ) : null;
$this->panel_index = 0;

if ( null !== $this->current_featured ) {
$item->classes[] = 'has-featured';
Expand Down Expand Up @@ -132,7 +198,7 @@ private function get_featured_card( bool $with_image ) {
if ( $with_image ) {
$card .= wp_get_attachment_image(
(int) get_post_thumbnail_id( $featured ),
'medium',
'large',
false,
array(
'class' => 'megamenu-featured--image',
Expand Down
46 changes: 40 additions & 6 deletions themes/osi/style.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion themes/osi/style.css.map

Large diffs are not rendered by default.

Loading