npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@microsoft/fabric-datagrid

v2.0.0

Published

A lightweight, high-performance React data grid component for Fabric Apps - Analytics

Downloads

11,107

Readme

@microsoft/fabric-datagrid

High-performance React data grid for Fabric Apps - Analytics

Quick Reference

Package: @microsoft/fabric-datagrid Purpose: High-performance React data grid component with sorting, filtering, tree rows, pagination, and virtualization. Use when: You need to display tabular data from a DataTable or Row[] as an interactive grid. Do NOT use when: You need charts/visualizations (use @microsoft/fabric-visuals), or you only need shared types/tokens (use @microsoft/fabric-visuals-core). Key exports: DataGrid, ImageCell, DataGridProps, GridColumnDef, Row, CellValue, SortConfig, SortDirection, CellRange Peer dependencies: @microsoft/fabric-visuals-core Install: npm install @microsoft/fabric-datagrid @microsoft/fabric-visuals-core

Ecosystem Context

@microsoft/fabric-datagrid is the tabular companion to the Fabric Apps - Analytics visualization stack:

  • It consumes DataTable and ColumnDef contracts from @microsoft/fabric-visuals-core.
  • It is a sibling package to @microsoft/fabric-visuals, which provides Vega-Lite chart rendering.
  • It uses VisualContainer from @microsoft/fabric-visuals-extensibility to optionally frame itself. See VisualContainer framing.
  • In typical apps, grid data originates from @microsoft/fabric-app-data queries, then gets shaped into a DataTable for display.

Installation

npm install @microsoft/fabric-datagrid @microsoft/fabric-visuals-core

@microsoft/fabric-visuals-core is required at runtime because DataGrid consumes its DataTable/VisualTheme types and injects shared design tokens.

Public API

All exports come from the package entry point:

export { DataGrid } from './components/data-grid';
export { ImageCell } from './components/image-cell/image-cell';
export type { DataGridProps, GridColumnDef, Row, CellValue, SortConfig, SortDirection } from './types';
export type { CellRange } from './hooks/use-selection';

DataGrid

import type { DataTable, VisualTheme } from '@microsoft/fabric-visuals-core';
import type { ReactNode } from 'react';

declare function DataGrid(props: DataGridProps): JSX.Element;

DataGrid accepts three data sources through props.data:

  • DataTable: derives grid columns from input.columns
  • Row[]: renders caller-provided row objects directly
  • string: fetches JSON from a URL and expects a Row[] payload

ImageCell

A memoized cell renderer component for displaying image thumbnails with a click-to-expand lightbox overlay.

interface ImageCellProps {
    src: string;
    alt?: string;
    className?: string;
}

declare const ImageCell: React.MemoExoticComponent<(props: ImageCellProps) => JSX.Element | null>;

Use as a cellRenderer in a GridColumnDef:

import { ImageCell } from '@microsoft/fabric-datagrid';

const columns: GridColumnDef[] = [
    { id: 'photo', header: 'Photo', cellRenderer: (value) => <ImageCell src={String(value)} alt="thumbnail" /> },
];

Props (DataGridProps)

interface DataGridProps {
    columns?: GridColumnDef[];
    data?: DataTable | Row[] | string;
    defaultSort?: SortConfig[];
    rowHeight?: number;
    theme?: VisualTheme;
    onColumnsChange?: (columns: GridColumnDef[]) => void;
    onRowToggle?: (rowId: string) => void;
    onFilterChange?: (columnId: string, selectedValues: CellValue[]) => void;
    onInteraction?: (events: InteractionEvent[]) => void;
    pageSize?: number;
    capabilities?: DataGridCapabilities;
    visualContainerCapabilities?: VisualContainerCapabilities;
    header?: HeaderProps;
}

