VisorVisor
ComponentsFeedback

Success Feedback

App-wide success/transition feedback pattern. useSuccessToast() fires an auto-dismissing success toast; SuccessLiveRegion provides an explicit a11y live region for screen readers.

Pattern vs Primitive: SuccessFeedback is the Borealis-recommended pattern for app-wide success confirmation — it wraps the Toast primitive with spec-mandated defaults (4s auto-dismiss, undo action support, a11y live region). Use Toast directly when you need full control.

Setup

Add <Toaster /> and <SuccessLiveRegion /> once in your root layout.

// app/layout.tsx
import { Toaster } from '@/components/ui/toast/toast';
import { SuccessLiveRegion } from '@/components/ui/success-feedback/success-feedback';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Toaster />
        <SuccessLiveRegion message="" />
      </body>
    </html>
  );
}

Basic Usage

Call showSuccess(title, options?) after any successful operation. The toast auto-dismisses after 4 seconds.

With Undo Action

Provide an action to give users a recovery path. The Borealis spec recommends Undo for destructive operations and View for created/exported items.

Common success scenarios in a Borealis-native app:

Installation

npx visor add success-feedback

This copies two files into your project:

  • components/ui/success-feedback/success-feedback.tsx — the hook + live region
  • components/ui/success-feedback/success-feedback.module.css — the styles

The pattern depends on the Toast primitive — install that first:

npx visor add toast

Usage

import { useSuccessToast, SuccessLiveRegion } from '@/components/ui/success-feedback/success-feedback';

// In your component
const { showSuccess } = useSuccessToast();

// Basic
showSuccess('Changes saved');

// With description
showSuccess('File uploaded', {
  description: 'report-q4-2025.pdf was saved to your documents.',
});

// With action
showSuccess('Message sent', {
  action: { label: 'Undo', onClick: handleUndo },
});

// Custom duration (clamped to 3000–8000ms)
showSuccess('Settings saved', { duration: 6000 });

API Reference

useSuccessToast()

Returns { showSuccess }.

showSuccess(title: string, options?: SuccessToastOptions): void

SuccessToastOptions

PropTypeDefaultDescription
descriptionstringOptional supporting sub-copy beneath the title
action{ label: string; onClick: () => void }Optional action affordance (e.g. "Undo", "View")
durationnumber4000Auto-dismiss in ms. Clamped to [3000, 8000] per Borealis spec
idstring | numberExplicit id for deduplication (Sonner merges same-id toasts)

SuccessLiveRegion

No props data available for “success-feedback”.

PropTypeDefaultDescription
messagestring""The success text to announce to screen readers

SuccessLiveRegion also accepts all standard <div> HTML attributes.

Accessibility

  • SuccessLiveRegion renders role="status" + aria-live="polite" + aria-atomic="true" so screen readers announce the message without interrupting the user.
  • The Toaster (Sonner) also provides its own aria-live="polite" container — both reinforce the announcement.
  • Toasts auto-dismiss after 4 seconds. Ensure any critical confirmation is also conveyed inline if the user might miss the toast.
  • Sonner respects prefers-reduced-motion: animations are suppressed when the OS setting is active.
  • The dismiss button in each toast is keyboard-accessible; focus does not jump when a toast appears.

Composition Rules (Borealis Spec)

Per the Borealis global state catalog:

  • Triggers: CRUD operations, file upload/export, settings saved, invite sent, link copied
  • Never for errors: Use inline validation (VI-587) or an error Banner for failures
  • Auto-dismiss: Default 4s; configurable 3–8s. Timer pauses on hover/keyboard focus (Sonner built-in)
  • Stacking: Max 3 visible toasts (Sonner default). Oldest is dismissed when the queue exceeds 3
  • Deduplication: Pass id to deduplicate identical messages within a 500ms window