feat(SW-650): added sitewide alert to use sticky position hook

This commit is contained in:
Erik Tiekstra
2024-10-24 10:23:19 +02:00
parent 63dbbac014
commit fbdfeafcb5
7 changed files with 87 additions and 23 deletions

View File

@@ -8,7 +8,7 @@ import useStickyPosition from "@/hooks/useStickyPosition"
import styles from "./mapWithCard.module.css"
export default function MapWithCardWrapper({ children }: PropsWithChildren) {
export default function MapWithCard({ children }: PropsWithChildren) {
const mapWithCardRef = useRef<HTMLDivElement>(null)
useStickyPosition({
ref: mapWithCardRef,

View File

@@ -0,0 +1,41 @@
"use client"
import { useRef } from "react"
import { StickyElementNameEnum } from "@/stores/sticky-position"
import Alert from "@/components/TempDesignSystem/Alert"
import useStickyPosition from "@/hooks/useStickyPosition"
import { SitewideAlertProps } from "./sitewideAlert"
import styles from "./sitewideAlert.module.css"
import { AlertTypeEnum } from "@/types/enums/alert"
export default function SiteWideAlertClient({ alert }: SitewideAlertProps) {
const alertRef = useRef(null)
useStickyPosition({
ref: alertRef,
name: StickyElementNameEnum.SITEWIDE_ALERT,
})
const isAlarm = alert.type === AlertTypeEnum.Alarm
return (
<div
ref={isAlarm ? alertRef : null}
className={`${styles.sitewideAlert} ${isAlarm ? styles.alarm : ""}`}
>
<Alert
variant="banner"
type={alert.type}
link={alert.link}
phoneContact={alert.phoneContact}
sidepeekCtaText={alert.sidepeekButton?.cta_text}
sidepeekContent={alert.sidepeekContent}
heading={alert.heading}
text={alert.text}
/>
</div>
)
}

View File

@@ -1,8 +1,6 @@
import { getSiteConfig } from "@/lib/trpc/memoizedRequests"
import Alert from "../TempDesignSystem/Alert"
import styles from "./sitewideAlert.module.css"
import SiteWideAlertClient from "./Client"
export function preload() {
void getSiteConfig()
@@ -15,19 +13,5 @@ export default async function SitewideAlert() {
return null
}
const { sitewideAlert } = siteConfig
return (
<div className={`${styles.sitewideAlert} ${styles[sitewideAlert.type]}`}>
<Alert
variant="banner"
type={sitewideAlert.type}
link={sitewideAlert.link}
phoneContact={sitewideAlert.phoneContact}
sidepeekCtaText={sitewideAlert.sidepeekButton?.cta_text}
sidepeekContent={sitewideAlert.sidepeekContent}
heading={sitewideAlert.heading}
text={sitewideAlert.text}
/>
</div>
)
return <SiteWideAlertClient alert={siteConfig.sitewideAlert} />
}

View File

@@ -0,0 +1,5 @@
import type { Alert } from "@/types/trpc/routers/contentstack/siteConfig"
export interface SitewideAlertProps {
alert: Alert
}

View File

@@ -6,12 +6,17 @@ import useStickyPositionStore, {
StickyElementNameEnum,
} from "@/stores/sticky-position"
import { debounce } from "@/utils/debounce"
interface UseStickyPositionProps {
ref?: React.RefObject<HTMLElement>
name?: StickyElementNameEnum
group?: string
}
// Global singleton ResizeObserver to observe the body only once
let resizeObserver: ResizeObserver | null = null
/**
* Custom hook to manage sticky positioning of elements within a page.
* This hook registers an element as sticky, calculates its top offset based on
@@ -83,6 +88,25 @@ export default function useStickyPosition({
}
}, [stickyElements, ref])
useEffect(() => {
if (!resizeObserver) {
const debouncedResizeHandler = debounce(() => {
updateHeights()
}, 100)
resizeObserver = new ResizeObserver(debouncedResizeHandler)
console.log("Initialized ResizeObserver")
}
resizeObserver.observe(document.body)
return () => {
if (resizeObserver) {
resizeObserver.unobserve(document.body)
}
}
}, [updateHeights])
return {
currentHeight: ref?.current?.offsetHeight || null,
allElements: getAllElements(),

View File

@@ -5,7 +5,7 @@ import type { System } from "@/types/requests/system"
import type { Edges } from "@/types/requests/utils/edges"
import type { NodeRefs } from "@/types/requests/utils/refs"
import type { HeaderRefs } from "@/types/trpc/routers/contentstack/header"
import type { Alert } from "@/types/trpc/routers/contentstack/siteConfig"
import type { AlertOutput } from "@/types/trpc/routers/contentstack/siteConfig"
import type { ContactConfig } from "./output"
export function getConnections({ header }: HeaderRefs) {
@@ -71,7 +71,7 @@ export function getFooterConnections(refs: FooterRefDataRaw) {
}
export function getAlertPhoneContactData(
alert: Alert,
alert: AlertOutput,
contactConfig: ContactConfig
) {
if (alert.phoneContact) {

View File

@@ -11,5 +11,15 @@ export type GetSiteConfigRefData = z.infer<typeof siteConfigRefSchema>
export type GetSiteConfigData = z.input<typeof siteConfigSchema>
export type SiteConfig = z.output<typeof siteConfigSchema>
export type Alert = z.output<typeof alertSchema>
export type SidepeekContent = Alert["sidepeekContent"]
export type AlertOutput = z.output<typeof alertSchema>
export type SidepeekContent = AlertOutput["sidepeekContent"]
export type AlertPhoneContact = {
displayText: string
phoneNumber?: string
footnote?: string | null
}
export type Alert = Omit<AlertOutput, "phoneContact"> & {
phoneContact: AlertPhoneContact | null
}