Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(toast): fixing maxVisibleToasts, solid variant promise, promise timer #4881

Merged
merged 4 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/slow-dogs-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@heroui/toast": patch
---

fixing maxVisibleToast functionality in toast (#4870)
For promises, starting the timer only after the promise is resolved
7 changes: 6 additions & 1 deletion packages/components/toast/src/toast-region.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ export function ToastRegion<T extends ToastProps>({
return null;
}

if (total - index <= 4 || (isHovered && total - index <= maxVisibleToasts + 1)) {
if (
disableAnimation ||
total - index <= 4 ||
(isHovered && total - index <= maxVisibleToasts + 1)
) {
return (
<Toast
key={toast.key}
Expand All @@ -85,6 +89,7 @@ export function ToastRegion<T extends ToastProps>({
heights={heights}
index={index}
isRegionExpanded={isHovered || isTouched}
maxVisibleToasts={maxVisibleToasts}
placement={placement}
setHeights={setHeights}
toastOffset={toastOffset}
Expand Down
2 changes: 1 addition & 1 deletion packages/components/toast/src/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
<Spinner
aria-label="loadingIcon"
classNames={{wrapper: getLoadingIconProps().className}}
color={color ?? "default"}
color={"current"}
/>
)
: null;
Expand Down
39 changes: 27 additions & 12 deletions packages/components/toast/src/use-toast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ interface Props<T> extends Omit<HTMLHeroUIProps<"div">, "title">, ToastProps {
isRegionExpanded: boolean;
placement?: ToastPlacement;
toastOffset?: number;
maxVisibleToasts: number;
}

export type UseToastProps<T = ToastProps> = Props<T> &
Expand Down Expand Up @@ -158,6 +159,7 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
icon,
onClose,
severity,
maxVisibleToasts,
...otherProps
} = props;

Expand Down Expand Up @@ -193,9 +195,18 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
}
}, []);

const [isLoading, setIsLoading] = useState<boolean>(!!promiseProp);

useEffect(() => {
if (!promiseProp) return;
promiseProp.finally(() => {
setIsLoading(false);
});
}, [promiseProp]);

useEffect(() => {
const updateProgress = (timestamp: number) => {
if (!timeout) {
if (!timeout || isLoading) {
return;
}

Expand Down Expand Up @@ -238,16 +249,16 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
cancelAnimationFrame(animationRef.current);
}
};
}, [timeout, shouldShowTimeoutProgess, state, isToastHovered, index, total, isRegionExpanded]);

const [isLoading, setIsLoading] = useState<boolean>(!!promiseProp);

useEffect(() => {
if (!promiseProp) return;
promiseProp.finally(() => {
setIsLoading(false);
});
}, [promiseProp]);
}, [
timeout,
shouldShowTimeoutProgess,
state,
isToastHovered,
index,
total,
isRegionExpanded,
isLoading,
]);

const Component = as || "div";
const loadingIcon: ReactNode = icon;
Expand Down Expand Up @@ -486,7 +497,10 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
"data-drag-value": number;
className: string;
} => {
const isCloseToEnd = total - index - 1 <= 2;
const comparingValue = isRegionExpanded
? maxVisibleToasts - 1
: Math.min(2, maxVisibleToasts - 1);
const isCloseToEnd = total - index - 1 <= comparingValue;
const dragDirection = placement === "bottom-center" || placement === "top-center" ? "y" : "x";
const dragConstraints = {left: 0, right: 0, top: 0, bottom: 0};
const dragElastic = getDragElasticConstraints(placement);
Expand Down Expand Up @@ -593,6 +607,7 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
shouldCloseToast,
slots,
toastOffset,
maxVisibleToasts,
],
);

Expand Down
26 changes: 18 additions & 8 deletions packages/components/toast/stories/toast.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export default {
"top-center",
],
},
maxVisibleToasts: {
control: {type: "number"},
},
hideCloseButton: {
control: {
type: "boolean",
Expand Down Expand Up @@ -80,7 +83,7 @@ const defaultProps = {
const Template = (args: ToastProps) => {
return (
<>
<ToastProvider placement={args.placement} />
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
<div>
<Button
onPress={() => {
Expand All @@ -100,7 +103,7 @@ const Template = (args: ToastProps) => {
const ShowTimeoutProgressTemplate = (args: ToastProps) => {
return (
<>
<ToastProvider placement={args.placement} />
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
<Button
onPress={() => {
addToast({
Expand All @@ -121,7 +124,7 @@ const ShowTimeoutProgressTemplate = (args: ToastProps) => {
const WithEndContentTemplate = (args) => {
return (
<>
<ToastProvider placement={args.placement} />
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
<Button
onPress={() => {
addToast({
Expand All @@ -147,7 +150,7 @@ const WithEndContentTemplate = (args) => {
const PlacementTemplate = (args: ToastProps) => {
return (
<>
<ToastProvider placement={args.placement} />
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
<div>
<Button
onPress={() => {
Expand All @@ -168,7 +171,11 @@ const PlacementTemplate = (args: ToastProps) => {
const DisableAnimationTemplate = (args: ToastProps) => {
return (
<>
<ToastProvider disableAnimation={true} placement={args.placement} />
<ToastProvider
disableAnimation={true}
maxVisibleToasts={args.maxVisibleToasts}
placement={args.placement}
/>
<div>
<Button
onPress={() => {
Expand All @@ -189,14 +196,16 @@ const DisableAnimationTemplate = (args: ToastProps) => {
const PromiseToastTemplate = (args: ToastProps) => {
return (
<>
<ToastProvider placement={args.placement} />
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
<div>
<Button
onPress={() => {
addToast({
title: "Toast Title",
description: "Toast Displayed Successfully",
promise: new Promise((resolve) => setTimeout(resolve, 5000)),
promise: new Promise((resolve) => setTimeout(resolve, 3000)),
timeout: 3000,
shouldShowTimeoutProgess: false,
...args,
});
}}
Expand Down Expand Up @@ -265,7 +274,7 @@ const CustomToastTemplate = (args) => {

return (
<>
<ToastProvider placement={args.placement} />
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
<div className="flex gap-2">
{colors.map((color, idx) => (
<CustomToastComponent key={idx} color={color} />
Expand All @@ -279,6 +288,7 @@ const CustomCloseButtonTemplate = (args) => {
return (
<>
<ToastProvider
maxVisibleToasts={args.maxVisibleToasts}
placement={args.placement}
toastProps={{
classNames: {
Expand Down