diff --git a/blocks/blogheader/blogheader.css b/blocks/blogheader/blogheader.css new file mode 100644 index 00000000..0ea1e197 --- /dev/null +++ b/blocks/blogheader/blogheader.css @@ -0,0 +1,154 @@ +main.has-sidebar > div.blogheader-container { + grid-column: 2 / span 2; + color: var(--background-color); + padding: 0; +} + +nav#blogheader { + --number-of-menu-items: 5; + + padding: 0; + margin: 0; +} + +nav#blogheader > div { + display: flex; + justify-content: space-between; + align-items: center; +} + +nav#blogheader ul { + display: table; + table-layout: fixed; + list-style-type: none; + padding: 0; + margin: 0; + margin-bottom: 3rem; + width: 100%; + background-color: var(--text-color); +} + +nav#blogheader li a { + font-size: 1.6rem; + font-family: var(--ff-gilroy-semibold); + font-weight: 400; + text-decoration: none; + transition: none; + background: inherit; + color: inherit; + line-height: 1.714; + -webkit-font-smoothing: antialiased; +} + +nav#blogheader li { + display: table-cell; + border-right: 1px solid white; + color: white; + text-align: center; + padding: 1.5rem 1.2rem; + width: calc(55rem / var(--number-of-menu-items)); +} + +nav#blogheader li.blogsearch-menu-container { + border: none; + text-align: right; + width: auto; + display: flex; + justify-content: flex-end; +} + +nav#blogheader li.active { + background-color: black; +} + +/* Style for the paragraph */ +nav#blogheader p { + margin: 0; + padding: 0; +} + +@media (min-width: 768px) { + div.blogheader-hamburger { + display: none; + visibility: hidden; + width: 0; + } +} + +@media (max-width: 767px ) { + div.blogheader-wrapper div.blogheader { + position: relative; + } + + nav#blogheader { + position: relative; + width: 100%; + } + + nav#blogheader div.blogheader-sections { + position: absolute; + z-index: 100; + top: 3.2rem; + display: block; + } + + nav#blogheader ul { + visibility: hidden; + display: none; + } + + #blogheader > div.blogheader-sections > ul > li.blogsearch-menu-container.blogsearch-wrapper { + padding: 1.2rem; + } + + nav#blogheader li { + display: table-row; + width: 100%; + } + + nav#blogheader li a { + padding: 0.8rem 0; + display: table-cell; + font-size: 1.6rem; + border-bottom: 0.1rem solid #f7f7f7; + } +} + +.blogheader-hamburger { + display: block; + width: 7rem; + height: 2.5rem; + float: right; + border-radius: 0.5rem; + background: #293e40; + position: relative; + right: 0; + color: white; + margin-bottom: 0.8rem; + padding-left: 0.4rem; +} + +.blogheader-hamburger button { + margin: 0; + text-align: left; + padding: 0; + background-color: inherit; +} + +.blogheader-hamburger button::after { + right: 10px; + margin: auto; + position: absolute; + top: 0.6rem; + opacity: 1; + cursor: pointer; + content: ""; + display: inline-block; + width: 8px; + height: 8px; + border-bottom: 2px solid #fff; + border-right: 2px solid #fff; + transform: rotate(45deg); + transition: all 500ms; + transform-origin: center center; +} \ No newline at end of file diff --git a/blocks/blogheader/blogheader.js b/blocks/blogheader/blogheader.js new file mode 100644 index 00000000..2c8e1e82 --- /dev/null +++ b/blocks/blogheader/blogheader.js @@ -0,0 +1,73 @@ +import { + getMetadata, decorateIcons, buildBlock, loadBlock, decorateBlock, fetchPlaceholders, +} from '../../scripts/aem.js'; +import { getLocaleInfo } from '../../scripts/scripts.js'; +import { li, div, button } from '../../scripts/dom-helpers.js'; + +const isDesktop = window.matchMedia('(min-width: 768px)'); + +function toggleMenu(nav, desktop) { + const expanded = nav.getAttribute('aria-expanded') === 'true'; + const expand = !expanded || desktop.matches; + + nav.setAttribute('aria-expanded', !!expand); + nav.style.visibility = expand ? 'visible' : 'hidden'; + nav.style.display = expand ? 'table' : 'none'; +} + +export default async function decorate(block) { + const blogHeaderMeta = getMetadata('blogheader'); + const localeInfo = getLocaleInfo(); + const blogHeaderPath = blogHeaderMeta + ? new URL(blogHeaderMeta).pathname + : 'blog-nav'; + + const blogHeaderResp = await fetch(`${localeInfo.urlPrefix}/blogs/fragments/${blogHeaderPath}.plain.html`); + + if (blogHeaderResp.ok) { + const placeholdersPromise = fetchPlaceholders(getLocaleInfo().placeholdersPrefix); + const blogHeaderHtml = await blogHeaderResp.text(); + + const blogHeader = document.createElement('nav'); + blogHeader.id = 'blogheader'; + blogHeader.innerHTML = blogHeaderHtml; + blogHeader.querySelector('nav > div').classList.add('blogheader-sections'); + + blogHeader + .querySelector(`li > a[href^='${window.location.pathname}'`) + ?.parentNode?.classList.add('active'); + + const numberOfSections = blogHeader.querySelectorAll('li').length; + blogHeader.style.setProperty('--number-of-menu-items', numberOfSections); + + decorateIcons(blogHeader); + const searchBlock = buildBlock('blogsearch', { elems: [] }); + const searchLi = li({ class: 'blogsearch-menu-container' }); + searchLi.appendChild(searchBlock); + const navSections = blogHeader.querySelector('ul'); + navSections.appendChild(searchLi); + navSections.setAttribute('aria-expanded', 'true'); + decorateBlock(searchBlock); + loadBlock(searchBlock); + + const placeholders = await placeholdersPromise; + + const menuText = placeholders.mobileMenu || 'Menu'; + blogHeader.prepend( + div({ + class: 'blogheader-hamburger', + }, + button({ + type: 'button', + 'aria-controls': 'nav', + 'aria-label': menuText, + onclick: () => toggleMenu(navSections, isDesktop), + }, menuText), + ), + ); + + isDesktop.addEventListener('change', () => toggleMenu(navSections, isDesktop)); + + block.append(blogHeader); + } +} diff --git a/blocks/blogsearch/blogsearch.css b/blocks/blogsearch/blogsearch.css new file mode 100644 index 00000000..71a1b840 --- /dev/null +++ b/blocks/blogsearch/blogsearch.css @@ -0,0 +1,45 @@ +.blogsearch { + width: 6rem; +} + +.blogsearch > form { + display: block; + padding-right: 10px; + height: 2.5rem; +} + +.blogsearch form > div { + position: relative; + height: 100%; +} + +.blogsearch form div i.search-icon { + background-image: url("/icons/blog-search-icon.webp"); + width: 1.5rem; + height: 1.5rem; + left: 1.3rem; + top: 0.7rem; + background-repeat: no-repeat; + display: block; + position: absolute; +} + +.blogsearch form div input { + background-color: rgb(255 255 255 / 10%); + background-image: none; + border-radius: 12px; + box-shadow: 0 2px 1px rgb(0 0 0 / 60%) inset, 0 1px 0 rgb(255 255 255 / 20%); + padding: 0; + margin: 0; + position: relative; + border-color: #293e40; + padding-left: 3rem; + color: #fff; + outline: 0; + height: 100%; + width: 100%; + display: inline-block; + line-height: inherit; + font-size: inherit; + font-family: inherit; +} \ No newline at end of file diff --git a/blocks/blogsearch/blogsearch.js b/blocks/blogsearch/blogsearch.js new file mode 100644 index 00000000..ad2d183f --- /dev/null +++ b/blocks/blogsearch/blogsearch.js @@ -0,0 +1,15 @@ +import { + div, form, input, i, +} from '../../scripts/dom-helpers.js'; + +export default async function decorate(block) { + block.innerHtml = ''; + block.textContent = ''; + block.append( + form({}, + div({}, + i({ class: 'search-icon' }), + input({ + type: 'text', + })))); +} diff --git a/icons/blog-search-icon.webp b/icons/blog-search-icon.webp new file mode 100644 index 00000000..388adb7d Binary files /dev/null and b/icons/blog-search-icon.webp differ diff --git a/icons/blogsearch.svg b/icons/blogsearch.svg new file mode 100644 index 00000000..8c09cf3e --- /dev/null +++ b/icons/blogsearch.svg @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/scripts/scripts.js b/scripts/scripts.js index e12c43a6..06e45753 100644 --- a/scripts/scripts.js +++ b/scripts/scripts.js @@ -120,6 +120,12 @@ export function formatDate(date) { }); } +function buildBlogHeader(main) { + const section = document.createElement('div'); + section.append(buildBlock('blogheader', { elems: [] })); + main.prepend(section); +} + /** * Builds an article header and prepends to main in a new section. * @param main @@ -164,10 +170,10 @@ function isArticlePage() { // eslint-disable-next-line no-unused-vars function buildAutoBlocks(main) { try { - // buildHeroBlock(main); if (isArticlePage()) { buildArticleHeader(main); } + buildBlogHeader(main); } catch (error) { // eslint-disable-next-line no-console console.error('Auto Blocking failed', error); @@ -181,7 +187,7 @@ function detectSidebar(main) { const sidebarOffset = Number.parseInt( sidebar.getAttribute('data-start-sidebar-at-section') || '2', 10, - ); + ) + 1; const numSections = main.children.length - 1; main.style = `grid-template-rows: repeat(${numSections}, auto);`;