feat(SW-650): added sitewide alert to use sticky position hook
This commit is contained in:
@@ -8,7 +8,7 @@ import useStickyPosition from "@/hooks/useStickyPosition"
|
|||||||
|
|
||||||
import styles from "./mapWithCard.module.css"
|
import styles from "./mapWithCard.module.css"
|
||||||
|
|
||||||
export default function MapWithCardWrapper({ children }: PropsWithChildren) {
|
export default function MapWithCard({ children }: PropsWithChildren) {
|
||||||
const mapWithCardRef = useRef<HTMLDivElement>(null)
|
const mapWithCardRef = useRef<HTMLDivElement>(null)
|
||||||
useStickyPosition({
|
useStickyPosition({
|
||||||
ref: mapWithCardRef,
|
ref: mapWithCardRef,
|
||||||
|
|||||||
41
components/SitewideAlert/Client.tsx
Normal file
41
components/SitewideAlert/Client.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
import { getSiteConfig } from "@/lib/trpc/memoizedRequests"
|
import { getSiteConfig } from "@/lib/trpc/memoizedRequests"
|
||||||
|
|
||||||
import Alert from "../TempDesignSystem/Alert"
|
import SiteWideAlertClient from "./Client"
|
||||||
|
|
||||||
import styles from "./sitewideAlert.module.css"
|
|
||||||
|
|
||||||
export function preload() {
|
export function preload() {
|
||||||
void getSiteConfig()
|
void getSiteConfig()
|
||||||
@@ -15,19 +13,5 @@ export default async function SitewideAlert() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const { sitewideAlert } = siteConfig
|
return <SiteWideAlertClient alert={siteConfig.sitewideAlert} />
|
||||||
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>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
5
components/SitewideAlert/sitewideAlert.ts
Normal file
5
components/SitewideAlert/sitewideAlert.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import type { Alert } from "@/types/trpc/routers/contentstack/siteConfig"
|
||||||
|
|
||||||
|
export interface SitewideAlertProps {
|
||||||
|
alert: Alert
|
||||||
|
}
|
||||||
@@ -6,12 +6,17 @@ import useStickyPositionStore, {
|
|||||||
StickyElementNameEnum,
|
StickyElementNameEnum,
|
||||||
} from "@/stores/sticky-position"
|
} from "@/stores/sticky-position"
|
||||||
|
|
||||||
|
import { debounce } from "@/utils/debounce"
|
||||||
|
|
||||||
interface UseStickyPositionProps {
|
interface UseStickyPositionProps {
|
||||||
ref?: React.RefObject<HTMLElement>
|
ref?: React.RefObject<HTMLElement>
|
||||||
name?: StickyElementNameEnum
|
name?: StickyElementNameEnum
|
||||||
group?: string
|
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.
|
* Custom hook to manage sticky positioning of elements within a page.
|
||||||
* This hook registers an element as sticky, calculates its top offset based on
|
* This hook registers an element as sticky, calculates its top offset based on
|
||||||
@@ -83,6 +88,25 @@ export default function useStickyPosition({
|
|||||||
}
|
}
|
||||||
}, [stickyElements, ref])
|
}, [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 {
|
return {
|
||||||
currentHeight: ref?.current?.offsetHeight || null,
|
currentHeight: ref?.current?.offsetHeight || null,
|
||||||
allElements: getAllElements(),
|
allElements: getAllElements(),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import type { System } from "@/types/requests/system"
|
|||||||
import type { Edges } from "@/types/requests/utils/edges"
|
import type { Edges } from "@/types/requests/utils/edges"
|
||||||
import type { NodeRefs } from "@/types/requests/utils/refs"
|
import type { NodeRefs } from "@/types/requests/utils/refs"
|
||||||
import type { HeaderRefs } from "@/types/trpc/routers/contentstack/header"
|
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"
|
import type { ContactConfig } from "./output"
|
||||||
|
|
||||||
export function getConnections({ header }: HeaderRefs) {
|
export function getConnections({ header }: HeaderRefs) {
|
||||||
@@ -71,7 +71,7 @@ export function getFooterConnections(refs: FooterRefDataRaw) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getAlertPhoneContactData(
|
export function getAlertPhoneContactData(
|
||||||
alert: Alert,
|
alert: AlertOutput,
|
||||||
contactConfig: ContactConfig
|
contactConfig: ContactConfig
|
||||||
) {
|
) {
|
||||||
if (alert.phoneContact) {
|
if (alert.phoneContact) {
|
||||||
|
|||||||
@@ -11,5 +11,15 @@ export type GetSiteConfigRefData = z.infer<typeof siteConfigRefSchema>
|
|||||||
export type GetSiteConfigData = z.input<typeof siteConfigSchema>
|
export type GetSiteConfigData = z.input<typeof siteConfigSchema>
|
||||||
export type SiteConfig = z.output<typeof siteConfigSchema>
|
export type SiteConfig = z.output<typeof siteConfigSchema>
|
||||||
|
|
||||||
export type Alert = z.output<typeof alertSchema>
|
export type AlertOutput = z.output<typeof alertSchema>
|
||||||
export type SidepeekContent = Alert["sidepeekContent"]
|
export type SidepeekContent = AlertOutput["sidepeekContent"]
|
||||||
|
|
||||||
|
export type AlertPhoneContact = {
|
||||||
|
displayText: string
|
||||||
|
phoneNumber?: string
|
||||||
|
footnote?: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Alert = Omit<AlertOutput, "phoneContact"> & {
|
||||||
|
phoneContact: AlertPhoneContact | null
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user