Merged in feat/SW-104-add-card (pull request #410)
Feat/SW-104 add card * feat: add api endpoints for adding and removing credit card * feat(SW-104): Added Sonner toast lib * feat(SW-104): Add route handlers for add card flow * feat(SW-104): Added link to route handler and trigger toast when query params from callback is set * feat(SW-104): Added translations for add card success toast * feat(SW-104): Refactored to use client request for initiate save card * fix(SW-104): Return proper status codes when initiating save card fails * fix(SW-104): remove delete card endpoint because it was added in SW-245 * fix(SW-104): remove console.log * fix(SW-104): Use api.post for save card request * fix(SW-104): move function declaration above export * fix(SW-104): handle response of save card and use Lang enum * fix(SW-104): added comment for why setTimeout is needed for toast and also removed lang prop * fix(SW-104): added type for AddCreditCardButton props * feat: add toasts * fix(SW-104): start using toasts from ToastHandler and fix problem with duplicate toasts * fix(SW-104): remove unnecessary wrapping div Approved-by: Michael Zetterberg
This commit is contained in:
96
components/TempDesignSystem/Toasts/index.tsx
Normal file
96
components/TempDesignSystem/Toasts/index.tsx
Normal file
@@ -0,0 +1,96 @@
|
||||
import { ExternalToast, toast as sonnerToast, Toaster } from "sonner"
|
||||
|
||||
import {
|
||||
CheckCircleIcon,
|
||||
CloseLarge,
|
||||
CrossCircle,
|
||||
InfoCircleIcon,
|
||||
WarningTriangle,
|
||||
} from "@/components/Icons"
|
||||
|
||||
import Button from "../Button"
|
||||
import Body from "../Text/Body"
|
||||
import { ToastsProps } from "./toasts"
|
||||
import { toastVariants } from "./variants"
|
||||
|
||||
import styles from "./toasts.module.css"
|
||||
|
||||
export function ToastHandler() {
|
||||
return <Toaster />
|
||||
}
|
||||
|
||||
function getIcon(variant: ToastsProps["variant"]) {
|
||||
switch (variant) {
|
||||
case "error":
|
||||
return CrossCircle
|
||||
case "info":
|
||||
return InfoCircleIcon
|
||||
case "success":
|
||||
return CheckCircleIcon
|
||||
case "warning":
|
||||
return WarningTriangle
|
||||
}
|
||||
}
|
||||
|
||||
export function Toast({ message, onClose, variant }: ToastsProps) {
|
||||
const className = toastVariants({ variant })
|
||||
const Icon = getIcon(variant)
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className={styles.iconContainer}>
|
||||
{Icon && <Icon color="white" height={24} width={24} />}
|
||||
</div>
|
||||
<Body className={styles.message}>{message}</Body>
|
||||
<Button onClick={onClose} variant="icon" intent="text">
|
||||
<CloseLarge />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const toast = {
|
||||
success: (message: string, options?: ExternalToast) =>
|
||||
sonnerToast.custom(
|
||||
(t) => (
|
||||
<Toast
|
||||
variant="success"
|
||||
message={message}
|
||||
onClose={() => sonnerToast.dismiss(t)}
|
||||
/>
|
||||
),
|
||||
options
|
||||
),
|
||||
info: (message: string, options?: ExternalToast) =>
|
||||
sonnerToast.custom(
|
||||
(t) => (
|
||||
<Toast
|
||||
variant="info"
|
||||
message={message}
|
||||
onClose={() => sonnerToast.dismiss(t)}
|
||||
/>
|
||||
),
|
||||
options
|
||||
),
|
||||
error: (message: string, options?: ExternalToast) =>
|
||||
sonnerToast.custom(
|
||||
(t) => (
|
||||
<Toast
|
||||
variant="error"
|
||||
message={message}
|
||||
onClose={() => sonnerToast.dismiss(t)}
|
||||
/>
|
||||
),
|
||||
options
|
||||
),
|
||||
warning: (message: string, options?: ExternalToast) =>
|
||||
sonnerToast.custom(
|
||||
(t) => (
|
||||
<Toast
|
||||
variant="warning"
|
||||
message={message}
|
||||
onClose={() => sonnerToast.dismiss(t)}
|
||||
/>
|
||||
),
|
||||
options
|
||||
),
|
||||
}
|
||||
38
components/TempDesignSystem/Toasts/toasts.module.css
Normal file
38
components/TempDesignSystem/Toasts/toasts.module.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.toast {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
border-radius: var(--Corner-radius-Large);
|
||||
overflow: hidden;
|
||||
background: var(--Base-Surface-Primary-light-Normal);
|
||||
box-shadow: 0px 0px 8px 2px rgba(0, 0, 0, 0.08);
|
||||
align-items: center;
|
||||
width: var(--width);
|
||||
}
|
||||
|
||||
.message {
|
||||
padding: var(--Spacing-x2) var(--Spacing-x-one-and-half);
|
||||
}
|
||||
|
||||
.success {
|
||||
--icon-background-color: var(--UI-Semantic-Success);
|
||||
}
|
||||
|
||||
.error {
|
||||
--icon-background-color: var(--UI-Semantic-Error);
|
||||
}
|
||||
|
||||
.warning {
|
||||
--icon-background-color: var(--UI-Semantic-Warning);
|
||||
}
|
||||
|
||||
.info {
|
||||
--icon-background-color: var(--UI-Semantic-Information);
|
||||
}
|
||||
|
||||
.iconContainer {
|
||||
display: flex;
|
||||
background-color: var(--icon-background-color);
|
||||
padding: var(--Spacing-x2);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
10
components/TempDesignSystem/Toasts/toasts.ts
Normal file
10
components/TempDesignSystem/Toasts/toasts.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { toastVariants } from "./variants"
|
||||
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
|
||||
export interface ToastsProps
|
||||
extends Omit<React.AnchorHTMLAttributes<HTMLDivElement>, "color">,
|
||||
VariantProps<typeof toastVariants> {
|
||||
message: string
|
||||
onClose: () => void
|
||||
}
|
||||
14
components/TempDesignSystem/Toasts/variants.ts
Normal file
14
components/TempDesignSystem/Toasts/variants.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import styles from "./toasts.module.css"
|
||||
|
||||
export const toastVariants = cva(styles.toast, {
|
||||
variants: {
|
||||
variant: {
|
||||
success: styles.success,
|
||||
info: styles.info,
|
||||
warning: styles.warning,
|
||||
error: styles.error,
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user