| Prop | Type | Required | Description | |------|------|----------|-------------| | data | DataTable \| Row[] \| string | no | Data source. A DataTable auto-derives columns and rows. A Row[] array provides data directly. A string URL triggers a fetch for JSON Row[]. | | columns | GridColumnDef[] | no | Column definitions. Auto-derived when data is a DataTable; required otherwise. | | defaultSort | SortConfig[] | no | Initial sort state (e.g. [{ columnId, direction }]). | | rowHeight | number | no | When set, enables row virtualization via @tanstack/react-virtual. Mutually exclusive with pageSize. | | pageSize | number | no | When set (> 0), enables pagination instead of virtualization. | | theme | VisualTheme | no | Visual theme from @microsoft/fabric-visuals-core. Maps to CSS custom properties. When omitted, the grid falls back to CSS variable defaults. | | onColumnsChange | (columns: GridColumnDef[]) => void | no | Fired after column resize or reorder. | | onRowToggle | (rowId: string) => void | no | Fired when a hierarchical row is expanded or collapsed. | | onFilterChange | (columnId: string, selectedValues: CellValue[]) => void | no | Fired when a column filter is applied or cleared. | | onInteraction | (events: InteractionEvent[]) => void | no | Fired when the user clicks a data row (select) or re-clicks the selected row (clear/deselect). See Interactivity. | | capabilities | DataGridCapabilities | no | Controls which built-in behaviors are active. See Capabilities. | | grandTotals | GrandTotalsConfig | no | Renders a computed or caller-provided grand-totals row inside <thead> or <tfoot>. See Grand Totals. | | visualContainerCapabilities | VisualContainerCapabilities | no | Container features to enable when the grid frames itself. See VisualContainer framing. | | header | HeaderProps | no | { title, subtitle } rendered by the framing container. Supplying it frames the grid. See VisualContainer framing. |

Exported types

type CellValue = ReactNode;

interface GridColumnDef {
    id: string;
    header: string;
    width?: number;
    minWidth?: number;
    children?: GridColumnDef[];
    sortable?: boolean;
    filterable?: boolean;
    cellRenderer?: (value: CellValue, row: Row) => ReactNode;
    numericStyling?: boolean;
}

interface Row {
    _id?: string;
    _children?: Row[];
    _expanded?: boolean;
    [columnId: string]: CellValue | Row[] | undefined;
}

interface GrandTotalsConfig {
    position: 'top' | 'bottom';
    data?: DataTable;
}

type SortDirection = 'asc' | 'desc';

interface SortConfig {
    columnId: string;
    direction: SortDirection;
}

interface FilterChangeDetail {
    columnId: string;
    selectedValues: CellValue[];
}

interface CellRange {
    startRow: number;
    startCol: number;
    endRow: number;
    endCol: number;
}

Type notes

| Export | Notes | | --- | --- | | DataGridProps.columns | Optional when data is a DataTable; the grid derives id from ColumnDef.name and header from ColumnDef.displayName ?? ColumnDef.name. | | GridColumnDef.children | Enables grouped headers. Groups render as <th> with colSpan; only leaf columns render data cells. | | GridColumnDef.sortable | Default: true for leaf columns. | | GridColumnDef.filterable | Default: true for leaf columns. | | GridColumnDef.cellRenderer | Receives the resolved cell value and the full Row. | | GridColumnDef.numericStyling | Right-aligns cells (headers stay left-aligned) and uses tabular digits so numbers line up by place. true forces it, false opts out, undefined (default) auto-detects from a bounded ~100-row sample (head + evenly-spaced tail) — set explicitly if a column's type boundary may fall between samples. Columns with a cellRenderer skip auto-detection. | | Row._children | Enables tree rows with expand/collapse toggles and per-level indentation. | | Row._expanded | Seeds the initial expanded state for tree rows. | | SortConfig[] | Supports multi-column default sort order. Interactive multi-sort uses Shift+click. Sort cycling: unsorted → asc → desc → unsorted. | | CellRange | Rectangular selection coordinates expressed in visible row/column indexes. |

Capabilities

DataGrid supports an optional capabilities prop that lets consumers selectively disable built-in interactions or opt into pagination/virtualization without setting explicit pageSize/rowHeight props. Pass a partial DataGridCapabilities object — omitted keys use defaults.

Interface

import type { DataGridCapabilities } from '@microsoft/fabric-datagrid';

interface DataGridCapabilities {
    disableSorting?: boolean;
    disableFiltering?: boolean;
    disableColumnResize?: boolean;
    disableColumnReorder?: boolean;
    disableSelection?: boolean;
    pagination?: boolean | number;
    virtualization?: boolean | number;
}

Capability flags

| Flag | Default | Effect | |------|---------|--------| | disableSorting | false | When true, removes sort-on-click from all column headers. The header cursor reverts to default. | | disableFiltering | false | When true, hides filter icons and prevents the filter overlay from opening. | | disableColumnResize | false | When true, removes resize handles between column headers. | | disableColumnReorder | false | When true, disables drag-to-reorder columns. | | disableSelection | false | When true, disables cell/row selection, Shift+arrow range, and Ctrl+C copy. | | pagination | false | true enables pagination with a default page size of 50. A number sets the exact page size. Lower priority than the pageSize prop. | | virtualization | false | true enables virtualized rendering with a default 36px row height. A number sets the row height. Lower priority than the rowHeight prop. |

