# Pivot Grid URL: /docs/web/components/pivot-grid A standalone pivot grid with 3-level row and column hierarchies, subtotals, grand totals, drilldown, pinning, resizing, and export. **Demo:** ```tsx 'use client'; // @custom-demo import { useCallback, useEffect, useMemo, useState } from 'react'; import { PivotGridToolbar, PivotGridView, usePivotGrid } from '@docyrus/ui/components/pivot-grid'; import { useMounted } from '@docyrus/ui/primitives/hooks/use-mounted'; import { AwesomeDialog, AwesomeDialogBody, AwesomeDialogHeader } from '@docyrus/ui/components/awesome-dialog'; import { Button } from '@docyrus/ui/primitives/ui/button'; import { Switch } from '@docyrus/ui/primitives/ui/switch'; import { cn } from '@docyrus/ui/primitives/lib/utils'; import { ChevronDownIcon, Maximize2Icon, Settings2Icon } from 'lucide-react'; import { createPivotGridDemoRows, pivotGridDemoColorRules, pivotGridDemoColumnDimensions, pivotGridDemoMeasures, pivotGridDemoRowDimensions, type PivotGridDemoRow } from '@ui/components/pivot-grid/pivot-grid-demo-data'; interface PivotGridDemoSurfaceProps { enableColorRules: boolean; pinGrandTotals: boolean; showConfigure: boolean; onEnableColorRulesChange: (value: boolean) => void; onPinGrandTotalsChange: (value: boolean) => void; onShowConfigureChange: (value: boolean) => void; height: number | 'auto'; showFullscreenButton?: boolean; onOpenFullscreen?: () => void; } function PivotGridDemoSurface({ enableColorRules, pinGrandTotals, showConfigure, onEnableColorRulesChange, onPinGrandTotalsChange, onShowConfigureChange, height, showFullscreenButton = false, onOpenFullscreen }: PivotGridDemoSurfaceProps) { const data = useMemo(() => createPivotGridDemoRows({ regions: 2, countriesPerRegion: 2, citiesPerCountry: 2, years: 2, quarters: 2, channels: 2 }), []); const measures = useMemo(() => pivotGridDemoMeasures.slice(0, 2), []); const getRowId = useCallback((row: PivotGridDemoRow) => row.id, []); const controller = usePivotGrid({ data, rowDimensions: pivotGridDemoRowDimensions, columnDimensions: pivotGridDemoColumnDimensions, measures, getRowId, cellColorRules: enableColorRules ? pivotGridDemoColorRules : undefined, height, className: height === 'auto' ? 'min-h-0 flex-1' : undefined }); const { pinColumns, table, unpinColumns, visibleLeafColumns } = controller; useEffect(() => { const grandTotalColumnIds = visibleLeafColumns .filter(column => column.kind === 'grand-total') .map(column => column.id); if (grandTotalColumnIds.length === 0) { return; } const hasPinnedGrandTotals = grandTotalColumnIds.every( columnId => table.getColumn(columnId)?.getIsPinned() === 'right' ); if (pinGrandTotals) { if (!hasPinnedGrandTotals) { pinColumns(grandTotalColumnIds, 'right'); } return; } if (hasPinnedGrandTotals) { unpinColumns(grandTotalColumnIds); } }, [ pinColumns, table, unpinColumns, visibleLeafColumns, pinGrandTotals ]); return (