mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-11 09:51:40 +00:00
feat(components): changed sonner defaults to use lucide icons (#7620)
* feat(components): changed sonner defaults to use lucide icons * Update new-york-v4 sonner.tsx * fix: icons and docs * fix * fix --------- Co-authored-by: shadcn <m@shadcn.com>
This commit is contained in:
@@ -68,7 +68,7 @@ npm install sonner next-themes
|
||||
|
||||
<Step>Add the Toaster component</Step>
|
||||
|
||||
```tsx title="app/layout.tsx" {1,9}
|
||||
```tsx showLineNumbers title="app/layout.tsx" {1,8}
|
||||
import { Toaster } from "@/components/ui/sonner"
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
@@ -76,8 +76,8 @@ export default function RootLayout({ children }) {
|
||||
<html lang="en">
|
||||
<head />
|
||||
<body>
|
||||
<main>{children}</main>
|
||||
<Toaster />
|
||||
<main>{children}</main>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
@@ -99,3 +99,56 @@ import { toast } from "sonner"
|
||||
```tsx
|
||||
toast("Event has been created.")
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
<ComponentPreview name="sonner-types" />
|
||||
|
||||
## Changelog
|
||||
|
||||
### 2025-10-13 Icons
|
||||
|
||||
We've updated the Sonner component to use icons from `lucide`. Update your `sonner.tsx` file to use the new icons.
|
||||
|
||||
```tsx showLineNumbers title="components/ui/sonner.tsx" {3-9,20-26}
|
||||
"use client"
|
||||
|
||||
import {
|
||||
CircleCheckIcon,
|
||||
InfoIcon,
|
||||
Loader2Icon,
|
||||
OctagonXIcon,
|
||||
TriangleAlertIcon,
|
||||
} from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
import { Toaster as Sonner, ToasterProps } from "sonner"
|
||||
|
||||
const Toaster = ({ ...props }: ToasterProps) => {
|
||||
const { theme = "system" } = useTheme()
|
||||
|
||||
return (
|
||||
<Sonner
|
||||
theme={theme 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" />,
|
||||
}}
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
"--normal-text": "var(--popover-foreground)",
|
||||
"--normal-border": "var(--border)",
|
||||
"--border-radius": "var(--radius)",
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Toaster }
|
||||
```
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "ui/sonner.tsx",
|
||||
"content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"content": "\"use client\"\n\nimport {\n CircleCheck,\n Info,\n LoaderCircle,\n OctagonX,\n TriangleAlert,\n} from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n icons={{\n success: <CircleCheck className=\"h-4 w-4\" />,\n info: <Info className=\"h-4 w-4\" />,\n warning: <TriangleAlert className=\"h-4 w-4\" />,\n error: <OctagonX className=\"h-4 w-4\" />,\n loading: <LoaderCircle className=\"h-4 w-4 animate-spin\" />,\n }}\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"type": "registry:ui",
|
||||
"target": ""
|
||||
}
|
||||
|
||||
@@ -6863,6 +6863,19 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sonner-types",
|
||||
"type": "registry:example",
|
||||
"registryDependencies": [
|
||||
"sonner"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/examples/sonner-types.tsx",
|
||||
"type": "registry:example"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spinner-demo",
|
||||
"type": "registry:example",
|
||||
|
||||
15
apps/v4/public/r/styles/new-york-v4/sonner-types.json
Normal file
15
apps/v4/public/r/styles/new-york-v4/sonner-types.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "sonner-types",
|
||||
"type": "registry:example",
|
||||
"registryDependencies": [
|
||||
"sonner"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/examples/sonner-types.tsx",
|
||||
"content": "\"use client\"\n\nimport { toast } from \"sonner\"\n\nimport { Button } from \"@/registry/new-york-v4/ui/button\"\n\nexport default function SonnerTypes() {\n return (\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" onClick={() => toast(\"Event has been created\")}>\n Default\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => toast.success(\"Event has been created\")}\n >\n Success\n </Button>\n <Button\n variant=\"outline\"\n onClick={() =>\n toast.info(\"Be at the area 10 minutes before the event time\")\n }\n >\n Info\n </Button>\n <Button\n variant=\"outline\"\n onClick={() =>\n toast.warning(\"Event start time cannot be earlier than 8am\")\n }\n >\n Warning\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => toast.error(\"Event has not been created\")}\n >\n Error\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => {\n const promise = () =>\n new Promise((resolve) =>\n setTimeout(() => resolve({ name: \"Event\" }), 2000)\n )\n\n toast.promise(promise(), {\n loading: \"Loading...\",\n success: (data) => `${data.name} has been created`,\n error: \"Error\",\n })\n }}\n >\n Promise\n </Button>\n </div>\n )\n}\n",
|
||||
"type": "registry:example"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/sonner.tsx",
|
||||
"content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n \"--border-radius\": \"var(--radius)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"content": "\"use client\"\n\nimport {\n CircleCheckIcon,\n InfoIcon,\n Loader2Icon,\n OctagonXIcon,\n TriangleAlertIcon,\n} from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n icons={{\n success: <CircleCheckIcon className=\"size-4\" />,\n info: <InfoIcon className=\"size-4\" />,\n warning: <TriangleAlertIcon className=\"size-4\" />,\n error: <OctagonXIcon className=\"size-4\" />,\n loading: <Loader2Icon className=\"size-4 animate-spin\" />,\n }}\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n \"--border-radius\": \"var(--radius)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -6863,6 +6863,19 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sonner-types",
|
||||
"type": "registry:example",
|
||||
"registryDependencies": [
|
||||
"sonner"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/examples/sonner-types.tsx",
|
||||
"type": "registry:example"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spinner-demo",
|
||||
"type": "registry:example",
|
||||
|
||||
@@ -6956,6 +6956,24 @@ export const Index: Record<string, any> = {
|
||||
categories: undefined,
|
||||
meta: undefined,
|
||||
},
|
||||
"sonner-types": {
|
||||
name: "sonner-types",
|
||||
description: "",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["sonner"],
|
||||
files: [{
|
||||
path: "registry/new-york-v4/examples/sonner-types.tsx",
|
||||
type: "registry:example",
|
||||
target: ""
|
||||
}],
|
||||
component: React.lazy(async () => {
|
||||
const mod = await import("@/registry/new-york-v4/examples/sonner-types.tsx")
|
||||
const exportName = Object.keys(mod).find(key => typeof mod[key] === 'function' || typeof mod[key] === 'object') || item.name
|
||||
return { default: mod.default || mod[exportName] }
|
||||
}),
|
||||
categories: undefined,
|
||||
meta: undefined,
|
||||
},
|
||||
"spinner-demo": {
|
||||
name: "spinner-demo",
|
||||
description: "",
|
||||
|
||||
61
apps/v4/registry/new-york-v4/examples/sonner-types.tsx
Normal file
61
apps/v4/registry/new-york-v4/examples/sonner-types.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client"
|
||||
|
||||
import { toast } from "sonner"
|
||||
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
|
||||
export default function SonnerTypes() {
|
||||
return (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<Button variant="outline" onClick={() => toast("Event has been created")}>
|
||||
Default
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => toast.success("Event has been created")}
|
||||
>
|
||||
Success
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
toast.info("Be at the area 10 minutes before the event time")
|
||||
}
|
||||
>
|
||||
Info
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() =>
|
||||
toast.warning("Event start time cannot be earlier than 8am")
|
||||
}
|
||||
>
|
||||
Warning
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => toast.error("Event has not been created")}
|
||||
>
|
||||
Error
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
toast.promise<{ name: string }>(
|
||||
() =>
|
||||
new Promise((resolve) =>
|
||||
setTimeout(() => resolve({ name: "Event" }), 2000)
|
||||
),
|
||||
{
|
||||
loading: "Loading...",
|
||||
success: (data) => `${data.name} has been created`,
|
||||
error: "Error",
|
||||
}
|
||||
)
|
||||
}}
|
||||
>
|
||||
Promise
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
CircleCheckIcon,
|
||||
InfoIcon,
|
||||
Loader2Icon,
|
||||
OctagonXIcon,
|
||||
TriangleAlertIcon,
|
||||
} from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
import { Toaster as Sonner, ToasterProps } from "sonner"
|
||||
|
||||
@@ -10,6 +17,13 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
<Sonner
|
||||
theme={theme 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" />,
|
||||
}}
|
||||
style={
|
||||
{
|
||||
"--normal-bg": "var(--popover)",
|
||||
|
||||
@@ -2016,6 +2016,17 @@ export const examples: Registry["items"] = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "sonner-types",
|
||||
type: "registry:example",
|
||||
registryDependencies: ["sonner"],
|
||||
files: [
|
||||
{
|
||||
path: "examples/sonner-types.tsx",
|
||||
type: "registry:example",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "spinner-demo",
|
||||
type: "registry:example",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "ui/sonner.tsx",
|
||||
"content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"content": "\"use client\"\n\nimport {\n CircleCheck,\n Info,\n LoaderCircle,\n OctagonX,\n TriangleAlert,\n} from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps<typeof Sonner>\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n icons={{\n success: <CircleCheck className=\"h-4 w-4\" />,\n info: <Info className=\"h-4 w-4\" />,\n warning: <TriangleAlert className=\"h-4 w-4\" />,\n error: <OctagonX className=\"h-4 w-4\" />,\n loading: <LoaderCircle className=\"h-4 w-4 animate-spin\" />,\n }}\n toastOptions={{\n classNames: {\n toast:\n \"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg\",\n description: \"group-[.toast]:text-muted-foreground\",\n actionButton:\n \"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground\",\n cancelButton:\n \"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground\",\n },\n }}\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"type": "registry:ui",
|
||||
"target": ""
|
||||
}
|
||||
|
||||
@@ -6863,6 +6863,19 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "sonner-types",
|
||||
"type": "registry:example",
|
||||
"registryDependencies": [
|
||||
"sonner"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/examples/sonner-types.tsx",
|
||||
"type": "registry:example"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "spinner-demo",
|
||||
"type": "registry:example",
|
||||
|
||||
15
apps/www/public/r/styles/new-york-v4/sonner-types.json
Normal file
15
apps/www/public/r/styles/new-york-v4/sonner-types.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
||||
"name": "sonner-types",
|
||||
"type": "registry:example",
|
||||
"registryDependencies": [
|
||||
"sonner"
|
||||
],
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/examples/sonner-types.tsx",
|
||||
"content": "\"use client\"\n\nimport { toast } from \"sonner\"\n\nimport { Button } from \"@/registry/new-york-v4/ui/button\"\n\nexport default function SonnerTypes() {\n return (\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"outline\" onClick={() => toast(\"Event has been created\")}>\n Default\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => toast.success(\"Event has been created\")}\n >\n Success\n </Button>\n <Button\n variant=\"outline\"\n onClick={() =>\n toast.info(\"Be at the area 10 minutes before the event time\")\n }\n >\n Info\n </Button>\n <Button\n variant=\"outline\"\n onClick={() =>\n toast.warning(\"Event start time cannot be earlier than 8am\")\n }\n >\n Warning\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => toast.error(\"Event has not been created\")}\n >\n Error\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => {\n const promise = () =>\n new Promise((resolve) =>\n setTimeout(() => resolve({ name: \"Event\" }), 2000)\n )\n\n toast.promise(promise(), {\n loading: \"Loading...\",\n success: (data) => `${data.name} has been created`,\n error: \"Error\",\n })\n }}\n >\n Promise\n </Button>\n </div>\n )\n}\n",
|
||||
"type": "registry:example"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
"files": [
|
||||
{
|
||||
"path": "registry/new-york-v4/ui/sonner.tsx",
|
||||
"content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n \"--border-radius\": \"var(--radius)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"content": "\"use client\"\n\nimport {\n CircleCheckIcon,\n InfoIcon,\n Loader2Icon,\n OctagonXIcon,\n TriangleAlertIcon,\n} from \"lucide-react\"\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner, ToasterProps } from \"sonner\"\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n <Sonner\n theme={theme as ToasterProps[\"theme\"]}\n className=\"toaster group\"\n icons={{\n success: <CircleCheckIcon className=\"size-4\" />,\n info: <InfoIcon className=\"size-4\" />,\n warning: <TriangleAlertIcon className=\"size-4\" />,\n error: <OctagonXIcon className=\"size-4\" />,\n loading: <Loader2Icon className=\"size-4 animate-spin\" />,\n }}\n style={\n {\n \"--normal-bg\": \"var(--popover)\",\n \"--normal-text\": \"var(--popover-foreground)\",\n \"--normal-border\": \"var(--border)\",\n \"--border-radius\": \"var(--radius)\",\n } as React.CSSProperties\n }\n {...props}\n />\n )\n}\n\nexport { Toaster }\n",
|
||||
"type": "registry:ui"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -24,7 +24,7 @@ type FormFieldContextValue<
|
||||
name: TName
|
||||
}
|
||||
|
||||
const FormFieldContext = React.createContext<FormFieldContextValue | null>(null);
|
||||
const FormFieldContext = React.createContext<FormFieldContextValue | null>(null)
|
||||
|
||||
const FormField = <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
@@ -70,7 +70,7 @@ type FormItemContextValue = {
|
||||
id: string
|
||||
}
|
||||
|
||||
const FormItemContext = React.createContext<FormItemContextValue| null>(null)
|
||||
const FormItemContext = React.createContext<FormItemContextValue | null>(null)
|
||||
|
||||
const FormItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
CircleCheck,
|
||||
Info,
|
||||
LoaderCircle,
|
||||
OctagonX,
|
||||
TriangleAlert,
|
||||
} from "lucide-react"
|
||||
import { useTheme } from "next-themes"
|
||||
import { Toaster as Sonner } from "sonner"
|
||||
|
||||
@@ -12,6 +19,13 @@ const Toaster = ({ ...props }: ToasterProps) => {
|
||||
<Sonner
|
||||
theme={theme as ToasterProps["theme"]}
|
||||
className="toaster group"
|
||||
icons={{
|
||||
success: <CircleCheck className="h-4 w-4" />,
|
||||
info: <Info className="h-4 w-4" />,
|
||||
warning: <TriangleAlert className="h-4 w-4" />,
|
||||
error: <OctagonX className="h-4 w-4" />,
|
||||
loading: <LoaderCircle className="h-4 w-4 animate-spin" />,
|
||||
}}
|
||||
toastOptions={{
|
||||
classNames: {
|
||||
toast:
|
||||
|
||||
@@ -24,7 +24,7 @@ type FormFieldContextValue<
|
||||
name: TName
|
||||
}
|
||||
|
||||
const FormFieldContext = React.createContext<FormFieldContextValue | null>(null);
|
||||
const FormFieldContext = React.createContext<FormFieldContextValue | null>(null)
|
||||
|
||||
const FormField = <
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
@@ -70,7 +70,7 @@ type FormItemContextValue = {
|
||||
id: string
|
||||
}
|
||||
|
||||
const FormItemContext = React.createContext<FormItemContextValue| null>(null)
|
||||
const FormItemContext = React.createContext<FormItemContextValue | null>(null)
|
||||
|
||||
const FormItem = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
|
||||
Reference in New Issue
Block a user