Usage

import { DataGrid } from '@microsoft/fabric-datagrid';
import type { DataGridCapabilities } from '@microsoft/fabric-datagrid';

const capabilities: DataGridCapabilities = {
    disableSorting: true,
    disableColumnReorder: true,
    pagination: 25,
};

export function ReadOnlyTable() {
    return <DataGrid data={data} capabilities={capabilities} />;
}

Explicit props (pageSize, rowHeight) always take priority over capability values. For example, if pageSize={10} is set on the component, capabilities.pagination is ignored.

VisualContainer framing

DataGrid can frame itself in a VisualContainer — the themed container from @microsoft/fabric-visuals-extensibility that draws a border and an optional title/subtitle header. No wrapper component is needed at the call site.

visualContainerCapabilities is unrelated to capabilities. capabilities configures grid behavior (sorting, pagination, …); visualContainerCapabilities configures the container around the grid.

When the grid frames itself

| Condition | Result | |-----------|--------| | No visualContainerCapabilities enabled and no header | Bare grid — no container, no chrome. | | At least one visualContainerCapabilities flag is true | Grid renders inside a VisualContainer. | | header is supplied | Grid renders inside a VisualContainer so the header has somewhere to render. | | Already inside a hand-authored VisualContainer | Grid renders bare into that container — it never frames twice. Its own header is ignored; set the header on the outer container instead. |

Usage

import { DataGrid } from '@microsoft/fabric-datagrid';

// Framed: bordered container with a header, and the built-in Copy Visual action.
export function RevenueTable() {
    return (
        <DataGrid
            data={data}
            header={{ title: 'Revenue by region', subtitle: 'FY26' }}
            visualContainerCapabilities={{ allowCopyVisual: true }}
        />
    );
}

// Bare: no container at all.
export function PlainTable() {
    return <DataGrid data={data} />;
}

For container features that DataGrid does not expose, such as custom toolbar actions, create the VisualContainer explicitly. Configure the header and custom actions on that outer container. DataGrid detects that it is already inside a VisualContainer and renders only the table, avoiding a nested container:

import { VisualContainer } from '@microsoft/fabric-visuals-extensibility';

<VisualContainer header={{ title: 'Revenue by region' }}>
    <DataGrid data={data} />
</VisualContainer>

See the VisualFramingProps and VisualContainerCapabilities definitions in @microsoft/fabric-visuals-core for the shared framing contract.

Rendering Modes

| Mode | Trigger | Behavior | |------|---------|----------| | Standard | No rowHeight or pageSize | Renders all rows in a plain <tbody>. | | Virtualized | rowHeight is set | Only visible rows are in the DOM (@tanstack/react-virtual, overscan: 5). Uses table-layout: fixed with flex rows. | | Paginated | pageSize is set | Shows pageSize rows per page with a pagination bar (first/prev/input/next/last). Page resets to 1 when data changes. |

Features

  • Sorting: Click a header to cycle (unsorted → asc → desc → unsorted). Shift+click for multi-column sort. Handles numbers, strings, booleans, and nulls (nulls sort last).
  • Column Filtering: Filter icon in header opens a portal overlay with search, "Select all" toggle, and virtualized checkbox list. Filtering by exclusion (unchecked values are hidden).
  • Column Resizing: Drag resize handles between headers. Uses direct DOM mutation during drag for 60fps, commits to React state on mouseup. Default width: 150px, min: 50px.
  • Column Reordering: Native HTML drag-and-drop with visual drop indicators.
  • Hierarchical Rows: Rows with _children render expand/collapse toggles (▸/▾) with 20px per-level indentation.
  • Grouped Headers: GridColumnDef.children enables multi-level header groups.
  • Data Fetching: Pass a URL string as data to auto-fetch JSON Row[]. Shows "Loading…" / "Error: ..." states.
  • Tooltip Truncation: Cells use CSS text-overflow ellipsis with native title tooltip only when content is actually truncated.
  • Interaction: Click rows to emit InteractionEvents. Click a row to emit a select event and click an already-selected row to emit a clear event.

Theming

Colors, typography, spacing, and border are controlled via a VisualTheme object from @microsoft/fabric-visuals-core. The theme prop is optional — when omitted, the grid falls back to its CSS variable defaults.

