From 411ebbcb7ae1887a77addd9ad7f0e4523b7fae88 Mon Sep 17 00:00:00 2001 From: mdickson-adbe <95774602+mdickson-adbe@users.noreply.github.com> Date: Tue, 23 Apr 2024 15:03:40 -0400 Subject: [PATCH] Assets 98992- Campaign details/overview (#69) * initial block structure * start mocking up structure * many changes - finish overview tab mockup - (mostly) finish deliverables tab * fix css- add top/bottom borders to rows * delete invalid metadata from new svgs * updates for mvp - Rename and hide various elements of page - Refactor tablebuilding function to deal with items that are missing categorization properties * hide total assets --- .../gmo-campaign-details.css | 325 +++++++++ .../gmo-campaign-details.js | 629 ++++++++++++++++++ icons/Express.svg | 10 - icons/collapse.svg | 19 + icons/trophy.svg | 7 + 5 files changed, 980 insertions(+), 10 deletions(-) create mode 100644 blocks/gmo-campaign-details/gmo-campaign-details.css create mode 100644 blocks/gmo-campaign-details/gmo-campaign-details.js create mode 100644 icons/collapse.svg create mode 100644 icons/trophy.svg diff --git a/blocks/gmo-campaign-details/gmo-campaign-details.css b/blocks/gmo-campaign-details/gmo-campaign-details.css new file mode 100644 index 00000000..c524497c --- /dev/null +++ b/blocks/gmo-campaign-details/gmo-campaign-details.css @@ -0,0 +1,325 @@ +body { + background-color: rgb(247, 246, 246); +} +.back-button { + margin-top: 20px; + background-color: #FFFFFF; + width: 65px; + height: 32px; + display: flex; + padding-left: 10px; + padding-right: 10px; + align-items: center; + border: 1px solid #D3D3D3; + border-radius: 4px; + & > .icon { + width: 20px; + height: 30px; + } + & > .back-label { + margin-left: 15px; + font: normal normal normal 14px/17px Adobe Clean; + font-weight: bold; + } +} +.gmo-campaign-details.block { + & .h1 { + font: normal normal bold 18px/27px Adobe Clean; + } + & .h2 { + font: normal normal bold 16px/20px Adobe Clean; + } + & .h3 { + font: normal normal bold 14px/21px Adobe Clean; + } + & > .main-body-wrapper { + display: flex; + flex-direction: column; + background: #FFFFFF; + border-radius: 6px; + box-shadow: 0px 3px 6px #0000000D; + margin-top: 20px; + min-height: 800px; + padding: 20px; + } +} + +.details-header-wrapper { + display: flex; + & > .header-title { + margin-left: 20px; + display: flex; + flex-direction: column; + & .icon-calendar { + width: 17px; + } + } + & .header-row1 { + display: flex; + align-items: center; + flex-wrap: wrap; + text-align: center; + line-height: 22px; + } + & .header-row2 { + display: flex; + align-items: center; + margin-top: 20px; + } + & .campaign-status { + background-color: #EEF8F5; + border-radius: 4px; + color: #33AB84; + font: normal normal normal 12px/15px Adobe Clean; + height: 24px; + line-height: 24px; + width: 72px; + margin-left: 10px; + text-align: center; + } + & .campaign-date { + font: normal normal normal 14px/21px Adobe Clean; + margin-left: 10px; + } +} +.campaign-img { + width: 80px; + height: 80px; + color: darkgray; + border: 1px solid black; + border-radius: 20px; + +} +.tab-wrapper { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + align-content: center; + width: 160px; + height: 50px; + font: normal normal normal 14px/17px Adobe Clean; + border-bottom: 2px solid #EAEAEA; + & > .tabBtn { + color: #747474; + height: 100%; + line-height: 50px; + &.active { + color: #323232; + border-bottom: 2px solid #323232; + } + } +} +.tab.two-column { + display: flex; + flex-direction: row; + justify-content: space-between; +} +.overview-wrapper { + display: flex; + flex-direction: column; + width: 800px; + & .overview-heading { + margin-top: 20px; + margin-bottom: 20px; + } + & .description { + margin-top: 10px; + font: normal normal normal 14px/21px Adobe Clean; + letter-spacing: 0px; + color: black; + } + & .button.no-bg { + font: normal normal normal 14px/17px Adobe Clean; + margin-top: 10px; + color: #505050; + } +} +.kpis-wrapper { + margin-top: 30px; + & ul { + columns: 2; + -webkit-columns: 2; + -moz-columns: 2; + font: normal normal normal 14px/21px Adobe Clean; + } +} +.use-cases-wrapper { + display: flex; + flex-direction: column; + margin-top: 30px; + & .tags-wrapper { + display: flex; + flex-direction: row; + margin-top: 10px; + } + & .use-case-tag { + font: normal normal normal 14px/17px Adobe Clean; + color: #505050; + border: 1px solid #D3D3D3; + border-radius: 4px; + padding: 0 10px 0 10px; + line-height: 32px; + &:not(:last-child) { + margin-right: 5px; + } + } +} +.links-wrapper { + margin-top: 30px; + & .links { + display: flex; + justify-content: space-between; + margin-top: 10px; + } + & .campaign-link { + font: normal normal normal 14px/21px Adobe Clean; + letter-spacing: 0px; + color: #0D66D0; + } +} +.infocards-wrapper { + margin-right: 40px; + & .card { + width: 360px; + border: 1px solid #D3D3D3; + border-radius: 4px; + background-color: #FFFFFF; + padding: 0px 15px 10px 15px; + &:not(:last-child) { + margin-bottom: 30px; + } + } +} +.card { + & .card-heading { + margin-top: 10px; + margin-bottom: 10px; + } +} +.milestone, .card-content { + font: normal normal normal 14px/21px Adobe Clean; + & .icon { + height: 18px; + margin-right: 5px; + } + display: flex; + align-items: center; + &:not(:last-child) { + margin-bottom: 5px; + } +} +.deliverables { + & > .page-heading { + display: flex; + margin-top: 20px; + margin-bottom: 25px; + & > .total-assets { + display: flex; + flex-direction: column; + justify-content: space-between; + & > span { + font: normal normal normal 14px/21px Adobe Clean; + } + } + } +} +.artifacts-wrapper { + display: flex; + flex-direction: column; + width: 400px; + margin-right: 100px; + & .links { + display: flex; + justify-content: space-between; + margin-top: 10px; + } + & .campaign-link { + font: normal normal normal 14px/21px Adobe Clean; + letter-spacing: 0px; + color: #0D66D0; + } +} +.table-wrapper { + font: normal normal bold 14px/21px Adobe Clean; + & > .table-header { + background: #f7f6f6 0% 0% no-repeat padding-box; + margin-left: -20px; + margin-right: -20px; + padding-left: 20px; + height: 64px; + color: #505050; + display: flex; + align-items: center; + } +} +.inactive { + display: none !important; + visibility: hidden; +} +.row { + height: 56px; + &:not(:last-child) { + border-bottom: 2px solid #F4F4F4; + } + &.datarow { + display: flex; + } + &.collapsible.header { + height: unset; + display: flex; + flex-direction: column; + line-height: 56px; + & > .heading-wrapper { + display: flex; + margin-left: 15px; + &.subheading { + margin-left: 25px; + } + & > .icon-next, & > .icon-collapse { + height: 10px; + width: 10px; + } + & > .headertext { + margin-left: 10px; + } + } + } + + & .property { + line-height: 56px; + } +} +.subheader { + &:nth-child(2) { + border-top: 2px solid #F4F4F4; + } + & > .row:nth-child(2) { + border-top: 2px solid #F4F4F4; + } +} +.column1 { + margin-left: 45px; +} +.column1 { + width: 140px; +} +.column3, & .column4, & .column5, & .column6 { + width: 110px; +} +.column2 { + width: 130px; +} +.column7 { + width: 170px; +} +.column8 { + width: 100px; +} +.column9 { + width: 90px; +} +.table-column { + &:not(:last-child) { + margin-right: 85px; + } +} \ No newline at end of file diff --git a/blocks/gmo-campaign-details/gmo-campaign-details.js b/blocks/gmo-campaign-details/gmo-campaign-details.js new file mode 100644 index 00000000..8ab24d33 --- /dev/null +++ b/blocks/gmo-campaign-details/gmo-campaign-details.js @@ -0,0 +1,629 @@ +import { decorateIcons } from '../../scripts/lib-franklin.js'; + + const testData = [ + { + 'category': 'Awareness', + 'subcategory': 'Meet AI Assistant', + 'name': 'Content Name', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Awareness', + 'subcategory': 'Meet AI Assistant', + 'name': 'Content Name', + 'type': 'Animated Display', + 'channel': 'All', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '86' + }, + { + 'category': 'Awareness', + 'subcategory': 'Customer Story', + 'name': 'Bryan', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Awareness', + 'subcategory': 'Customer Story', + 'name': 'Maegan', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '17' + }, + { + 'category': 'Awareness', + 'subcategory': 'Influencer Videos and Social Owned Content', + 'name': 'Influencer', + 'type': 'Streaming Video', + 'channel': 'Tiktok', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '0%' + }, + { + 'category': 'Education', + 'subcategory': 'Meet AI Assistant', + 'name': 'Content Name', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Education', + 'subcategory': 'Meet AI Assistant', + 'name': 'Content Name', + 'type': 'Animated Display', + 'channel': 'All', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '86' + }, + { + 'category': 'Education', + 'subcategory': 'Customer Story', + 'name': 'Bryan', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Conversion', + 'subcategory': 'Meet the new AI Assistant', + 'name': 'Richard', + 'type': 'Influencer Content', + 'channel': 'TikTok', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '12' + }, + { + 'category': 'Conversion', + 'subcategory': 'Meet the new AI Assistant', + 'name': 'Antonio', + 'type': 'Influencer Content', + 'channel': 'YouTube', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '5' + }, + { + 'category': 'Conversion', + 'subcategory': 'Financial Report', + 'name': 'Citigroup', + 'type': 'Documentation', + 'channel': 'None', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '77' + }, + { + 'category': 'Conversion', + 'subcategory': 'Adobe Owned Use Cases', + 'name': 'David', + 'type': 'Streaming Video', + 'channel': 'Twitch.tv', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '97%' + }, + { + 'category': 'Conversion', + 'subcategory': 'Adobe Owned Use Cases', + 'name': 'Charles', + 'type': 'Media', + 'channel': 'x.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '100' + }, + { + 'category': 'Conversion', + 'subcategory': 'Early Access Offer', + 'name': 'Ashley', + 'type': 'Influencer Content', + 'channel': 'TikTok', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '26' + }, + { + 'category': 'Conversion', + 'subcategory': 'Email - AI Assistant + Early Access Offer', + 'name': 'Missy', + 'type': 'Artificial Intelligence', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '67' + }, + { + 'category': 'Conversion', + 'subcategory': 'Influencer Use Cases / CAMP', + 'name': 'Logan', + 'type': 'Streaming Video', + 'channel': 'YouTube', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '89' + }, + { + 'category': 'Use', + 'subcategory': 'Content Supply Chain', + 'name': 'Content Name', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Use', + 'subcategory': 'Content Supply Chain', + 'name': 'Content Name', + 'type': 'Animated Display', + 'channel': 'All', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '86' + }, + { + 'category': 'Use', + 'subcategory': 'Content Supply Chain', + 'name': 'Bryan', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Use', + 'subcategory': 'Content Supply Chain', + 'name': 'Maegan', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '17' + }, + { + 'category': 'Use', + 'subcategory': 'Content Supply Chain', + 'name': 'Bryan', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Use', + 'subcategory': 'Content Supply Chain', + 'name': 'Maegan', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '17' + }, + { + 'category': 'Use', + 'subcategory': 'Customer Story', + 'name': 'Bryan', + 'type': 'Streaming Video', + 'channel': 'Adobe.com', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '57' + }, + { + 'category': 'Use', + 'subcategory': 'Customer Story', + 'name': 'Maegan', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '17' + }, + { + 'category': '', + 'subcategory': '', + 'name': 'Empty Cat Empty Sub', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '35' + }, + { + 'category': '', + 'subcategory': 'Empty Category', + 'name': 'Empty Category Name', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '35' + }, + { + 'subcategory': 'No Category', + 'name': 'No Category Name', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '35' + }, + { + 'category': '', + 'name': 'No Subcategory Name', + 'type': 'Animated Display', + 'channel': 'Display', + 'reviewLinkName': 'Review Link', + 'reviewLinkHref': '#', + 'finalAssetName': 'Final Asset', + 'finalAssetHref': '#', + 'kpi': 'KPI', + 'statusUpdate': '35' + } +]; + +export default async function decorate(block) { + const rows = buildTable(testData); + block.innerHTML = ` +
+ + Back +
+
+
+
+
+
+
+ Express Mobile Beta +
In Progress
+
+
+ + 03/07/2024 +
+
+
+
+
Overview
+
Deliverables
+
Calendar
+
+
+
+ At a Glance + Product Value + + Express mobile public beta is not a major at scale marketing moment (due to the limited nature of beta experience) with key audiences of + Existing Express users, investors and media. Marketing approach is signaling to the market our continued momentum with the new mobile + beta release, focusing efforts on PR, social/community and in-app surfaces. + +
Read more
+
+ KPIs to Measure Success +
    +
  • PR impressions & dedicated earned stories
  • +
  • Mobile exports
  • +
  • Community & social interactions
  • +
  • 100% by EOL
  • +
+
+
+ Hero Use Cases +
+
Text to Image
+
Use Case 2
+
+
+ +
+
+
+
Milestones
+
+ + Milestone 1 +
+
+ + Milestone 2 +
+
+ + Milestone 3 +
+
+
+
Products
+
+ + Adobe Express Mobile App +
+
+
+
Audiences
+
+ + Existing Express Users +
+
+
+
+
+
+
+ Links to Important Artifacts + +
+
+
Total Assets
+ 7 +
+
+
+
+
Deliverable Name
+
Deliverable Type
+
Channel
+
Review Link
+
Final Asset
+
KPI
+
Status Update
+
Completion Date
+
Lead / Driver
+
+
+
+
+
+
+
+
+ `; + const tableRoot = block.querySelector('.table-content'); + tableRoot.appendChild(rows); + block.querySelector('.tab-wrapper').addEventListener('click', (event) => { + switchTab(event.target); + }) + decorateIcons(block); +} + +function switchTab(tab) { + if (tab.classList.contains('active') || tab.classList.contains('tab-wrapper')) { + return; + } + document.querySelector('.tabBtn.active').classList.toggle('active'); + document.querySelector(`.tab:not(.inactive)`).classList.toggle('inactive'); + const targetTab = tab.dataset.target; + const tabElement = document.getElementById(targetTab); + tabElement.classList.toggle('inactive'); + tab.classList.toggle('active'); +} + +function buildTable(data) { + const rows = document.createElement('div'); + const uniqueCategories = getUniqueValues(data, 'category'); + let isRowHidden = true; + let emptyCategory = false; + uniqueCategories.forEach((category) => { + // build header row + let headerRow; + if (!((category == undefined) || (category === ''))) { + headerRow = buildHeaderRow(category, 'header', false); + attachListener(headerRow); + rows.appendChild(headerRow); + } else { + emptyCategory = true; + headerRow = rows; + } + const matchingCampaigns = data.filter(campaign => campaign.category === category); + // create subcategory headings + const subCats = getUniqueValues(matchingCampaigns, 'subcategory'); + subCats.forEach((subCat) => { + let subCatHeader; + if (!((subCat == undefined) || (subCat === ''))) { + if(emptyCategory) { + subCatHeader = buildHeaderRow(subCat, 'category', false); + } else { + subCatHeader = buildHeaderRow(subCat, 'subcategory', true); + } + attachListener(subCatHeader); + headerRow.appendChild(subCatHeader); + } else { + subCatHeader = rows; + isRowHidden = false; + } + + const matchingSubs = data.filter(campaign => campaign.subcategory === subCat); + matchingSubs.forEach((campaign) => { + const tableRow = buildTableRow(campaign, isRowHidden); + subCatHeader.appendChild(tableRow); + isRowHidden = true; + }); + }); + }) + return rows; +} + +function getUniqueValues(array, filterValue) { + const uniqueValues = new Set(); + array.forEach(obj => { + uniqueValues.add(obj[filterValue]); + }) + return Array.from(uniqueValues); +} + +/** + * @param {string} category - String value of the category property + * @param {string} headerType - Type of header. Either 'category' or 'subcategory' + * @param {boolean} isInactive - Determines whether or not the header will be hidden initially + */ +function buildHeaderRow(category, headerType, isInactive) { + const headerRow = document.createElement('div'); + headerRow.classList.add('row', 'collapsible', 'header'); + let divopen; + if (headerType === 'subcategory') { + headerRow.classList.add('subheader'); + divopen = '
'; + } else { + divopen = '
'; + } + if (isInactive) headerRow.classList.add('inactive'); + headerRow.innerHTML = ` + ${divopen} + + +
${category}
+
`; + return headerRow; +} + +function buildTableRow(campaignJson, createHidden) { + console.log(campaignJson); + const dataRow = document.createElement('div'); + dataRow.classList.add('row', 'datarow'); + if (createHidden) dataRow.classList.add('inactive'); + dataRow.innerHTML = ` +
${campaignJson.name}
+
${campaignJson.type}
+
${campaignJson.channel}
+
${campaignJson.reviewLinkName}
+
${campaignJson.finalAssetName}
+
${campaignJson.kpi}
+
${campaignJson.statusUpdate}
+
${campaignJson.dueDate}
+
${campaignJson.driver}
+ ` + return dataRow; +} + +function attachListener(htmlElement) { + htmlElement.querySelector('.heading-wrapper').addEventListener('click', (event) => { + const arrow = event.target; + const headerRow = arrow.closest('.row.collapsible'); + const rowChildren = headerRow.children; + headerRow.querySelector('.icon-next').classList.toggle('inactive'); + headerRow.querySelector('.icon-collapse').classList.toggle('inactive'); + Array.from(rowChildren).forEach((child) => { + //if child has 'row' class, then toggle 'visible' class + if (child.classList.contains('row')) child.classList.toggle('inactive'); + }) + }) +} \ No newline at end of file diff --git a/icons/Express.svg b/icons/Express.svg index 92f46e2d..233d3445 100644 --- a/icons/Express.svg +++ b/icons/Express.svg @@ -1,15 +1,5 @@ - - - - - - - - -]>