style(social): elevate Profile + GroupDetailView to SaaS Premium

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
senke 2026-02-07 14:15:35 +01:00
parent 98eab26fa6
commit a51f67a843
8 changed files with 34 additions and 34 deletions

View file

@ -9,7 +9,7 @@ const meta: Meta<typeof GroupDetailView> = {
tags: ['autodocs'],
decorators: [
(Story) => (
<div className="bg-kodo-background min-h-layout-page-sm p-4">
<div className="bg-background min-h-layout-page-sm p-4">
<Story />
</div>
),

View file

@ -24,14 +24,14 @@ export const GroupDetailView: React.FC<GroupDetailViewProps> = ({
if (loading) {
return (
<div className="flex justify-center py-24 min-h-layout-page-sm">
<Loader2 className="w-10 h-10 text-kodo-steel animate-spin" />
<Loader2 className="w-10 h-10 text-muted-foreground animate-spin" />
</div>
);
}
if (!group) {
return (
<div className="text-center py-24 text-kodo-content-dim min-h-layout-page-sm">
<div className="text-center py-24 text-muted-foreground min-h-layout-page-sm">
Group not found
</div>
);

View file

@ -20,15 +20,15 @@ export function GroupDetailViewEvents({ events }: GroupDetailViewEventsProps) {
variant="default"
className="flex items-center gap-6"
>
<div className="text-center p-4 bg-kodo-slate rounded-lg min-w-20">
<div className="text-xs text-kodo-steel uppercase font-bold">
<div className="text-center p-4 bg-muted rounded-xl min-w-20">
<div className="text-xs text-muted-foreground uppercase font-bold">
{month}
</div>
<div className="text-2xl font-bold text-white">{day}</div>
<div className="text-2xl font-bold text-foreground">{day}</div>
</div>
<div className="flex-1">
<h3 className="text-lg font-bold text-white">{event.title}</h3>
<div className="flex items-center gap-2 text-kodo-content-dim text-sm mt-1">
<h3 className="text-lg font-bold text-foreground tracking-tight">{event.title}</h3>
<div className="flex items-center gap-2 text-muted-foreground text-sm mt-1">
<Users className="w-4 h-4" /> {event.attendees} Attending
</div>
</div>

View file

@ -22,8 +22,8 @@ export function GroupDetailViewHeader({
onLeave,
}: GroupDetailViewHeaderProps) {
return (
<div className="relative rounded-2xl overflow-hidden bg-kodo-graphite border border-kodo-steel">
<div className="h-64 bg-kodo-ink relative">
<div className="relative rounded-2xl overflow-hidden bg-muted border border-border">
<div className="h-64 bg-card relative">
<img
src={group.coverUrl}
alt=""
@ -52,7 +52,7 @@ export function GroupDetailViewHeader({
<Button
variant="ghost"
size="sm"
className="bg-black/50 backdrop-blur text-kodo-red hover:bg-kodo-red/20 border-none"
className="bg-black/50 backdrop-blur text-destructive hover:bg-destructive/20 border-none"
onClick={onLeave}
>
<LogOut className="w-4 h-4 mr-2" /> Leave
@ -69,11 +69,11 @@ export function GroupDetailViewHeader({
<div className="flex flex-col md:flex-row justify-between items-start gap-4">
<div>
<div className="flex items-center gap-4 mb-2">
<h1 className="text-3xl font-display font-bold text-white">
<h1 className="text-3xl font-display font-bold text-foreground tracking-tight">
{group.name}
</h1>
<span
className={`px-2 py-0.5 rounded text-xs font-bold uppercase border flex items-center gap-1 ${group.isPrivate ? 'border-kodo-gold text-kodo-gold' : 'border-kodo-cyan text-kodo-cyan'}`}
className={`px-2 py-0.5 rounded text-xs font-bold uppercase border flex items-center gap-1 ${group.isPrivate ? 'border-warning text-warning' : 'border-primary text-primary'}`}
>
{group.isPrivate ? (
<Lock className="w-3 h-3" />
@ -83,26 +83,26 @@ export function GroupDetailViewHeader({
{group.isPrivate ? 'Private' : 'Public'}
</span>
</div>
<p className="text-kodo-content-dim max-w-2xl leading-relaxed">
<p className="text-muted-foreground max-w-2xl leading-relaxed">
{group.description}
</p>
</div>
<div className="flex gap-6 text-sm text-kodo-content-dim font-mono bg-kodo-ink/50 p-4 rounded-xl border border-kodo-steel/30">
<div className="flex gap-6 text-sm text-muted-foreground font-mono bg-card/50 p-4 rounded-xl border border-border">
<div className="text-center">
<div className="font-bold text-white text-lg">
<div className="font-bold text-foreground text-lg">
{group.members.toLocaleString()}
</div>
<div className="text-xs uppercase">Members</div>
</div>
<div className="w-px bg-kodo-steel/50" />
<div className="w-px bg-border" />
<div className="text-center">
<div className="font-bold text-white text-lg">124</div>
<div className="font-bold text-foreground text-lg">124</div>
<div className="text-xs uppercase">Posts</div>
</div>
<div className="w-px bg-kodo-steel/50" />
<div className="w-px bg-border" />
<div className="text-center">
<div className="font-bold text-white text-lg">
<div className="font-bold text-foreground text-lg">
{group.events.length}
</div>
<div className="text-xs uppercase">Events</div>
@ -111,13 +111,13 @@ export function GroupDetailViewHeader({
</div>
</div>
<div className="px-6 md:px-8 border-t border-kodo-steel/50 flex gap-6 overflow-x-auto">
<div className="px-6 md:px-8 border-t border-border flex gap-6 overflow-x-auto">
{TABS.map((tab) => (
<button
key={tab}
type="button"
onClick={() => onTabChange(tab)}
className={`py-4 text-sm font-bold uppercase tracking-wider border-b-2 transition-colors ${activeTab === tab ? 'text-white border-kodo-cyan' : 'text-kodo-content-dim border-transparent hover:text-kodo-text-main'}`}
className={`py-4 text-sm font-bold uppercase tracking-wider border-b-2 transition-colors duration-[var(--duration-normal)] ${activeTab === tab ? 'text-foreground border-primary' : 'text-muted-foreground border-transparent hover:text-foreground'}`}
>
{tab}
</button>

View file

@ -15,7 +15,7 @@ export function GroupDetailViewMembers({
{membersList.map((member) => (
<div
key={member.id}
className="flex items-center gap-4 p-4 bg-kodo-ink rounded-lg border border-kodo-steel hover:border-kodo-steel/50 transition-colors"
className="flex items-center gap-4 p-4 bg-card rounded-xl border border-border hover:border-border transition-colors duration-[var(--duration-normal)]"
>
<img
src={member.avatar}
@ -23,9 +23,9 @@ export function GroupDetailViewMembers({
className="w-12 h-12 rounded-full"
/>
<div className="flex-1">
<div className="font-bold text-white">{member.username}</div>
<div className="font-bold text-foreground">{member.username}</div>
{member.role && (
<span className="text-xs bg-kodo-slate px-1.5 py-0.5 rounded text-kodo-content-dim">
<span className="text-xs bg-muted px-1.5 py-0.5 rounded text-muted-foreground">
{member.role}
</span>
)}
@ -35,7 +35,7 @@ export function GroupDetailViewMembers({
</Button>
</div>
))}
<div className="col-span-full text-center py-8 text-kodo-content-dim text-sm">
<div className="col-span-full text-center py-8 text-muted-foreground text-sm">
+ {Math.max(0, totalMembers - membersList.length)} others
</div>
</div>

View file

@ -14,10 +14,10 @@ export function GroupDetailViewSidebar({
return (
<div className="lg:col-span-4 space-y-6">
<Card variant="default">
<h3 className="font-bold text-white mb-4 uppercase text-xs tracking-wider">
<h3 className="font-bold text-foreground mb-4 uppercase text-xs tracking-wider">
About
</h3>
<p className="text-sm text-kodo-content-dim mb-4">
<p className="text-sm text-muted-foreground mb-4">
Created Aug 2022
<br />
Located in Tokyo, JP
@ -26,7 +26,7 @@ export function GroupDetailViewSidebar({
{['Synthesizers', 'Hardware', 'Eurorack', 'Music'].map((tag) => (
<span
key={tag}
className="px-2 py-1 bg-kodo-ink border border-kodo-steel rounded text-xs text-kodo-content-dim"
className="px-2 py-1 bg-card border border-border rounded-xl text-xs text-muted-foreground"
>
#{tag}
</span>
@ -35,7 +35,7 @@ export function GroupDetailViewSidebar({
</Card>
<Card variant="glass">
<h3 className="font-bold text-white mb-4 uppercase text-xs tracking-wider">
<h3 className="font-bold text-foreground mb-4 uppercase text-xs tracking-wider">
Group Admins
</h3>
<div className="flex -space-x-2 overflow-hidden mb-4">
@ -44,7 +44,7 @@ export function GroupDetailViewSidebar({
key={m.id}
src={m.avatar}
alt=""
className="inline-block h-8 w-8 rounded-full ring-2 ring-kodo-graphite"
className="inline-block h-8 w-8 rounded-full ring-2 ring-border"
title={m.username}
/>
))}

View file

@ -3,7 +3,7 @@ import { Skeleton } from '@/components/ui/skeleton';
export function GroupDetailViewSkeleton() {
return (
<div className="space-y-6 pb-20">
<div className="rounded-2xl overflow-hidden bg-kodo-graphite border border-kodo-steel">
<div className="rounded-2xl overflow-hidden bg-muted border border-border">
<Skeleton className="h-64 w-full rounded-none" />
<div className="p-6 md:p-8">
<div className="flex flex-col md:flex-row justify-between gap-4">
@ -18,7 +18,7 @@ export function GroupDetailViewSkeleton() {
</div>
</div>
</div>
<div className="px-6 md:px-8 border-t border-kodo-steel/50 flex gap-6 py-4">
<div className="px-6 md:px-8 border-t border-border flex gap-6 py-4">
<Skeleton className="h-4 w-16" />
<Skeleton className="h-4 w-20" />
<Skeleton className="h-4 w-16" />

View file

@ -12,7 +12,7 @@ const meta: Meta<typeof UserProfilePage> = {
(Story, context) => {
const initialEntries = context.parameters.initialEntries ?? ['/u/demo'];
return (
<div className="bg-kodo-background min-h-screen">
<div className="bg-background min-h-screen">
<MemoryRouter initialEntries={initialEntries}>
<Routes>
<Route path="/u/:username" element={<Story />} />