data-grid-sub-data-grid

PreviousNext
Docs
reuicomponent

Preview

Loading preview…
registry/default/components/data-grid/sub-data-grid.tsx
import { useMemo, useState } from 'react';
import Link from 'next/link';
import { Avatar, AvatarFallback, AvatarImage } from '@/registry/default/ui/avatar';
import { Badge } from '@/registry/default/ui/badge';
import { Button } from '@/registry/default/ui/button';
import { DataGrid, DataGridContainer } from '@/registry/default/ui/data-grid';
import { DataGridColumnHeader } from '@/registry/default/ui/data-grid-column-header';
import { DataGridPagination } from '@/registry/default/ui/data-grid-pagination';
import { DataGridTable } from '@/registry/default/ui/data-grid-table';
import { ScrollArea, ScrollBar } from '@/registry/default/ui/scroll-area';
import {
  ColumnDef,
  ExpandedState,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  PaginationState,
  SortingState,
  useReactTable,
} from '@tanstack/react-table';
import type { VariantProps } from 'class-variance-authority';
import { SquareMinus, SquarePlus, User } from 'lucide-react';

interface OrderItemData {
  id: string;
  productName: string;
  category: string;
  price: string;
  quantity: number;
}

interface Data {
  id: string;
  orderNumber: string;
  customer: string;
  customerEmail: string;
  customerAvatar: string;
  total: string;
  status: {
    label: string;
    variant: VariantProps<typeof Badge>['variant'];
  };
  items: OrderItemData[];
}

