Files
erika/docs/component-usage-audit.md

59 lines
4.0 KiB
Markdown

# Component Usage Audit
This audit counts source files that import each component. “Used once” means a component file is imported by exactly one source file; the exported component may still be rendered multiple times inside that importer.
## Consolidated route-specific components
The following one-importer files were removed from the shared `components` directory:
| Previous component | New location |
| --- | --- |
| `components/LinkCard.tsx` | Static link-list rendering is in [`app/page.tsx`](../app/page.tsx). |
| `components/link-carousel.tsx` | The interactive boundary is in [`app/client.tsx`](../app/client.tsx). |
| `components/admin-form-editor-parts.tsx` | `SortableQuestion` is in [`app/admin/form/[id]/client.tsx`](../app/admin/form/%5Bid%5D/client.tsx); `SaveStatusIndicator` is now shared. |
| `components/form-admin-sidebar.tsx` | [`app/admin/form/[id]/sidebar-client.tsx`](../app/admin/form/%5Bid%5D/sidebar-client.tsx) |
| `components/login-dialog.tsx` | [`app/form/client.tsx`](../app/form/client.tsx) |
| `components/results-filters.tsx` | [`app/admin/form/[id]/result/client.tsx`](../app/admin/form/%5Bid%5D/result/client.tsx) |
| `components/space-background.tsx` | Removed because the homepage already renders its background directly and the component had no imports. |
These route client files remain separate where hooks, event handlers, or browser APIs require a narrow Next.js client boundary.
## Shared component created from duplicated code
[`components/save-status-indicator.tsx`](../components/save-status-indicator.tsx) is imported by all three autosaving admin clients:
- [`app/admin/form/[id]/client.tsx`](../app/admin/form/%5Bid%5D/client.tsx)
- [`app/admin/form/[id]/extra/client.tsx`](../app/admin/form/%5Bid%5D/extra/client.tsx)
- [`app/admin/form/[id]/result/[submissionId]/client.tsx`](../app/admin/form/%5Bid%5D/result/%5BsubmissionId%5D/client.tsx)
This replaced three nearly identical `SaveStatusIndicator` implementations.
## Remaining one-importer shared components
| Component | Why it remains shared |
| --- | --- |
| [`components/admin-shell.tsx`](../components/admin-shell.tsx) | It is transitively used by five admin routes through `admin-shell-server.tsx` and provides the client half of a server/client boundary. |
| [`components/formatted-text.tsx`](../components/formatted-text.tsx) | It is generic and rendered twice by the public form client. |
| [`components/guarded-link.tsx`](../components/guarded-link.tsx) | It is generic autosave-safe navigation and is rendered repeatedly by the form admin sidebar. |
| [`components/page-progress.tsx`](../components/page-progress.tsx) | It is intentionally a root-layout singleton. |
| [`components/rich-text-editor.tsx`](../components/rich-text-editor.tsx) | It is a generic editor control, rendered twice, and kept behind a dynamic client import. |
| [`components/theme-provider.tsx`](../components/theme-provider.tsx) | It is intentionally a root-layout provider singleton. |
## One-importer shadcn primitives
The following design-system primitives each currently have one importer:
- [`components/ui/alert.tsx`](../components/ui/alert.tsx)
- [`components/ui/avatar.tsx`](../components/ui/avatar.tsx)
- [`components/ui/context-menu.tsx`](../components/ui/context-menu.tsx)
- [`components/ui/form.tsx`](../components/ui/form.tsx)
- [`components/ui/input-group.tsx`](../components/ui/input-group.tsx)
- [`components/ui/radio-group.tsx`](../components/ui/radio-group.tsx)
- [`components/ui/sheet.tsx`](../components/ui/sheet.tsx)
These remain in `components/ui` because they are design-system primitives rather than feature components.
## Remaining reuse opportunity
[`components/guarded-link.tsx`](../components/guarded-link.tsx) protects navigation while autosaves are pending, but the back, previous, and next submission links in [`app/admin/form/[id]/result/[submissionId]/page.tsx`](../app/admin/form/%5Bid%5D/result/%5BsubmissionId%5D/page.tsx) still use ordinary links. Those links should use `GuardedLink` if pending note saves must always finish before navigation.