diff --git a/assets/css/animations.css b/assets/css/animations.css index 705dd93..73ed961 100644 --- a/assets/css/animations.css +++ b/assets/css/animations.css @@ -1485,6 +1485,184 @@ transition: none; } } +/********** Mobile Menu (Ollie Menu Designer mobileMenuSlug drawer) **********/ +/* + * Logo row + close button. The close button is WP core's own + * .wp-block-navigation__responsive-container-close — rendered as a sibling before the injected + * mobileMenuSlug content, not part of this template part — so it can only be reached and aligned + * via a global selector, not through markup here. Core's default top:0/right:0 plus the content's + * default padding-top: calc(2rem + 24px) (wp-includes/blocks/navigation/style.css) is what was + * producing the oversized gap above the logo; both are overridden to the same spacing token here + * so the logo row and the close button land on the same line. Styled with the same circular + * icon-button language as the header's search/theme-toggle buttons + * (styles/blocks/groups/header-icon-button.json) for visual consistency. + * + * Scoped under .site-header: this theme only has the one core/navigation instance (the header's), + * but these are otherwise generic core class names that would restyle any Navigation block's + * overlay drawer anywhere on the site if left unscoped. + */ +.site-header .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content { + padding-top: var(--wp--preset--spacing--20); +} + +.site-header .wp-block-navigation__responsive-container-close { + position: absolute; + top: var(--wp--preset--spacing--20); + right: var(--wp--preset--spacing--20); + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); +} +.site-header .wp-block-navigation__responsive-container-close svg { + inline-size: 20px; + block-size: 20px; +} +.site-header .wp-block-navigation__responsive-container-close:hover, .site-header .wp-block-navigation__responsive-container-close:focus-visible { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); +} + +@media (prefers-reduced-motion: reduce) { + .site-header .wp-block-navigation__responsive-container-close { + transition: none; + } +} +/* + * core/details already ships a full card-style accordion (border, background, chevron, hover, + * [open] state) globally via styles/presets/blocks/core-details.json + _details-motion.scss. The + * mobile drawer wants that same disclosure mechanism but flattened into a full-width list row + * (no individual card border/background/shadow, no hover lift) with a divider between siblings + * instead — none of which is expressible in theme.json, so it's layered on here rather than + * duplicating the chevron/open logic that already exists. + */ +.mobile-menu > .mobile-menu-accordion, +.mobile-menu > .mobile-menu-link-row { + border: none; + border-bottom: 1px solid var(--wp--custom--color--border--card); + border-radius: 0; +} +.mobile-menu > .mobile-menu-accordion:last-child, +.mobile-menu > .mobile-menu-link-row:last-child { + border-bottom: none; +} + +.mobile-menu > .mobile-menu-accordion { + background: none; + box-shadow: none; +} +.mobile-menu > .mobile-menu-accordion:hover, .mobile-menu > .mobile-menu-accordion[open], .mobile-menu > .mobile-menu-accordion[open]:hover { + background: none; + border-color: var(--wp--custom--color--border--card); + box-shadow: none; +} +.mobile-menu > .mobile-menu-accordion:last-child { + border-bottom: none; +} +.mobile-menu > .mobile-menu-accordion { + /* + * Fixed min-block-size (rather than relying on padding + line-height parity with + * .mobile-menu-link-row below) so every top-level row — whether a with its chevron + * or a plain — renders at the exact same height regardless of small content differences. + * padding-inline-end keeps a little clearance for the chevron: zeroing it entirely (matching + * the row's flush-left text) let the rotated 10px chevron's diagonal corners get clipped by + * .wp-block-details's own overflow:hidden. + */ +} +.mobile-menu > .mobile-menu-accordion > summary { + min-block-size: 3rem; + padding-inline: 0 var(--wp--preset--spacing--10); + padding-block: 0; + font-size: var(--wp--preset--font-size--200); + font-weight: var(--wp--custom--typography--font-weight--semibold); +} +.mobile-menu > .mobile-menu-accordion > :where(:not(summary)) { + padding-inline: 0; +} +.mobile-menu > .mobile-menu-accordion[open] > summary { + border-bottom-color: var(--wp--custom--color--border--card); +} +.mobile-menu > .mobile-menu-accordion { + /* + * The card-style focus ring from _details-motion.scss's base :focus-within rule doesn't fit + * this flattened row (it draws a border-colour box-shadow meant for the bordered card look), + * so it's suppressed above — but that must not mean no focus indicator at all. :focus-visible + * on the summary itself restores a visible keyboard-focus outline instead. + */ +} +.mobile-menu > .mobile-menu-accordion:focus-within { + box-shadow: none; +} +.mobile-menu > .mobile-menu-accordion > summary:focus-visible { + outline: 2px solid var(--wp--custom--color--focus--ring); + outline-offset: -2px; +} + +.mobile-menu-link-row { + margin: 0; +} +.mobile-menu-link-row a { + display: flex; + align-items: center; + min-block-size: 3rem; + font-family: var(--wp--preset--font-family--heading); + font-size: var(--wp--preset--font-size--200); + font-weight: var(--wp--custom--typography--font-weight--semibold); + color: var(--wp--custom--color--text--default); + text-decoration: none; +} +.mobile-menu-link-row a:focus-visible { + outline: 2px solid var(--wp--custom--color--focus--ring); + outline-offset: -2px; +} + +/* + * Footer CTAs (Book a consultation / Start a project): reuse the existing pill button styles, + * just stretched to the drawer's full width. No top border here — Contact (the row directly + * above) isn't actually :last-child of .mobile-menu once this buttons group follows it, so its + * own row divider already renders; adding one here too produced a doubled-up divider line. + */ +.mobile-menu-actions { + padding-block-start: var(--wp--preset--spacing--20); +} +.mobile-menu-actions .wp-block-button { + width: 100%; +} +.mobile-menu-actions .wp-block-button__link { + display: block; + width: 100%; + text-align: center; +} + +/* + * Services accordion: phase groups are separated by dashed dividers rather than solid ones, + * keeping the lighter-weight hierarchy the desktop Services panel also uses between phase + * columns. core/separator has no "style: dashed" support declared in its block.json, so setting + * that via a block style attribute fails Gutenberg's save-output validation — the dashed look is + * applied here instead, against the plain default-attribute wp:separator markup. + */ +.mobile-menu-accordion-services hr.wp-block-separator { + margin-block: var(--wp--preset--spacing--10); + border-style: dashed; +} + +.mobile-menu-brand { + min-block-size: 44px; + padding-block-end: var(--wp--preset--spacing--20); + border-block-end: 1px solid var(--wp--custom--color--border--card); +} +.mobile-menu-brand .wp-block-site-logo img { + display: block; + max-block-size: 32px; + inline-size: auto; +} + /********** Site Footer **********/ /* * "LightSpeed notes" badge: a flex group with no explicit width constraint defaults to filling diff --git a/functions.php b/functions.php index a13e320..fefcbd2 100644 --- a/functions.php +++ b/functions.php @@ -37,6 +37,10 @@ function ls_theme_setup() { // Add support for editor styles. add_theme_support( 'editor-styles' ); + // Required for core/site-logo to render (used by the mobile menu's logo row); without this, + // the block outputs nothing even when a Site Logo is set via the Site Editor. + add_theme_support( 'custom-logo' ); + // Enqueue editor styles. animations.css must be listed here (not just enqueued via // enqueue_block_editor_assets) so the header/footer interactive-control CSS — the collapsed // search field, the icon-toggle button shell — reliably reaches the Site Editor's iframed canvas. diff --git a/parts/mobile-menu.html b/parts/mobile-menu.html new file mode 100644 index 0000000..5a851e9 --- /dev/null +++ b/parts/mobile-menu.html @@ -0,0 +1,331 @@ + +
+
+ + + +
Work + +
+ + + +
Solutions +
+

WordPress

+ + + +

Publishing

+ + + +

AI

+ + + +

AI Chatbots

+ + + +

WooCommerce

+ + + +

Tour Operators

+ + + +

Design Systems

+ + + + +
+
+ + + +
Services +
+
+
+ + + +

Discover

+
+ + + +

Discovery

+ + + +
+ + + +
+
+ + + +

Create

+
+ + + +

Content

+ + + +

Design

+ + + +
+ + + +
+
+ + + +

Build

+
+ + + +

Development

+ + + +

Migrations

+ + + +
+ + + +
+
+ + + +

Launch

+
+ + + +

Hosting

+ + + +

Performance

+ + + +

Security

+ + + +

Training

+ + + +
+ + + +
+
+ + + +

Grow

+
+ + + +

Support

+ + + +

SEO

+ + + +

Accessibility

+ + + +

Email marketing

+ + + +
+ + + +
+
+ + + +

Evolve

+
+ + + +

AI

+ + + + +
+
+ + + + + + + +
Pricing + +
+ + + +
Insights + +
+ + + +
About + +
+ + + + + + + + +
+ diff --git a/patterns/header.php b/patterns/header.php index 80b12b9..e2fa509 100644 --- a/patterns/header.php +++ b/patterns/header.php @@ -15,7 +15,7 @@
<?php echo esc_attr__( 'LightSpeed', 'ls-theme' ); ?>
- +
diff --git a/src/scss/animations.scss b/src/scss/animations.scss index 15d5124..c9594a0 100644 --- a/src/scss/animations.scss +++ b/src/scss/animations.scss @@ -6,6 +6,7 @@ @use "animations/button-motion"; @use "animations/faq-motion"; @use "animations/menu-motion"; +@use "animations/mobile-menu-motion"; @use "animations/footer-motion"; @use "animations/header-motion"; @use "animations/taxonomy-filter"; \ No newline at end of file diff --git a/src/scss/animations/_mobile-menu-motion.scss b/src/scss/animations/_mobile-menu-motion.scss new file mode 100644 index 0000000..cbf0b62 --- /dev/null +++ b/src/scss/animations/_mobile-menu-motion.scss @@ -0,0 +1,196 @@ +@use "../abstracts/mixins/motion"; + +/********** Mobile Menu (Ollie Menu Designer mobileMenuSlug drawer) **********/ + +/* + * Logo row + close button. The close button is WP core's own + * .wp-block-navigation__responsive-container-close — rendered as a sibling before the injected + * mobileMenuSlug content, not part of this template part — so it can only be reached and aligned + * via a global selector, not through markup here. Core's default top:0/right:0 plus the content's + * default padding-top: calc(2rem + 24px) (wp-includes/blocks/navigation/style.css) is what was + * producing the oversized gap above the logo; both are overridden to the same spacing token here + * so the logo row and the close button land on the same line. Styled with the same circular + * icon-button language as the header's search/theme-toggle buttons + * (styles/blocks/groups/header-icon-button.json) for visual consistency. + * + * Scoped under .site-header: this theme only has the one core/navigation instance (the header's), + * but these are otherwise generic core class names that would restyle any Navigation block's + * overlay drawer anywhere on the site if left unscoped. + */ +.site-header .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) + .wp-block-navigation__responsive-container-content { + padding-top: var(--wp--preset--spacing--20); +} + +.site-header .wp-block-navigation__responsive-container-close { + position: absolute; + top: var(--wp--preset--spacing--20); + right: var(--wp--preset--spacing--20); + display: flex; + align-items: center; + justify-content: center; + min-inline-size: 44px; + min-block-size: 44px; + padding: var(--wp--preset--spacing--10); + border: 1px solid var(--wp--custom--color--border--card); + border-radius: var(--wp--preset--border-radius--500); + background-color: color-mix(in srgb, var(--wp--custom--color--surface--highlight) 4%, transparent); + transition: background-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard), + border-color var(--wp--custom--animation--duration--base) var(--wp--custom--animation--easing--standard); + + svg { + inline-size: 20px; + block-size: 20px; + } + + &:hover, + &:focus-visible { + background-color: var(--wp--custom--color--surface--card-raised); + border-color: var(--wp--custom--color--phase--create); + } +} + +@include motion.reduced-motion { + .site-header .wp-block-navigation__responsive-container-close { + transition: none; + } +} + +/* + * core/details already ships a full card-style accordion (border, background, chevron, hover, + * [open] state) globally via styles/presets/blocks/core-details.json + _details-motion.scss. The + * mobile drawer wants that same disclosure mechanism but flattened into a full-width list row + * (no individual card border/background/shadow, no hover lift) with a divider between siblings + * instead — none of which is expressible in theme.json, so it's layered on here rather than + * duplicating the chevron/open logic that already exists. + */ +.mobile-menu > .mobile-menu-accordion, +.mobile-menu > .mobile-menu-link-row { + border: none; + border-bottom: 1px solid var(--wp--custom--color--border--card); + border-radius: 0; + + &:last-child { + border-bottom: none; + } +} + +.mobile-menu > .mobile-menu-accordion { + background: none; + box-shadow: none; + + &:hover, + &[open], + &[open]:hover { + background: none; + border-color: var(--wp--custom--color--border--card); + box-shadow: none; + } + + &:last-child { + border-bottom: none; + } + + /* + * Fixed min-block-size (rather than relying on padding + line-height parity with + * .mobile-menu-link-row below) so every top-level row — whether a with its chevron + * or a plain — renders at the exact same height regardless of small content differences. + * padding-inline-end keeps a little clearance for the chevron: zeroing it entirely (matching + * the row's flush-left text) let the rotated 10px chevron's diagonal corners get clipped by + * .wp-block-details's own overflow:hidden. + */ + > summary { + min-block-size: 3rem; + padding-inline: 0 var(--wp--preset--spacing--10); + padding-block: 0; + font-size: var(--wp--preset--font-size--200); + font-weight: var(--wp--custom--typography--font-weight--semibold); + } + + > :where(:not(summary)) { + padding-inline: 0; + } + + &[open] > summary { + border-bottom-color: var(--wp--custom--color--border--card); + } + + /* + * The card-style focus ring from _details-motion.scss's base :focus-within rule doesn't fit + * this flattened row (it draws a border-colour box-shadow meant for the bordered card look), + * so it's suppressed above — but that must not mean no focus indicator at all. :focus-visible + * on the summary itself restores a visible keyboard-focus outline instead. + */ + &:focus-within { + box-shadow: none; + } + + > summary:focus-visible { + outline: 2px solid var(--wp--custom--color--focus--ring); + outline-offset: -2px; + } +} + +.mobile-menu-link-row { + margin: 0; + + a { + display: flex; + align-items: center; + min-block-size: 3rem; + font-family: var(--wp--preset--font-family--heading); + font-size: var(--wp--preset--font-size--200); + font-weight: var(--wp--custom--typography--font-weight--semibold); + color: var(--wp--custom--color--text--default); + text-decoration: none; + + &:focus-visible { + outline: 2px solid var(--wp--custom--color--focus--ring); + outline-offset: -2px; + } + } +} + +/* + * Footer CTAs (Book a consultation / Start a project): reuse the existing pill button styles, + * just stretched to the drawer's full width. No top border here — Contact (the row directly + * above) isn't actually :last-child of .mobile-menu once this buttons group follows it, so its + * own row divider already renders; adding one here too produced a doubled-up divider line. + */ +.mobile-menu-actions { + padding-block-start: var(--wp--preset--spacing--20); + + .wp-block-button { + width: 100%; + } + + .wp-block-button__link { + display: block; + width: 100%; + text-align: center; + } +} + +/* + * Services accordion: phase groups are separated by dashed dividers rather than solid ones, + * keeping the lighter-weight hierarchy the desktop Services panel also uses between phase + * columns. core/separator has no "style: dashed" support declared in its block.json, so setting + * that via a block style attribute fails Gutenberg's save-output validation — the dashed look is + * applied here instead, against the plain default-attribute wp:separator markup. + */ +.mobile-menu-accordion-services hr.wp-block-separator { + margin-block: var(--wp--preset--spacing--10); + border-style: dashed; +} + +.mobile-menu-brand { + min-block-size: 44px; + padding-block-end: var(--wp--preset--spacing--20); + border-block-end: 1px solid var(--wp--custom--color--border--card); + + .wp-block-site-logo img { + display: block; + max-block-size: 32px; + inline-size: auto; + } +} diff --git a/theme.json b/theme.json index 1f2b7e9..8458fc8 100644 --- a/theme.json +++ b/theme.json @@ -717,6 +717,11 @@ "name": "services-mega-menu", "title": "Services Mega Menu", "area": "uncategorized" + }, + { + "name": "mobile-menu", + "title": "Mobile Menu", + "area": "uncategorized" } ], "customTemplates": [