index.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. "use client";
  2. import { XCircle } from "@phosphor-icons/react/dist/ssr/XCircle";
  3. import clsx from "clsx";
  4. import type { ComponentProps, ReactNode } from "react";
  5. import { Heading } from "react-aria-components";
  6. import styles from "./index.module.scss";
  7. import { Button } from "../Button/index.js";
  8. import { ModalDialog } from "../ModalDialog/index.js";
  9. export { ModalDialogTrigger as AlertTrigger } from "../ModalDialog/index.js";
  10. const CLOSE_DURATION_IN_S = 0.1;
  11. export const CLOSE_DURATION_IN_MS = CLOSE_DURATION_IN_S * 1000;
  12. type OwnProps = Pick<ComponentProps<typeof ModalDialog>, "children"> & {
  13. icon?: ReactNode | undefined;
  14. title: ReactNode;
  15. };
  16. type Props = Omit<
  17. ComponentProps<typeof ModalDialog>,
  18. keyof OwnProps | "overlayClassName"
  19. > &
  20. OwnProps;
  21. export const Alert = ({
  22. icon,
  23. title,
  24. children,
  25. className,
  26. ...props
  27. }: Props) => (
  28. <ModalDialog
  29. overlayClassName={styles.modalOverlay ?? ""}
  30. variants={{
  31. visible: {
  32. y: 0,
  33. transition: { type: "spring", duration: 0.75, bounce: 0.5 },
  34. },
  35. hidden: {
  36. y: "calc(100% + 2rem)",
  37. transition: { ease: "linear", duration: CLOSE_DURATION_IN_S },
  38. },
  39. unmounted: { y: "calc(100% + 2rem)" },
  40. }}
  41. className={clsx(styles.alert, className)}
  42. {...props}
  43. >
  44. {(...args) => (
  45. <>
  46. <Button
  47. className={styles.closeButton ?? ""}
  48. beforeIcon={(props) => <XCircle weight="fill" {...props} />}
  49. slot="close"
  50. hideText
  51. rounded
  52. variant="ghost"
  53. size="sm"
  54. >
  55. Close
  56. </Button>
  57. <Heading className={styles.title} slot="title">
  58. {icon && <div className={styles.icon}>{icon}</div>}
  59. <div>{title}</div>
  60. </Heading>
  61. <div className={styles.body}>
  62. {typeof children === "function" ? children(...args) : children}
  63. </div>
  64. </>
  65. )}
  66. </ModalDialog>
  67. );