Skip to content

feat: add Sonner toast notifications and integrate into UI components#64

Merged
Aunshon merged 2 commits intomainfrom
add-toast
Mar 5, 2026
Merged

feat: add Sonner toast notifications and integrate into UI components#64
Aunshon merged 2 commits intomainfrom
add-toast

Conversation

@Aunshon
Copy link
Collaborator

@Aunshon Aunshon commented Mar 5, 2026

Summary by CodeRabbit

  • New Features

    • Added a toast notification system with theme sync, custom icons, and multiple variants (success, error, warning, info, default).
    • Supports actions, descriptions, custom JSX content, positions, loading and promise-based states.
  • Documentation

    • Added comprehensive interactive examples demonstrating all toast capabilities, positions, color variants, close behavior, and expanded sequences.
  • Public API

    • Exposed toast and Toaster for app-wide use.

@Aunshon Aunshon self-assigned this Mar 5, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 5, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Adds the Sonner toast library, a themed Toaster wrapper with custom icons and styles, Storybook stories demonstrating many toast patterns/positions, and exposes Toaster and toast through the public API; also updates package.json to include the new dependency.

Changes

Cohort / File(s) Summary
Dependency
package.json
Added dependency: sonner ^2.0.7.
UI Component
src/components/ui/sonner.tsx
New Toaster React wrapper around Sonner: maps theme via useThemeOptional, supplies custom lucide-react icons, injects CSS variable styles, forwards ToasterProps, and exports Toaster.
UI Barrel
src/components/ui/index.ts
Added export for Toaster from ./sonner; duplicate export occurrence present in diff.
Public API
src/index.ts
Re-exported Toaster from UI barrel and toast from sonner in the package public exports.
Storybook
src/components/ui/Sonner.stories.tsx
Added Storybook stories showcasing many toast scenarios: default types, descriptive, success/info/warning/error, loading, action/cancel, promise-based, custom JSX, positions, rich colors, close button, and expanded sequences.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I nibble code and polish light,
Toasts pop bright from day to night,
Icons shine, themes align,
Sonner sings — a carrot-sized design! 🥕✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add Sonner toast notifications and integrate into UI components' accurately and concisely describes the main changes: adding the Sonner library for toast notifications and integrating it into the UI component system.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-toast

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a 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

🧹 Nitpick comments (2)
src/components/ui/sonner.tsx (1)

16-35: Merge icons/style defaults instead of letting props replace them wholesale.

Because ...props is applied on Line 34, passing icons or style overrides the wrapper defaults entirely. If this wrapper is intended to preserve design-system defaults, merge those props.