const demoData: Data[] = [
  {
    id: '1',
    orderNumber: 'SO-001',
    customer: 'John Smith',
    customerEmail: 'john.smith@email.com',
    customerAvatar: '1.png',
    total: '$459.97',
    status: {
      label: 'Shipped',
      variant: 'primary',
    },
    items: [
      { id: '1-1', productName: 'Wireless Headphones', category: 'Electronics', price: '$199.99', quantity: 1 },
      { id: '1-2', productName: 'Phone Case', category: 'Accessories', price: '$99.99', quantity: 1 },
      { id: '1-3', productName: 'Screen Protector', category: 'Accessories', price: '$29.99', quantity: 2 },
      { id: '1-4', productName: 'Charging Cable', category: 'Electronics', price: '$19.99', quantity: 1 },
      { id: '1-5', productName: 'Bluetooth Speaker', category: 'Electronics', price: '$89.99', quantity: 1 },
      { id: '1-6', productName: 'Phone Stand', category: 'Accessories', price: '$39.99', quantity: 1 },
      { id: '1-7', productName: 'Cable Management', category: 'Accessories', price: '$19.99', quantity: 2 },
      { id: '1-8', productName: 'Wireless Charger', category: 'Electronics', price: '$49.99', quantity: 1 },
      { id: '1-9', productName: 'Gaming Mouse', category: 'Electronics', price: '$79.99', quantity: 1 },
      { id: '1-10', productName: 'Gaming Keyboard', category: 'Electronics', price: '$59.99', quantity: 1 },
      { id: '1-11', productName: 'Mouse Pad', category: 'Accessories', price: '$19.99', quantity: 1 },
      { id: '1-12', productName: 'Desk Lamp', category: 'Home', price: '$79.99', quantity: 1 },
    ],
  },
  {
    id: '2',
    orderNumber: 'SO-002',
    customer: 'Sarah Johnson',
    customerEmail: 'sarah.johnson@email.com',
    customerAvatar: '2.png',
    total: '$249.48',
    status: {
      label: 'Processing',
      variant: 'info',
    },
    items: [
      { id: '2-1', productName: 'Running Shoes', category: 'Sports', price: '$89.99', quantity: 1 },
      { id: '2-2', productName: 'Sports Socks', category: 'Sports', price: '$59.51', quantity: 1 },
      { id: '2-3', productName: 'Water Bottle', category: 'Sports', price: '$24.99', quantity: 1 },
      { id: '2-4', productName: 'Fitness Tracker', category: 'Electronics', price: '$74.99', quantity: 1 },
    ],
  },
  {
    id: '3',
    orderNumber: 'SO-003',
    customer: 'Mike Davis',
    customerEmail: 'mike.davis@email.com',
    customerAvatar: '3.png',
    total: '$189.97',
    status: {
      label: 'Delivered',
      variant: 'success',
    },
    items: [
      { id: '3-1', productName: 'Coffee Mug', category: 'Home', price: '$89.99', quantity: 1 },
      { id: '3-2', productName: 'Coffee Beans', category: 'Food', price: '$24.99', quantity: 1 },
      { id: '3-3', productName: 'Coffee Grinder', category: 'Home', price: '$49.99', quantity: 1 },
      { id: '3-4', productName: 'Milk Frother', category: 'Home', price: '$24.99', quantity: 1 },
      { id: '3-5', productName: 'Coffee Filter', category: 'Home', price: '$9.99', quantity: 1 },
      { id: '3-6', productName: 'Sugar Bowl', category: 'Home', price: '$19.99', quantity: 1 },
      { id: '3-7', productName: 'Tea Set', category: 'Home', price: '$39.99', quantity: 1 },
      { id: '3-8', productName: 'Creamer', category: 'Food', price: '$14.99', quantity: 1 },
      { id: '3-9', productName: 'Coffee Table', category: 'Furniture', price: '$199.99', quantity: 1 },
      { id: '3-10', productName: 'Placemats', category: 'Home', price: '$12.99', quantity: 1 },
      { id: '3-11', productName: 'Napkins', category: 'Home', price: '$7.99', quantity: 1 },
      { id: '3-12', productName: 'Candles', category: 'Home', price: '$16.99', quantity: 1 },
      { id: '3-13', productName: 'Vase', category: 'Home', price: '$29.99', quantity: 1 },
      { id: '3-14', productName: 'Flowers', category: 'Home', price: '$24.99', quantity: 1 },
      { id: '3-15', productName: 'Table Runner', category: 'Home', price: '$18.99', quantity: 1 },
    ],
  },
  {
    id: '4',
    orderNumber: 'SO-004',
    customer: 'Emily Wilson',
    customerEmail: 'emily.wilson@email.com',
    customerAvatar: '4.png',
    total: '$299.97',
    status: {
      label: 'Cancelled',
      variant: 'destructive',
    },
    items: [
      { id: '4-1', productName: 'Laptop Stand', category: 'Electronics', price: '$99.99', quantity: 1 },
      { id: '4-2', productName: 'Wireless Mouse', category: 'Electronics', price: '$49.99', quantity: 1 },
      { id: '4-3', productName: 'Keyboard', category: 'Electronics', price: '$79.99', quantity: 1 },
      { id: '4-4', productName: 'Monitor', category: 'Electronics', price: '$69.99', quantity: 1 },
      { id: '4-5', productName: 'Webcam', category: 'Electronics', price: '$89.99', quantity: 1 },
      { id: '4-6', productName: 'Microphone', category: 'Electronics', price: '$59.99', quantity: 1 },
      { id: '4-7', productName: 'Headphones', category: 'Electronics', price: '$129.99', quantity: 1 },
      { id: '4-8', productName: 'USB Hub', category: 'Electronics', price: '$29.99', quantity: 1 },
      { id: '4-9', productName: 'Cable Organizer', category: 'Accessories', price: '$19.99', quantity: 1 },
      { id: '4-10', productName: 'Desk Mat', category: 'Office', price: '$24.99', quantity: 1 },
    ],
  },
  {
    id: '5',
    orderNumber: 'SO-005',
    customer: 'David Brown',
    customerEmail: 'david.brown@email.com',
    customerAvatar: '5.png',
    total: '$179.97',
    status: {
      label: 'Pending',
      variant: 'warning',
    },
    items: [
      { id: '5-1', productName: 'Desk Lamp', category: 'Home', price: '$79.99', quantity: 1 },
      { id: '5-2', productName: 'Desk Organizer', category: 'Home', price: '$39.99', quantity: 1 },
      { id: '5-3', productName: 'Notebook Set', category: 'Office', price: '$29.99', quantity: 1 },
      { id: '5-4', productName: 'Pen Set', category: 'Office', price: '$29.99', quantity: 1 },
      { id: '5-5', productName: 'Stapler', category: 'Office', price: '$12.99', quantity: 1 },
      { id: '5-6', productName: 'Paper Clips', category: 'Office', price: '$4.99', quantity: 1 },
      { id: '5-7', productName: 'Binder', category: 'Office', price: '$8.99', quantity: 1 },
      { id: '5-8', productName: 'Highlighter', category: 'Office', price: '$6.99', quantity: 1 },
      { id: '5-9', productName: 'Eraser', category: 'Office', price: '$2.99', quantity: 1 },
      { id: '5-10', productName: 'Ruler', category: 'Office', price: '$3.99', quantity: 1 },
      { id: '5-11', productName: 'Calculator', category: 'Office', price: '$19.99', quantity: 1 },
      { id: '5-12', productName: 'Calendar', category: 'Office', price: '$14.99', quantity: 1 },
      { id: '5-13', productName: 'Whiteboard', category: 'Office', price: '$24.99', quantity: 1 },
      { id: '5-14', productName: 'Markers', category: 'Office', price: '$9.99', quantity: 1 },
      { id: '5-15', productName: 'Push Pins', category: 'Office', price: '$5.99', quantity: 1 },
    ],
  },
  {
    id: '6',
    orderNumber: 'SO-006',
    customer: 'Lisa Anderson',
    customerEmail: 'lisa.anderson@email.com',
    customerAvatar: '6.png',
    total: '$329.95',
    status: {
      label: 'Shipped',
      variant: 'primary',
    },
    items: [
      { id: '6-1', productName: 'Bluetooth Speaker', category: 'Electronics', price: '$129.99', quantity: 1 },
      { id: '6-2', productName: 'Phone Stand', category: 'Accessories', price: '$39.99', quantity: 1 },
      { id: '6-3', productName: 'Cable Management', category: 'Accessories', price: '$19.99', quantity: 2 },
      { id: '6-4', productName: 'Wireless Charger', category: 'Electronics', price: '$49.99', quantity: 1 },
      { id: '6-5', productName: 'Smart Watch', category: 'Electronics', price: '$199.99', quantity: 1 },
      { id: '6-6', productName: 'Fitness Band', category: 'Electronics', price: '$79.99', quantity: 1 },
      { id: '6-7', productName: 'Phone Case', category: 'Accessories', price: '$24.99', quantity: 1 },
      { id: '6-8', productName: 'Screen Protector', category: 'Accessories', price: '$14.99', quantity: 1 },
      { id: '6-9', productName: 'Car Mount', category: 'Accessories', price: '$29.99', quantity: 1 },
      { id: '6-10', productName: 'Power Bank', category: 'Electronics', price: '$39.99', quantity: 1 },
      { id: '6-11', productName: 'USB Cable', category: 'Electronics', price: '$9.99', quantity: 1 },
      { id: '6-12', productName: 'Adapter', category: 'Electronics', price: '$19.99', quantity: 1 },
      { id: '6-13', productName: 'Headphones', category: 'Electronics', price: '$89.99', quantity: 1 },
      { id: '6-14', productName: 'Earbuds', category: 'Electronics', price: '$59.99', quantity: 1 },
      { id: '6-15', productName: 'Microphone', category: 'Electronics', price: '$49.99', quantity: 1 },
    ],
  },
  {
    id: '7',
    orderNumber: 'SO-007',
    customer: 'Robert Taylor',
    customerEmail: 'robert.taylor@email.com',
    customerAvatar: '7.png',
    total: '$159.96',
    status: {
      label: 'Processing',
      variant: 'info',
    },
    items: [
      { id: '7-1', productName: 'Gaming Mouse', category: 'Electronics', price: '$79.99', quantity: 1 },
      { id: '7-2', productName: 'Gaming Keyboard', category: 'Electronics', price: '$59.99', quantity: 1 },
      { id: '7-3', productName: 'Mouse Pad', category: 'Accessories', price: '$19.99', quantity: 1 },
      { id: '7-4', productName: 'Gaming Headset', category: 'Electronics', price: '$99.99', quantity: 1 },
      { id: '7-5', productName: 'Gaming Chair', category: 'Furniture', price: '$299.99', quantity: 1 },
      { id: '7-6', productName: 'Gaming Desk', category: 'Furniture', price: '$199.99', quantity: 1 },
      { id: '7-7', productName: 'RGB Strip', category: 'Electronics', price: '$29.99', quantity: 1 },
      { id: '7-8', productName: 'Controller', category: 'Electronics', price: '$49.99', quantity: 1 },
      { id: '7-9', productName: 'Gaming Monitor', category: 'Electronics', price: '$399.99', quantity: 1 },
      { id: '7-10', productName: 'Graphics Card', category: 'Electronics', price: '$599.99', quantity: 1 },
      { id: '7-11', productName: 'RAM', category: 'Electronics', price: '$89.99', quantity: 1 },
      { id: '7-12', productName: 'SSD', category: 'Electronics', price: '$129.99', quantity: 1 },
      { id: '7-13', productName: 'CPU', category: 'Electronics', price: '$299.99', quantity: 1 },
      { id: '7-14', productName: 'Motherboard', category: 'Electronics', price: '$199.99', quantity: 1 },
      { id: '7-15', productName: 'Power Supply', category: 'Electronics', price: '$149.99', quantity: 1 },
    ],
  },
  {
    id: '8',
    orderNumber: 'SO-008',
    customer: 'Jennifer Martinez',
    customerEmail: 'jennifer.martinez@email.com',
    customerAvatar: '8.png',
    total: '$89.97',
    status: {
      label: 'Delivered',
      variant: 'success',
    },
    items: [
      { id: '8-1', productName: 'Yoga Mat', category: 'Sports', price: '$29.99', quantity: 1 },
      { id: '8-2', productName: 'Water Bottle', category: 'Sports', price: '$19.99', quantity: 1 },
      { id: '8-3', productName: 'Resistance Bands', category: 'Sports', price: '$39.99', quantity: 1 },
      { id: '8-4', productName: 'Dumbbells', category: 'Sports', price: '$49.99', quantity: 1 },
      { id: '8-5', productName: 'Kettlebell', category: 'Sports', price: '$59.99', quantity: 1 },
      { id: '8-6', productName: 'Jump Rope', category: 'Sports', price: '$14.99', quantity: 1 },
      { id: '8-7', productName: 'Foam Roller', category: 'Sports', price: '$24.99', quantity: 1 },
      { id: '8-8', productName: 'Exercise Ball', category: 'Sports', price: '$34.99', quantity: 1 },
      { id: '8-9', productName: 'Yoga Block', category: 'Sports', price: '$12.99', quantity: 1 },
      { id: '8-10', productName: 'Stretching Strap', category: 'Sports', price: '$9.99', quantity: 1 },
      { id: '8-11', productName: 'Gym Towel', category: 'Sports', price: '$7.99', quantity: 1 },
      { id: '8-12', productName: 'Sports Bra', category: 'Clothing', price: '$29.99', quantity: 1 },
      { id: '8-13', productName: 'Workout Shorts', category: 'Clothing', price: '$24.99', quantity: 1 },
      { id: '8-14', productName: 'Running Shoes', category: 'Sports', price: '$89.99', quantity: 1 },
      { id: '8-15', productName: 'Protein Shaker', category: 'Sports', price: '$12.99', quantity: 1 },
    ],
  },
  {
    id: '9',
    orderNumber: 'SO-009',
    customer: 'Christopher Lee',
    customerEmail: 'christopher.lee@email.com',
    customerAvatar: '9.png',
    total: '$199.98',
    status: {
      label: 'Cancelled',
      variant: 'destructive',
    },
    items: [
      { id: '9-1', productName: 'Smart Watch', category: 'Electronics', price: '$199.99', quantity: 1 },
      { id: '9-2', productName: 'Watch Band', category: 'Accessories', price: '$29.99', quantity: 1 },
      { id: '9-3', productName: 'Charging Dock', category: 'Electronics', price: '$39.99', quantity: 1 },
      { id: '9-4', productName: 'Screen Protector', category: 'Accessories', price: '$14.99', quantity: 1 },
      { id: '9-5', productName: 'Case', category: 'Accessories', price: '$19.99', quantity: 1 },
      { id: '9-6', productName: 'Strap', category: 'Accessories', price: '$24.99', quantity: 1 },
      { id: '9-7', productName: 'Cable', category: 'Electronics', price: '$9.99', quantity: 1 },
      { id: '9-8', productName: 'Adapter', category: 'Electronics', price: '$12.99', quantity: 1 },
      { id: '9-9', productName: 'Mount', category: 'Accessories', price: '$16.99', quantity: 1 },
      { id: '9-10', productName: 'Stand', category: 'Accessories', price: '$22.99', quantity: 1 },
      { id: '9-11', productName: 'Cover', category: 'Accessories', price: '$8.99', quantity: 1 },
      { id: '9-12', productName: 'Grip', category: 'Accessories', price: '$11.99', quantity: 1 },
      { id: '9-13', productName: 'Lens', category: 'Accessories', price: '$6.99', quantity: 1 },
      { id: '9-14', productName: 'Filter', category: 'Accessories', price: '$4.99', quantity: 1 },
      { id: '9-15', productName: 'Cleaning Kit', category: 'Accessories', price: '$7.99', quantity: 1 },
    ],
  },
  {
    id: '10',
    orderNumber: 'SO-010',
    customer: 'Amanda White',
    customerEmail: 'amanda.white@email.com',
    customerAvatar: '10.png',
    total: '$149.97',
    status: {
      label: 'Pending',
      variant: 'warning',
    },
    items: [
      { id: '10-1', productName: 'Kitchen Knife Set', category: 'Home', price: '$79.99', quantity: 1 },
      { id: '10-2', productName: 'Cutting Board', category: 'Home', price: '$29.99', quantity: 1 },
      { id: '10-3', productName: 'Utensil Set', category: 'Home', price: '$39.99', quantity: 1 },
      { id: '10-4', productName: 'Dish Towels', category: 'Home', price: '$12.99', quantity: 1 },
      { id: '10-5', productName: 'Pot Holders', category: 'Home', price: '$8.99', quantity: 1 },
      { id: '10-6', productName: 'Trivet', category: 'Home', price: '$14.99', quantity: 1 },
      { id: '10-7', productName: 'Measuring Cups', category: 'Home', price: '$16.99', quantity: 1 },
      { id: '10-8', productName: 'Measuring Spoons', category: 'Home', price: '$9.99', quantity: 1 },
      { id: '10-9', productName: 'Mixing Bowls', category: 'Home', price: '$24.99', quantity: 1 },
      { id: '10-10', productName: 'Spatula', category: 'Home', price: '$6.99', quantity: 1 },
      { id: '10-11', productName: 'Whisk', category: 'Home', price: '$4.99', quantity: 1 },
      { id: '10-12', productName: 'Ladle', category: 'Home', price: '$7.99', quantity: 1 },
      { id: '10-13', productName: 'Tongs', category: 'Home', price: '$11.99', quantity: 1 },
      { id: '10-14', productName: 'Can Opener', category: 'Home', price: '$13.99', quantity: 1 },
      { id: '10-15', productName: 'Bottle Opener', category: 'Home', price: '$5.99', quantity: 1 },
    ],
  },
  {
    id: '11',
    orderNumber: 'SO-011',
    customer: 'Michael Garcia',
    customerEmail: 'michael.garcia@email.com',
    customerAvatar: '11.png',
    total: '$279.96',
    status: {
      label: 'Shipped',
      variant: 'primary',
    },
    items: [
      { id: '11-1', productName: 'Office Chair', category: 'Furniture', price: '$199.99', quantity: 1 },
      { id: '11-2', productName: 'Desk Mat', category: 'Office', price: '$19.99', quantity: 1 },
      { id: '11-3', productName: 'Monitor Stand', category: 'Electronics', price: '$59.99', quantity: 1 },
      { id: '11-4', productName: 'Desk Lamp', category: 'Office', price: '$39.99', quantity: 1 },
      { id: '11-5', productName: 'Pen Holder', category: 'Office', price: '$12.99', quantity: 1 },
      { id: '11-6', productName: 'File Organizer', category: 'Office', price: '$24.99', quantity: 1 },
      { id: '11-7', productName: 'Stapler', category: 'Office', price: '$16.99', quantity: 1 },
      { id: '11-8', productName: 'Paper Clips', category: 'Office', price: '$4.99', quantity: 1 },
      { id: '11-9', productName: 'Binder', category: 'Office', price: '$8.99', quantity: 1 },
      { id: '11-10', productName: 'Highlighter', category: 'Office', price: '$6.99', quantity: 1 },
      { id: '11-11', productName: 'Eraser', category: 'Office', price: '$2.99', quantity: 1 },
      { id: '11-12', productName: 'Ruler', category: 'Office', price: '$3.99', quantity: 1 },
      { id: '11-13', productName: 'Calculator', category: 'Office', price: '$19.99', quantity: 1 },
      { id: '11-14', productName: 'Calendar', category: 'Office', price: '$14.99', quantity: 1 },
      { id: '11-15', productName: 'Whiteboard', category: 'Office', price: '$24.99', quantity: 1 },
    ],
  },
  {
    id: '12',
    orderNumber: 'SO-012',
    customer: 'Jessica Thompson',
    customerEmail: 'jessica.thompson@email.com',
    customerAvatar: '12.png',
    total: '$119.97',
    status: {
      label: 'Processing',
      variant: 'info',
    },
    items: [
      { id: '12-1', productName: 'Skincare Set', category: 'Beauty', price: '$59.99', quantity: 1 },
      { id: '12-2', productName: 'Face Mask', category: 'Beauty', price: '$29.99', quantity: 1 },
      { id: '12-3', productName: 'Moisturizer', category: 'Beauty', price: '$29.99', quantity: 1 },
      { id: '12-4', productName: 'Cleanser', category: 'Beauty', price: '$19.99', quantity: 1 },
      { id: '12-5', productName: 'Toner', category: 'Beauty', price: '$24.99', quantity: 1 },
      { id: '12-6', productName: 'Serum', category: 'Beauty', price: '$39.99', quantity: 1 },
      { id: '12-7', productName: 'Eye Cream', category: 'Beauty', price: '$34.99', quantity: 1 },
      { id: '12-8', productName: 'Sunscreen', category: 'Beauty', price: '$16.99', quantity: 1 },
      { id: '12-9', productName: 'Exfoliant', category: 'Beauty', price: '$22.99', quantity: 1 },
      { id: '12-10', productName: 'Lip Balm', category: 'Beauty', price: '$7.99', quantity: 1 },
      { id: '12-11', productName: 'Hand Cream', category: 'Beauty', price: '$12.99', quantity: 1 },
      { id: '12-12', productName: 'Body Lotion', category: 'Beauty', price: '$18.99', quantity: 1 },
      { id: '12-13', productName: 'Shampoo', category: 'Beauty', price: '$14.99', quantity: 1 },
      { id: '12-14', productName: 'Conditioner', category: 'Beauty', price: '$14.99', quantity: 1 },
      { id: '12-15', productName: 'Hair Mask', category: 'Beauty', price: '$19.99', quantity: 1 },
    ],
  },
  {
    id: '13',
    orderNumber: 'SO-013',
    customer: 'Daniel Rodriguez',
    customerEmail: 'daniel.rodriguez@email.com',
    customerAvatar: '13.png',
    total: '$89.98',
    status: {
      label: 'Delivered',
      variant: 'success',
    },
    items: [
      { id: '13-1', productName: 'T-Shirt', category: 'Clothing', price: '$19.99', quantity: 2 },
      { id: '13-2', productName: 'Jeans', category: 'Clothing', price: '$49.99', quantity: 1 },
      { id: '13-3', productName: 'Hoodie', category: 'Clothing', price: '$39.99', quantity: 1 },
      { id: '13-4', productName: 'Sweater', category: 'Clothing', price: '$34.99', quantity: 1 },
      { id: '13-5', productName: 'Jacket', category: 'Clothing', price: '$79.99', quantity: 1 },
      { id: '13-6', productName: 'Shorts', category: 'Clothing', price: '$24.99', quantity: 1 },
      { id: '13-7', productName: 'Pants', category: 'Clothing', price: '$44.99', quantity: 1 },
      { id: '13-8', productName: 'Dress', category: 'Clothing', price: '$59.99', quantity: 1 },
      { id: '13-9', productName: 'Skirt', category: 'Clothing', price: '$29.99', quantity: 1 },
      { id: '13-10', productName: 'Blouse', category: 'Clothing', price: '$34.99', quantity: 1 },
      { id: '13-11', productName: 'Socks', category: 'Clothing', price: '$9.99', quantity: 1 },
      { id: '13-12', productName: 'Underwear', category: 'Clothing', price: '$14.99', quantity: 1 },
      { id: '13-13', productName: 'Hat', category: 'Clothing', price: '$19.99', quantity: 1 },
      { id: '13-14', productName: 'Scarf', category: 'Clothing', price: '$16.99', quantity: 1 },
      { id: '13-15', productName: 'Gloves', category: 'Clothing', price: '$12.99', quantity: 1 },
    ],
  },
  {
    id: '14',
    orderNumber: 'SO-014',
    customer: 'Ashley Clark',
    customerEmail: 'ashley.clark@email.com',
    customerAvatar: '14.png',
    total: '$199.97',
    status: {
      label: 'Shipped',
      variant: 'primary',
    },
    items: [
      { id: '14-1', productName: 'Tablet', category: 'Electronics', price: '$199.99', quantity: 1 },
      { id: '14-2', productName: 'Tablet Case', category: 'Accessories', price: '$29.99', quantity: 1 },
      { id: '14-3', productName: 'Screen Protector', category: 'Accessories', price: '$14.99', quantity: 1 },
      { id: '14-4', productName: 'Stylus', category: 'Accessories', price: '$39.99', quantity: 1 },
      { id: '14-5', productName: 'Keyboard', category: 'Electronics', price: '$79.99', quantity: 1 },
      { id: '14-6', productName: 'Mouse', category: 'Electronics', price: '$49.99', quantity: 1 },
      { id: '14-7', productName: 'Charging Cable', category: 'Electronics', price: '$19.99', quantity: 1 },
      { id: '14-8', productName: 'Power Adapter', category: 'Electronics', price: '$24.99', quantity: 1 },
      { id: '14-9', productName: 'Stand', category: 'Accessories', price: '$34.99', quantity: 1 },
      { id: '14-10', productName: 'Mount', category: 'Accessories', price: '$19.99', quantity: 1 },
      { id: '14-11', productName: 'Cover', category: 'Accessories', price: '$16.99', quantity: 1 },
      { id: '14-12', productName: 'Grip', category: 'Accessories', price: '$11.99', quantity: 1 },
      { id: '14-13', productName: 'Lens', category: 'Accessories', price: '$6.99', quantity: 1 },
      { id: '14-14', productName: 'Filter', category: 'Accessories', price: '$4.99', quantity: 1 },
      { id: '14-15', productName: 'Cleaning Kit', category: 'Accessories', price: '$7.99', quantity: 1 },
    ],
  },
  {
    id: '15',
    orderNumber: 'SO-015',
    customer: 'Kevin Wilson',
    customerEmail: 'kevin.wilson@email.com',
    customerAvatar: '15.png',
    total: '$159.96',
    status: {
      label: 'Pending',
      variant: 'warning',
    },
    items: [
      { id: '15-1', productName: 'Gaming Headset', category: 'Electronics', price: '$99.99', quantity: 1 },
      { id: '15-2', productName: 'Gaming Controller', category: 'Electronics', price: '$59.99', quantity: 1 },
      { id: '15-3', productName: 'Gaming Mouse', category: 'Electronics', price: '$79.99', quantity: 1 },
      { id: '15-4', productName: 'Gaming Keyboard', category: 'Electronics', price: '$129.99', quantity: 1 },
      { id: '15-5', productName: 'Gaming Chair', category: 'Furniture', price: '$299.99', quantity: 1 },
      { id: '15-6', productName: 'Gaming Desk', category: 'Furniture', price: '$199.99', quantity: 1 },
      { id: '15-7', productName: 'RGB Strip', category: 'Electronics', price: '$29.99', quantity: 1 },
      { id: '15-8', productName: 'Mouse Pad', category: 'Accessories', price: '$19.99', quantity: 1 },
      { id: '15-9', productName: 'Gaming Monitor', category: 'Electronics', price: '$399.99', quantity: 1 },
      { id: '15-10', productName: 'Graphics Card', category: 'Electronics', price: '$599.99', quantity: 1 },
      { id: '15-11', productName: 'RAM', category: 'Electronics', price: '$89.99', quantity: 1 },
      { id: '15-12', productName: 'SSD', category: 'Electronics', price: '$129.99', quantity: 1 },
      { id: '15-13', productName: 'CPU', category: 'Electronics', price: '$299.99', quantity: 1 },
      { id: '15-14', productName: 'Motherboard', category: 'Electronics', price: '$199.99', quantity: 1 },
      { id: '15-15', productName: 'Power Supply', category: 'Electronics', price: '$149.99', quantity: 1 },
    ],
  },
];

