diff --git a/blocks/hero-horizontal-tabs/hero-horizontal-tabs.css b/blocks/hero-horizontal-tabs/hero-horizontal-tabs.css index e7b921871..0772f87cf 100644 --- a/blocks/hero-horizontal-tabs/hero-horizontal-tabs.css +++ b/blocks/hero-horizontal-tabs/hero-horizontal-tabs.css @@ -2,13 +2,26 @@ main .hero-horizontal-tabs-wrapper { background-color: var(--primary); } +main .hero-horiz-tabs-panel { + position: relative; + display: flex; + flex-direction: column; + justify-content: space-between; + padding-right: 6rem; +} + +main .hero-horiz-tabs-nav { + margin-left: 16px; +} + main .hero-horizontal-tabs.block { display: flex; flex-direction: column; + margin-bottom: 5rem; } -main .hero-horiz-tabs-panel { - position: relative; +main div.tab-item.hidden { + display: none; } main .hero-horiz-tabs-text { @@ -55,29 +68,29 @@ main .hero-horiz-tabs-img picture > img { min-width: 100%; } -main .hero-horizontal-tabs nav { - position: absolute; - bottom: 0; - left: 1rem; +main .hero-horizontal-tabs nav ul { + list-style: none; display: flex; + align-items: flex-end; } -main .hero-horizontal-tabs nav a { +main .hero-horizontal-tabs nav button { background-color: var(--transparent-blue-light-color); padding: 11px 16px; - color: var(--link-color); + color: var(--light-black); border-left: 1px solid #d9dfe2; font-size: var(--body-font-size-s); - font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-medium); + border-radius: 0; } -main .hero-horizontal-tabs nav a:hover { +main .hero-horizontal-tabs nav button:hover { text-decoration: none; background-color: white; color: var(--primary); } -main .hero-horizontal-tabs nav a.current { +main .hero-horizontal-tabs nav button.current { background-color: white; color: var(--primary); } @@ -94,6 +107,10 @@ main .hero-horizontal-tabs nav a.current { min-width: 436px; } + main .hero-horiz-tabs-nav { + margin-left: 0; + } + main .hero-horiz-tabs-text > h6 { font-size: var(--heading-font-size-xxs); } @@ -109,11 +126,11 @@ main .hero-horizontal-tabs nav a.current { main .hero-horizontal-tabs nav { position: absolute; - bottom: 0; left: 0; + bottom: 0; } - main .hero-horizontal-tabs nav a { + main .hero-horizontal-tabs nav button { font-size: var(--body-font-size-l); font-weight: var(--font-weight-regular); padding: 16px 32px 18px; diff --git a/blocks/hero-horizontal-tabs/hero-horizontal-tabs.js b/blocks/hero-horizontal-tabs/hero-horizontal-tabs.js index 93717b858..f9e4cf989 100644 --- a/blocks/hero-horizontal-tabs/hero-horizontal-tabs.js +++ b/blocks/hero-horizontal-tabs/hero-horizontal-tabs.js @@ -1,47 +1,124 @@ import { getNamedValueFromTable } from '../../scripts/scripts.js'; -function normalizeURL(url) { - if (url.endsWith('/')) { - return url; +export function createTabs($block, text) { + const $ul = $block.querySelector('ul'); + if (!$ul) { + return null; } - return url.concat('/'); -} + /** @type TabInfo[] */ + const tabs = [...$ul.querySelectorAll('li')].map(($li) => { + const title = $li.textContent; + const name = title.toLowerCase().trim(); + return { + title, + name, + $tab: $li, + }; + }); + const panel = document.createElement('div'); + panel.classList.add('hero-horiz-tabs-panel'); + if (text) panel.appendChild(text); + // turn ul html element into nav + const nav = document.createElement('nav'); + nav.classList.add('hero-horiz-tabs-nav'); -function getImage(block) { - const div = getNamedValueFromTable(block, 'Image'); - div.classList.add('hero-horiz-tabs-img'); - return div; -} + nav.replaceChildren($ul); + panel.appendChild(nav); + // move $ul below section div + $block.replaceChildren(panel); + + // search referenced sections and move them inside the tab-container + const $wrapper = $block.parentElement; + const $container = $wrapper.parentElement; + const $sections = document.querySelectorAll('[data-tab]'); + + // move the tab's sections before the tab riders. + [...$sections].forEach(($tabContent) => { + const name = $tabContent.dataset.tab.toLowerCase().trim(); + /** @type TabInfo */ + const tab = tabs.find((t) => t.name === name); + if (tab) { + const sectionWrapper = document.createElement('div'); -export function getTabs(block, curLocation) { - const tabs = document.createElement('nav'); - const div = getNamedValueFromTable(block, 'tabs'); + [...$tabContent.classList].forEach((c) => { + sectionWrapper.classList.add(c); + }); - div.querySelectorAll('ul > li > a').forEach((a) => { - if (normalizeURL(a.href) === normalizeURL(curLocation.href)) { - a.classList.add('current'); + sectionWrapper.classList.add(); + const $el = document.createElement('div'); + $el.classList.add('tab-item'); + $el.append(...$tabContent.children); + $el.classList.add('hidden'); + sectionWrapper.append($el); + $container.insertBefore(sectionWrapper, $wrapper); + $tabContent.remove(); + tab.$content = $el; } - tabs.appendChild(a); }); return tabs; } +function getImage(block) { + const div = getNamedValueFromTable(block, 'Image'); + if (!div) return null; + div.classList.add('hero-horiz-tabs-img'); + return div; +} + function getText(block) { const div = getNamedValueFromTable(block, 'Contents'); + if (!div) return null; div.classList.add('hero-horiz-tabs-text'); return div; } -export default async function decorate(block, curLocation = window.location) { - const text = getText(block); - const image = getImage(block); - const tabs = getTabs(block, curLocation); +export default function decorate($block) { + const image = getImage($block); + const text = getText($block); + const tabs = createTabs($block, text); + + // move the tab riders in front + const $wrapper = $block.parentElement; + const $container = $wrapper.parentElement; + $container.insertBefore($wrapper, $container.firstElementChild); + + tabs.forEach((tab, index) => { + const $button = document.createElement('button'); + const { $tab, title, name } = tab; + $button.textContent = title.split(','); + $button.classList.add('tab'); + + $tab.replaceChildren($button); - const leftDiv = document.createElement('div'); - leftDiv.classList.add('hero-horiz-tabs-panel'); - leftDiv.append(text); - leftDiv.append(tabs); + $tab.addEventListener('click', () => { + const $activeButton = $block.querySelector('button.active'); + + if ($activeButton !== $tab) { + $activeButton.classList.remove('active'); + // remove active class from parent li + $activeButton.parentElement.classList.remove('active'); + + $button.classList.add('active'); + // add active class to parent li + $tab.classList.add('active'); + + tabs.forEach((t) => { + if (name === t.name) { + t.$content.classList.remove('hidden'); + } else { + t.$content.classList.add('hidden'); + } + }); + } + }); + + if (index === 0) { + $button.classList.add('active'); + // add active class to parent li + $tab.classList.add('active'); + if (tab.$content) tab.$content.classList.remove('hidden'); + } + }); - block.replaceChildren(leftDiv); - block.append(image); + if (image) $block.append(image); } diff --git a/blocks/horizontal-list/horizontal-list.css b/blocks/horizontal-list/horizontal-list.css new file mode 100644 index 000000000..c4d6e6a0d --- /dev/null +++ b/blocks/horizontal-list/horizontal-list.css @@ -0,0 +1,31 @@ +.horizontal-list ul { + list-style-type: none; + margin: 0; + padding: 0; + overflow: hidden; +} + +.horizontal-list.careers-tags ul { + font-size: var(--body-font-size-xs); +} + +.horizontal-list li { + display: inline-block; + margin-right: 1rem; + text-align: center; +} + +.horizontal-list li::before { + display: inline-block; + content: ''; + background: inherit; + background-color: var(--text-color); + height: 12px; + width: 12px; + margin-right: 4px; + border-radius: 50%; +} + +.horizontal-list li:last-child { + margin-right: 0; +} diff --git a/blocks/horizontal-list/horizontal-list.js b/blocks/horizontal-list/horizontal-list.js new file mode 100644 index 000000000..4ec2ea3e3 --- /dev/null +++ b/blocks/horizontal-list/horizontal-list.js @@ -0,0 +1,5 @@ +export default function decorate(block) { + const list = block.children[0].children[0].children[0]; + + block.replaceChildren(list); +} diff --git a/blocks/link/link.css b/blocks/link/link.css index b31db5c78..c49b425d4 100644 --- a/blocks/link/link.css +++ b/blocks/link/link.css @@ -10,3 +10,10 @@ left: 0.3rem; top: 0.05rem; } + +.link.block.arrow a::after { + content: url("../../icons/angle-right-blue.svg"); + position:relative; + left: 0.3rem; + top: 0.5rem; +} \ No newline at end of file diff --git a/blocks/network-item/network-item.css b/blocks/network-item/network-item.css new file mode 100644 index 000000000..b20d2c093 --- /dev/null +++ b/blocks/network-item/network-item.css @@ -0,0 +1,83 @@ +.network-item div.tags { + display: flex; + flex-wrap: wrap; + margin-bottom: 24px; +} + +.network-item .tags div { + display: flex; + font-size: var(--body-font-size-xs); + margin-right: 1rem; + align-items: center; +} + +.network-item .tags div::before { + display: inline-block; + content: ''; + background: inherit; + background-color: var(--text-color); + height: 12px; + width: 12px; + margin-right: 4px; + border-radius: 50%; +} + +.network-item h3.title { + font-weight: var(--font-weight-bold); +} + +.network-item .tags div.blue { + color: #009CBD; /* oral care */ +} + +.network-item .tags div.yellow { + color: #D9AB41; /* safety mobility */ +} + +.network-item .tags div.orange { + color: #F87C56; /* health beauty */ +} + +.network-item .tags div.green { + color: #00A499; /* living environment */ +} + +.network-item .tags div.green::before { + background-color: #00A499; /* living environment */ +} + +.network-item .tags div.blue::before { + background-color: #009CBD; /* oral care */ +} + +.network-item .tags div.yellow::before { + background-color: #D9AB41; /* safety mobility */ +} + +.network-item .tags div.orange::before { + background-color: #F87C56; /* health beauty */ +} + +.network-item .tags div:last-child { + margin-right: 0; +} + +div.network-item { + margin-bottom: 24px; + border-bottom: 1px solid #3c465033; +} + +.network-item div.our-hr a::after { + content: url("../../icons/angle-right-blue.svg"); + position:relative; + left: 0.3rem; + top: 0.5rem; +} + +div.network-item h3.title, +div.network-item div.recruiting-link, +div.network-item div.career-opportunities, +div.network-item div.our-hr, +div.network-item div.website { + padding-bottom: 1rem; +} \ No newline at end of file diff --git a/blocks/network-item/network-item.js b/blocks/network-item/network-item.js new file mode 100644 index 000000000..67f326316 --- /dev/null +++ b/blocks/network-item/network-item.js @@ -0,0 +1,119 @@ +import { readBlockConfig } from '../../scripts/lib-franklin.js'; + +function addCareerTagColor(tagDiv) { + if (tagDiv.innerText === 'Oral Care') { + tagDiv.classList.add('blue'); + } else if (tagDiv.innerText === 'Safety & Mobility') { + tagDiv.classList.add('yellow'); + } else if (tagDiv.innerText === 'Living Environment') { + tagDiv.classList.add('green'); + } else if (tagDiv.innerText === 'Health & Beauty') { + tagDiv.classList.add('orange'); + } +} + +function createTagsDiv(tags) { + const tagsDiv = document.createElement('div'); + tagsDiv.classList.add('tags'); + tags.forEach((tag) => { + const tagDiv = document.createElement('div'); + tagDiv.innerText = tag.trim(); + addCareerTagColor(tagDiv); + tagsDiv.append(tagDiv); + }); + return tagsDiv; +} + +function createWebsiteDiv(website) { + const websiteDiv = document.createElement('div'); + websiteDiv.classList.add('website'); + const websiteA = document.createElement('a'); + websiteA.href = website; + websiteA.innerText = 'View Website'; + websiteDiv.append(websiteA); + return websiteDiv; +} + +function createCareerOpportunitiesDiv() { + const careerOpportunitiesDiv = document.createElement('div'); + const careerOpportunitiesStrong = document.createElement('strong'); + careerOpportunitiesDiv.classList.add('career-opportunities'); + careerOpportunitiesStrong.innerText = 'Career Opportunities'; + careerOpportunitiesDiv.append(careerOpportunitiesStrong); + return careerOpportunitiesDiv; +} + +function createOurHrDiv() { + const ourHrDiv = document.createElement('div'); + ourHrDiv.classList.add('our-hr'); + const ourHrA = document.createElement('a'); + ourHrA.href = 'https://www.sunstar.com/contact/'; + ourHrA.innerText = 'Our HR Department'; + ourHrDiv.append(ourHrA); + return ourHrDiv; +} + +function createRecruitingLinkDiv(recruitingLink, recruitingLinkText) { + const recruitingLinkDiv = document.createElement('div'); + recruitingLinkDiv.classList.add('recruiting-link'); + const recruitingLinkA = document.createElement('a'); + recruitingLinkA.href = recruitingLink; + if (recruitingLinkText) { + recruitingLinkA.innerText = recruitingLinkText; + } else { + recruitingLinkA.innerText = 'View Open Positions'; + } + recruitingLinkDiv.append(recruitingLinkA); + return recruitingLinkDiv; +} + +export default function decorate(block) { + const blockCfg = readBlockConfig(block); + let { title } = blockCfg; + + if (Array.isArray(blockCfg.title)) { + title = title.join('\n'); + } + + const tags = [...blockCfg.tags.split(',')]; + + const recruitingLink = blockCfg['recruiting-link']; + const recruitingLinkText = blockCfg['recruiting-link-text']; + + const { website } = blockCfg; + let websiteDiv; + let recruitingLinkDiv; + + const titleDiv = document.createElement('h3'); + titleDiv.classList.add('title'); + titleDiv.innerText = title; + + const tagsDiv = createTagsDiv(tags); + + if (recruitingLink) { + recruitingLinkDiv = createRecruitingLinkDiv(recruitingLink, recruitingLinkText); + } + + if (website) { + websiteDiv = createWebsiteDiv(website); + } + + const ourHrDiv = createOurHrDiv(); + + block.replaceChildren(titleDiv, tagsDiv); + + if (website) { + block.append(websiteDiv); + } + + const careerOpportunitiesDiv = createCareerOpportunitiesDiv(); + block.append(careerOpportunitiesDiv); + + if (recruitingLink) { + block.append(recruitingLinkDiv); + } + + block.append(ourHrDiv); + + return block; +} diff --git a/icons/angle-right-blue.svg b/icons/angle-right-blue.svg new file mode 100644 index 000000000..7a43cbf8d --- /dev/null +++ b/icons/angle-right-blue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/styles/styles.css b/styles/styles.css index 0c18a1597..c978b42c7 100644 --- a/styles/styles.css +++ b/styles/styles.css @@ -761,6 +761,13 @@ main .section.light-blue { font-size: 2.25rem; } + /* section - bottom-border */ + main .section.bottom-border { + border-bottom: 1px solid var(--overlay-background-color); + padding-bottom: 2rem; + margin-bottom: 2rem; + } + /* section - spaced */ main .section.spaced h2 { font-size: var(--heading-font-size-xl); diff --git a/test/blocks/hero-horizontal-tabs/hero-horizontal-tabs.test.js b/test/blocks/hero-horizontal-tabs/hero-horizontal-tabs.test.js index 49d698d4a..5108ac482 100644 --- a/test/blocks/hero-horizontal-tabs/hero-horizontal-tabs.test.js +++ b/test/blocks/hero-horizontal-tabs/hero-horizontal-tabs.test.js @@ -27,11 +27,7 @@ describe('Hero Horizontal Tabs', () => { it('Render Tabs', async () => { const block = document.querySelector('.hero-horizontal-tabs'); - const loc = { - href: `${window.location.origin}/global-network/the-americas`, - }; - - await scripts.default(block, loc); + await scripts.default(block); expect(block.children.length).to.equals(2); expect(['hero-horiz-tabs-panel']).to.deep.equal([...block.children[0].classList]); @@ -39,15 +35,13 @@ describe('Hero Horizontal Tabs', () => { expect(['hero-horiz-tabs-text']).to.deep.equal([...block.children[0].children[0].classList]); const nav = block.children[0].children[1]; expect(nav.tagName).to.equal('NAV'); - expect(nav.children.length).to.equal(3); - const a0 = nav.children[0]; - expect(a0.href.endsWith('/global-network/the-americas/')).to.be.true; - expect(a0.innerText).to.equal('The Americas'); - expect([...a0.classList]).to.include('current'); - expect(nav.children[1].href.endsWith('/global-network/asia/')).to.be.true; - expect([...nav.children[1].classList]).to.not.include('current'); - expect(nav.children[2].href.endsWith('/global-network/europe/')).to.be.true; - expect([...nav.children[2].classList]).to.not.include('current'); + const tabs = [...nav.querySelectorAll('li')]; + expect(tabs.length).to.equal(3); + + expect(tabs[0].innerText).to.equal('The Americas'); + expect([...tabs[0].classList]).to.include('active'); + expect([...tabs[1].classList]).to.not.include('active'); + expect([...tabs[2].classList]).to.not.include('active'); expect(['hero-horiz-tabs-img']).to.deep.equal([...block.children[1].classList]); }); @@ -55,21 +49,17 @@ describe('Hero Horizontal Tabs', () => { it('Render Tabs2', async () => { const block = document.querySelector('.hero-horizontal-tabs'); - const loc = { - href: `${window.location.origin}/global-network/asia/`, - }; - - await scripts.default(block, loc); + await scripts.default(block); const nav = block.children[0].children[1]; expect(nav.tagName).to.equal('NAV'); - expect(nav.children.length).to.equal(3); - expect(nav.children[0].href.endsWith('/global-network/the-americas/')).to.be.true; - expect([...nav.children[0].classList]).to.not.include('current'); - expect(nav.children[1].href.endsWith('/global-network/asia/')).to.be.true; - expect([...nav.children[1].classList]).to.include('current'); - expect(nav.children[2].href.endsWith('/global-network/europe/')).to.be.true; - expect([...nav.children[2].classList]).to.not.include('current'); + + const tabs = [...nav.querySelectorAll('li')]; + expect(tabs.length).to.equal(3); + + expect([...tabs[0].classList]).to.include('active'); + expect([...tabs[1].classList]).to.not.include('active'); + expect([...tabs[2].classList]).to.not.include('active'); expect(['hero-horiz-tabs-img']).to.deep.equal([...block.children[1].classList]); });