nyuchimzizi
Mzizi — an open-architecture project of the Bundu Foundation, operated and developed by Nyuchi. Built on the Five African Minerals palette.
Built by Nyuchi Africav4.0.39
Universal branded empty state with dynamic mineral accent, contextual illustration placeholder, title, description, and optional action CTA. Every screen across the ecosystem uses this when there is no content to display — "No events yet", "Your wallet is empty", "No messages", "Start your first lesson". The empty state guides users toward the creation action for that domain.
View the full component source code below.
"use client"
import * as React from "react"
import { cn } from "@/lib/utils"
import { useNyuchiHarness } from "@/lib/harness"
/* ═══════════════════════════════════════════════════════════════
NYUCHI EMPTY STATE — Universal Brand Component (Pre-Wired)
The branded empty state for the entire ecosystem. Every app,
every feed, every list uses this when content is absent.
Dynamic mineral accent via --brand-accent.
✅ HARNESS ✅ TOKENS ✅ STRICT MINERAL RULES ✅ TOUCH 48px+
npx shadcn@latest add https://design.nyuchi.com/api/v1/ui/nyuchi-empty-state
═══════════════════════════════════════════════════════════════ */
interface NyuchiEmptyStateProps {
/** Illustration or emoji shown above the title */
icon?: React.ReactNode
/** Primary message — what is empty */
title: string
/** Supporting explanation — what the user can do */
description?: string
/** Primary CTA label */
actionLabel?: string
/** Primary CTA handler */
onAction?: () => void
/** Secondary action label */
secondaryLabel?: string
/** Secondary action handler */
onSecondary?: () => void
/** Compact mode for inline empty states within cards */
compact?: boolean
className?: string
}
export function NyuchiEmptyState({
icon,
title,
description,
actionLabel,
onAction,
secondaryLabel,
onSecondary,
compact = false,
className,
}: NyuchiEmptyStateProps) {
const { log, motion, LiveRegion } = useNyuchiHarness("empty-state")
const animStyle = React.useMemo(() => motion.prefersReduced ? {} : { animation: `nyuchi-fade-slide-up ${motion.enterDuration}ms ${motion.enterEasing} both` }, [motion])
return (
<div
data-slot="nyuchi-empty-state" data-portal="https://design.nyuchi.com/components/nyuchi-empty-state" role="status"
className={cn(
"flex flex-col items-center justify-center text-center",
compact ? "py-8 px-4" : "py-16 px-6",
className
)}
>
{icon && (
<div className={cn(
"flex items-center justify-center rounded-full bg-[var(--brand-accent,var(--color-malachite,#64FFDA))]/10",
compact ? "size-12 text-xl mb-3" : "size-16 text-2xl mb-4"
)}>
{icon}
</div>
)}
<h3
className={cn(
"font-semibold text-foreground",
compact ? "text-sm" : "text-base"
)}
style={{ fontFamily: "var(--font-serif)" }}
>
{title}
</h3>
{description && (
<p className={cn(
"text-muted-foreground leading-relaxed max-w-[280px]",
compact ? "text-xs mt-1" : "text-sm mt-2"
)}>
{description}
</p>
)}
{(onAction || onSecondary) && (
<div className={cn("flex items-center gap-2", compact ? "mt-4" : "mt-6")}>
{onAction && actionLabel && (
<button
onClick={onAction}
className="h-12 rounded-full bg-[var(--brand-accent,var(--color-malachite,#64FFDA))] text-[#0A0A0A] px-6 text-[13px] font-medium transition-opacity focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary,#00B0FF)] hover:opacity-80"
>
{actionLabel}
</button>
)}
{onSecondary && secondaryLabel && (
<button
onClick={onSecondary}
className="h-12 rounded-full bg-muted text-foreground border border-border px-6 text-[13px] font-medium transition-opacity focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-primary,#00B0FF)] hover:opacity-80"
>
{secondaryLabel}
</button>
)}
</div>
)}
</div>
)
}
npx shadcn@latest add https://mzizi.dev/api/v1/ui/nyuchi-empty-stateFetch this component's metadata and source code from the registry API.
/api/v1/ui/nyuchi-empty-state