Color mapping (theme prop → CSS variables)

| VisualTheme field | CSS variable | Default | Description | |---|---|---|---| | foreground | --dg-text-color | var(--color-foreground) | Text color for body cells | | foreground | --dg-header-color | var(--color-card-foreground) | Text color for header cells | | brandForeground | --dg-highlight-color | var(--color-brand-foreground) | Color for drop indicators, active filter icons, resize handle hover | | background | --dg-bg-color | var(--color-card) | Body background color | | backgroundSecondary | --dg-header-bg | var(--color-muted) | Background color for header rows | | backgroundHover | --dg-hover-color | var(--color-hover) | Background color on row/header hover | | stroke | --dg-border-color | var(--color-border) | Border color for cell and header borders |

Border mapping (theme.border → CSS variables)

| VisualTheme field | CSS variable | Default | Description | |---|---|---|---| | border.width | --dg-border-width | 1px | Thickness of cell and header borders. Accepts a number (px) or a CSS length string. | | border.radius | --dg-border-radius | token default | Corner radius of the grid frame. Accepts a number (px) or a CSS length string. |

Both border.width and border.radius accept either a number (interpreted as pixels) or a CSS length string. A bare-number string is also treated as pixels, so 2, '2', and '2px' are equivalent, while '0.5rem' is used verbatim. Set border.width to 0 to remove the borders.

Layout CSS variables

| CSS variable | Default | Description | |---|---|---| | --dg-font-family | var(--font-base) | Font face for the grid | | --dg-font-size | var(--text-200) | Font size for cells and headers | | --dg-cell-padding | var(--spacing-s-nudge) var(--spacing-m) | Padding inside <th> and <td> cells |

Key Constraints & Gotchas

DataTable auto-derives columns; Row[] does not

// ✅ DO: Pass a DataTable — columns are auto-derived from ColumnDef[]
<DataGrid data={dataTable} />

// ✅ DO: When using Row[], provide explicit columns
<DataGrid data={rows} columns={columnDefs} />

// ❌ DON'T: Pass Row[] without columns — headers will be missing
<DataGrid data={rows} />

Container must have a bounded height for scrolling and virtualization

DataGrid renders to fit its parent. To engage scrolling and sticky headers, the parent must resolve to a definite height. Use design tokens for the bound (e.g., a flex/grid cell or a tokenized max-height). Do not use hardcoded pixel values.

// ✅ DO: Wrap DataGrid in a sized container
<div style={{ height: 400 }}>
    <DataGrid data={data} rowHeight={40} />
</div>

// ❌ DON'T: Render without a height constraint — virtualization won't activate and no scroll bar appears
<DataGrid data={data} rowHeight={40} />

Virtualized mode (rowHeight set) always requires a bounded parent — without one the virtualizer cannot determine the visible window and will render only overscan rows.

Virtualization and pagination are mutually exclusive

  • Virtualization activates when rowHeight is set and pageSize is NOT set.
  • Pagination activates when pageSize is set — the grid renders the full page without virtualization.

Tree rows are data-driven

// ✅ DO: Use _children and _expanded in row data
const rows: Row[] = [
    { _id: "1", name: "Parent", _expanded: true, _children: [
        { _id: "1.1", name: "Child" }
    ]},
];

DataTable format

  • DataTable uses column-major schema (columns: ColumnDef[]) with row-major values (rows: unknown[][]).
  • Row values are aligned to columns by index.
  • Missing row entries are normalized to null.

Theme is optional

  • theme?: VisualTheme can be provided to map theme values to CSS custom properties for foreground, background, borders, typography, etc. When omitted, the grid falls back to its CSS variable defaults.
// ✅ DO: Pass a theme for explicit control
import { useCssTheme } from '@microsoft/fabric-visuals';
const theme = useCssTheme();
<DataGrid data={data} theme={theme} />

// ✅ Also OK: Omit theme — the grid uses CSS variable defaults
<DataGrid data={data} />

Minimal Usage Examples

Render a DataTable

import { DataGrid } from '@microsoft/fabric-datagrid';
import type { DataTable } from '@microsoft/fabric-visuals-core';

const data: DataTable = {
    columns: [
        { name: 'category', displayName: 'Category' },
        { name: 'sales', displayName: 'Sales', format: '$#,##0.00' },
    ],
    rows: [
        ['Bikes', 1250.5],
        ['Accessories', 420.25],
    ],
};

export function Example() {
    return <DataGrid data={data} />;
}

