-
-
Notifications
You must be signed in to change notification settings - Fork 70
feat: add toasts #175
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
base: main
Are you sure you want to change the base?
feat: add toasts #175
Conversation
This is mostly just as an example on how to use them :P
WalkthroughIntroduces a reusable toast system (hook, container, styles) and integrates it into PublishServerSettings. Replaces a browser alert with toast notifications for bump cooldown and errors. Adds per-toast timers, drag-to-dismiss, and optional actions. Updates JSX structure for ServerBumpModal without changing logic. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant PublishServerSettings
participant useToast as Toast Store
participant ToastContainer
User->>PublishServerSettings: Click "Bump" / "Publish"
PublishServerSettings->>PublishServerSettings: Check cooldown / errors
alt Cooldown or Error
PublishServerSettings->>useToast: pushToast({ title, message, color, duration })
useToast-->>ToastContainer: toasts()
ToastContainer->>ToastContainer: Start timer, show progress
opt User closes or drags past threshold
ToastContainer->>useToast: removeToast(id)
end
alt Timer expires
ToastContainer->>useToast: removeToast(id)
end
else Allowed
PublishServerSettings->>PublishServerSettings: Proceed with normal flow
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/servers/settings/PublishServerSettings.tsx(4 hunks)src/components/ui/toasts/ToastContainer.tsx(1 hunks)src/components/ui/toasts/ToastStyles.module.scss(1 hunks)src/components/ui/toasts/useToast.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/components/ui/toasts/ToastContainer.tsx (1)
src/components/ui/toasts/useToast.ts (1)
useToast(12-29)
src/components/servers/settings/PublishServerSettings.tsx (2)
src/components/ui/toasts/useToast.ts (1)
useToast(12-29)src/components/ui/toasts/ToastContainer.tsx (1)
ToastContainer(5-117)
| const startTimer = () => { | ||
| const start = Date.now(); | ||
| const duration = toast.duration ?? 4000; | ||
| interval = window.setInterval(() => { | ||
| const elapsed = Date.now() - start; | ||
| const remaining = Math.max(duration - elapsed, 0); | ||
| setProgress(remaining / duration); | ||
| if (remaining <= 0) { | ||
| clearInterval(interval); | ||
| triggerRemove(); | ||
| } | ||
| }, 50); | ||
| }; | ||
|
|
||
| startTimer(); | ||
| onCleanup(() => clearInterval(interval)); | ||
|
|
||
| const triggerRemove = () => { | ||
| clearInterval(interval); | ||
| setIsRemoving(true); | ||
| setTimeout(() => removeToast(toast.id), 300); | ||
| }; | ||
|
|
||
| const onPointerDown = (e: PointerEvent) => { | ||
| const target = e.target as HTMLElement; | ||
| if (target.closest(`.${style.close}`) || target.closest(`.${style.action}`)) return; | ||
|
|
||
| startX = e.clientX; | ||
| clearInterval(interval); | ||
| }; | ||
|
|
||
| const onPointerMove = (e: PointerEvent) => { | ||
| if (startX !== null) { | ||
| const delta = e.clientX - startX; | ||
| setDragX(delta); | ||
| } | ||
| }; | ||
|
|
||
| const onPointerUp = () => { | ||
| if (Math.abs(dragX()) > 120) { | ||
| setDragX(dragX() > 0 ? 500 : -500); | ||
| triggerRemove(); | ||
| } else { | ||
| setDragX(0); | ||
| startTimer(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duration 0 toasts are getting auto-dismissed and corrupting the progress bar
pushToast treats duration: 0 as “stick around”, but ToastContainer still starts the countdown: it divides by zero (progress becomes NaN%) and calls triggerRemove, so sticky toasts disappear almost instantly. Guard against duration === 0 whenever starting/restarting the timer.
- const [progress, setProgress] = createSignal(1);
- const [dragX, setDragX] = createSignal(0);
- const [isRemoving, setIsRemoving] = createSignal(false);
- let interval: number;
+ const [progress, setProgress] = createSignal(1);
+ const [dragX, setDragX] = createSignal(0);
+ const [isRemoving, setIsRemoving] = createSignal(false);
+ let interval: number | undefined;
...
- const startTimer = () => {
- const start = Date.now();
- const duration = toast.duration ?? 4000;
+ const startTimer = () => {
+ const duration = toast.duration ?? 4000;
+ if (duration === 0) return;
+ const start = Date.now();
...
- startTimer();
- onCleanup(() => clearInterval(interval));
+ if (toast.duration !== 0) {
+ startTimer();
+ }
+ onCleanup(() => interval !== undefined && clearInterval(interval));
...
- clearInterval(interval);
+ if (interval !== undefined) clearInterval(interval);
...
- clearInterval(interval);
+ if (interval !== undefined) clearInterval(interval);
...
- setDragX(0);
- startTimer();
+ setDragX(0);
+ if (toast.duration !== 0) {
+ startTimer();
+ }🤖 Prompt for AI Agents
In src/components/ui/toasts/ToastContainer.tsx around lines 18 to 63, the timer
logic doesn't guard for toast.duration === 0 so sticky toasts start a countdown
(causing division-by-zero NaN progress and auto-dismiss). Fix by making
startTimer return immediately when duration === 0 (and setProgress(1) or leave
progress full), and only call startTimer again (e.g., after pointerUp) if
toast.duration !== 0; also ensure any progress calculation divides by duration
only when duration > 0 to avoid NaN.
Introduces a Toast UI Component
This update adds a new toast component for displaying notifications in the UI. The file changed included serves primarily as an example and a foundation for editing on the toast system. The hope for it is to eventually replace existing alerts with a more user-friendly system
Summary by CodeRabbit
New Features
Style