bo-grid v3.1.0

Columns

.md

Column types

Pick a column type for each column, from prices and percentages to badges, ratings and progress bars, or register your own.

A column’s type decides how its values look and behave: the number format, the alignment, how it sorts and which filter it offers. Data types format numbers, dates and money. Rich types draw the value as a small widget. When none fits, register a type of your own with cellTypes, or draw the cell yourself with custom cells.

Every column below is a built-in type. Sort any of them: each sorts by its plain value, not by the widget.

column-types.svelte GitHub ↗

Data types

TypeValueShows
textstringText; sub names a field shown as a second, dimmer line
pricenumberA price with two decimals, in the column’s locale
percentnumberA signed percentage (+1.20%), coloured up or down
volumenumberA compact count: 1.2K, 3.4M, 1.1B, 2.0T
numbernumberA number with decimals places (default 2)
currencynumberMoney in currency (default USD), through Intl.NumberFormat
dateepoch ms (or a Date)A date; dateStyle is 'short' or 'medium' (default)
relativeepoch msA relative time: “3 hours ago”
heatmapnumberThe value on a colour ramp from min to max
sparklinecandlesA small chart drawn from the row field named by sparkKey

Rich types

TypeValueShows
avatardisplay nameInitials in a circle, with an optional sub line
badgestringA pill; tones maps values to up, down, amber, info or neutral
progressnumberA bar from min to max
ratingnumberStars out of max
tagsstring array, or a comma-separated stringChips
booleanbooleantrueLabel or falseLabel
linktextA link to href(row); newTab opens a new tab
customanythingWhatever the grid’s cell snippet draws
const columns: ColumnDef[] = [
  { type: 'avatar', key: 'name', header: 'Member', sub: 'role' },
  { type: 'badge', key: 'status', header: 'Status', tones: { Active: 'up', Away: 'amber', Offline: 'neutral' } },
  { type: 'progress', key: 'workload', header: 'Workload', min: 0, max: 100 },
  { type: 'rating', key: 'rating', header: 'Rating', max: 5 },
  { type: 'tags', key: 'skills', header: 'Skills' },
  { type: 'boolean', key: 'remote', header: 'Where', trueLabel: 'Remote', falseLabel: 'Office' },
  { type: 'link', key: 'email', header: 'Email', href: (r) => `mailto:${r.email}` },
];
  • link blocks unsafe hrefs (javascript: and data: URLs).
  • Rich types take their colours from the theme, so they follow light and dark themes with no extra code.
  • A widget is only how a value is drawn: sorting, filtering, copying and export use the value itself.

Registered cell types

When the same kind of column appears in several grids, such as a country, a money amount or an order status, define it once and give it a name. cellTypes maps a name to column defaults, and a column that says cellType: 'name' gets them under its own fields:

<script lang="ts">
  import { Grid, type CellTypeDef, type ColumnDef } from 'bo-grid';
  import CountryCell from './CountryCell.svelte';

  const cellTypes: Record<string, CellTypeDef> = {
    country: { extends: 'text', component: CountryCell, filter: 'set', width: 140 },
    money: { extends: 'number', decimals: 0, format: (v) => `$${Number(v).toLocaleString()}` },
  };
  const columns: ColumnDef[] = [
    { cellType: 'country', key: 'country', header: 'Country' },
    { cellType: 'money', key: 'rate', header: 'Rate', width: 96 }, // its own width wins
  ];
</script>

<Grid {rows} {columns} {cellTypes} height={560} />
  • extends names the built-in type the new one builds on: its formatting, sorting, filtering, alignment, aggregation and export. It defaults to custom when the entry draws the cell itself (component or render), and to text otherwise.
  • An entry can set any column field: format, compare, align, filter, width, cellClass, tooltip, editable, and type options such as decimals.
  • An unknown cellType renders as plain text rather than failing.
  • Outside the grid, resolveColumns(columns, cellTypes) returns the same resolved columns, for toCSV, printTable or pivot.

The Team example registers a country type with a flag component: see Custom cells.

Reference

Grid props from the types
cellTypes Record<string, CellTypeDef> Default undefined

Reusable column types, by name. A column with cellType: 'name' gets that entry's defaults (format, compare, align, filter, width, a component renderer…) under its own fields, and the built-in type named by extends for sorting, filtering and export.

Example
<Grid {rows} {columns} height={480}
  cellTypes={{ qty: { extends: 'number', decimals: 0, width: 80, format: (v) => Number(v).toLocaleString() } }} />
defaultColumn DefaultColumn Default undefined

Settings applied under every column — its own fields (and a registered cellType) win.

Example
<Grid {rows} {columns} height={480} defaultColumn={{ minWidth: 72, sortable: false }} />
locale string Default undefined

BCP 47 locale for the grid's own number formatting (aggregation bar, pager row count), and the default for each column's locale. Unset, the runtime's locale.

Column options from the types
format (value: unknown, row?: GridRow) => string

Custom display formatter, overriding the built-in type formatter. Applies to display, tooltip, copy and (formatted) export. row is absent for aggregate cells.

Example
{ type: 'number', key: 'qty', header: 'Qty', format: (v) => Number(v).toLocaleString('vi-VN') }
component Component<CellTypeProps>

Svelte component that draws this cell (receives value, row, column and the formatted text). Display only, like render. Usually supplied by a registered cellTypes entry, but any column can set it. It updates in place as its props change; under api.patchRows, row is a fresh view of the patched row on each patch (same fields, new identity), so read it reactively ($derived, markup) rather than once at mount.

Example
{ type: 'text', key: 'country', header: 'Country', component: CountryCell }
locale string Default undefined

BCP 47 locale for this column's built-in formatting (price, date, currency, relative). Unset, the grid's locale, then en-US.

Every type and the options it adds are listed in the Props reference.