// Sub-table component for order items
function OrderItemsSubTable({ items }: { items: OrderItemData[] }) {
  const [sorting, setSorting] = useState<SortingState>([]);
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: 5, // Show 3 items per page for sub-tables
  });

  const columns = useMemo<ColumnDef<OrderItemData>[]>(
    () => [
      {
        accessorKey: 'productName',
        header: ({ column }) => <DataGridColumnHeader title="Product" column={column} />,
        cell: (info) => info.getValue() as string,
        enableSorting: true,
        size: 200,
      },
      {
        accessorKey: 'category',
        header: ({ column }) => <DataGridColumnHeader title="Category" column={column} />,
        cell: (info) => info.getValue() as string,
        enableSorting: true,
        size: 120,
      },
      {
        accessorKey: 'price',
        header: ({ column }) => <DataGridColumnHeader title="Price" column={column} />,
        cell: (info) => info.getValue() as string,
        enableSorting: true,
        size: 100,
      },
      {
        accessorKey: 'quantity',
        header: ({ column }) => <DataGridColumnHeader title="Qty" column={column} />,
        cell: (info) => info.getValue() as number,
        enableSorting: true,
        size: 80,
      },
    ],
    [],
  );

  const table = useReactTable({
    data: items,
    columns,
    pageCount: Math.ceil(items.length / pagination.pageSize),
    state: {
      sorting,
      pagination,
    },
    onSortingChange: setSorting,
    onPaginationChange: setPagination,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getRowId: (row: OrderItemData) => row.id,
  });

  return (
    <div className="bg-muted/30 p-4">
      <DataGrid
        table={table}
        recordCount={items.length}
        tableLayout={{
          cellBorder: true,
          rowBorder: true,
          headerBackground: true,
          headerBorder: true,
        }}
      >
        <div className="w-full space-y-2.5">
          <div className="bg-card rounded-lg border border-muted-foreground/20">
            <DataGridContainer>
              <ScrollArea>
                <DataGridTable />
                <ScrollBar orientation="horizontal" />
              </ScrollArea>
            </DataGridContainer>
          </div>
          <DataGridPagination className="pb-1.5" />
        </div>
      </DataGrid>
    </div>
  );
}

