Skip to content

Instantly share code, notes, and snippets.

@diegohaz
Last active October 23, 2024 06:47
Show Gist options
  • Save diegohaz/341ed774ebac3b4dd820ae48d8bc822c to your computer and use it in GitHub Desktop.
Save diegohaz/341ed774ebac3b4dd820ae48d8bc822c to your computer and use it in GitHub Desktop.
// notifications.tsx
import * as Ariakit from "@ariakit/react";
interface Item extends Ariakit.NotificationStoreItem {
onUndo?: () => void;
}
export function useNotification() {
const notification = Ariakit.useNotificationContext();
if (!notification) {
throw new Error("Missing NotificationProvider");
}
return notification as Ariakit.NotificationStore<Item>;
}
export function Notifications({ children }) {
return (
<Ariakit.NotificationProvider>
{children}
<div>
<Ariakit.NotificationItems<Item>>
{(items) => (
items.map(({ onUndo, ...props }) => (
<Ariakit.Notification key={props.id} {...props}>
{props.children}
<Ariakit.NotificationDismiss />
{onUndo && <button onClick={onUndo}>Undo</button>}
</Ariakit.Notification>
))
)}
</Ariakit.NotificationItems>
</div>
</Ariakit.NotificationProvider>
);
}
// index.tsx
import { Notifications, useNotification } from "./notifications.tsx";
function Example() {
const { push } = useNotification();
return (
<>
<button
onClick={() => {
push("Hello");
push("Hello", { role: "status" });
push("Hello", { onUndo: () => {}, timeout: 10000 });
push("Hello", { visuallyHidden: true });
}}
>
Push notification
</button>
</>
);
}
export default function App() {
return (
<Notifications>
<Example />
</Notifications>
);
}
import * as Ariakit from "@ariakit/react";
function Example() {
const notification = Ariakit.useNotificationContext();
return (
<>
<button
onClick={() => {
notification?.push("Hello");
notification?.push("Hello", { role: "status" });
notification?.push("Hello", { timeout: 10000 });
notification?.push("Hello", { visuallyHidden: true });
}}
>
Push notification
</button>
</>
);
}
export default function App() {
return (
<Ariakit.NotificationProvider>
<Example />
<div>
<Ariakit.NotificationItems>
{(items) => (
items.map((props) => (
<Ariakit.Notification key={props.id} {...props}>
{props.children}
<Ariakit.NotificationDismiss />
</Ariakit.Notification>
))
)}
</Ariakit.NotificationItems>
</div>
</Ariakit.NotificationProvider>
);
}
@diegohaz
Copy link
Author

diegohaz commented Oct 22, 2024

Comment by @alvarlagerlof for future reference:

How does your notification store handle multiple SSR renders on a single server? Does it leak state considering it's module scoped?

https://x.com/alvarlagerlof/status/1848740406365753802

This could become an issue if someone needs to render an initial notification on the server. They might have to instantiate the store within the component, which would prevent them from exporting push, or they might need to mutate the store on the server, potentially affecting other clients (this needs testing).

Edit: Updated the code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment