From f885ac73d3329fc4fcc8efe8e2de037883118e81 Mon Sep 17 00:00:00 2001 From: Moheeb Zara Date: Fri, 15 May 2026 20:39:04 -0700 Subject: [PATCH] feat(ux): adopt shared Empty primitive across all empty states - one Empty/EmptyHeader/EmptyMedia/EmptyTitle/EmptyDescription component replaces ~18 ad-hoc empty states - projects gains a real empty state (was four bare columns) with a create CTA wired to the existing handler - governance/ops/customize/comms/comments empty states unified; existing CTAs and conditions preserved (presentational only) --- app/(app)/comms/comms-client.tsx | 24 +++- app/(app)/contacts/contacts-client.tsx | 23 ++-- .../customize/panels/area-leads-panel.tsx | 10 +- app/(app)/customize/panels/areas-panel.tsx | 12 +- app/(app)/customize/panels/invites-panel.tsx | 12 +- .../customize/panels/onboarding-panel.tsx | 11 ++ app/(app)/customize/panels/roles-panel.tsx | 10 +- app/(app)/customize/panels/tiers-panel.tsx | 12 +- app/(app)/dashboard/page.tsx | 25 +++- app/(app)/financials/page.tsx | 10 +- app/(app)/incidents/page.tsx | 15 ++- app/(app)/members/members-client.tsx | 13 +- app/(app)/ops/ops-client.tsx | 115 +++++++++++------- app/(app)/payments/payments-client.tsx | 13 +- app/(app)/projects/projects-client.tsx | 19 +++ app/(app)/proposals/page.tsx | 15 ++- app/(app)/recruitment/page.tsx | 17 ++- app/(app)/tasks/tasks-client.tsx | 26 ++-- components/comments/comment-thread.tsx | 8 +- 19 files changed, 297 insertions(+), 93 deletions(-) diff --git a/app/(app)/comms/comms-client.tsx b/app/(app)/comms/comms-client.tsx index 1d8c1da..304bddc 100644 --- a/app/(app)/comms/comms-client.tsx +++ b/app/(app)/comms/comms-client.tsx @@ -8,6 +8,7 @@ import { Hash, Users2, Send, ChevronLeft, Plus } from 'lucide-react' import { createChannel } from '@/lib/actions' import type { Tables } from '@/types/database' import { PageTitle } from '@/components/ui/page-title' +import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription } from '@/components/ui/empty' type Channel = Tables<'comms_channels'> type Message = Tables<'comms_messages'> @@ -269,6 +270,9 @@ export default function CommsClient({ member, space, channels }: Props) { {/* New channel inline form */}
+ {channels.length === 0 && ( +

No channels yet. Create the first one.

+ )} {!showNewChannel ? (
diff --git a/app/(app)/contacts/contacts-client.tsx b/app/(app)/contacts/contacts-client.tsx index 3c67890..64b89dd 100644 --- a/app/(app)/contacts/contacts-client.tsx +++ b/app/(app)/contacts/contacts-client.tsx @@ -1,10 +1,11 @@ 'use client' import { useState } from 'react' -import { Plus, X, Pencil } from 'lucide-react' +import { Plus, X, Pencil, Contact as ContactIcon } from 'lucide-react' import { createContact, updateContact, deleteContact } from '@/lib/actions' import type { Tables } from '@/types/database' import { PageTitle } from '@/components/ui/page-title' +import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyContent } from '@/components/ui/empty' type Contact = Tables<'contacts'> @@ -238,12 +239,20 @@ export function ContactsClient({ contacts: initialContacts }: { contacts: Contac ))} ) : ( -
-

No contacts yet

- -
+ + + + No contacts yet + + + + + )} diff --git a/app/(app)/customize/panels/area-leads-panel.tsx b/app/(app)/customize/panels/area-leads-panel.tsx index 36df6b8..08115e1 100644 --- a/app/(app)/customize/panels/area-leads-panel.tsx +++ b/app/(app)/customize/panels/area-leads-panel.tsx @@ -3,8 +3,10 @@ import { useState } from 'react' import { useRouter } from 'next/navigation' import { toast } from 'sonner' +import { UserCog } from 'lucide-react' import { createAreaLeadRole, assignAreaLead, unassignAreaLead, deleteAreaLeadRole } from '@/lib/actions' import { Card } from './card' +import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyDescription } from '@/components/ui/empty' interface AreaLead { id: string @@ -64,7 +66,13 @@ export function AreaLeadsPanel({ isAdmin, areaLeads: initial, members }: Props) )} {rows.length === 0 ? ( -

No area-lead roles yet.

+ + + + No area-lead roles yet + Create a role per shop area, then assign a member to it. Roles without a member show as Vacant. + + ) : (