Skip to content

Commit 42be1f1

Browse files
authored
feat: marketplace toast component (#149)
* feat: marketplace toast component * feat: controller toaster demo * feat: catch controller toast events * feat: use preset color in toasts * fix: fixed confirming transaction toast icon * chore: ported toasts to sonner * chore: use single toaster component * chore: handle toast close button * chore: optional toaster id * feat: added txHash to transaction toast * fix: toaster layout review * feat: collapse transaction toasts * feat: catch controller network switch event * fix: draft achievement layout * fix: fixed toasts font size * chore: review suggestions * fix: fixed build
1 parent b49e970 commit 42be1f1

29 files changed

+1547
-676
lines changed

.storybook/preview.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { Preview, ReactRenderer } from "@storybook/react";
33
import { withThemeByClassName } from "@storybook/addon-themes";
44
import { themes } from "@storybook/theming";
55
import { SonnerToaster } from "../src/components/primitives/sonner";
6-
import { Toaster } from "../src/components/primitives/toast/toaster";
76

87
import "../src/index.css";
98
import { useThemeEffect } from "../src/hooks/theme";
@@ -61,8 +60,9 @@ const preview: Preview = {
6160
return (
6261
<>
6362
<Story />
64-
<SonnerToaster />
65-
<Toaster />
63+
{Story().type.name !== "ControllerToasterDemo" &&
64+
<SonnerToaster />
65+
}
6666
</>
6767
)
6868
},

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
"peerDependencies": {
152152
"react": "^18.2.0 || ^19.0.0",
153153
"react-dom": "^18.2.0 || ^19.0.0",
154-
"sonner": "^1.4.41",
154+
"sonner": "^2.0.7",
155155
"starknet": "^8.5.4",
156156
"viem": "^2.21.32"
157157
},

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/icons/state/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export * from "./singular-oval";
4747
export * from "./singular-shape";
4848
export * from "./space-invader";
4949
export * from "./sparkles";
50+
export * from "./sparkles-draft";
5051
export * from "./stack-diamond";
5152
export * from "./stack-oval";
5253
export * from "./stack-shape";

src/components/icons/state/sparkles-draft.tsx

Lines changed: 95 additions & 0 deletions
Large diffs are not rendered by default.

src/components/icons/utility/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ export * from "./spinner-pixel";
5555
export * from "./spinner";
5656
export * from "./times-circle";
5757
export * from "./times";
58+
export * from "./transaction";
5859
export * from "./transfer";
5960
export * from "./trash";
6061
export * from "./verified";
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { forwardRef, memo } from "react";
2+
import { iconVariants } from "../utils";
3+
import { IconProps } from "../types";
4+
5+
export const TransactionIcon = memo(
6+
forwardRef<SVGSVGElement, IconProps>(
7+
({ className, size, ...props }, forwardedRef) => (
8+
<svg
9+
viewBox="0 0 11 9"
10+
className={iconVariants({ size, className })}
11+
ref={forwardedRef}
12+
{...props}
13+
>
14+
<path
15+
d="M5.31833 0.000198737C5.565 -0.00646793 5.78333 0.155199 5.84833 0.393532L7.08167 4.91353L7.37667 4.32353C7.55667 3.96187 7.92667 3.73353 8.33 3.73353H10.1333C10.4283 3.73353 10.6667 3.97187 10.6667 4.26687C10.6667 4.56187 10.4283 4.8002 10.1333 4.8002H8.33L7.41 6.63853C7.31167 6.83687 7.1 6.95187 6.88 6.9302C6.66 6.90853 6.47667 6.75353 6.41833 6.5402L5.395 2.78853L4.255 8.11187C4.20333 8.35187 3.99667 8.5252 3.75167 8.53353C3.50667 8.54187 3.28833 8.38187 3.22167 8.14687L2.265 4.8002H0.533333C0.238333 4.8002 0 4.56187 0 4.26687C0 3.97187 0.238333 3.73353 0.533333 3.73353H2.265C2.74167 3.73353 3.16 4.04853 3.29 4.50687L3.66 5.8002L4.81167 0.421865C4.86333 0.181865 5.07333 0.0068654 5.31833 0.000198737Z"
16+
fill="currentColor"
17+
/>
18+
</svg>
19+
),
20+
),
21+
);
22+
23+
TransactionIcon.displayName = "TransactionIcon";

src/components/primitives/sonner.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
11
"use client";
22

33
import { useMemo } from "react";
4-
import { Toaster as Sonner } from "sonner";
4+
import { Toaster as SonnerToster } from "sonner";
5+
import { ControllerPresetProvider } from "@/utils/context/presets";
56

6-
type SonnerToasterProps = React.ComponentProps<typeof Sonner>;
7+
type SonnerToasterProps = React.ComponentProps<typeof SonnerToster> & {
8+
toasterId?: string;
9+
};
710

8-
const SonnerToaster = ({ ...props }: SonnerToasterProps) => {
11+
const SonnerToaster = ({ toasterId, ...props }: SonnerToasterProps) => {
912
const theme = useMemo(
1013
() => localStorage.getItem("vite-ui-colorScheme") ?? "system",
1114
[],
1215
);
1316

1417
return (
15-
<Sonner
16-
theme={theme as SonnerToasterProps["theme"]}
17-
className="toaster group"
18-
duration={1000}
19-
toastOptions={{
20-
classNames: {
21-
toast:
22-
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
23-
description: "group-[.toast]:text-foreground-400",
24-
actionButton:
25-
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
26-
cancelButton:
27-
"group-[.toast]:bg-background-200 group-[.toast]:text-foreground-400",
28-
},
29-
}}
30-
{...props}
31-
/>
18+
<ControllerPresetProvider>
19+
<SonnerToster
20+
theme={theme as SonnerToasterProps["theme"]}
21+
className="toaster group"
22+
duration={1000}
23+
id={toasterId}
24+
toastOptions={{
25+
classNames: {
26+
toast:
27+
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg rounded-lg",
28+
description: "group-[.toast]:text-foreground-400",
29+
actionButton:
30+
"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
31+
cancelButton:
32+
"group-[.toast]:bg-background-200 group-[.toast]:text-foreground-400",
33+
},
34+
}}
35+
{...props}
36+
/>
37+
</ControllerPresetProvider>
3238
);
3339
};
3440

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
import {
5+
showErrorToast,
6+
showSuccessToast,
7+
showTransactionToast,
8+
showMarketplaceToast,
9+
showAchievementToast,
10+
showNetworkSwitchToast,
11+
} from "@/components/primitives/toast/specialized-toasts";
12+
import { useToast, ToasterToast } from "./use-toast";
13+
import {
14+
ToastPosition,
15+
ErrorToastOptions,
16+
SuccessToastOptions,
17+
TransactionToastOptions,
18+
MarketplaceToastOptions,
19+
AchievementToastOptions,
20+
CONTROLLER_TOAST_MESSAGE_TYPE,
21+
NetworkSwitchToastOptions,
22+
} from "./types";
23+
import { SonnerToaster } from "@/components/primitives/sonner";
24+
25+
export type ControllerNotificationTypes =
26+
| "error"
27+
| "success"
28+
| "network-switch"
29+
| "transaction"
30+
| "marketplace"
31+
| "achievement";
32+
33+
export function ControllerToaster({
34+
position = "bottom-right",
35+
disabledTypes = [],
36+
collapseTransactions,
37+
toasterId,
38+
}: {
39+
position?: ToastPosition;
40+
disabledTypes?: ControllerNotificationTypes[];
41+
collapseTransactions?: boolean;
42+
toasterId?: string | undefined;
43+
}) {
44+
const { toast } = useToast();
45+
46+
useEffect(() => {
47+
const eventHandler = (event: any) => {
48+
const variant =
49+
event.data.type === CONTROLLER_TOAST_MESSAGE_TYPE
50+
? event.data.options.variant
51+
: undefined;
52+
if (!variant) return;
53+
54+
if (variant == "error" && !disabledTypes.includes("error")) {
55+
const options = event.data.options as ErrorToastOptions;
56+
toast(
57+
showErrorToast({
58+
...options,
59+
toasterId,
60+
}) as ToasterToast,
61+
);
62+
} else if (variant == "success" && !disabledTypes.includes("success")) {
63+
const options = event.data.options as SuccessToastOptions;
64+
toast(
65+
showSuccessToast({
66+
...options,
67+
toasterId,
68+
}) as ToasterToast,
69+
);
70+
} else if (
71+
variant == "network-switch" &&
72+
!disabledTypes.includes("network-switch")
73+
) {
74+
const options = event.data.options as NetworkSwitchToastOptions;
75+
toast(
76+
showNetworkSwitchToast({
77+
...options,
78+
toasterId,
79+
}) as ToasterToast,
80+
);
81+
} else if (
82+
variant == "transaction" &&
83+
!disabledTypes.includes("transaction")
84+
) {
85+
const options = event.data.options as TransactionToastOptions;
86+
toast(
87+
showTransactionToast({
88+
...options,
89+
isExpanded:
90+
collapseTransactions !== undefined ? !collapseTransactions : true,
91+
duration: options.status == "confirming" ? 0 : options.duration,
92+
toasterId,
93+
toastId: options.txHash || undefined,
94+
}) as ToasterToast,
95+
);
96+
} else if (
97+
variant == "marketplace" &&
98+
!disabledTypes.includes("marketplace")
99+
) {
100+
const options = event.data.options as MarketplaceToastOptions;
101+
toast(
102+
showMarketplaceToast({
103+
title: `${options.action[0].toUpperCase()}${options.action.slice(1)}`,
104+
...options,
105+
toasterId,
106+
}) as ToasterToast,
107+
);
108+
} else if (
109+
variant == "achievement" &&
110+
!disabledTypes.includes("achievement")
111+
) {
112+
const options = event.data.options as AchievementToastOptions;
113+
toast(
114+
showAchievementToast({
115+
...options,
116+
toasterId,
117+
}) as ToasterToast,
118+
);
119+
}
120+
};
121+
window.addEventListener("message", eventHandler);
122+
return () => {
123+
window.removeEventListener("message", eventHandler);
124+
};
125+
}, [disabledTypes.join(","), collapseTransactions, toasterId]);
126+
127+
return <SonnerToaster position={position} toasterId={toasterId} />;
128+
}
Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
// Re-export existing toast primitives
21
export * from "./toast";
3-
export * from "./toaster";
42
export * from "./use-toast";
5-
6-
// Export new specialized toast components
3+
export * from "./controller-toaster";
74
export * from "./specialized-toasts";

0 commit comments

Comments
 (0)