Skip to main content
Use Case

Build a Dashboard with React and Tailwind CSS v4

Assemble a production-ready analytics dashboard with responsive sidebar, stat cards, data tables, and accessible navigation — using Ninna UI components and Tailwind v4.

Why Ninna UI for dashboards

Dashboards demand a lot from a component library: responsive layouts, data tables, cards, navigation, and consistent theming across dozens of widgets. Ninna UI ships all of these as tree-shakeable npm packages with zero-runtime CSS theming, so your dashboard stays fast and maintainable.

The layout primitives (Stack, Flex, Grid, SimpleGrid, Container) handle responsive structure, while data-display components (Card, Stat, Table) give you accessible data presentation out of the box.

1. Set up the page shell

Use a CSS grid for the sidebar + main content split. Tailwind v4 utilities handle the responsive breakpoint behaviour:

import { Container } from "@ninna-ui/layout";

export default function DashboardLayout() {
  return (
    <div className="grid min-h-screen grid-cols-1 md:grid-cols-[240px_1fr]">
      <aside className="border-r border-base-200 bg-base-100 p-4">
        {/* Navigation */}
      </aside>
      <main className="p-6">
        <Container>{/* Dashboard content */}</Container>
      </main>
    </div>
  );
}

2. Add stat cards

Use SimpleGrid for a responsive row of metric cards. The Stat component from @ninna-ui/data-display gives you accessible label/value semantics:

import { SimpleGrid } from "@ninna-ui/layout";
import { Card, Stat } from "@ninna-ui/data-display";

<SimpleGrid columns={{ base: 1, sm: 2, lg: 4 }} gap="4">
  <Card><Stat label="Revenue" value="$48.2k" trend="+12%" /></Card>
  <Card><Stat label="Users" value="1,204" trend="+8%" /></Card>
  <Card><Stat label="Churn" value="2.1%" trend="-0.3%" /></Card>
  <Card><Stat label="MRR" value="$12.4k" trend="+15%" /></Card>
</SimpleGrid>

3. Build a data table

The Table component from @ninna-ui/data-display provides accessible table semantics. For sortable/filterable tables, start from the data-table-filters block:

import { Table } from "@ninna-ui/data-display";

<Table>
  <Table.Head>
    <Table.Row>
      <Table.Header>Name</Table.Header>
      <Table.Header>Status</Table.Header>
      <Table.Header>Plan</Table.Header>
    </Table.Row>
  </Table.Head>
  <Table.Body>
    <Table.Row>
      <Table.Cell>Alice</Table.Cell>
      <Table.Cell>Active</Table.Cell>
      <Table.Cell>Pro</Table.Cell>
    </Table.Row>
  </Table.Body>
</Table>

4. Mobile sidebar with Drawer

On mobile, the sidebar should collapse into a drawer. The Drawer from @ninna-ui/overlays handles focus trapping and keyboard navigation automatically:

import { Drawer } from "@ninna-ui/overlays";
import { Button } from "@ninna-ui/primitives";

<Drawer>
  <Drawer.Trigger asChild>
    <Button variant="ghost">Menu</Button>
  </Drawer.Trigger>
  <Drawer.Content>
    {/* Navigation links */}
  </Drawer.Content>
</Drawer>

Related Blocks

Component Docs

FAQ