Efniv0.1

Components

Toast

Transient, non-blocking feedback. Powered by Sonner; the Toaster is already mounted at the app root — call toast() from anywhere.

When to usefor transient feedback the operator can miss without consequences — "saved", "copied", "undo".

Import

import { toast } from "sonner"

Setup

Mount the Toaster once at the app root. It takes its theme as a prop — the library component is framework-free, so the host reads the theme and passes it in.

// app/toaster.tsx — your side of the boundary
"use client";

import { useTheme } from "next-themes";
import type { ToasterProps } from "sonner";
import { Toaster as EfniToaster } from "@ravnhq/efni/sonner";

export function Toaster(props: ToasterProps) {
  const { theme = "system" } = useTheme();
  return <EfniToaster theme={theme as ToasterProps["theme"]} {...props} />;
}

// app/layout.tsx
<Toaster />

Variants

import { toast } from "sonner";

toast("Mission MB-4472 saved.");
toast.success("Waypoint reached.", { description: "…" });
toast.error("Mission aborted.", { description: "…" });

With action

toast("Draft saved.", {
  action: { label: "Undo", onClick: () => toast.success("Reverted.") },
});

Do & don't

Confirm actions the operator can safely miss — save, copy, dispatch — with a quick toast.

Don't put a decision or destructive confirmation in a toast — use Alert dialog for anything that can't be reversed.

Accessibility

  • Sonner posts to a polite live region so screen readers announce the content without stealing focus.
  • Alt+T (Sonner default) focuses the toast region for keyboard users.
  • Keep the message short — assistive tech will read it as one utterance.

Guidelines

Do
  • Lead with what happened (Saved), then optionally include when/who in the description.
  • Provide Undo for reversible actions — it removes the need for a confirm dialog.
  • Match tone to outcome — success for saves, error for failures. Info sparingly.
Don't
  • Don't fire more than one toast per operator action.
  • Don't use toast for validation errors on a form — surface them inline via FormMessage.
  • Don't stack toasts to hint at progress — use Progress instead.

Props

PropTypeDefaultDescription
…propsToasterProps—Everything Toaster passes to the element it renders.
toast(message, options?)(string | ReactNode, options?) => id—Fire a default toast. Returns an id for later dismiss/update.
toast.success / .info / .warning / .errorsame signature—Tone-specific helpers, each with a matching icon.
options.descriptionstring | ReactNode—Secondary line shown under the message.
options.action{ label, onClick }—Inline action button (e.g. Undo).
<Toaster theme>"light" | "dark" | "system""system"Theme for the mounted Toaster. Passed in by the host app — the library component reads no theme hook of its own.
options.durationnumber4000Auto-dismiss delay, milliseconds. Use Infinity to keep it until clicked.