Components
Overview of the UI component library built on Radix UI and shadcn/ui.
Component Library
Admindek ships 35+ accessible UI components, all available from @dashboardpack/core/components/ui/. They are built on top of Radix UI primitives and styled with Tailwind CSS following the shadcn/ui conventions, giving you fully accessible, unstyled-by-default building blocks that integrate seamlessly with the design system.
Importing Components
Each component lives in its own module within the ui/ directory. Import only what you need — tree-shaking ensures unused components are excluded from the production bundle.
import { Button } from "@dashboardpack/core/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@dashboardpack/core/components/ui/card";
import { Badge } from "@dashboardpack/core/components/ui/badge";
import { Input } from "@dashboardpack/core/components/ui/input";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@dashboardpack/core/components/ui/dialog";DataTable
The shared DataTable component is available from @dashboardpack/core/components/shared/data-table. It is used across the Users, Orders, Invoices, and Products pages and provides a consistent, feature-rich table experience out of the box.
Built-in features include:
- Column sorting (ascending / descending)
- Global text filtering
- Pagination with configurable page size
- Faceted filters (dropdown multi-select per column)
- CSV export of the current filtered data set
- Mobile card view for small viewports
- Row selection with bulk-action support
- Column visibility toggle
import { DataTable } from "@dashboardpack/core/components/shared/data-table";
import type { ColumnDef } from "@tanstack/react-table";
type User = { id: string; name: string; email: string };
const columns: ColumnDef<User>[] = [
{ accessorKey: "name", header: "Name" },
{ accessorKey: "email", header: "Email" },
];
export function UsersTable({ data }: { data: User[] }) {
return <DataTable columns={columns} data={data} />;
}ConfirmDialog
The ConfirmDialog component provides a reusable confirmation modal for destructive actions such as deleting a record or revoking access. It is imported from @dashboardpack/core/components/shared/confirm-dialog and is used across the Users, Invoices, and Settings pages.
Pass an open state, an onConfirm callback, and optional title/description props. The dialog handles focus management and keyboard dismissal automatically via the underlying Radix UI Dialog primitive.
import { ConfirmDialog } from "@dashboardpack/core/components/shared/confirm-dialog";
export function DeleteUserButton({ userId }: { userId: string }) {
const [open, setOpen] = useState(false);
async function handleConfirm() {
await deleteUser(userId);
setOpen(false);
}
return (
<>
<button onClick={() => setOpen(true)}>Delete</button>
<ConfirmDialog
open={open}
onOpenChange={setOpen}
onConfirm={handleConfirm}
title="Delete user?"
description="This action cannot be undone."
/>
</>
);
}Form Components
All forms in Admindek are built with react-hook-form for state management and Zod for schema validation. The Form, FormField, FormItem, FormLabel, FormControl, and FormMessage primitives from the ui/form module wire react-hook-form's context into accessible label/error associations automatically.
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@dashboardpack/core/components/ui/form";
import { Input } from "@dashboardpack/core/components/ui/input";
import { Button } from "@dashboardpack/core/components/ui/button";
const schema = z.object({
email: z.string().email("Enter a valid email address"),
});
type FormValues = z.infer<typeof schema>;
export function EmailForm() {
const form = useForm<FormValues>({
resolver: zodResolver(schema),
defaultValues: { email: "" },
});
function onSubmit(values: FormValues) {
console.log(values);
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="[email protected]" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
);
}