export default function DataGridDemo() {
  const [pagination, setPagination] = useState<PaginationState>({
    pageIndex: 0,
    pageSize: 5,
  });
  const [sorting, setSorting] = useState<SortingState>([]);
  const [expandedRows, setExpandedRows] = useState<ExpandedState>({});
  const [columnOrder, setColumnOrder] = useState<string[]>(['expand', 'orderNumber', 'customer', 'total', 'status']);

  const columns = useMemo<ColumnDef<Data>[]>(
    () => [
      {
        id: 'expand',
        header: () => null,
        cell: ({ row }) => {
          return row.getCanExpand() ? (
            <Button onClick={row.getToggleExpandedHandler()} mode="icon" size="sm" variant="ghost">
              {row.getIsExpanded() ? <SquareMinus /> : <SquarePlus />}
            </Button>
          ) : null;
        },
        size: 25,
        enableResizing: false,
        meta: {
          expandedContent: (row) => <OrderItemsSubTable items={row.items} />,
        },
      },
      {
        accessorKey: 'customer',
        id: 'customer',
        header: ({ column }) => <DataGridColumnHeader title="Customer" visibility={true} column={column} />,
        cell: ({ row }) => {
          return (
            <div className="flex items-center gap-3">
              <Avatar className="size-8">
                <AvatarImage src={`/media/avatars/${row.original.customerAvatar}`} alt={row.original.customer} />
                <AvatarFallback>{row.original.customer.charAt(0)}</AvatarFallback>
              </Avatar>
              <div className="space-y-px">
                <div className="font-medium text-foreground">{row.original.customer}</div>
                <div className="text-muted-foreground">{row.original.customerEmail}</div>
              </div>
            </div>
          );
        },
        enableSorting: true,
        enableHiding: true,
        enableResizing: true,
        size: 200,
      },
      {
        accessorKey: 'items',
        id: 'items',
        header: ({ column }) => <DataGridColumnHeader title="Items" visibility={true} column={column} />,
        cell: (info) => {
          const items = info.getValue() as OrderItemData[];
          const itemCount = items.length;
          return (
            <div
              className="text-sm font-medium text-foreground hover:text-primary cursor-pointer"
              onClick={() => info.row.getToggleExpandedHandler()()}
            >
              {itemCount} {itemCount === 1 ? 'item' : 'items'}
            </div>
          );
        },
        enableSorting: true,
        enableHiding: true,
        enableResizing: true,
        size: 120,
      },
      {
        accessorKey: 'total',
        id: 'total',
        header: ({ column }) => <DataGridColumnHeader title="Total" visibility={true} column={column} />,
        cell: (info) => info.getValue() as string,
        enableSorting: true,
        enableHiding: true,
        enableResizing: true,
        size: 100,
      },
      {
        accessorKey: 'status',
        id: 'status',
        header: ({ column }) => <DataGridColumnHeader title="Status" visibility={true} column={column} />,
        cell: ({ row }) => {
          const status = row.original.status;
          return (
            <Badge variant={status.variant} appearance="light">
              {status.label}
            </Badge>
          );
        },
        enableSorting: true,
        enableHiding: true,
        enableResizing: true,
        size: 120,
      },
    ],
    [],
  );

  const table = useReactTable({
    columns,
    data: demoData,
    pageCount: Math.ceil((demoData?.length || 0) / pagination.pageSize),
    getRowId: (row: Data) => row.id,
    getRowCanExpand: (row) => Boolean(row.original.items && row.original.items.length > 0),
    state: {
      pagination,
      sorting,
      expanded: expandedRows,
      columnOrder,
    },
    columnResizeMode: 'onChange',
    onPaginationChange: setPagination,
    onSortingChange: setSorting,
    onExpandedChange: setExpandedRows,
    onColumnOrderChange: setColumnOrder,
    getCoreRowModel: getCoreRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
  });

  return (
    <DataGrid
      table={table}
      recordCount={demoData?.length || 0}
      tableLayout={{
        columnsPinnable: true,
        columnsResizable: true,
        columnsMovable: true,
        columnsVisibility: true,
      }}
    >
      <div className="w-full space-y-2.5">
        <DataGridContainer>
          <ScrollArea>
            <DataGridTable />
            <ScrollBar orientation="horizontal" />
          </ScrollArea>
        </DataGridContainer>
        <DataGridPagination />
      </div>
    </DataGrid>
  );
}

Installation

npx shadcn@latest add @reui/data-grid-sub-data-grid

Usage

import { DataGridSubDataGrid } from "@/components/data-grid-sub-data-grid"
<DataGridSubDataGrid />