From 8973ac0ab9c21d53f725d28849f1d86c0443a843 Mon Sep 17 00:00:00 2001 From: Liam Johnston Date: Tue, 18 Jun 2024 16:28:54 +1200 Subject: [PATCH 1/7] Site alert --- .../AlertBanner/AlertBanner.mount.tsx | 29 +++++ .../static_src/components/ComponentsInit.tsx | 4 + .../global/components/site-alert.scss | 114 ++++++++++++++++++ .../images/sprites_src/two-tone/info.svg | 9 ++ .../images/sprites_src/two-tone/warning.svg | 14 +++ cdhweb/static_src/styles.scss | 1 + templates/includes/header.html | 4 + templates/includes/site_alert.html | 51 ++++++++ 8 files changed, 226 insertions(+) create mode 100644 cdhweb/static_src/components/AlertBanner/AlertBanner.mount.tsx create mode 100644 cdhweb/static_src/global/components/site-alert.scss create mode 100644 cdhweb/static_src/images/sprites_src/two-tone/info.svg create mode 100644 cdhweb/static_src/images/sprites_src/two-tone/warning.svg create mode 100644 templates/includes/site_alert.html diff --git a/cdhweb/static_src/components/AlertBanner/AlertBanner.mount.tsx b/cdhweb/static_src/components/AlertBanner/AlertBanner.mount.tsx new file mode 100644 index 00000000..0d36e4d9 --- /dev/null +++ b/cdhweb/static_src/components/AlertBanner/AlertBanner.mount.tsx @@ -0,0 +1,29 @@ +import { InitComponent } from '../ComponentsInit'; + +const initComponent: InitComponent = (component) => { + const alertId = component.getAttribute('data-alert-id'); + if (!alertId) { + throw Error('No banner alert ID supplied'); + } + const alertHasBeenDismissed = !!localStorage.getItem(alertId); + + if (alertHasBeenDismissed) + return () => { + // Alert has previously been dismissed. No need to show it. Abort. + }; + + component.classList.remove('u-hidden'); + const dismissBtn = component.querySelector('button'); + + dismissBtn?.addEventListener('click', () => { + localStorage.setItem(alertId, alertId); + component.classList.add('u-hidden'); + }); + + return () => { + // Return a cleanup function + // nothing to do in this case; + }; +}; + +export default initComponent; diff --git a/cdhweb/static_src/components/ComponentsInit.tsx b/cdhweb/static_src/components/ComponentsInit.tsx index 0472449d..56418a4a 100644 --- a/cdhweb/static_src/components/ComponentsInit.tsx +++ b/cdhweb/static_src/components/ComponentsInit.tsx @@ -1,5 +1,6 @@ import MainNavMobile from './MainNavMobile/MainNavMobile.mount'; import MainNavDesktop from './MainNavDesktop/MainNavDesktop.mount'; +import AlertBanner from './AlertBanner/AlertBanner.mount'; /** * This is where the page is hydrated with types of components. @@ -55,6 +56,9 @@ async function ComponentInit( case 'main-nav-desktop': return mountSyncComponent(MainNavDesktop); + case 'alert-banner': + return mountSyncComponent(AlertBanner); + case 'accordion': return mountAsyncComponent( import( diff --git a/cdhweb/static_src/global/components/site-alert.scss b/cdhweb/static_src/global/components/site-alert.scss new file mode 100644 index 00000000..ae0e0e33 --- /dev/null +++ b/cdhweb/static_src/global/components/site-alert.scss @@ -0,0 +1,114 @@ +.alert-banner { + --alert-accent-color: var(--color-brand-100); + --alert-bg-color: var(--color-brand-5); + + // This linear gradient has a hard stop in the middle and goes full width. + // This is so we get the left-side full bleed for the decoration area. + // The content area has a white background which hides this trickery. + background-image: linear-gradient( + to right, + var(--alert-accent-color) 50%, + var(--alert-bg-color) 50% + ); + + line-height: 1.5; + border-block-end: 1px solid var(--color-brand-110); +} + +.alert-banner--informational { + --alert-accent-color: var(--color-brand-100); +} +.alert-banner--warning { + --alert-accent-color: var(--color-brand-100); +} +.alert-banner--emergency { + --alert-accent-color: var(--color-red-100); +} + +// has `grid-standard` +.alert-banner__grid { + // background-color: var(--color-white); + + // d = decoration (left color block and icon) + // c = content (including dismiss button) + grid-template-areas: 'd c c c c c c c c c c c'; + + @include lg { + grid-template-areas: 'd d c c c c c c c c c c'; + } +} + +.alert-banner__decoration { + --icon-accent-color: var(--icon-accent-color-dark); + + grid-area: d; + background-color: var(--alert-accent-color); + + // icon placement + display: grid; + justify-content: end; + padding: 6px 4px; + + @include lg { + padding: 20px 8px; + } + + :where(svg) { + width: 20px; + aspect-ratio: 1; + } +} + +.alert-banner__content { + grid-area: c; + background-color: var(--alert-bg-color); + position: relative; // for pseudo element placement + + font-size: px2rem(16); + padding-block: 8px; + + @include lg { + padding-block: 16px; + } + + // Visually add left padding to the alert content + &::before { + content: ''; + position: absolute; + top: 0; + left: calc(-1 * var(--standard-gap)); + width: var(--standard-gap); + height: 100%; + background-color: var(--alert-bg-color); + } +} + +.alert-banner__heading { + font-size: px2rem(20); +} + +// Wrapper for a) text and b) dismiss button +.alert-banner__content--dismissable { + display: grid; + grid-template-columns: 1fr auto; + align-items: start; + gap: 12px; +} + +.alert-banner__text { + max-inline-size: px2rem(1080); +} + +.alert-banner__dismiss-btn { + background: none; + border: none; + font: inherit; + cursor: pointer; + + padding: 4px; + + :where(svg) { + width: px2rem(18); + aspect-ratio: 1; + } +} diff --git a/cdhweb/static_src/images/sprites_src/two-tone/info.svg b/cdhweb/static_src/images/sprites_src/two-tone/info.svg new file mode 100644 index 00000000..a78022a2 --- /dev/null +++ b/cdhweb/static_src/images/sprites_src/two-tone/info.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/cdhweb/static_src/images/sprites_src/two-tone/warning.svg b/cdhweb/static_src/images/sprites_src/two-tone/warning.svg new file mode 100644 index 00000000..41d25b69 --- /dev/null +++ b/cdhweb/static_src/images/sprites_src/two-tone/warning.svg @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/cdhweb/static_src/styles.scss b/cdhweb/static_src/styles.scss index 433cc64d..4757164d 100644 --- a/cdhweb/static_src/styles.scss +++ b/cdhweb/static_src/styles.scss @@ -50,6 +50,7 @@ // All other components go here: @import './global/components/main-nav-mobile.scss'; @import './global/components/main-nav-desktop.scss'; +@import './global/components/site-alert.scss'; @import './global/components/skip-link.scss'; @import './global/components/home-hero.scss'; @import './global/components/standard-hero.scss'; diff --git a/templates/includes/header.html b/templates/includes/header.html index 668079c2..741ae693 100644 --- a/templates/includes/header.html +++ b/templates/includes/header.html @@ -9,6 +9,10 @@ {% secondary_navigation as secondary_nav %}
+ + {# BED TODO if there are alerts, include this: #} + {% include 'includes/site_alert.html' %} +