Shared UI and Editor Patterns
Component Library
Section titled “Component Library”The dashboard uses shadcn/ui — a set of accessible, composable components built on Radix UI primitives. Configuration lives in components.json.
All shadcn/ui components are in src/components/ui/ and include: Button, Card, Dialog, Drawer, DropdownMenu, Form, Input, Select, Sheet, Table, Tabs, Tooltip, and ~30 more.
Layout Components
Section titled “Layout Components”| Component | Location | Purpose |
|---|---|---|
DashboardLayout | src/components/layout/ | Wrapper with sidebar + header |
Header | src/components/layout/ | Top navigation bar |
Sidebar | src/components/layout/ | Left nav with role-based links |
All forms use React Hook Form with Zod schemas for validation. The pattern:
const schema = z.object({ title: z.string().min(1, "Title is required"),});
const form = useForm<z.infer<typeof schema>>({ resolver: zodResolver(schema),});CKEditor Integration
Section titled “CKEditor Integration”The rich text editor is CKEditor 5 Classic, wrapped in a custom component CKEditorWithS3 at src/components/ui/ckeditor.tsx.
It includes:
- Custom toolbar configuration
- Dark/light mode visual adaptation (synced with ThemeContext)
- Built-in upload adapter wired to the signed S3 URL flow — images dropped or pasted into the editor are uploaded to S3 automatically
Notifications
Section titled “Notifications”Toast notifications use Sonner via a <Toaster> component mounted at the app root. Call toast.success(), toast.error(), etc. from any component.
Loading States
Section titled “Loading States”PageSkeleton is the standard loading fallback used inside Suspense boundaries for lazy-loaded routes.