# Hackerspace.sh - Component Reference > **Last Updated**: 2026-03-10 > Complete reference for all React components, their props, and usage patterns. --- ## Table of Contents 1. [App Shell Components](#1-app-shell-components) 2. [Page Components](#2-page-components) 3. [Client Components](#3-client-components) 4. [UI Components](#4-ui-components) 5. [Component Patterns](#5-component-patterns) --- ## 1. App Shell Components ### `AppSidebar` **File**: `components/app-sidebar.tsx` **Purpose**: Main navigation sidebar for the app. **Props**: ```typescript interface AppSidebarProps { member: SpaceMember & { spaces: Space } taskBadge?: number // Count for tasks badge commsBadge?: number // Count for unread messages paymentBadge?: number // Count for unlinked payments } ``` **Usage**: ```tsx ``` **Features**: - Renders navigation grouped by section (Workspace, People, Admin) - Shows badges for tasks and payments - Displays user info with sign out - Highlights active route - Admin section only visible to admin/board roles **Navigation Structure**: ``` WORKSPACE ├── Dashboard /dashboard ├── Tasks & Chores /tasks ├── Projects /projects ├── Ops & Facilities /ops └── Comms /comms PEOPLE ├── Members /members ├── Payments /payments └── Contacts /contacts ADMIN (admin/board only) ├── Import / Sync /import └── Settings /settings ``` --- ### `AppShell` **File**: `components/app-shell.tsx` **Purpose**: Wrapper component for app layout (currently unused). **Status**: Available but not integrated into layout. --- ## 2. Page Components ### Page Structure Pattern All feature pages follow a consistent Server Component + Client Component pattern: ``` feature/ ├── page.tsx # Server Component (data fetching) └── feature-client.tsx # Client Component (UI + interactions) ``` ### Dashboard Page **File**: `app/(app)/dashboard/page.tsx` **Type**: Server Component **Data Fetched**: - Member stats (active members count) - Task stats (open tasks count) - Payment stats (unlinked payments count) - Recent tasks (top 5) - Active projects (in_progress, blocked, review) - Recent activity (last 6 items) **Features**: - 4 stat cards with badges - Quick chores list with claim buttons - Active projects with progress bars - Payment alerts section - Recent activity feed --- ### Tasks Page **Files**: - `app/(app)/tasks/page.tsx` (Server) - `app/(app)/tasks/tasks-client.tsx` (Client) **Client Props**: ```typescript interface Props { tasks: Task[] members: { id: string; display_name: string; user_id: string }[] currentUserId: string spaceId: string } ``` **Features**: - Tabbed view (Chores, Ongoing, My Tasks, Done) - Area filter dropdown - Create task modal - Claim/Complete/Delete actions - Status badges **State Management**: - Local state for tasks (optimistic updates) - Form state for create modal - Tab and filter state --- ### Projects Page **Files**: - `app/(app)/projects/page.tsx` (Server) - `app/(app)/projects/projects-client.tsx` (Client) **Client Props**: ```typescript interface Props { projects: Project[] spaceId: string } ``` **Features**: - 4-column Kanban (Backlog, In Progress, Review, Done) - Status change via dropdown - Create project modal - Delete action - Progress bars --- ### Members Page **Files**: - `app/(app)/members/page.tsx` (Server) - `app/(app)/members/members-client.tsx` (Client) **Client Props**: ```typescript interface Props { members: Member[] currentRole: string } ``` **Features**: - Tabbed view (All, Payment Issues, Pending Approval, Inactive) - Search and tier filter - Add member modal (admin/board only) - Edit member modal - Approve/Remove actions - Payment status indicators --- ### Payments Page **Files**: - `app/(app)/payments/page.tsx` (Server) - `app/(app)/payments/payments-client.tsx` (Client) **Client Props**: ```typescript interface Props { payments: Payment[] members: Member[] integrations: Integration[] currentRole: string spaceId: string } ``` **Features**: - Platform summary cards (PayPal, Zeffy, Venmo, Cash) - Transactions table with filtering - Log cash modal - Link member modal - Platform connection status --- ### Comms Page **Files**: - `app/(app)/comms/page.tsx` (Server) - `app/(app)/comms/comms-client.tsx` (Client) **Client Props**: ```typescript interface Props { member: any space: any channels: any[] } ``` **Features**: - Channel sidebar (General, Areas, Projects) - Real-time message subscription - Message input with send - User avatars and timestamps - @mention and #channel highlighting **Real-time**: ```typescript const subscription = supabase .channel(`channel:${selectedChannel.id}`) .on('postgres_changes', { event: '*', schema: 'public', table: 'comms_messages', filter: `channel_id=eq.${selectedChannel.id}` }, payload => { if (payload.eventType === 'INSERT') { setMessages(prev => [...prev, payload.new]) } }) .subscribe() ``` --- ### Contacts Page **Files**: - `app/(app)/contacts/page.tsx` (Server) - `app/(app)/contacts/contacts-client.tsx` (Client) **Features**: - Search functionality - Grouped by type (Vendors, Landlord, Partners) - Add/Edit contact modals - Delete with confirmation - Contact type badges --- ### Ops Page **File**: `app/(app)/ops/page.tsx` (Server Component) **Features**: - Tabbed view (Knowledge Base, Processes, Secrets, Area Leads) - Search knowledge base - Pinned/Critical entries section - Area-based entries - Area leads sidebar - Secrets vault (admin/board only) --- ### Settings Page **Files**: - `app/(app)/settings/page.tsx` (Server) - `app/(app)/settings/settings-client.tsx` (Client) **Client Props**: ```typescript interface Props { space: Space isAdmin: boolean integrations: Integration[] currentRole: string } ``` **Features**: - Space settings tab (name, slug, approval settings) - Roles & permissions info - Integrations management (PayPal, Zeffy, Venmo, Stripe) - Webhook secret management --- ### Import Page **File**: `app/(app)/import/page.tsx` (Server Component) **Features**: - Step indicator (Upload, Map, Preview, Import) - File drop zone - Column mapping preview - Database connector form **Status**: UI only, file processing not implemented. --- ## 3. Client Components ### TaskClaimButton **File**: `components/task-claim-button.tsx` **Props**: ```typescript interface Props { taskId: string onClaim?: () => void } ``` **Usage**: ```tsx refresh()} /> ``` --- ### ThemeProvider **File**: `components/theme-provider.tsx` **Purpose**: Wraps app with next-themes provider. **Usage** (in layout): ```tsx {children} ``` --- ## 4. UI Components All shadcn/ui components are available in `components/ui/`. Key components: ### Layout Components - `Card`, `CardHeader`, `CardTitle`, `CardContent`, `CardFooter` - `Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader` - `Sheet`, `SheetTrigger`, `SheetContent` - `Tabs`, `TabsList`, `TabsTrigger`, `TabsContent` - `Table`, `TableHeader`, `TableRow`, `TableCell` ### Form Components - `Button` - Primary actions - `Input` - Text input - `Textarea` - Multi-line input - `Select`, `SelectTrigger`, `SelectContent`, `SelectItem` - `Checkbox` - Boolean input - `Switch` - Toggle input - `Label` - Form labels ### Feedback Components - `Badge` - Status indicators - `Alert`, `AlertTitle`, `AlertDescription` - `Spinner` - Loading indicator - `Skeleton` - Loading placeholder - `Toast`, `Toaster` - Notifications ### Navigation Components - `Breadcrumb`, `BreadcrumbItem`, `BreadcrumbLink` - `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent` - `NavigationMenu` --- ## 5. Component Patterns ### Server/Client Split ```typescript // page.tsx (Server Component) export default async function FeaturePage() { const supabase = await createClient() const { data } = await supabase.from('table').select('*') return } // feature-client.tsx (Client Component) 'use client' export function FeatureClient({ data }: { data: Item[] }) { const [items, setItems] = useState(data) // Interactive UI } ``` ### Modal Pattern ```tsx const [showModal, setShowModal] = useState(false) const [form, setForm] = useState({ field: '' }) const [loading, setLoading] = useState(false) const [error, setError] = useState('') async function handleSubmit(e: React.FormEvent) { e.preventDefault() setLoading(true) setError('') const result = await serverAction(form) if (result.error) { setError(result.error) setLoading(false) return } // Update local state setShowModal(false) setForm({ field: '' }) setLoading(false) } return ( <> {showModal && (
{/* Form fields */} {error &&

{error}

}
)} ) ``` ### Optimistic Update Pattern ```tsx async function handleAction(id: string) { // Optimistically update UI setItems(prev => prev.map(item => item.id === id ? { ...item, status: 'updated' } : item )) // Call server const result = await serverAction(id) if (result.error) { // Revert on error setItems(prev => prev.map(item => item.id === id ? { ...item, status: 'original' } : item )) } } ``` ### Tab Pattern ```tsx const [activeTab, setActiveTab] = useState<'tab1' | 'tab2'>('tab1') const tabData = { tab1: items.filter(i => i.type === 'type1'), tab2: items.filter(i => i.type === 'type2'), } return ( <>
{(['tab1', 'tab2'] as const).map(tab => ( ))}
{tabData[activeTab].map(item => (
{/* Render item */}
))}
) ``` ### Filter Pattern ```tsx const [search, setSearch] = useState('') const [filter, setFilter] = useState('') const filtered = items.filter(item => { const matchesSearch = !search || item.name.toLowerCase().includes(search.toLowerCase()) const matchesFilter = !filter || item.type === filter return matchesSearch && matchesFilter }) return ( <> setSearch(e.target.value)} placeholder="Search..." /> {filtered.map(item => (
{/* Render */}
))} ) ``` --- ## 6. Styling Patterns ### Page Header ```tsx

Page Title

``` ### Tab Bar ```tsx
{tabs.map(tab => ( ))}
``` ### Card List ```tsx
{items.map(item => (
{/* Item content */}
))}
``` ### Status Badge ```tsx {status.toUpperCase()} ``` ### Monospace Label ```tsx

SECTION LABEL

```