Core Components
- StatCard - KPI metrics with trend indicators
- RecentOrders - Data tables with actions
- Charts - ApexCharts data visualizations
- Grid Layout - Responsive 8-column system
Comprehensive dashboard featuring KPI metrics, data visualization, responsive grid layouts, and interactive components built with React 19 and ApexCharts.
StatCard Components ApexCharts Integration Grid LayoutModular dashboard components with responsive grid layouts and centralized data management:
Core Components
Key Features
The dashboard uses an 8-column responsive grid system to organize KPI cards and visualization components:
// Dashboard main structureexport default function Dashboard() {const cardDataList: StatCardData[] = [ { name: 'Page Views', value: 12450, iconName: 'lucide:eye', description: 'Total page visits within selected timeframe', percentage: '0.4%', isMoney: false, percentageType: 'down', }, { name: 'Total Revenue', value: 9863, iconName: 'material-symbols:monetization-on-outline-rounded', description: 'Aggregated revenue from all channels', percentage: '13.5%', isMoney: true, percentageType: 'up', } // Additional cards...]
return ( <div className="grid grid-cols-4 xl:grid-cols-8 gap-6 items-start"> {cardDataList.map((item) => ( <StatCard key={item.name} data={item} className="col-span-4 sm:col-span-2" /> ))} <RecentOrders className="col-span-4 xl:col-span-5" /> <TopReferralSources className="col-span-4 lg:col-span-2 xl:col-span-3" /> <MonthlyRevenueComparison className="col-span-4 xl:col-span-5" /> </div>)}
KPI metric cards with interactive tooltips and trend indicators:
Key Features:
// StatCard interface and key propsexport interface StatCardData {name: stringvalue: number | stringiconName: stringdescription: stringpercentage: stringisMoney: booleanpercentageType: 'up' | 'down'}
// StatCard with tooltip and trend indicatorexport default function StatCard({ data, className }: StatCardProps) {return ( <Card className={cn('p-5', className)}> <div className="flex items-center"> <span className="bg-gray-100 dark:bg-gray-500/50 p-1 rounded-sm"> <Icon className="text-sm" icon={data.iconName} /> </span> <span className="ps-2">{data.name}</span> {/* Interactive tooltip with description */} <TooltipProvider> <Tooltip> <TooltipTrigger className="ms-auto"> <Icon icon="majesticons:exclamation-circle-line" /> </TooltipTrigger> <TooltipContent className="max-w-70"> {data.description} </TooltipContent> </Tooltip> </TooltipProvider> </div> {/* Value and percentage display */} <div className="text-2xl font-medium flex items-center"> <span> {data.isMoney && '$'}{formatNumber(data.value)} </span> <TrendBadge percentage={data.percentage} type={data.percentageType} /> </div> </Card>)}
Recent Orders table with avatar integration and action dropdowns:
Table Features:
// Recent Orders table componentexport default function RecentOrders({ className }) {const tableDataList = [ { id: '#1044', customer: 'Daniel Zhang', amount: '$199.00', date: 'Jul 23' }, { id: '#1043', customer: 'Emma Watson', amount: '$59.99', date: 'Jul 23' }, // Additional orders...]
return ( <Card className={className}> <CardHeader className="flex flex-row items-center justify-between"> <CardTitle>Recent Orders</CardTitle> <div className="cursor-pointer text-muted-foreground hover:text-gray-700"> See All <Icon icon="formkit:right" /> </div> </CardHeader> <CardContent> <Table> <TableHeader className="bg-gray-100 dark:bg-gray-800"> <TableRow className="border-none"> <TableHead>Order ID</TableHead> <TableHead>Customer</TableHead> <TableHead>Amount</TableHead> <TableHead>Date</TableHead> <TableHead></TableHead> </TableRow> </TableHeader> <TableBody> {tableDataList.map((item, index) => ( <TableRow key={item.id} className="border-dashed"> <TableCell>{item.id}</TableCell> <TableCell> <div className="flex items-center"> <Avatar className="size-7 me-1"> <AvatarImage src={`https://vertaui.com/avatar/cartoon/${index + 5}.png`} /> </Avatar> <span className="max-w-40 truncate">{item.customer}</span> </div> </TableCell> <TableCell>{item.amount}</TableCell> <TableCell>{item.date}</TableCell> <TableCell> <ActionsDropdown item={item} /> </TableCell> </TableRow> ))} </TableBody> </Table> </CardContent> </Card>)}
Interactive area chart with year selection and data comparison:
Chart Features:
// Monthly Revenue Chart with ApexChartsexport default function MonthlyRevenueComparison({ className }) {const [selectedYear, setSelectedYear] = useState('2025')
// Generate mock data based on selected yearconst generateYearlyData = (year: number) => { const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] const currentYear = new Date().getFullYear() const endMonth = year === currentYear ? new Date().getMonth() : 11
return Array.from({ length: endMonth + 1 }, (_, i) => ({ month: months[i], actual: Math.floor(Math.random() * 5000) + 5000, target: Math.floor(Math.random() * 3000) + 5000, }))}
// Memoized data and chart configurationconst dataList = useMemo(() => generateYearlyData(+selectedYear), [selectedYear])const chartOptions = useMemo(() => ({ xaxis: { categories: dataList.map(item => item.month) },}), [dataList])
const chartSeries = useMemo(() => [ { name: 'Actual', data: dataList.map(item => item.actual) }, { name: 'Target', data: dataList.map(item => item.target) },], [dataList])
return ( <Card className={className}> <CardHeader className="flex flex-row items-center justify-between"> <CardTitle>Monthly Revenue Comparison</CardTitle> <Select value={selectedYear} onValueChange={setSelectedYear}> <SelectTrigger className="w-30"> <SelectValue placeholder="Select year" /> </SelectTrigger> <SelectContent> <SelectItem value="2024">2024</SelectItem> <SelectItem value="2025">2025</SelectItem> </SelectContent> </Select> </CardHeader> <CardContent> {/* Chart legend with totals */} <div className="flex items-center gap-x-6 pt-3"> <LegendItem color="bg-primary" label="Total actual" value={formatCompactNumber(totalActual)} /> <LegendItem color="bg-chart-1" label="Total target" value={formatCompactNumber(totalTarget)} /> </div> <AreaChart className="h-85" options={chartOptions} series={chartSeries} /> </CardContent> </Card>)}
Dashboard Grid Layout Create responsive 8-column grid system using Tailwind CSS classes
StatCard Components Implement KPI cards with Iconify icons, tooltips, and trend indicators
Data Table Components Build tables with avatars, dropdown actions, and styled headers
ApexCharts Integration Add interactive charts with memoized options and dynamic data
Responsive Breakpoints Configure mobile-first responsive behavior across device sizes
Flexible 8-column grid with mobile-first breakpoints:
col-span-4
- Full width KPI cardssm:col-span-2
- Two KPI cards per rowlg:col-span-2
- Balanced component sizingxl:col-span-8
- Complex multi-column layoutsxl:col-span-5
- Large component spansxl:col-span-3
- Sidebar component sizingDashboard components use structured mock data for development and testing:
// Dashboard data structureconst cardDataList: StatCardData[] = [{ name: 'Page Views', value: 12450, iconName: 'lucide:eye', description: 'Total page visits within selected timeframe', percentage: '0.4%', isMoney: false, percentageType: 'down',},{ name: 'Total Revenue', value: 9863, iconName: 'material-symbols:monetization-on-outline-rounded', description: 'Aggregated revenue from all channels', percentage: '13.5%', isMoney: true, percentageType: 'up',}// Additional metrics...]
// Table mock dataconst tableDataList = [{ id: '#1044', customer: 'Daniel Zhang', amount: '$199.00', date: 'Jul 23' },{ id: '#1043', customer: 'Emma Watson', amount: '$59.99', date: 'Jul 23' }// Additional orders...]
Dynamic chart data with year-aware generation logic:
// Dynamic chart data generationconst generateYearlyData = (year: number) => {const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']const currentYear = new Date().getFullYear()const currentMonth = new Date().getMonth()const endMonth = year === currentYear ? currentMonth : 11
const data = []for (let i = 0; i <= endMonth; i++) { data.push({ month: months[i], actual: Math.floor(Math.random() * 5000) + 5000, target: Math.floor(Math.random() * 3000) + 5000, })}return data}
// Memoized usage in componentsconst dataList = useMemo(() => generateYearlyData(+selectedYear), [selectedYear])const totalActual = useMemo(() =>dataList.reduce((sum, item) => sum + item.actual, 0), [dataList])
Optimized rendering with strategic memoization:
// Memoized chart configurationconst chartOptions: ApexOptions = useMemo(() => ({xaxis: { categories: dataList.map((item) => item.month),},}), [dataList])
const chartSeries = useMemo(() => [{ name: 'Actual', data: dataList.map((item) => item.actual) },{ name: 'Target', data: dataList.map((item) => item.target) },], [dataList])
// Memoized calculationsconst totalActual = useMemo(() =>dataList.reduce((sum, item) => sum + item.actual, 0), [dataList])const totalTarget = useMemo(() =>dataList.reduce((sum, item) => sum + item.target, 0), [dataList])
// Component memoization for stable propsconst StatCard = memo(({ data, className }: StatCardProps) => {return ( <Card className={cn('p-5', className)}> {/* Component content */} </Card>)})
Contextual help tooltips with backdrop blur effects:
// Enhanced tooltip with backdrop blur<TooltipProvider><Tooltip> <TooltipTrigger className="ms-auto text-muted-foreground"> <Icon icon="majesticons:exclamation-circle-line" /> </TooltipTrigger> <TooltipContent className="max-w-70 bg-foreground/85 backdrop-blur-[2px]" side="left" > {data.description} </TooltipContent></Tooltip></TooltipProvider>
External avatar service integration with fallback handling:
// Avatar with external service<Avatar className="size-7 me-1 inline-block"><AvatarImage src={`https://vertaui.com/avatar/cartoon/${index + 5}.png?id=1`} alt="avatar"/><AvatarFallback> {customer.split(' ').map(n => n[0]).join('').toUpperCase()}</AvatarFallback></Avatar>
useMemo
for chart options and data calculationsReact.memo
for components with stable propsThe dashboard provides a solid foundation for data-rich admin interfaces with modern React patterns and performance optimizations.