Grand Totals

A single sticky grand-totals row can be computed from the filter-narrowed data or supplied by the caller.

<DataGrid theme={theme} data={dataTable} grandTotals={{ position: 'top' }} />
// or
<DataGrid theme={theme} data={dataTable} grandTotals={{ position: 'bottom' }} />
// or render values computed by a backend query
<DataGrid
    theme={theme}
    data={dataTable}
    grandTotals={{
        position: 'bottom',
        data: totalsDataTable,
    }}
/>
  • Computed totals. Omit data to compute totals from DataTable columns with a defaultAggregation that DataGrid honors. No row renders when no supported aggregation is configured. P0 honors only 'sum' and 'count'; a column declaring 'min' | 'max' | 'average' is treated as unaggregated and renders a blank total cell.
  • Provided totals. Set data to a DataTable that bypasses client aggregation and schema aggregation defaults. Values and formats are matched to rendered columns by ColumnDef.name, so the totals table may use a different column order or omit irrelevant columns. The caller owns fetching and updating this table when backend filter context changes.
  • Placement. 'top' puts the row inside <thead> (sticky with the header on vertical scroll); 'bottom' puts it inside <tfoot> (sticky to the bottom of the scroll container).
  • Label. DataGrid uses Total when the first leaf-column value is null or undefined; a populated provided value is preserved.
  • Formatting. Provided values use formats from the provided totals table. Computed sum values retain body-column formats, while computed count values use integer formatting.
  • Hierarchical data — leaves only. Aggregations walk only _children leaves; values on parent rows are ignored. count over a 3-parent / 9-leaf hierarchy is 9, regardless of expand/collapse state.
  • Filter-aware, sort/pagination/virtualisation independent. Filtering recomputes client totals; callers must replace provided totals data when backend filter context changes. Sort, pagination, and virtualisation do not affect either form.
  • Row[] input. Totals cannot be computed from Row[] today because defaultAggregation lives on the body DataTable schema, but a provided totals DataTable is supported.
  • A11y. The row is announced as Grand totals and value cells as Summary for <column>: <value>. The visible label cell uses role="rowheader"; value cells use role="gridcell" with aria-readonly="true".

Manual columns with Row[] and sorting

import { DataGrid } from '@microsoft/fabric-datagrid';
import type { GridColumnDef, Row, SortConfig } from '@microsoft/fabric-datagrid';
import { useCssTheme } from '@microsoft/fabric-visuals';

const columns: GridColumnDef[] = [
    { id: 'name', header: 'Name', sortable: true, filterable: true },
    { id: 'score', header: 'Score', width: 100 },
];

const rows: Row[] = [
    { name: 'Alice', score: 95 },
    { name: 'Bob', score: 87 },
];

const theme = useCssTheme();

<DataGrid columns={columns} data={rows} theme={theme} defaultSort={[{ columnId: 'score', direction: 'desc' }]} />

Virtualized with theming

import { DataGrid } from '@microsoft/fabric-datagrid';
import { lightThemeColors, type DataTable, type VisualTheme } from '@microsoft/fabric-visuals-core';

const theme: VisualTheme = {
    ...lightThemeColors,
    backgroundHover: '#f0f6ff',
};

export function Example() {
    return (
        <div style={{ height: 320 }}>
            <DataGrid data={data} rowHeight={40} theme={theme} />
        </div>
    );
}

Interaction events

import { DataGrid } from '@microsoft/fabric-datagrid';
import type { DataTable, InteractionEvent } from '@microsoft/fabric-visuals-core';
import { useCssTheme } from '@microsoft/fabric-visuals';

function handleInteraction(events: InteractionEvent[]) {
    for (const event of events) {
        if (event.action === 'select') {
            console.log('Selected:', event.selections);
        } else if (event.action === 'clear') {
            console.log('Deselected');
        }
    }
}

export function Example() {
    const theme = useCssTheme();
    return <DataGrid data={data} theme={theme} onInteraction={handleInteraction} />;
}

Trademarks

This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow Microsoft's Trademark & Brand Guidelines. Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies.

Security

Microsoft takes the security of our software products and services seriously, which includes all source code repositories in our GitHub organizations.

Please do not report security vulnerabilities through public GitHub issues.

For security reporting information, locations, contact information, and policies, please review the latest guidance for Microsoft repositories at https://aka.ms/SECURITY.md.

Code of conduct

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.

See full Microsoft Open Source Code of Conduct