diff --git a/blocks/all.php b/blocks/all.php index c973909..9f3aa9e 100644 --- a/blocks/all.php +++ b/blocks/all.php @@ -43,5 +43,8 @@ function ( array $categories ) { // Load optional blocks. require_once plugin_dir_path( __FILE__ ) . 'legacy/header/class-header-block.php'; +require_once plugin_dir_path( __FILE__ ) . 'site-header/class-site-header-block.php'; +require_once plugin_dir_path( __FILE__ ) . 'desktop-menu/class-desktop-menu-block.php'; +require_once plugin_dir_path( __FILE__ ) . 'mobile-menu/class-mobile-menu-block.php'; require_once plugin_dir_path( __FILE__ ) . 'post-listing/class-post-listing-block.php'; require_once plugin_dir_path( __FILE__ ) . 'search-and-filter/class-search-and-filter-block.php'; diff --git a/blocks/desktop-menu/assets/_desktop-menu.scss b/blocks/desktop-menu/assets/_desktop-menu.scss new file mode 100644 index 0000000..48ff7f9 --- /dev/null +++ b/blocks/desktop-menu/assets/_desktop-menu.scss @@ -0,0 +1,23 @@ +@use '/scss/globals'; + +@mixin render { + .desktop-menu__wrapper { + & > ul { + display: flex; + flex-wrap: wrap; + gap: globals.$space-vertical globals.$space-horizontal; + margin: 0; + padding: 0; + list-style-type: none; + + & > li { + margin: 0; + padding: 0; + + & > a { + display: block; + } + } + } + } +} diff --git a/blocks/desktop-menu/class-desktop-menu-block.php b/blocks/desktop-menu/class-desktop-menu-block.php new file mode 100644 index 0000000..e31e64b --- /dev/null +++ b/blocks/desktop-menu/class-desktop-menu-block.php @@ -0,0 +1,69 @@ +'; + + /** + * {@inheritdoc} + */ + protected function name(): string { + return 'desktop-menu'; + } + + /** + * {@inheritdoc} + */ + protected function label(): string { + return 'Desktop Menu'; + } + + /** + * {@inheritdoc} + */ + protected function fields(): array { + return array( + array( + 'key' => 'field_desktop_menu_block_menu_location', + 'name' => 'menu_location', + 'label' => 'Menu', + 'type' => 'select', + 'choices' => $this->get_menu_choices(), + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function template(): string { + return __DIR__ . '/templates/block.php'; + } + + /** + * {@inheritdoc} + */ + protected function use_default_wrapper_template(): bool { + return false; + } +} diff --git a/blocks/desktop-menu/templates/block.php b/blocks/desktop-menu/templates/block.php new file mode 100644 index 0000000..8768c7f --- /dev/null +++ b/blocks/desktop-menu/templates/block.php @@ -0,0 +1,26 @@ +get_field( 'menu_location' ); +?> + +
+ + Please select a menu. + + render_menu_by_location( $menu_location ); ?> + +
diff --git a/blocks/mobile-menu/assets/_mobile-menu.scss b/blocks/mobile-menu/assets/_mobile-menu.scss new file mode 100644 index 0000000..dbe1294 --- /dev/null +++ b/blocks/mobile-menu/assets/_mobile-menu.scss @@ -0,0 +1,75 @@ +@use '/scss/globals'; + +@mixin render { + .mobile-menu__wrapper { + display: flex; + flex-direction: column; + flex-grow: 1; + padding: globals.$space-vertical globals.$space-horizontal; + } + + .mobile-menu__toggle-wrapper { + display: flex; + justify-content: flex-end; + padding-bottom: globals.$space-vertical; + } + + .mobile-menu__toggle { + display: block; + position: relative; + width: 40px; + height: 40px; + overflow: hidden; + background-color: grey; + border: none; + font-size: 0; + text-indent: 100px; + white-space: nowrap; + cursor: pointer; + + &::after { + content: ''; + display: block; + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + background-color: black; + mask-image: url('data:image/svg+xml,%3Csvg%20width%3D%2238%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%207.1210938%200.7265625%20L%203.7265625%204.1210938%20L%2015.605469%2016%20L%203.7265625%2027.878906%20L%207.1210938%2031.273438%20L%2019%2019.394531%20L%2030.878906%2031.273438%20L%2034.273438%2027.878906%20L%2022.394531%2016%20L%2034.273438%204.1210938%20L%2030.878906%200.7265625%20L%2019%2012.605469%20L%207.1210938%200.7265625%20z%20%22%20%2F%3E%3C%2Fsvg%3E'); + mask-size: 100%; + mask-position: center; + mask-repeat: no-repeat; + transform: translate(-50%, -50%); + } + } + + .mobile-menu__inner { + display: flex; + flex-direction: column; + flex-grow: 1; + margin-bottom: calc(globals.$space-bottom * -1); + + & > * { + margin-bottom: globals.$space-bottom; + } + + ul { + display: flex; + flex-direction: column; + margin: 0; + padding: 0; + gap: globals.$space-vertical globals.$space-horizontal; + list-style-type: none; + + & > li { + margin: 0; + padding: 0; + + & > a { + display: block; + } + } + } + } +} diff --git a/blocks/mobile-menu/assets/mobile-menu.js b/blocks/mobile-menu/assets/mobile-menu.js new file mode 100644 index 0000000..f5076c1 --- /dev/null +++ b/blocks/mobile-menu/assets/mobile-menu.js @@ -0,0 +1,74 @@ +/** + * @class Mobile_Menu + * @classdesc + * Manages the behavior of a mobile menu component. + * Provides the ability to close the menu via the internal toggle element. + * Triggers a 'mobile_menu_toggle' event, which can be handled externally to show or hide the menu. + */ +class Mobile_Menu { + + /** + * Stores references to relevant DOM elements for the mobile menu. + * @type {Object} + * @property {jQuery} wrapper - The top-level menu wrapper element. + * @property {jQuery} toggle - The toggle element used to trigger menu open/close. + */ + elements = {}; + + /** + * Creates an instance of Mobile_Menu. + * @param {jQuery} wrapper - The jQuery object representing the menu's wrapper element. + */ + constructor(wrapper) { + this.loadElements(wrapper); // Cache relevant DOM elements. + this.initializeToggle(); // Attach event listeners to the toggle. + } + + /** + * Caches references to important DOM elements within the menu wrapper. + * + * @param {jQuery} wrapper - The menu's outer wrapper element. + */ + loadElements(wrapper) { + this.elements.wrapper = wrapper; + this.elements.toggle = wrapper.find('.mobile-menu__toggle'); + } + + /** + * Sets up the event listener for the toggle element. + * When clicked, it calls the toggle() method to trigger the menu event. + */ + initializeToggle() { + this.elements.toggle.on( + 'click', + () => { + this.toggle(); + } + ); + } + + /** + * Triggers a global event to toggle the mobile menu's state. + * Separate scripts should listen for the 'mobile_menu_toggle' event and handle show/hide logic. + */ + toggle() { + jQuery(window).trigger('mobile_menu_toggle'); + } +} + +jQuery(document).ready( + () => { + // Store all Mobile_Menu instances globally for potential later access. + window.mobileMenu = []; + + // Find all menu wrappers on the page. + let wrappers = jQuery('.mobile-menu__wrapper'); + + // Instantiate a Mobile_Menu controller for each wrapper found. + wrappers.each( + (index) => { + window.mobileMenu.push(new Mobile_Menu(wrappers.eq(index))); + } + ); + } +); diff --git a/blocks/mobile-menu/class-mobile-menu-block.php b/blocks/mobile-menu/class-mobile-menu-block.php new file mode 100644 index 0000000..bc8f61b --- /dev/null +++ b/blocks/mobile-menu/class-mobile-menu-block.php @@ -0,0 +1,106 @@ + 'field_mobile_menu_block_menu_location', + 'name' => 'menu_location', + 'label' => 'Menu', + 'type' => 'select', + 'choices' => $this->get_menu_choices(), + ), + ), + __DIR__ . '/templates/menu.php', + array(), + 'menu' + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function template(): string { + return __DIR__ . '/templates/block.php'; + } + + /** + * {@inheritdoc} + */ + protected function use_default_wrapper_template(): bool { + return false; + } + + /** + * {@inheritdoc} + */ + protected function setup(): bool { + $this->register_script(); + return parent::setup(); + } + + /** + * Registers the mobile-menu JavaScript file. + */ + protected function register_script() { + add_action( + 'wp_enqueue_scripts', + function () { + wp_register_script( + 'mobile_menu', + plugin_dir_url( __FILE__ ) . 'assets/mobile-menu.js', + array( + 'jquery', + ), + 1, + true + ); + } + ); + } +} diff --git a/blocks/mobile-menu/templates/block.php b/blocks/mobile-menu/templates/block.php new file mode 100644 index 0000000..12ddabd --- /dev/null +++ b/blocks/mobile-menu/templates/block.php @@ -0,0 +1,42 @@ + + +
+
+ +
+ + +
diff --git a/blocks/mobile-menu/templates/menu.php b/blocks/mobile-menu/templates/menu.php new file mode 100644 index 0000000..5f1f9ac --- /dev/null +++ b/blocks/mobile-menu/templates/menu.php @@ -0,0 +1,26 @@ +get_field( 'menu_location' ); +?> + +
+ + Please select a menu. + + render_menu_by_location( $menu_location ); ?> + +
diff --git a/blocks/site-header/assets/_site-header.scss b/blocks/site-header/assets/_site-header.scss new file mode 100644 index 0000000..c89b3f5 --- /dev/null +++ b/blocks/site-header/assets/_site-header.scss @@ -0,0 +1,174 @@ +@use '/scss/globals'; +@use '/scss/extenders/container'; + +@mixin render { + .site-header__outer-wrapper { + @extend %container__outer-wrapper; + } + + .site-header__wrapper { + @extend %container__wrapper; + opacity: 0; + } + + .site-header__wrapper--active { + opacity: 1; + } + + .site-header__inner { + @extend %container__inner; + } + + .site-header__sections { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: globals.$space-vertical globals.$space-horizontal; + + & > *:first-child { + margin-right: auto; + } + } + + .site-header__section--device-visibility-mobile { + @media only screen and (min-width: globals.$breakpoint-medium) { + display: none; + } + } + + .site-header__section--device-visibility-desktop { + display: none; + + @media only screen and (min-width: globals.$breakpoint-medium) { + display: initial; + } + } + + .site-header__section--desktop-menu { + display: none; + + @media only screen and (min-width: globals.$breakpoint-medium) { + display: unset; + } + } + + .site-header__section--mobile-menu-toggle { + @media only screen and (min-width: globals.$breakpoint-medium) { + display: none; + } + } + + .site-header__logo { + a, + img { + display: block; + width: 100%; + height: auto; + } + } + + .site-header__mobile-menu-toggle { + display: block; + position: relative; + width: 40px; + height: 40px; + overflow: hidden; + background-color: grey; + border: none; + font-size: 0; + text-indent: 100px; + white-space: nowrap; + cursor: pointer; + + &::before, + &::after { + content: ''; + display: block; + position: absolute; + top: 50%; + left: 50%; + width: 20px; + height: 20px; + background-color: black; + mask-size: 100%; + mask-position: center; + mask-repeat: no-repeat; + transform: translate(-50%, -50%); + } + + &::before { + mask-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2238%22%20height%3D%2232%22%3E%3Cpath%20d%3D%22M%200%2C0%20H%2038.4%20V%204.8%20H%200%20Z%20m%200%2C13.6%20h%2038.4%20v%204.8%20H%200%20Z%20M%200%2C27.2%20H%2038.4%20V%2032%20H%200%20Z%22%2F%3E%3C%2Fsvg%3E'); + } + + &::after { + mask-image: url('data:image/svg+xml,%3Csvg%20width%3D%2238%22%20height%3D%2232%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M%207.1210938%200.7265625%20L%203.7265625%204.1210938%20L%2015.605469%2016%20L%203.7265625%2027.878906%20L%207.1210938%2031.273438%20L%2019%2019.394531%20L%2030.878906%2031.273438%20L%2034.273438%2027.878906%20L%2022.394531%2016%20L%2034.273438%204.1210938%20L%2030.878906%200.7265625%20L%2019%2012.605469%20L%207.1210938%200.7265625%20z%20%22%20%2F%3E%3C%2Fsvg%3E'); + opacity: 0; + } + + &[aria-checked="true"] { + &::before { + opacity: 0; + } + &::after { + opacity: 1; + } + } + } + + .site-header__general { + margin-bottom: calc(globals.$space-bottom * -1); + + & > * { + margin-bottom: globals.$space-bottom; + } + } + + .site-header__mobile-menu-outer-wrapper { + @media only screen and (min-width: globals.$breakpoint-medium) { + display: none; + } + } + + .site-header__mobile-menu-wrapper { + position: fixed; + top: 0; + right: 0%; + z-index: 1000; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + transition: background-color 0.5s; + + &[hidden] { + display: block; + right: -100%; + background-color: rgba(0, 0, 0, 0); + transition: left 0s linear 0.5s, right 0s linear 0.5s, background-color 0.5s; + } + } + + .site-header__mobile-menu { + display: flex; + flex-direction: column; + position: absolute; + top: 0; + right: 0; + z-index: 1100; + width: 80%; + max-width: 300px; + height: 100%; + overflow: auto; + background-color: white; + transition: transform 0.5s; + + & > .wp-block-template-part { + display: flex; + flex-grow: 1; + flex-direction: column; + } + } + + .site-header__mobile-menu-wrapper[hidden] .site-header__mobile-menu { + transform: translate(100%, 0); + } +} diff --git a/blocks/site-header/assets/site-header.js b/blocks/site-header/assets/site-header.js new file mode 100644 index 0000000..1e24f3c --- /dev/null +++ b/blocks/site-header/assets/site-header.js @@ -0,0 +1,236 @@ +/** + * Class representing a site header component with accessibility and mobile menu support. + * + * This class ensures that each header instance is uniquely identified, manages ARIA and inert + * attributes for accessibility, and sets up event listeners for responsive and accessible + * mobile menu toggling. + */ +class Site_Header { + + /** + * Unique instance number for this header, used to generate unique IDs for internal elements. + * @type {number|null} + */ + instanceNumber = null; + + /** + * Stores jQuery references to important DOM elements in the header. + * @type {Object} + * @property {jQuery} wrapper - The main header wrapper element. + * @property {jQuery} mobileMenuToggle - The mobile menu toggle button. + * @property {jQuery} mobileMenuWrapper - The mobile menu wrapper element. + */ + elements = {}; + + /** + * Create a Site_Header instance. + * @param {jQuery} wrapper - The jQuery-wrapped root element for the site header instance. + */ + constructor(wrapper) { + this.setInstanceNumber(); + this.loadElements(wrapper); + this.assignHiddenAttributes(); + jQuery(window).resize(() => {this.assignHiddenAttributes()}); + this.initializeMobileMenu(); + this.activate(); + } + + /** + * Sets a unique instance number for this header instance. + * This is used to generate unique IDs for elements such as the mobile menu. + * The number is stored on the global window object to ensure uniqueness across instances. + */ + setInstanceNumber() { + if (typeof window.headerCount == 'undefined') { + window.headerCount = -1; + } + + window.headerCount++; + this.instanceNumber = window.headerCount; + } + + /** + * Loads and stores key DOM elements for this instance. + * @param {jQuery} wrapper - The jQuery-wrapped root element for the site header instance. + */ + loadElements(wrapper) { + this.elements.wrapper = wrapper; + this.elements.mobileMenuToggle = wrapper.find('.site-header__mobile-menu-toggle'); + this.elements.mobileMenuWrapper = wrapper.find('.site-header__mobile-menu-wrapper'); + } + + /** + * Assigns `aria-hidden` and `inert` attributes to specific elements based on their visibility. + * + * This method ensures that assistive technology (such as screen readers) correctly ignores + * elements that are not visually visible to users. It uses a visibility check relying on + * layout and computed style support (via `hasLayoutSupport`). If this support is not present, + * the function halts to avoid incorrectly marking all elements as hidden. + * + * For each target element: + * - If the element is not visible (`:visible` is false), it assigns `aria-hidden="true"` + * and sets the `inert` property to `true`. + * - If the element is visible, it removes the `aria-hidden` attribute and sets the `inert` + * property to `false`. + */ + assignHiddenAttributes() { + // Define selectors for elements whose visibility should control ARIA/inert state. + let selectors = [ + '.site-header__section--desktop-menu', + '.site-header__section--mobile-menu-toggle', + '.site-header__mobile-menu-outer-wrapper' + ]; + + // Find all target elements within the wrapper. + let elements = this.elements.wrapper.find(selectors.join(', ')); + + // Prevent further execution if layout and computed style support is not available. + // This avoids marking all elements as hidden when the environment cannot determine visibility. + if (!this.helpers.hasLayoutSupport()) { + return; + } + + elements.each( + (index) => { + let element = elements.eq(index); + + // If the element is not visible, mark it as hidden for assistive technology. + if ( ! element.is(':visible') ) { + element.attr('aria-hidden', 'true'); + element.prop('inert', true); + return; + } + + // If visible, remove hidden attributes/properties. + element.removeAttr('aria-hidden'); + element.prop('inert', false); + } + ); + } + + /** + * Initializes the mobile menu functionality for this header instance. + * + * - Sets a unique ID on the mobile menu wrapper and links it to the toggle button via `aria-controls`. + * - Attaches click event listeners for toggling the mobile menu. + * - Listens for a custom 'mobile_menu_toggle' event on the window. + */ + initializeMobileMenu() { + let id = 'header-mobile-menu-wrapper-' + this.instanceNumber; + + this.elements.mobileMenuToggle.attr('aria-controls', id); + this.elements.mobileMenuWrapper.prop('id', id); + + this.elements.mobileMenuToggle.on( + 'click', + () => { + this.toggleMobileMenu(); + } + ); + + this.elements.mobileMenuWrapper.on( + 'click', + (event) => { + if(!this.elements.mobileMenuWrapper.is(event.target)) { + return; + } + + this.toggleMobileMenu(); + } + ); + + jQuery(window).on( + 'mobile_menu_toggle', + () => { + this.toggleMobileMenu(); + } + ); + } + + /** + * Toggles the visibility and ARIA/inert attributes of the mobile menu. + * + * This method: + * - Updates `aria-checked` and `aria-expanded` on the toggle button. + * - Shows/hides the menu wrapper with `hidden`, `aria-hidden`, and `inert`. + */ + toggleMobileMenu() { + let checked = this.elements.mobileMenuToggle.attr('aria-checked') == 'true' ? true : false; + + checked = ! checked; + + this.elements.mobileMenuToggle.attr('aria-checked', checked ? 'true' : 'false'); + this.elements.mobileMenuToggle.attr('aria-expanded', checked ? 'true' : 'false'); + document.activeElement.blur(); + this.elements.mobileMenuWrapper.prop('inert', ! checked); + this.elements.mobileMenuWrapper.prop('hidden', ! checked); + this.elements.mobileMenuWrapper.attr('aria-hidden', checked ? 'false' : true); + } + + /** + * Adds the 'site-header__wrapper--active' class to the wrapper after initialization. + * This can be used in CSS to make the header opaque or trigger other visual changes. + */ + activate() { + this.elements.wrapper.addClass('site-header__wrapper--active'); + } + + /** + * Helper functions for the Site_Header class. + * @type {Object} + */ + helpers = { + /** + * Checks if the environment supports layout and computed style features needed + * for determining element visibility as browsers do. + * + * Specifically, verifies: + * - window.getComputedStyle is available and functional + * - offsetWidth reflects the element's width + * - getClientRects() returns at least one rect for a visible element + * + * @returns {boolean} True if layout and computed style features are supported; otherwise, false. + */ + hasLayoutSupport: () => { + // Ensure getComputedStyle exists and is a function. + if (typeof window.getComputedStyle !== 'function') return false; + + // Create a visible test element with explicit size. + var el = document.createElement('div'); + el.style.display = 'block'; + el.style.width = '10px'; + el.style.height = '10px'; + document.body.appendChild(el); + + // Check for correct computed style, offsetWidth, and getClientRects support. + var result = + window.getComputedStyle(el).width === '10px' && // CSS width is correctly reported + el.offsetWidth === 10 && // offsetWidth reflects the set width + typeof el.getClientRects === 'function' && // getClientRects exists + el.getClientRects().length > 0; // getClientRects returns at least one rect + + // Clean up the test element. + document.body.removeChild(el); + + return result; + } + } +} + +/** + * On document ready, initialize a Site_Header instance for each `.site-header__wrapper` element. + * Each instance is stored globally in window.siteHeader. + */ +jQuery(document).ready( + () => { + window.siteHeader = []; + + let wrappers = jQuery('.site-header__wrapper'); + + wrappers.each( + (index) => { + window.siteHeader.push(new Site_Header(wrappers.eq(index))); + } + ); + } +); diff --git a/blocks/site-header/class-site-header-block.php b/blocks/site-header/class-site-header-block.php new file mode 100644 index 0000000..6a95b6a --- /dev/null +++ b/blocks/site-header/class-site-header-block.php @@ -0,0 +1,164 @@ +'; + + /** + * {@inheritdoc} + */ + protected function name(): string { + return 'site-header'; + } + + /** + * {@inheritdoc} + */ + protected function label(): string { + return 'Site header'; + } + + /** + * {@inheritdoc} + */ + protected function child_blocks(): array { + return array( + new Child_Block( + 'general', + 'General', + array( + array( + 'key' => 'field_header_block_general_device_visibility', + 'name' => 'device_visibility', + 'label' => 'Device Visibility', + 'type' => 'select', + 'choices' => array( + 'all' => 'All', + 'mobile' => 'Mobile Only', + 'desktop' => 'Desktop Only', + ), + ), + ), + __DIR__ . '/templates/general.php', + array(), + 'editor-help' + ), + new Child_Block( + 'logo', + 'Logo', + array( + array( + 'key' => 'field_header_block_logo_information', + 'name' => 'information', + 'label' => 'Information', + 'type' => 'message', + 'message' => 'This will render the file located at: "/images/logo.svg", relative to the active theme root directory.', + ), + ), + __DIR__ . '/templates/logo.php', + array(), + '', + ), + new Child_Block( + 'desktop-menu', + 'Desktop Menu', + array( + array( + 'key' => 'field_header_block_desktop_menu_information', + 'name' => 'information', + 'label' => 'Information', + 'type' => 'message', + 'message' => 'The "desktop-menu" template part will be rendered here.', + ), + ), + __DIR__ . '/templates/desktop-menu.php', + array(), + '' + ), + new Child_Block( + 'mobile-menu-toggle', + 'Mobile Menu Toggle', + array( + array( + 'key' => 'field_header_block_mobile_menu_toggle_information', + 'name' => 'information', + 'label' => 'Information', + 'type' => 'message', + 'message' => 'This button will toggle the display of the "mobile-menu" template part.', + ), + ), + __DIR__ . '/templates/mobile-menu-toggle.php', + array(), + 'menu' + ), + ); + } + + /** + * {@inheritdoc} + */ + protected function template(): string { + return __DIR__ . '/templates/block.php'; + } + + /** + * {@inheritdoc} + */ + protected function modifier_classes(): array { + $classes = array(); + + if ( is_admin() ) { + array_push( $classes, 'active' ); + } + + return $classes; + } + + /** + * {@inheritdoc} + */ + protected function setup(): bool { + $this->register_script(); + return parent::setup(); + } + + /** + * Registers the header JavaScript file. + */ + protected function register_script() { + add_action( + 'wp_enqueue_scripts', + function () { + wp_register_script( + 'site_header', + plugin_dir_url( __FILE__ ) . 'assets/site-header.js', + array( + 'jquery', + ), + 1, + true + ); + } + ); + } +} diff --git a/blocks/site-header/templates/block.php b/blocks/site-header/templates/block.php new file mode 100644 index 0000000..ae944f1 --- /dev/null +++ b/blocks/site-header/templates/block.php @@ -0,0 +1,34 @@ + + +
+ +
+ +
+ +
diff --git a/blocks/site-header/templates/desktop-menu.php b/blocks/site-header/templates/desktop-menu.php new file mode 100644 index 0000000..0efd463 --- /dev/null +++ b/blocks/site-header/templates/desktop-menu.php @@ -0,0 +1,16 @@ + + +
+
+ ' ); ?> +
+
diff --git a/blocks/site-header/templates/general.php b/blocks/site-header/templates/general.php new file mode 100644 index 0000000..6176d54 --- /dev/null +++ b/blocks/site-header/templates/general.php @@ -0,0 +1,32 @@ + 'Place any content here.', + ), + ), +); +?> + +
+ +
\ No newline at end of file diff --git a/blocks/site-header/templates/logo.php b/blocks/site-header/templates/logo.php new file mode 100644 index 0000000..bfc5f62 --- /dev/null +++ b/blocks/site-header/templates/logo.php @@ -0,0 +1,21 @@ + + + diff --git a/blocks/site-header/templates/mobile-menu-toggle.php b/blocks/site-header/templates/mobile-menu-toggle.php new file mode 100644 index 0000000..956fab7 --- /dev/null +++ b/blocks/site-header/templates/mobile-menu-toggle.php @@ -0,0 +1,26 @@ + + +
+
+ +
+