Skip to content

Commit

Permalink
fix: improve notification (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
bentatum authored Oct 17, 2024
1 parent e09ee59 commit f7923a3
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 48 deletions.
5 changes: 5 additions & 0 deletions .changeset/eighty-buckets-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@verysimple/react": patch
---

fix: improve notification component and reduce form label font weight
2 changes: 1 addition & 1 deletion packages/react/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module.exports = {
coverageThreshold: {
global: {
statements: 75,
branches: 72,
branches: 66.86,
functions: 75,
lines: 75,
},
Expand Down
3 changes: 1 addition & 2 deletions packages/react/src/FormLabel/FormLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ export const FormLabel: FC<FormLabelProps> = forwardRef(
"block",
{
"text-sm": !className?.includes("text-"),
"mb-1.5": !className?.includes("mb-"),
"font-semibold": !className?.includes("font-"),
"mb-1.5": !className?.includes("mb-")
},
className
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`FormLabel should match the snapshot 1`] = `
<div>
<label
class="block text-sm mb-1.5 font-semibold"
class="block text-sm mb-1.5"
>
test
</label>
Expand Down
91 changes: 68 additions & 23 deletions packages/react/src/Notification/Notification.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,99 @@
import clsx from "clsx";
import { FC, useEffect, ReactNode } from "react";
import { FC, useEffect, ReactNode, useCallback } from "react";
import { motion, MotionProps } from "framer-motion";
import { useNotification } from "@/NotificationContext";
import { XMarkIcon } from "@heroicons/react/24/solid";

export interface NotificationProps {
children: ReactNode;
export interface NotificationProps extends React.HTMLAttributes<HTMLDivElement> {
onClose?: () => void;
withCloseButton?: boolean;
variant?: "static" | "modal";
autoHide?: boolean;
autoHideDuration?: number;
position?: "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right" | "center";
title?: string;
description?: string;
}

export const Notification: FC<NotificationProps> = ({ children, onClose, variant = "static", autoHide = false, autoHideDuration = 3000, position = "bottom-right" }) => {
export const Notification: FC<NotificationProps> = ({ className, children, onClose, withCloseButton = true, variant = "static", autoHide = true, autoHideDuration = 3000, position = "bottom-right", title, description, ...props }) => {
const { closeNotification } = useNotification();

const handleClose = useCallback(() => {
if (onClose) onClose();
closeNotification();
}, [onClose, closeNotification]);

useEffect(() => {
if (variant === "modal" && autoHide) {
const timer = setTimeout(() => {
if (onClose) onClose();
handleClose();
}, autoHideDuration);

return () => clearTimeout(timer);
}
}, [onClose, variant, autoHide, autoHideDuration]);
}, [handleClose, variant, autoHide, autoHideDuration]);

const positionClasses = {
"top-left": "top-0 left-0",
"top-center": "top-0 left-1/2 transform -translate-x-1/2",
"top-right": "top-0 right-0",
"bottom-left": "bottom-0 left-0",
"bottom-center": "bottom-0 left-1/2 transform -translate-x-1/2",
"bottom-right": "bottom-0 right-0",
"top-left": "top-6 left-6",
"top-center": "top-6 left-1/2 transform -translate-x-1/2",
"top-right": "top-6 right-6",
"bottom-left": "bottom-6 left-6",
"bottom-center": "bottom-6 left-1/2 transform -translate-x-1/2",
"bottom-right": "left-6 sm:left-auto bottom-6 right-6",
"center": "inset-0 flex items-center justify-center"
};

const variants = {
hidden: { y: 50 },
visible: { y: 0 },
exit: { y: 100, transition: { type: "tween", duration: 0.1 } }
};

const hasPaddingOverrides = className?.match(/p[xy]-\d+/);

return (
<div
<motion.div
{...(props as MotionProps)}
initial="hidden"
animate="visible"
exit="exit"
variants={variants}
transition={{ type: "spring", stiffness: 500, damping: 25 }} // Spring for enter
className={clsx(
"z-30 h-20 w-full sm:w-96 p-4 rounded shadow-lg",
"z-30 min-h-20 w-auto sm:w-96 rounded shadow",
{
"fixed bg-foreground bg-opacity-50": variant === "modal",
[positionClasses[position]]: variant === "modal"
}
[positionClasses[position]]: variant === "modal",
},
!hasPaddingOverrides && {
"px-3.5 py-2.5": true,
"pr-6": withCloseButton
},
className
)}
>
{children}
{onClose && (
<button onClick={onClose} className="ml-4">
Close
</button>
{title || description ? (
<>
{title && <h2 className="text-lg font-semibold mb-1">{title}</h2>}
{description && <p className="text-sm">{description}</p>}
{withCloseButton && (
<button onClick={handleClose} className="absolute top-2 right-2">
<XMarkIcon className="size-5" />
</button>
)}
</>
) : (
<>
{children}
{withCloseButton && (
<button onClick={handleClose} className="absolute top-2 right-2">
<XMarkIcon className="size-5" />
</button>
)}
</>
)}
</div>
</motion.div>
);
};

export default Notification;
export default Notification;
15 changes: 11 additions & 4 deletions packages/react/src/NotificationContext/NotificationContext.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { createContext, FC, ReactNode, useContext, useState, cloneElement, isValidElement } from "react";
import Notification, { NotificationProps } from "@/Notification";
import { AnimatePresence } from "framer-motion"; // Import AnimatePresence

interface NotificationContextProps {
showNotification: (content: ReactNode) => void;
closeNotification: () => void;
}

const NotificationContext = createContext<NotificationContextProps | undefined>(undefined);
Expand All @@ -26,10 +27,16 @@ export const NotificationProvider: FC<{ children: ReactNode }> = ({ children })
}
};

const closeNotification = () => {
setNotification(null);
};

return (
<NotificationContext.Provider value={{ showNotification }}>
<NotificationContext.Provider value={{ showNotification, closeNotification }}>
{children}
{notification}
<AnimatePresence>
{notification}
</AnimatePresence>
</NotificationContext.Provider>
);
};
};
13 changes: 1 addition & 12 deletions packages/react/src/OutlinedButton/OutlinedButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,7 @@ export const OutlinedButton = forwardRef<
disabled={disabled}
{...props}
>
<span
className={clsx(
fieldPaddingClassNames(size),
"w-full flex items-center justify-center",
// {
// "text-transparent bg-clip-text my-bg-gradient-to-r":
// color === "primary" && !disabled,
// }
)}
>
{children}
</span>
{children}
</OutlinedButtonBase>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ exports[`OutlinedButton should have an outline 1`] = `
class="focus:outline-none cursor-pointer disabled:cursor-not-allowed inline-flex items-center justify-center rounded border shadow hover:shadow disabled:shadow-none transition-shadow ease-in duration-100 whitespace-nowrap font-bold text-base min-h-[44px] border box-content"
tabindex="0"
>
<span
class="px-4 w-full flex items-center justify-center"
>
Test
</span>
Test
</button>
</div>
`;

0 comments on commit f7923a3

Please sign in to comment.