Shared Components
Moved to UI Library
The shared UI components have been moved to the @elcto/ui package. See the UI Library documentation for complete component reference.
Both the Backend Dashboard and Heimdall ID use the shared @elcto/ui component library located at shared/ui/.
Quick Reference
Importing Components
// Import from the shared library
import { Button, Modal, Alert, Dropdown } from "@elcto/ui/components";
import { cn } from "@elcto/ui/utils";
// Or from local re-exports
import { Button, Modal, Alert } from "@/components/ui";
Available Components
| Component | Description | Docs |
|---|---|---|
| Alert | Status messages with variants | View |
| Avatar | User avatar with fallback | View |
| Badge | Status badges and labels | View |
| Banner | Full-width notification banners | View |
| BlurredText | Privacy-aware text display | View |
| Button | Interactive buttons | View |
| Card | Content containers | View |
| CodeInput | OTP/verification input | View |
| Dropdown | Dropdown menus | View |
| FloatingInput | Inputs with floating labels | View |
| LoadingSpinner, Spinner | Loading indicators | View |
| Modal | Dialog windows | View |
| Table | Data tables | View |
| Tooltip | Hover tooltips | View |
Platform Icons
import {
TwitchIcon,
DiscordIcon,
YouTubeIcon,
KickIcon,
SteamIcon,
GitHubIcon,
} from "@elcto/ui/components";
<TwitchIcon className="w-5 h-5 text-[var(--twitch)]" />
See Icons documentation for all available icons.
Auth Components
ProtectedRoute
Wrap pages that require authentication.
import { ProtectedRoute } from "@/components/auth/ProtectedRoute";
export default function DashboardPage() {
return (
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
);
}
// With required permissions
<ProtectedRoute requiredPermissions={["gps:write", "users:read"]}>
<AdminPanel />
</ProtectedRoute>
// With custom fallback
<ProtectedRoute fallback={<CustomLoginPrompt />}>
<Content />
</ProtectedRoute>
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Protected content |
requiredPermissions | string[] | - | Required permissions |
fallback | ReactNode | <LoginRedirect /> | Fallback component |
ProtectedContent
Conditionally render content based on auth state.
import { ProtectedContent } from "@/components/auth/ProtectedContent";
<ProtectedContent>
{/* Only shown when authenticated */}
<UserMenu />
</ProtectedContent>
<ProtectedContent fallback={<LoginButton />}>
<LogoutButton />
</ProtectedContent>
<ProtectedContent requiredPermissions={["admin"]}>
<AdminTools />
</ProtectedContent>
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Protected content |
fallback | ReactNode | null | Fallback when not authenticated |
requiredPermissions | string[] | - | Required permissions |
UserButton
Display user info with dropdown menu.
import { UserButton } from "@/components/auth/UserButton";
// Basic usage
<UserButton />
// With custom menu items
<UserButton
menuItems={[
{ label: "Settings", href: "/settings" },
{ label: "Help", href: "/help" },
]}
/>
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
menuItems | MenuItem[] | - | Additional menu items |
showEmail | boolean | true | Show email in dropdown |
Layout Components
DashboardLayout
The main layout for authenticated dashboard pages.
import { DashboardLayout } from "@/components/layouts/DashboardLayout";
export default function Page() {
return (
<DashboardLayout
title="GPS Data"
breadcrumbs={[
{ label: "Dashboard", href: "/dashboard" },
{ label: "GPS Data" }
]}
>
<GpsDataContent />
</DashboardLayout>
);
}
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | Page content |
title | string | - | Page title |
breadcrumbs | Breadcrumb[] | - | Breadcrumb navigation |
OverlayLayout
Full-screen overlay layout for modals and overlays.
import { OverlayLayout } from "@/layouts/OverlayLayout";
export default function ModalPage() {
return (
<OverlayLayout onClose={() => router.back()}>
<div className="bg-white rounded-lg p-6 max-w-md w-full">
<h2>Modal Content</h2>
{/* ... */}
</div>
</OverlayLayout>
);
}
Footer
The site footer component.
import { Footer } from "@/components/layout/Footer";
export default function Layout({ children }) {
return (
<>
<main>{children}</main>
<Footer />
</>
);
}
Providers
SessionProvider
Wrap your app with the session provider for auth state.
// src/app/layout.tsx
import { SessionProvider } from "@/components/providers/SessionProvider";
export default function RootLayout({ children }) {
return (
<html>
<body>
<SessionProvider>
{children}
</SessionProvider>
</body>
</html>
);
}
ApolloWrapper
GraphQL client provider (Backend Dashboard only).
// src/app/layout.tsx
import { ApolloWrapper } from "@/components/providers/ApolloWrapper";
export default function RootLayout({ children }) {
return (
<html>
<body>
<SessionProvider>
<ApolloWrapper>
{children}
</ApolloWrapper>
</SessionProvider>
</body>
</html>
);
}
Styling
See Design Tokens for the complete styling reference.
CSS Variables
/* Use CSS variables from @elcto/ui */
background-color: var(--bg-card);
color: var(--text-primary);
border-color: var(--border-subtle);
Utility Classes
/* Button variants */
.btn-brand /* Primary brand button */
.btn-secondary /* Secondary button */
/* Card styles */
.card /* Elevated card */
.card-flat /* Flat card */
/* Text colors */
.text-primary /* Primary text */
.text-secondary /* Secondary text */
.text-muted /* Muted text */
Best Practices
Loading States
import { LoadingSpinner, Alert } from "@/components/ui";
function DataTable() {
const { data, isLoading, error } = useQuery(...);
if (isLoading) return <LoadingSpinner />;
if (error) return <Alert variant="error">{error.message}</Alert>;
return <Table data={data} />;
}
Component Composition
import { Card, CardHeader, CardContent } from "@/components/ui";
<Card>
<CardHeader>
<h3>Title</h3>
</CardHeader>
<CardContent>
Content here
</CardContent>
</Card>
Next Steps
- UI Library - Complete component reference
- Design Tokens - Colors, spacing, theming
- Backend - Backend documentation
- ID - Identity service documentation
- Authentication Flow - Auth flow details