feat(LOY-522): Move focus to the newly loaded stay in sidepeek for upcoming and previous stay * feat(LOY-522): Moved focus to the newly loaded stay in sidepeek for upcoming and previous stay Approved-by: Anton Gunnarsson
90 lines
2.4 KiB
TypeScript
90 lines
2.4 KiB
TypeScript
"use client"
|
|
|
|
import { useEffect } from "react"
|
|
import { Dialog, Modal, ModalOverlay } from "react-aria-components"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import usePopStateHandler from "@scandic-hotels/common/hooks/usePopStateHandler"
|
|
|
|
import { IconButton } from "../IconButton"
|
|
import { Typography } from "../Typography"
|
|
|
|
import SidePeekSEO from "./SidePeekSEO"
|
|
|
|
import { KeepBodyVisible } from "./KeepBodyVisible"
|
|
import styles from "./sidePeek.module.css"
|
|
|
|
interface SidePeekSelfControlledProps extends React.PropsWithChildren {
|
|
title: string
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
sidePeekSEO?: boolean
|
|
}
|
|
|
|
export default function SidePeekSelfControlled({
|
|
children,
|
|
isOpen,
|
|
onClose,
|
|
title,
|
|
sidePeekSEO = true,
|
|
}: SidePeekSelfControlledProps) {
|
|
const intl = useIntl()
|
|
|
|
function handleClose(moveBack = false) {
|
|
if (moveBack) {
|
|
window.history.back()
|
|
} else {
|
|
onClose()
|
|
}
|
|
}
|
|
|
|
// Only register popstate handler when open
|
|
usePopStateHandler(() => handleClose(), isOpen)
|
|
|
|
useEffect(() => {
|
|
if (isOpen) {
|
|
window.history.pushState(null, "", window.location.href)
|
|
}
|
|
}, [isOpen])
|
|
|
|
return (
|
|
<>
|
|
<ModalOverlay
|
|
className={styles.overlay}
|
|
isDismissable
|
|
onOpenChange={() => handleClose(true)}
|
|
isOpen={isOpen}
|
|
>
|
|
<Modal className={styles.modal}>
|
|
<Dialog className={styles.dialog} aria-label={title}>
|
|
<aside className={styles.aside}>
|
|
<header className={styles.header}>
|
|
<div className={styles.headerContent}>
|
|
{title ? (
|
|
<Typography variant="Title/md" className={styles.heading}>
|
|
<h2>{title}</h2>
|
|
</Typography>
|
|
) : null}
|
|
<IconButton
|
|
variant="Muted"
|
|
emphasis
|
|
onPress={() => handleClose(true)}
|
|
aria-label={intl.formatMessage({
|
|
id: "common.close",
|
|
defaultMessage: "Close",
|
|
})}
|
|
iconName="close"
|
|
/>
|
|
</div>
|
|
</header>
|
|
<div className={styles.sidePeekContent}>{children}</div>
|
|
<KeepBodyVisible />
|
|
</aside>
|
|
</Dialog>
|
|
</Modal>
|
|
</ModalOverlay>
|
|
{sidePeekSEO && <SidePeekSEO title={title}>{children}</SidePeekSEO>}
|
|
</>
|
|
)
|
|
}
|