block · 93/108
Profile Page
Identity, account actions, contact details, and recent activity in a sidebar or stacked layout.
Install
Install manuallyView source on GitHub
Composes
- profile-page.tsx11
- activity-timeline.tsx9
- author-card.tsx4
- description-list.tsx4
Accessibility4 checks
- The identity card is an article named by the person's name. The avatar is decorative; initials replace a missing photo.
- Account actions are a labelled group of native buttons. Destructive actions use danger text, not color alone, with a clear verb.
- Contact details are a description list, so each value is read with its term.
- Activity groups are sections named by their dates. Each event uses a time element with a machine-readable dateTime.
Application surfaces
Amara Okafor
Operations lead · Lagos
Runs fulfilment for the West Africa warehouses and owns the returns policy.
Contact details
- amara@northwind.example
- Phone
- +234 803 555 0142
- Time zone
- West Africa Time (UTC+1)
- Member since
- March 2023
Recent activity
Today
September 28
Code example
usage.tsx"use client";import { FileText, MessageSquare, UserPlus } from "lucide-react";import { useState } from "react";import { ProfilePage, ProfilePageAction, ProfilePageActions, ProfilePageActivity, ProfilePageAside, ProfilePageDetails, ProfilePageIdentity, ProfilePageMain, ProfilePageSection, ProfilePageSectionHeader, ProfilePageSectionTitle, type ProfilePageVariant,} from "@/components/uai/profile-page";import { ActivityTimelineActor, ActivityTimelineContent, ActivityTimelineDate, ActivityTimelineEvent, ActivityTimelineEvents, ActivityTimelineGroup, ActivityTimelineMarker, ActivityTimelineTime, ActivityTimelineTitle,} from "@/components/ui/uai/activity-timeline";import { AuthorCardAvatar, AuthorCardBio, AuthorCardName, AuthorCardRole,} from "@/components/ui/uai/author-card";import { DescriptionListAction, DescriptionListDetails, DescriptionListItem, DescriptionListTerm,} from "@/components/ui/uai/description-list";export function ProfilePagePreview({ variant = "sidebar" }: { variant?: ProfilePageVariant }) { const [copied, setCopied] = useState(false); return ( <ProfilePage variant={variant}> <ProfilePageAside> <ProfilePageIdentity> <AuthorCardAvatar name="Amara Okafor" /> <div style={{ display: "grid", gap: 2 }}> <AuthorCardName>Amara Okafor</AuthorCardName> <AuthorCardRole>Operations lead · Lagos</AuthorCardRole> </div> <AuthorCardBio> Runs fulfilment for the West Africa warehouses and owns the returns policy. </AuthorCardBio> </ProfilePageIdentity> <ProfilePageActions> <ProfilePageAction emphasis="primary">Edit profile</ProfilePageAction> <ProfilePageAction>Send message</ProfilePageAction> <ProfilePageAction tone="danger">Deactivate</ProfilePageAction> </ProfilePageActions> </ProfilePageAside> <ProfilePageMain> <ProfilePageSection> <ProfilePageSectionHeader> <ProfilePageSectionTitle>Contact details</ProfilePageSectionTitle> </ProfilePageSectionHeader> <ProfilePageDetails> <DescriptionListItem> <DescriptionListTerm>Email</DescriptionListTerm> <DescriptionListDetails> amara@northwind.example <DescriptionListAction aria-label="Copy email address" onClick={() => { void navigator.clipboard?.writeText("amara@northwind.example"); setCopied(true); }} > {copied ? "Copied" : "Copy"} </DescriptionListAction> </DescriptionListDetails> </DescriptionListItem> <DescriptionListItem> <DescriptionListTerm>Phone</DescriptionListTerm> <DescriptionListDetails>+234 803 555 0142</DescriptionListDetails> </DescriptionListItem> <DescriptionListItem> <DescriptionListTerm>Time zone</DescriptionListTerm> <DescriptionListDetails>West Africa Time (UTC+1)</DescriptionListDetails> </DescriptionListItem> <DescriptionListItem> <DescriptionListTerm>Member since</DescriptionListTerm> <DescriptionListDetails>March 2023</DescriptionListDetails> </DescriptionListItem> </ProfilePageDetails> </ProfilePageSection> <ProfilePageSection> <ProfilePageSectionHeader> <ProfilePageSectionTitle>Recent activity</ProfilePageSectionTitle> </ProfilePageSectionHeader> <ProfilePageActivity> <ActivityTimelineGroup> <ActivityTimelineDate>Today</ActivityTimelineDate> <ActivityTimelineEvents> <ActivityTimelineEvent> <ActivityTimelineMarker> <FileText size={14} /> </ActivityTimelineMarker> <ActivityTimelineContent> <ActivityTimelineTitle> <ActivityTimelineActor>Amara</ActivityTimelineActor> updated the returns policy </ActivityTimelineTitle> <ActivityTimelineTime dateTime="2026-09-30T09:12">09:12</ActivityTimelineTime> </ActivityTimelineContent> </ActivityTimelineEvent> <ActivityTimelineEvent> <ActivityTimelineMarker> <MessageSquare size={14} /> </ActivityTimelineMarker> <ActivityTimelineContent> <ActivityTimelineTitle> <ActivityTimelineActor>Amara</ActivityTimelineActor> replied on order #4817 </ActivityTimelineTitle> <ActivityTimelineTime dateTime="2026-09-30T08:40">08:40</ActivityTimelineTime> </ActivityTimelineContent> </ActivityTimelineEvent> </ActivityTimelineEvents> </ActivityTimelineGroup> <ActivityTimelineGroup> <ActivityTimelineDate>September 28</ActivityTimelineDate> <ActivityTimelineEvents> <ActivityTimelineEvent> <ActivityTimelineMarker> <UserPlus size={14} /> </ActivityTimelineMarker> <ActivityTimelineContent> <ActivityTimelineTitle> <ActivityTimelineActor>Amara</ActivityTimelineActor> invited Tomás Rivera to Fulfilment </ActivityTimelineTitle> <ActivityTimelineTime dateTime="2026-09-28T16:05">16:05</ActivityTimelineTime> </ActivityTimelineContent> </ActivityTimelineEvent> </ActivityTimelineEvents> </ActivityTimelineGroup> </ProfilePageActivity> </ProfilePageSection> </ProfilePageMain> </ProfilePage> );}Manual installation
profile-page.tsxLoading component source…