diff --git a/site/components/sections/toast-example.tsx b/site/components/sections/toast-example.tsx
index 4ac4478..a2ebb23 100644
--- a/site/components/sections/toast-example.tsx
+++ b/site/components/sections/toast-example.tsx
@@ -169,6 +169,18 @@ const examples: Array<{
});
},
},
+ {
+ title: 'Custom Position',
+ emoji: '⬇️',
+ snippet: `toast.success('Always at the bottom.', {
+ position: "bottom-center"
+})`,
+ action: () => {
+ toast.success('Always at the bottom.', {
+ position: 'bottom-center',
+ });
+ },
+ },
];
export const ToastExample = () => {
diff --git a/site/pages/docs/use-toaster.mdx b/site/pages/docs/use-toaster.mdx
index 748da2b..0177feb 100644
--- a/site/pages/docs/use-toaster.mdx
+++ b/site/pages/docs/use-toaster.mdx
@@ -23,16 +23,18 @@ Headless mode is perfectly suited to add notifications to your React Native app.
```jsx
const Notifications = () => {
- const { visibleToasts, handlers } = useToaster();
+ const { toasts, handlers } = useToaster();
const { startPause, endPause } = handlers;
return (
- {visibleToasts.map((toast) => (
-
- {toast.message}
-
- ))}
+ {toasts
+ .filter((toast) => toast.visible)
+ .map((toast) => (
+
+ {toast.message}
+
+ ))}
);
};
diff --git a/src/components/toaster.tsx b/src/components/toaster.tsx
index 4861445..133fbcf 100644
--- a/src/components/toaster.tsx
+++ b/src/components/toaster.tsx
@@ -73,10 +73,12 @@ export const Toaster: React.FC = ({
onMouseLeave={handlers.endPause}
>
{toasts.map((t) => {
- const offset = handlers.calculateOffset(t.id, {
+ const toastPosition = t.position || position;
+ const offset = handlers.calculateOffset(t, {
reverseOrder,
+ defaultPosition: position,
});
- const positionStyle = getPositionStyle(position, offset);
+ const positionStyle = getPositionStyle(toastPosition, offset);
const ref = t.height
? undefined
@@ -96,7 +98,7 @@ export const Toaster: React.FC = ({
{renderToast ? (
renderToast(t)
) : (
-
+
)}
);
diff --git a/src/core/types.ts b/src/core/types.ts
index e680861..16a1f5b 100644
--- a/src/core/types.ts
+++ b/src/core/types.ts
@@ -38,6 +38,7 @@ export interface Toast {
icon?: Renderable;
duration?: number;
pauseDuration: number;
+ position?: ToastPosition;
role: 'status' | 'alert';
ariaLive: 'assertive' | 'off' | 'polite';
diff --git a/src/core/use-toaster.ts b/src/core/use-toaster.ts
index 736c638..73cf841 100644
--- a/src/core/use-toaster.ts
+++ b/src/core/use-toaster.ts
@@ -1,11 +1,10 @@
import { useEffect, useMemo } from 'react';
import { dispatch, ActionType, useStore } from './store';
import { toast } from './toast';
-import { DefaultToastOptions } from './types';
+import { DefaultToastOptions, Toast, ToastPosition } from './types';
export const useToaster = (toastOptions?: DefaultToastOptions) => {
const { toasts, pausedAt } = useStore(toastOptions);
- const visibleToasts = toasts.filter((t) => t.visible);
useEffect(() => {
if (pausedAt) {
@@ -54,28 +53,39 @@ export const useToaster = (toastOptions?: DefaultToastOptions) => {
toast: { id: toastId, height },
}),
calculateOffset: (
- toastId: string,
- opts?: { reverseOrder?: boolean; margin?: number }
+ toast: Toast,
+ opts?: {
+ reverseOrder?: boolean;
+ gutter?: number;
+ defaultPosition?: ToastPosition;
+ }
) => {
- const { reverseOrder = false, margin = 8 } = opts || {};
- const toastIndex = toasts.findIndex((toast) => toast.id === toastId);
- const toastsBefore = toasts.filter(
+ const { reverseOrder = false, gutter = 8, defaultPosition } =
+ opts || {};
+
+ const relevantToasts = toasts.filter(
+ (t) =>
+ (t.position || defaultPosition) ===
+ (toast.position || defaultPosition)
+ );
+ const toastIndex = relevantToasts.findIndex((t) => t.id === toast.id);
+ const toastsBefore = relevantToasts.filter(
(toast, i) => i < toastIndex && toast.visible
).length;
- const offset = visibleToasts
+ const offset = relevantToasts
+ .filter((t) => t.visible)
.slice(...(reverseOrder ? [toastsBefore + 1] : [0, toastsBefore]))
- .reduce((acc, t) => acc + (t.height || 0) + margin, 0);
+ .reduce((acc, t) => acc + (t.height || 0) + gutter, 0);
return offset;
},
}),
- [toasts, visibleToasts, pausedAt]
+ [toasts, pausedAt]
);
return {
toasts,
- visibleToasts,
handlers,
};
};