Skip to content

Commit 29df4f5

Browse files
authored
fix(toast): fixing maxVisibleToasts, solid variant promise, promise timer (heroui-inc#4881)
* fix: maxVisibleToasts functionality * chore: adding the changeset * fix: starting the toast timer when the promise is resolved * fix: spinner invisible in solid variants
1 parent 57b1181 commit 29df4f5

File tree

5 files changed

+58
-22
lines changed

5 files changed

+58
-22
lines changed

.changeset/slow-dogs-travel.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@heroui/toast": patch
3+
---
4+
5+
fixing maxVisibleToast functionality in toast (#4870)
6+
For promises, starting the timer only after the promise is resolved

packages/components/toast/src/toast-region.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ export function ToastRegion<T extends ToastProps>({
7474
return null;
7575
}
7676

77-
if (total - index <= 4 || (isHovered && total - index <= maxVisibleToasts + 1)) {
77+
if (
78+
disableAnimation ||
79+
total - index <= 4 ||
80+
(isHovered && total - index <= maxVisibleToasts + 1)
81+
) {
7882
return (
7983
<Toast
8084
key={toast.key}
@@ -85,6 +89,7 @@ export function ToastRegion<T extends ToastProps>({
8589
heights={heights}
8690
index={index}
8791
isRegionExpanded={isHovered || isTouched}
92+
maxVisibleToasts={maxVisibleToasts}
8893
placement={placement}
8994
setHeights={setHeights}
9095
toastOffset={toastOffset}

packages/components/toast/src/toast.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const Toast = forwardRef<"div", ToastProps>((props, ref) => {
6969
<Spinner
7070
aria-label="loadingIcon"
7171
classNames={{wrapper: getLoadingIconProps().className}}
72-
color={color ?? "default"}
72+
color={"current"}
7373
/>
7474
)
7575
: null;

packages/components/toast/src/use-toast.ts

+27-12
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ interface Props<T> extends Omit<HTMLHeroUIProps<"div">, "title">, ToastProps {
119119
isRegionExpanded: boolean;
120120
placement?: ToastPlacement;
121121
toastOffset?: number;
122+
maxVisibleToasts: number;
122123
}
123124

124125
export type UseToastProps<T = ToastProps> = Props<T> &
@@ -158,6 +159,7 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
158159
icon,
159160
onClose,
160161
severity,
162+
maxVisibleToasts,
161163
...otherProps
162164
} = props;
163165

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

198+
const [isLoading, setIsLoading] = useState<boolean>(!!promiseProp);
199+
200+
useEffect(() => {
201+
if (!promiseProp) return;
202+
promiseProp.finally(() => {
203+
setIsLoading(false);
204+
});
205+
}, [promiseProp]);
206+
196207
useEffect(() => {
197208
const updateProgress = (timestamp: number) => {
198-
if (!timeout) {
209+
if (!timeout || isLoading) {
199210
return;
200211
}
201212

@@ -238,16 +249,16 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
238249
cancelAnimationFrame(animationRef.current);
239250
}
240251
};
241-
}, [timeout, shouldShowTimeoutProgess, state, isToastHovered, index, total, isRegionExpanded]);
242-
243-
const [isLoading, setIsLoading] = useState<boolean>(!!promiseProp);
244-
245-
useEffect(() => {
246-
if (!promiseProp) return;
247-
promiseProp.finally(() => {
248-
setIsLoading(false);
249-
});
250-
}, [promiseProp]);
252+
}, [
253+
timeout,
254+
shouldShowTimeoutProgess,
255+
state,
256+
isToastHovered,
257+
index,
258+
total,
259+
isRegionExpanded,
260+
isLoading,
261+
]);
251262

252263
const Component = as || "div";
253264
const loadingIcon: ReactNode = icon;
@@ -486,7 +497,10 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
486497
"data-drag-value": number;
487498
className: string;
488499
} => {
489-
const isCloseToEnd = total - index - 1 <= 2;
500+
const comparingValue = isRegionExpanded
501+
? maxVisibleToasts - 1
502+
: Math.min(2, maxVisibleToasts - 1);
503+
const isCloseToEnd = total - index - 1 <= comparingValue;
490504
const dragDirection = placement === "bottom-center" || placement === "top-center" ? "y" : "x";
491505
const dragConstraints = {left: 0, right: 0, top: 0, bottom: 0};
492506
const dragElastic = getDragElasticConstraints(placement);
@@ -593,6 +607,7 @@ export function useToast<T extends ToastProps>(originalProps: UseToastProps<T>)
593607
shouldCloseToast,
594608
slots,
595609
toastOffset,
610+
maxVisibleToasts,
596611
],
597612
);
598613

packages/components/toast/stories/toast.stories.tsx

+18-8
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ export default {
4949
"top-center",
5050
],
5151
},
52+
maxVisibleToasts: {
53+
control: {type: "number"},
54+
},
5255
hideCloseButton: {
5356
control: {
5457
type: "boolean",
@@ -80,7 +83,7 @@ const defaultProps = {
8083
const Template = (args: ToastProps) => {
8184
return (
8285
<>
83-
<ToastProvider placement={args.placement} />
86+
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
8487
<div>
8588
<Button
8689
onPress={() => {
@@ -100,7 +103,7 @@ const Template = (args: ToastProps) => {
100103
const ShowTimeoutProgressTemplate = (args: ToastProps) => {
101104
return (
102105
<>
103-
<ToastProvider placement={args.placement} />
106+
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
104107
<Button
105108
onPress={() => {
106109
addToast({
@@ -121,7 +124,7 @@ const ShowTimeoutProgressTemplate = (args: ToastProps) => {
121124
const WithEndContentTemplate = (args) => {
122125
return (
123126
<>
124-
<ToastProvider placement={args.placement} />
127+
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
125128
<Button
126129
onPress={() => {
127130
addToast({
@@ -147,7 +150,7 @@ const WithEndContentTemplate = (args) => {
147150
const PlacementTemplate = (args: ToastProps) => {
148151
return (
149152
<>
150-
<ToastProvider placement={args.placement} />
153+
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
151154
<div>
152155
<Button
153156
onPress={() => {
@@ -168,7 +171,11 @@ const PlacementTemplate = (args: ToastProps) => {
168171
const DisableAnimationTemplate = (args: ToastProps) => {
169172
return (
170173
<>
171-
<ToastProvider disableAnimation={true} placement={args.placement} />
174+
<ToastProvider
175+
disableAnimation={true}
176+
maxVisibleToasts={args.maxVisibleToasts}
177+
placement={args.placement}
178+
/>
172179
<div>
173180
<Button
174181
onPress={() => {
@@ -189,14 +196,16 @@ const DisableAnimationTemplate = (args: ToastProps) => {
189196
const PromiseToastTemplate = (args: ToastProps) => {
190197
return (
191198
<>
192-
<ToastProvider placement={args.placement} />
199+
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
193200
<div>
194201
<Button
195202
onPress={() => {
196203
addToast({
197204
title: "Toast Title",
198205
description: "Toast Displayed Successfully",
199-
promise: new Promise((resolve) => setTimeout(resolve, 5000)),
206+
promise: new Promise((resolve) => setTimeout(resolve, 3000)),
207+
timeout: 3000,
208+
shouldShowTimeoutProgess: false,
200209
...args,
201210
});
202211
}}
@@ -265,7 +274,7 @@ const CustomToastTemplate = (args) => {
265274

266275
return (
267276
<>
268-
<ToastProvider placement={args.placement} />
277+
<ToastProvider maxVisibleToasts={args.maxVisibleToasts} placement={args.placement} />
269278
<div className="flex gap-2">
270279
{colors.map((color, idx) => (
271280
<CustomToastComponent key={idx} color={color} />
@@ -279,6 +288,7 @@ const CustomCloseButtonTemplate = (args) => {
279288
return (
280289
<>
281290
<ToastProvider
291+
maxVisibleToasts={args.maxVisibleToasts}
282292
placement={args.placement}
283293
toastProps={{
284294
classNames: {

0 commit comments

Comments
 (0)