Merged in feat/SW-1676-modify-contact-details-my-stay-anonymous (pull request #1468)
Feat/SW-1676 modify contact details my stay anonymous * feat(SW-1676): Modify guest details step 1 * feat(SW-1676) Integration to api to update guest details * feat(SW-1676) Reuse of old modal * feat(SW-1676) updated modify guest * feat(SW-1676) cleanup * feat(SW-1676) updated myStayReturnRoute to sessionStorage Approved-by: Niclas Edenvin
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { CloseLargeIcon } from "@/components/Icons"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
||||
|
||||
import styles from "./modalContent.module.css"
|
||||
|
||||
import type { ReactNode } from "react"
|
||||
|
||||
interface ModalContentProps {
|
||||
title?: string
|
||||
content: ReactNode
|
||||
primaryAction: {
|
||||
label: string
|
||||
onClick: () => void
|
||||
intent?: "primary" | "secondary" | "text"
|
||||
isLoading?: boolean
|
||||
disabled?: boolean
|
||||
} | null
|
||||
secondaryAction: {
|
||||
label: string
|
||||
onClick: () => void
|
||||
intent?: "primary" | "secondary" | "text"
|
||||
} | null
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
export function ModalContentWithActions({
|
||||
title,
|
||||
content,
|
||||
primaryAction,
|
||||
secondaryAction,
|
||||
onClose,
|
||||
}: ModalContentProps) {
|
||||
return (
|
||||
<>
|
||||
{title && (
|
||||
<header className={styles.header}>
|
||||
<Subtitle>{title}</Subtitle>
|
||||
<button onClick={onClose} type="button" className={styles.close}>
|
||||
<CloseLargeIcon color="uiTextMediumContrast" />
|
||||
</button>
|
||||
</header>
|
||||
)}
|
||||
<div className={styles.content}>{content}</div>
|
||||
<footer className={styles.footer}>
|
||||
{secondaryAction && (
|
||||
<Button
|
||||
theme="base"
|
||||
intent={secondaryAction.intent ?? "text"}
|
||||
color="burgundy"
|
||||
onClick={secondaryAction.onClick}
|
||||
>
|
||||
{secondaryAction.label}
|
||||
</Button>
|
||||
)}
|
||||
{primaryAction && (
|
||||
<Button
|
||||
theme="base"
|
||||
intent={primaryAction.intent ?? "secondary"}
|
||||
onClick={primaryAction.onClick}
|
||||
disabled={primaryAction.isLoading || primaryAction.disabled}
|
||||
>
|
||||
{primaryAction.label}
|
||||
</Button>
|
||||
)}
|
||||
</footer>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Spacing-x3);
|
||||
padding: var(--Spacing-x1) var(--Spacing-x3) var(--Spacing-x4);
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: var(--Spacing-x3) var(--Spacing-x3) var(--Spacing-x1)
|
||||
var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
border-top: 1px solid var(--Base-Border-Subtle);
|
||||
padding: var(--Spacing-x3);
|
||||
}
|
||||
|
||||
.close {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.content {
|
||||
width: 640px;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
type ModalProps,
|
||||
} from "./modal"
|
||||
import { fade, slideInOut } from "./motionVariants"
|
||||
import { modalContentVariants } from "./variants"
|
||||
|
||||
import styles from "./modal.module.css"
|
||||
|
||||
@@ -36,9 +37,15 @@ function InnerModal({
|
||||
children,
|
||||
title,
|
||||
subtitle,
|
||||
withActions,
|
||||
hideHeader,
|
||||
}: PropsWithChildren<InnerModalProps>) {
|
||||
const intl = useIntl()
|
||||
|
||||
const contentClassNames = modalContentVariants({
|
||||
withActions: withActions,
|
||||
})
|
||||
|
||||
function modalStateHandler(newAnimationState: AnimationState) {
|
||||
setAnimation((currentAnimationState) =>
|
||||
newAnimationState === AnimationStateEnum.hidden &&
|
||||
@@ -79,27 +86,34 @@ function InnerModal({
|
||||
>
|
||||
{({ close }) => (
|
||||
<>
|
||||
<header
|
||||
className={`${styles.header} ${!subtitle ? styles.verticalCenter : ""}`}
|
||||
>
|
||||
<div>
|
||||
{title && (
|
||||
<Subtitle type="one" color="uiTextHighContrast">
|
||||
{title}
|
||||
</Subtitle>
|
||||
)}
|
||||
{subtitle && (
|
||||
<Preamble asChild>
|
||||
<span>{subtitle}</span>
|
||||
</Preamble>
|
||||
)}
|
||||
</div>
|
||||
{!hideHeader && (
|
||||
<header
|
||||
className={`${styles.header} ${!subtitle ? styles.verticalCenter : ""}`}
|
||||
>
|
||||
<div>
|
||||
{title && (
|
||||
<Subtitle type="one" color="uiTextHighContrast">
|
||||
{title}
|
||||
</Subtitle>
|
||||
)}
|
||||
{subtitle && (
|
||||
<Preamble asChild>
|
||||
<span>{subtitle}</span>
|
||||
</Preamble>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<button onClick={close} type="button" className={styles.close}>
|
||||
<CloseLargeIcon color="uiTextMediumContrast" />
|
||||
</button>
|
||||
</header>
|
||||
<section className={styles.content}>{children}</section>
|
||||
<button
|
||||
onClick={close}
|
||||
type="button"
|
||||
className={styles.close}
|
||||
>
|
||||
<CloseLargeIcon color="uiTextMediumContrast" />
|
||||
</button>
|
||||
</header>
|
||||
)}
|
||||
|
||||
<section className={contentClassNames}>{children}</section>
|
||||
</>
|
||||
)}
|
||||
</Dialog>
|
||||
@@ -116,6 +130,8 @@ export default function Modal({
|
||||
title,
|
||||
subtitle,
|
||||
children,
|
||||
withActions = false,
|
||||
hideHeader = false,
|
||||
}: PropsWithChildren<ModalProps>) {
|
||||
const [animation, setAnimation] = useState<AnimationState>(
|
||||
AnimationStateEnum.visible
|
||||
@@ -142,6 +158,8 @@ export default function Modal({
|
||||
isOpen={isOpen}
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
withActions={withActions}
|
||||
hideHeader={hideHeader}
|
||||
>
|
||||
{children}
|
||||
</InnerModal>
|
||||
@@ -163,6 +181,7 @@ export default function Modal({
|
||||
setAnimation={setAnimation}
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
withActions={withActions}
|
||||
>
|
||||
{children}
|
||||
</InnerModal>
|
||||
|
||||
@@ -49,10 +49,17 @@
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--Spacing-x2);
|
||||
padding: 0 var(--Spacing-x3) var(--Spacing-x4);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.contentWithActions {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.contentWithoutActions {
|
||||
padding: 0 var(--Spacing-x3) var(--Spacing-x4);
|
||||
}
|
||||
|
||||
.close {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
@@ -12,6 +12,8 @@ export type ModalProps = {
|
||||
onAnimationComplete?: VoidFunction
|
||||
title?: string
|
||||
subtitle?: string
|
||||
withActions?: boolean
|
||||
hideHeader?: boolean
|
||||
} & (
|
||||
| { trigger: JSX.Element; isOpen?: never; onToggle?: never }
|
||||
| {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import styles from "./modal.module.css"
|
||||
|
||||
const config = {
|
||||
variants: {
|
||||
withActions: {
|
||||
true: styles.contentWithActions,
|
||||
false: styles.contentWithoutActions,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
withActions: false,
|
||||
},
|
||||
} as const
|
||||
|
||||
export const modalContentVariants = cva(styles.content, config)
|
||||
Reference in New Issue
Block a user