refactor: Move Sidepeek param logic to SidePeekProvider
This commit is contained in:
@@ -75,7 +75,7 @@ export default function Link({
|
||||
trackPageViewStart()
|
||||
startTransition(() => {
|
||||
startRouterTransition()
|
||||
router.push(href)
|
||||
router.push(href, { scroll })
|
||||
})
|
||||
}}
|
||||
href={href}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { PropsWithChildren } from "react"
|
||||
|
||||
import { CloseIcon } from "@/components/Icons"
|
||||
import { SidePeekContentProps } from "@/components/TempDesignSystem/SidePeek/types"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
|
||||
import Button from "../../Button"
|
||||
|
||||
import styles from "./sidePeekItem.module.css"
|
||||
|
||||
function SidePeekItem({
|
||||
title,
|
||||
children,
|
||||
isActive = false,
|
||||
onClose,
|
||||
}: PropsWithChildren<SidePeekContentProps>) {
|
||||
return isActive ? (
|
||||
<aside className={styles.sidePeekItem}>
|
||||
<header className={styles.header}>
|
||||
<Title color="burgundy" textTransform="uppercase" level="h2" as="h3">
|
||||
{title}
|
||||
</Title>
|
||||
<Button
|
||||
intent="text"
|
||||
onClick={() => {
|
||||
onClose && onClose()
|
||||
}}
|
||||
>
|
||||
<CloseIcon color="burgundy" height={32} width={32} />
|
||||
</Button>
|
||||
</header>
|
||||
{children}
|
||||
</aside>
|
||||
) : null
|
||||
}
|
||||
|
||||
export default SidePeekItem
|
||||
@@ -1,27 +0,0 @@
|
||||
.sidePeekItem {
|
||||
display: grid;
|
||||
grid-template-rows: min-content auto;
|
||||
gap: var(--Spacing-x4);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content>* {
|
||||
padding: var(--Spacing-x3) var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-bottom: 1px solid var(--Base-Border-Subtle);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.header:has(> h2) {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1367px) {
|
||||
.content>* {
|
||||
padding: var(--Spacing-x4);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
"use client"
|
||||
|
||||
import { useIsSSR } from "@react-aria/ssr"
|
||||
import React, { Children, cloneElement } from "react"
|
||||
import { useContext } from "react"
|
||||
import {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
} from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { SidePeekContentKey } from "@/components/TempDesignSystem/SidePeek/types"
|
||||
import { CloseIcon } from "@/components/Icons"
|
||||
import { SidePeekContext } from "@/components/SidePeekProvider"
|
||||
|
||||
import Button from "../Button"
|
||||
import Title from "../Text/Title"
|
||||
|
||||
import styles from "./sidePeek.module.css"
|
||||
|
||||
@@ -17,33 +22,61 @@ import type { SidePeekProps } from "./sidePeek"
|
||||
|
||||
function SidePeek({
|
||||
children,
|
||||
title,
|
||||
contentKey,
|
||||
handleClose,
|
||||
activeSidePeek,
|
||||
isOpen,
|
||||
}: React.PropsWithChildren<SidePeekProps>) {
|
||||
const sidePeekChildren = Children.map(children, (child) => {
|
||||
if (!React.isValidElement(child)) {
|
||||
return child
|
||||
}
|
||||
return cloneElement(child as React.ReactElement, {
|
||||
isActive:
|
||||
(child.props.contentKey as SidePeekContentKey) === activeSidePeek,
|
||||
onClose: handleClose,
|
||||
})
|
||||
})
|
||||
|
||||
const isSSR = useIsSSR()
|
||||
return isSSR ? (
|
||||
<div>{children}</div>
|
||||
) : (
|
||||
const intl = useIntl()
|
||||
const context = useContext(SidePeekContext)
|
||||
function onClose() {
|
||||
const closeHandler = handleClose || context?.handleClose
|
||||
closeHandler && closeHandler(false)
|
||||
}
|
||||
|
||||
if (isSSR) {
|
||||
return (
|
||||
<div>
|
||||
<h2>{title}</h2>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<DialogTrigger>
|
||||
<ModalOverlay
|
||||
className={styles.overlay}
|
||||
isOpen={!!activeSidePeek}
|
||||
onOpenChange={handleClose}
|
||||
isOpen={isOpen || contentKey === context?.activeSidePeek}
|
||||
onOpenChange={onClose}
|
||||
isDismissable
|
||||
>
|
||||
<Modal className={styles.sidePeek}>
|
||||
<Dialog className={styles.dialog}>{sidePeekChildren}</Dialog>
|
||||
<Modal className={styles.modal}>
|
||||
<Dialog className={styles.dialog}>
|
||||
<aside className={styles.sidePeek}>
|
||||
<header className={styles.header}>
|
||||
{title ? (
|
||||
<Title
|
||||
color="burgundy"
|
||||
textTransform="uppercase"
|
||||
level="h2"
|
||||
as="h3"
|
||||
>
|
||||
{title}
|
||||
</Title>
|
||||
) : null}
|
||||
<Button
|
||||
aria-label={intl.formatMessage({ id: "Close" })}
|
||||
className={styles.closeButton}
|
||||
intent="text"
|
||||
onPress={onClose}
|
||||
>
|
||||
<CloseIcon color="burgundy" height={32} width={32} />
|
||||
</Button>
|
||||
</header>
|
||||
<div className={styles.sidePeekContent}>{children}</div>
|
||||
</aside>
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</ModalOverlay>
|
||||
</DialogTrigger>
|
||||
|
||||
@@ -1,38 +1,9 @@
|
||||
.sidePeek {
|
||||
position: fixed;
|
||||
top: var(--current-mobile-site-header-height);
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: calc(100vh - var(--current-mobile-site-header-height));
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
z-index: 100;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
.sidePeek[data-entering] {
|
||||
animation: slide-up 300ms;
|
||||
}
|
||||
|
||||
.sidePeek[data-exiting] {
|
||||
animation: slide-up 300ms reverse;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: var(--current-mobile-site-header-height);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
.modal {
|
||||
--sidepeek-desktop-width: 600px;
|
||||
}
|
||||
@keyframes slide-in {
|
||||
from {
|
||||
right: -600px;
|
||||
right: calc(-1 * var(--sidepeek-desktop-width));
|
||||
}
|
||||
|
||||
to {
|
||||
@@ -46,24 +17,84 @@
|
||||
}
|
||||
|
||||
to {
|
||||
top: var(--current-mobile-site-header-height);
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-color: var(--Base-Background-Primary-Normal);
|
||||
z-index: 100;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.85);
|
||||
}
|
||||
|
||||
.modal[data-entering] {
|
||||
animation: slide-up 300ms;
|
||||
}
|
||||
|
||||
.modal[data-exiting] {
|
||||
animation: slide-up 300ms reverse;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sidePeek {
|
||||
display: grid;
|
||||
grid-template-rows: min-content auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
border-bottom: 1px solid var(--Base-Border-Subtle);
|
||||
align-items: center;
|
||||
padding: var(--Spacing-x4);
|
||||
}
|
||||
|
||||
.header:has(> h2) {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.closeButton {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sidePeekContent {
|
||||
padding: var(--Spacing-x4);
|
||||
}
|
||||
@media screen and (min-width: 1367px) {
|
||||
.sidePeek {
|
||||
.modal {
|
||||
top: 0;
|
||||
right: 0px;
|
||||
width: 600px;
|
||||
width: var(--sidepeek-desktop-width);
|
||||
height: 100vh;
|
||||
}
|
||||
.sidePeek[data-entering] {
|
||||
|
||||
.modal[data-entering] {
|
||||
animation: slide-in 250ms;
|
||||
}
|
||||
|
||||
.sidePeek[data-exiting] {
|
||||
.modal[data-exiting] {
|
||||
animation: slide-in 250ms reverse;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export interface SidePeekProps {
|
||||
handleClose: (isOpen: boolean) => void
|
||||
activeSidePeek: string | null
|
||||
contentKey: string
|
||||
title: string
|
||||
isOpen?: boolean
|
||||
handleClose?: (isOpen: boolean) => void
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
export type SidePeekContentKey = string
|
||||
|
||||
export type SidePeekProps = {
|
||||
activeContent: string | null
|
||||
onClose: (isOpen: boolean) => void
|
||||
@@ -7,7 +5,7 @@ export type SidePeekProps = {
|
||||
|
||||
export type SidePeekContentProps = {
|
||||
title?: string
|
||||
contentKey: SidePeekContentKey
|
||||
contentKey: string
|
||||
isActive?: boolean
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user