Snackbar
A short message at the bottom of the screen with one optional action.
Preview
Message archived
import { Snackbar, SnackbarAction } from "@/components/ui/Snackbar";
export function SnackbarDemo() {
return (
<Snackbar position="inline" action={<SnackbarAction>Undo</SnackbarAction>}>
Message archived
</Snackbar>
);
}Installation
Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces
pnpm dlx shadcn@latest add @aura/snackbarManual
Install the following dependencies:
pnpm install @radix-ui/react-iconsCopy and paste the class names utility into your utils/class-names.ts file.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the Snackbar component into your components/ui/Snackbar.tsx file.
"use client";
import * as React from "react";
import { Cross2Icon } from "@radix-ui/react-icons";
import { cn } from "@/utils/class-names";
type SnackbarProps = React.ComponentProps<"div"> & {
open?: boolean;
onOpenChange?: (open: boolean) => void;
action?: React.ReactNode;
position?: "fixed" | "inline";
};
function Snackbar({
className,
open = true,
onOpenChange,
action,
position = "fixed",
children,
...props
}: SnackbarProps) {
if (!open) return null;
return (
<div
role="status"
data-slot="snackbar"
className={cn(
"z-50 flex max-w-full items-center gap-1 rounded-sm bg-gray-12 px-1.5 py-1 text-gray-1 shadow-md",
position === "fixed"
? "fixed inset-x-2 bottom-2 mx-auto w-fit"
: "relative w-fit",
className,
)}
{...props}
>
<p className="m-0">{children}</p>
{action}
{onOpenChange ? (
<button
type="button"
aria-label="Dismiss"
className="inline-flex size-2 items-center justify-center rounded-sm text-gray-1 hover:bg-gray-a3 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-8"
onClick={() => onOpenChange(false)}
>
<Cross2Icon className="icon" />
</button>
) : null}
</div>
);
}
function SnackbarAction({
className,
...props
}: React.ComponentProps<"button">) {
return (
<button
type="button"
data-slot="snackbar-action"
className={cn(
"font-medium text-accent-9 hover:text-accent-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-8",
className,
)}
{...props}
/>
);
}
export { Snackbar, SnackbarAction };