Proposed refactor
-const Toaster = ({ ...props }: ToasterProps) => {
+const Toaster = ({ icons, style, theme, ...props }: ToasterProps) => {
   const theme = useThemeOptional();
   const mode = theme?.mode ?? "system";

   return (
     <Sonner
-      theme={mode as ToasterProps["theme"]}
+      theme={theme ?? (mode as ToasterProps["theme"])}
       className="toaster group"
       icons={{
         success: <CircleCheckIcon className="size-4" />,
         info: <InfoIcon className="size-4" />,
         warning: <TriangleAlertIcon className="size-4" />,
         error: <OctagonXIcon className="size-4" />,
         loading: <Loader2Icon className="size-4 animate-spin" />,
+        ...icons,
       }}
       style={
         {
           "--normal-bg": "var(--popover)",
           "--normal-text": "var(--popover-foreground)",
           "--normal-border": "var(--border)",
           "--border-radius": "var(--radius)",
+          ...(style as React.CSSProperties),
         } as React.CSSProperties
       }
       {...props}
     />
   );
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/sonner.tsx` around lines 16 - 35, The Sonner wrapper
currently lets incoming props.icons and props.style fully replace the defaults
because {...props} is spread last; update the component in
src/components/ui/sonner.tsx to merge defaults with incoming props instead:
define the defaultIcons and defaultStyle (matching the existing icons and style
object) and pass icons={...defaultIcons, ...(props?.icons)} and
style={{...defaultStyle, ...(props?.style)}} (or use Object.assign) when
rendering <Sonner ... /> so callers can override specific keys without
discarding design-system defaults.
src/components/ui/Sonner.stories.tsx (1)

157-160: Use Promise directly instead of window.Promise.

Line 158 can use the global Promise constructor directly; this keeps the story less browser-coupled and more idiomatic.

Proposed tweak
-              new window.Promise<{ name: string }>((resolve) =>
+              new Promise<{ name: string }>((resolve) =>
                 setTimeout(() => resolve({ name: "Sonner" }), 2000)
               ),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/ui/Sonner.stories.tsx` around lines 157 - 160, Replace the
browser-coupled constructor usage "new window.Promise<{ name: string }>(...)"
with the global Promise constructor by removing "window." so the story uses "new
Promise<{ name: string }>(...)" instead; locate the arrow function that returns
"new window.Promise" in Sonner.stories (the async story helper) and update it to
use Promise to keep the code idiomatic and environment-agnostic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Line 78: Update the package.json peerDependencies so they match Sonner 2.x's
React requirement: in package.json's "peerDependencies" replace the current
react and react-dom ranges that allow ">=17.0.0" with ranges that require React
18+ (e.g., ">=18.0.0" or the equivalent semver like "^18.0.0 || ^19.0.0") so the
declared peers align with the installed "sonner": "^2.0.7" constraint.

---

Nitpick comments:
In `@src/components/ui/Sonner.stories.tsx`:
- Around line 157-160: Replace the browser-coupled constructor usage "new
window.Promise<{ name: string }>(...)" with the global Promise constructor by
removing "window." so the story uses "new Promise<{ name: string }>(...)"
instead; locate the arrow function that returns "new window.Promise" in
Sonner.stories (the async story helper) and update it to use Promise to keep the
code idiomatic and environment-agnostic.

In `@src/components/ui/sonner.tsx`:
- Around line 16-35: The Sonner wrapper currently lets incoming props.icons and
props.style fully replace the defaults because {...props} is spread last; update
the component in src/components/ui/sonner.tsx to merge defaults with incoming
props instead: define the defaultIcons and defaultStyle (matching the existing
icons and style object) and pass icons={...defaultIcons, ...(props?.icons)} and
style={{...defaultStyle, ...(props?.style)}} (or use Object.assign) when
rendering <Sonner ... /> so callers can override specific keys without
discarding design-system defaults.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5273f740-d87b-4345-b266-5432eb123c5f

📥 Commits

Reviewing files that changed from the base of the PR and between 8569d21 and 997e4f6.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • package.json
  • src/components/ui/Sonner.stories.tsx
  • src/components/ui/index.ts
  • src/components/ui/sonner.tsx
  • src/index.ts

"input-otp": "^1.4.2",
"lucide-react": "^0.563.0",
"recharts": "^2.15.4",
"sonner": "^2.0.7",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Sonner 2.0.7 peerDependencies ==="
npm view sonner@2.0.7 peerDependencies --json

echo ""
echo "=== Current library peerDependencies ==="
python - <<'PY'
import json
with open("package.json") as f:
    pkg = json.load(f)
print(json.dumps(pkg.get("peerDependencies", {}), indent=2))
PY

Repository: getdokan/plugin-ui

Length of output: 295


Update peerDependencies to reflect Sonner's React 18+ requirement.

Sonner 2.0.7 requires react@^18.0.0 || ^19.0.0 and react-dom@^18.0.0 || ^19.0.0, but the current peer ranges declare >=17.0.0. This mismatch creates install conflicts for consumers using React 17. Update peer ranges to >=18.0.0:

Proposed fix
  "peerDependencies": {
-    "react": ">=17.0.0",
-    "react-dom": ">=17.0.0"
+    "react": ">=18.0.0",
+    "react-dom": ">=18.0.0"
  },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 78, Update the package.json peerDependencies so they
match Sonner 2.x's React requirement: in package.json's "peerDependencies"
replace the current react and react-dom ranges that allow ">=17.0.0" with ranges
that require React 18+ (e.g., ">=18.0.0" or the equivalent semver like "^18.0.0
|| ^19.0.0") so the declared peers align with the installed "sonner": "^2.0.7"
constraint.

@Aunshon Aunshon merged commit 3d3c206 into main Mar 5, 2026
1 check passed
@Aunshon Aunshon deleted the add-toast branch March 5, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant