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
Standard profile page with cover image, avatar, stats, tabs, and action buttons.
View the full component source code below.
"use client"
import { useNyuchiHarness } from "@/lib/harness"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { useNyuchiHarness } from "@/lib/harness"
import { Badge } from "@/components/ui/badge"
import { useNyuchiHarness } from "@/lib/harness"
import { Button } from "@/components/ui/button"
import { useNyuchiHarness } from "@/lib/harness"
import { Card, CardContent } from "@/components/ui/card"
import { useNyuchiHarness } from "@/lib/harness"
import { Separator } from "@/components/ui/separator"
import { useNyuchiHarness } from "@/lib/harness"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { useNyuchiHarness } from "@/lib/harness"
import { MapPin, Share2, MessageCircle, UserPlus, Calendar } from "@/lib/icons"
const stats = [
{ label: "Followers", value: "2,847", color: "text-cobalt" },
{ label: "Following", value: "382", color: "text-tanzanite" },
{ label: "Posts", value: "1,204", color: "text-malachite" },
]
const posts = [
{ title: "Exploring Matobo Hills this weekend", date: "2d ago", likes: 48, category: "Travel" },
{
title: "Best maize varieties for this season",
date: "5d ago",
likes: 132,
category: "Farming",
},
{ title: "Recap: Harare marathon experience", date: "1w ago", likes: 96, category: "Sports" },
]
function ProfilePage() {
const { log, motion, LiveRegion } = useNyuchiHarness("profile-page")
const animStyle = React.useMemo(() => motion.prefersReduced ? {} : { animation: `nyuchi-fade-slide-up ${motion.enterDuration}ms ${motion.enterEasing} both` }, [motion])
if (loading) return (<div data-slot="profile-page" data-portal="https://design.nyuchi.com/components/profile-page" data-loading role="main" className="animate-pulse min-h-screen bg-background"><div className="h-48 bg-muted" /><div className="mx-auto max-w-3xl px-4 -mt-12 space-y-4"><div className="flex items-end gap-4"><div className="size-24 rounded-full border-4 border-background bg-muted" /><div className="space-y-2 pb-2"><div className="h-5 w-32 rounded bg-muted" /><div className="h-3 w-20 rounded bg-muted" /></div></div><div className="flex gap-6">{Array.from({length:3}).map((_,i)=>(<div key={i} className="text-center space-y-1"><div className="h-4 w-8 mx-auto rounded bg-muted" /><div className="h-2.5 w-12 rounded bg-muted" /></div>))}</div><div className="h-12 rounded-full bg-muted" /><div className="space-y-3">{Array.from({length:4}).map((_,i)=>(<div key={i} className="h-20 rounded-[var(--radius-lg,14px)] bg-muted" />))}</div></div></div>)
if (loading) return (<div data-slot="profile-page" data-loading role="main" className="animate-pulse min-h-screen bg-background"><div className="h-48 bg-muted" /><div className="px-4 -mt-12"><div className="size-20 rounded-full bg-card border-4 border-background" /><div className="mt-3 space-y-2"><div className="h-5 w-1/3 rounded bg-muted" /><div className="h-3 w-1/4 rounded bg-muted" /></div><div className="flex gap-6 mt-4">{Array.from({length:3}).map((_,i)=>(<div key={i} className="space-y-1"><div className="h-4 w-8 rounded bg-muted" /><div className="h-2.5 w-12 rounded bg-muted" /></div>))}</div></div></div>)
return (
<div data-slot="profile-page" role="main" className="min-h-screen bg-background">
<div className="mx-auto max-w-3xl">
{/* Cover image area */}
<div className="relative h-48 rounded-b-2xl bg-muted sm:h-56">
{/* Mineral accent stripe on left edge */}
<div className="absolute top-0 left-0 flex h-full w-1 flex-col overflow-hidden rounded-bl-2xl">
<div className="flex-1 bg-cobalt" />
<div className="flex-1 bg-tanzanite" />
<div className="flex-1 bg-malachite" />
<div className="flex-1 bg-gold" />
<div className="flex-1 bg-terracotta" />
</div>
</div>
{/* Profile header */}
<div className="relative px-4 sm:px-6">
<div className="-mt-12 flex flex-col sm:-mt-16 sm:flex-row sm:items-end sm:gap-5">
<Avatar className="size-24 ring-4 ring-background sm:size-24">
<AvatarImage src="/avatars/01.png" alt="Tendai Moyo" />
<AvatarFallback className="text-xl">TM</AvatarFallback>
</Avatar>
<div className="mt-3 flex flex-1 flex-col gap-3 sm:mt-0 sm:flex-row sm:items-center sm:justify-between">
<div>
<h1 className="font-serif text-2xl font-semibold text-foreground">Tendai Moyo</h1>
<p className="text-sm text-muted-foreground">@tendai_m</p>
</div>
<div className="flex gap-2">
<Button size="sm">
<UserPlus className="size-4" />
Follow
</Button>
<Button variant="outline" size="sm">
<MessageCircle className="size-4" />
Message
</Button>
<Button variant="ghost" size="icon-sm">
<Share2 className="size-4" />
</Button>
</div>
</div>
</div>
{/* Bio */}
<p className="mt-4 text-sm text-foreground">
Building the future of African tech, one line at a time. Community advocate and
open-source enthusiast based in Harare.
</p>
<div className="mt-2 flex flex-wrap items-center gap-3 text-sm text-muted-foreground">
<span className="flex items-center gap-1">
<MapPin className="size-3.5" />
Harare, Zimbabwe
</span>
<span className="flex items-center gap-1">
<Calendar className="size-3.5" />
Joined March 2024
</span>
</div>
{/* Stats */}
<div className="mt-4 flex gap-6">
{stats.map((stat) => (
<div key={stat.label} className="text-center">
<p className={`text-lg font-semibold ${stat.color}`}>{stat.value}</p>
<p className="text-xs text-muted-foreground">{stat.label}</p>
</div>
))}
</div>
<Separator className="mt-4" />
</div>
{/* Tabs */}
<div className="px-4 pt-2 sm:px-6">
<Tabs defaultValue="posts">
<TabsList>
<TabsTrigger value="posts">Posts</TabsTrigger>
<TabsTrigger value="about">About</TabsTrigger>
<TabsTrigger value="activity">Activity</TabsTrigger>
</TabsList>
<TabsContent value="posts" className="mt-4 space-y-3">
{posts.map((post) => (
<Card key={post.title} size="sm">
<CardContent className="flex items-start justify-between gap-4">
<div className="space-y-1">
<p className="text-sm font-medium text-foreground">{post.title}</p>
<div className="flex items-center gap-2">
<Badge variant="secondary">{post.category}</Badge>
<span className="text-xs text-muted-foreground">{post.date}</span>
</div>
</div>
<span className="text-xs text-muted-foreground">{post.likes} likes</span>
</CardContent>
</Card>
))}
</TabsContent>
<TabsContent value="about" className="mt-4">
<Card size="sm">
<CardContent className="space-y-3 text-sm text-muted-foreground">
<p>
Software engineer passionate about building technology that serves African
communities. Contributor to mukoko and several open-source projects.
</p>
<Separator />
<div className="flex flex-wrap gap-2">
<Badge variant="outline">TypeScript</Badge>
<Badge variant="outline">React</Badge>
<Badge variant="outline">Flutter</Badge>
<Badge variant="outline">Open Source</Badge>
</div>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="activity" className="mt-4">
<Card size="sm">
<CardContent className="text-sm text-muted-foreground">
<p>Recent activity will appear here.</p>
</CardContent>
</Card>
</TabsContent>
</Tabs>
</div>
</div>
</div>
)
}
export { ProfilePage }
npx shadcn@latest add https://mzizi.dev/api/v1/ui/nyuchi-profile-pageFetch this component's metadata and source code from the registry API.
/api/v1/ui/nyuchi-profile-pagecomponents/blocks/profile-page.tsx