import * as React from "react"; /** * EmptyState — three-part empty state: visual → headline → explanation → one CTA. * * Variants: * - first-use : encouraging headline + create CTA. * - no-results: echoes the query + a "Clear search" action. * - error : neutral message + retry; announced via role="status". * * SaglitzDesign: exactly one primary action, >=44px CTA, visible focus, * only transform/opacity animate (ease-out enter). */ type BaseProps = { icon?: React.ReactNode; // decorative; wrapped with aria-hidden headline: string; description: string; className?: string; }; function Shell({ icon, headline, description, children, live, className = "", }: BaseProps & { children: React.ReactNode; live?: boolean }) { const headingId = React.useId(); return (
{icon && ( )}

{headline}

{description}

{children}
{/* keyframes; motion-reduce users skip the animation via motion-safe above */}
); } const primaryBtn = "inline-flex min-h-11 items-center justify-center rounded-lg bg-indigo-600 px-5 text-sm font-medium text-white " + "hover:bg-indigo-700 active:bg-indigo-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-600 " + "focus-visible:ring-offset-2 dark:focus-visible:ring-indigo-400 dark:focus-visible:ring-offset-neutral-950 " + "disabled:opacity-60 disabled:cursor-not-allowed"; const secondaryBtn = "inline-flex min-h-11 items-center justify-center rounded-lg px-4 text-sm font-medium text-neutral-700 " + "hover:bg-neutral-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-600 " + "dark:text-neutral-200 dark:hover:bg-neutral-800"; /* --- first-use ------------------------------------------------------------ */ export function EmptyStateFirstUse({ icon, headline = "Create your first project", description = "Projects keep your work organized. Start with one and invite your team later.", ctaLabel = "New project", onCreate, }: Partial & { ctaLabel?: string; onCreate: () => void }) { return ( ); } /* --- no-results ----------------------------------------------------------- */ export function EmptyStateNoResults({ icon, query, onClear, }: Partial & { query: string; onClear: () => void }) { return ( ); } /* --- error ---------------------------------------------------------------- */ export function EmptyStateError({ icon, description = "Something went wrong loading this. Check your connection and try again.", onRetry, loading = false, }: Partial & { onRetry: () => void; loading?: boolean }) { return ( ); } /* -------------------------------------------------------------------------- */ /* Usage */ /* -------------------------------------------------------------------------- */ const FolderIcon = ( ); export function EmptyStateExamples() { return (
{}} /> {}} /> {}} />
); }