OverviewGetting startedComponentsIconsGuidesExamples
OverviewGetting startedComponentsIconsGuidesExamples
GitHub repositoryJoin the c2n-webcomponents Discord

Table

Virtualized data grid with declarative columns, sorting, selection, pinning and resizing.

c2-table

A data grid: a scrolling, virtualized table built from a rows array (or an async dataSource) and a set of c2-table-column definitions given as light-DOM children. Sorting, row selection, column pinning, column resizing and keyboard navigation are built in; every cell can be rendered by a function, so a cell body can be any markup — including other c2 components.

Rows and columns are readable from markup as JSON attributes as well as from script as properties, so a table can be authored without a build step:

<c2-table row-key="id" selection="multiple" checkbox-selection sortable stripe style="height: 320px">
  <c2-table-column field="name" header="Name" width="2fr" pinned="start"></c2-table-column>
  <c2-table-column field="score" header="Score" width="120px" align="end" format="number"></c2-table-column>
</c2-table>

Layout. The table is one CSS grid: the header row and every body row are grid items using grid-template-columns: subgrid, so columns stay aligned without any scroll syncing, and pinned columns are position: sticky cells rather than separate containers. Give the host a height (or --c2-table--max-height) — the body scrolls inside it.

Styling one column. Every cell carries two parts named after its column — cell-<field> on the cell box and cell-content-<field> on the text inside it — so a single column can be given its own colour, alignment or pill shape from outside: ::part(cell-content-status) { border-radius: 999px; background: #f4f4f5 }. Rows are ::part(row) and ::part(row-selected).

Styling renderer output. What renderCell (or renderGroup) returns is placed in the table's own shadow root, so a page stylesheet cannot select it — but a part it carries is exposed as-is: return html`<span part="badge badge-${row.status}">…</span>` (or a node with that attribute) and style it with c2-table::part(badge). A part cannot be combined with an attribute or class selector, so encode the variant in the part name itself. Content slotted through a cell-slot column stays in the light DOM and takes page styles directly.

Styling one row. ::part(row) cannot be conditioned on row data (::part() takes no attribute selector), so rowPart adds part names of your own to a row from its data: table.rowPart = ({ row }) => row.failed ? 'row-failed' : undefined makes c2-table::part(row-failed) { background: #fef2f2 } work. rowStyle sets inline styles from the same context instead.

Virtualization windows the rows to the visible range plus an overscan margin. It needs a uniform row height, which it measures from the first rendered row, so theme the height with --c2-table__row--height (row-height is only the estimate used for the first paint). It turns on automatically past virtual-threshold rows; virtual="always" and virtual="never" force it. range-change reports the rows in the window and renderedRange holds the last one.

Wrapping cells. Cells clip their text to one line by default, which is what a windowed grid of uniform rows needs. wrap lets body cells grow instead: text wraps, rows take the height of their tallest cell (at least --c2-table__row--height), cell content is top-aligned with --c2-table__cell__wrap--padding and no longer clipped. Variable row heights cannot be windowed, so wrap turns virtualization off whatever virtual says and every row is rendered — keep it for tables of a few hundred rows, or page them with page-size.

Realtime updates. Add animate-updates when replacing rows with successive snapshots. Matching rows are found by row-key (or index), and their finite numeric fields are interpolated over update-duration. With a stable key, added rows expand in and deleted rows collapse out. Nested numbers in arrays and objects animate too, so a custom renderCell such as a sparkline receives the same transient row as the formatted cells around it. Add highlight-updates to pulse row backgrounds, and optionally choose its numeric direction with update-highlight-field. Only rendered rows are interpolated, and reduced-motion preferences are respected.

Row keys. Selection, value and events name a row by its key: the row-key field of the row (or getRowKey(row)) as a string, so { id: 7 } is "7". Without a row-key the key is the row's position, which points at another row after a sort, so set one on any selectable table. keyOf(row), isSelected(row), selectRows(rows) and deselectRows(rows) work from the rows themselves when the key rule is beside the point.

Summary row. Give a column summary="sum" (or avg, min, max, count, or a function of the rows) and the table adds a totals row below the body. It is a row of the same grid, so every value sits under its own column whatever the order, width or pinning, is formatted with the column's format, and stays in view while the body scrolls. Values are keyed by the column's id, which defaults to its field; summary-label puts text such as Total in a column with no value and summary-span stretches it across the columns after it. Aggregates cover every row (summary-scope="page" limits them to the page on show). A dataSource only holds the rows it has fetched, so give it the server's totals through summaryValues instead, which also overrides any computed value:

<c2-table summary-values='{"amount": 128450.5}'>
  <c2-table-column field="name" summary-label="Total"></c2-table-column>
  <c2-table-column field="amount" format="currency" align="end"></c2-table-column>
  <c2-table-column field="qty" align="end" summary="sum"></c2-table-column>
</c2-table>

Grouping. group-by="region,status" gathers the rows into collapsible groups, outermost level first; the grid becomes a treegrid. With the default group-display="row" each group is a row of the grid: its label and row count in the first column (or the one marked group-column), and under every column with a summary that aggregate over the group's rows, formatted like the column. group-display="band" draws one full-width band per group instead. A group is named by its path, region=EMEA/status=Paid: expanded-groups lists the open ones (every group is open until then, or closed with groups-collapsed), group-toggle reports a click, and a group's checkbox selects its rows. The groups of the rows at the top stay under the header while their rows scroll, and a page that starts inside a group repeats its headers; pages count display lines, so a closed group takes one. Grouping is done on the client and does not apply to a dataSource.

<c2-table row-key="id" group-by="region" selection="multiple" checkbox-selection>
  <c2-table-column field="customer" header="Customer"></c2-table-column>
  <c2-table-column field="region" hidden></c2-table-column>
  <c2-table-column field="amount" format="currency" align="end" summary="sum"></c2-table-column>
</c2-table>

Wrapped in a c2-context-menu, a right-clicked or long-pressed body cell answers the menu's request with the same detail as cell-click (row, rowIndex, key, column, value), which the menu passes on as context.data with this table as context.source, so renderContextMenu can build the rows for that cell. The cell also takes the keyboard focus.

Attributes

NameTypeDefaultDescription
aria-labelstring | nullnullThe host's aria-label, observed so the grid inside the shadow root is named after it: the host is not the grid, so a name set on it would otherwise name nothing.
aria-labelledbystring | nullnullThe host's aria-labelledby. ARIA cannot resolve a light-DOM id from inside the shadow root, so the referenced elements' text is copied onto the grid instead, and aria-labelledby wins over aria-label as ARIA ranks them.
rowsTableRow[][]The rows to display. An array in the property, JSON in the attribute.
columnsTableColumnConfig[] | undefined—Column definitions, as an alternative to c2-table-column children. Children win when both are present.
row-keystring—Field holding the identity of a row — its key — used for selection, DOM reuse, animated updates and cell slots; may be a dotted path. A key is always a string: { id: 7 } has the key "7". Without one (or where the field is empty) a row's key is its position in the sorted dataset, which moves when the rows are sorted or replaced — so a selection would move with it. Set it whenever rows can be selected.
selectionTableSelectionModenonesingle selects one row at a time, multiple supports ⌘/ctrl-click and shift-click ranges. A click selects the row alone; clicking the row that is already the whole selection clears it, and ⌘/ctrl-click or Space toggles one row.
checkbox-selectionbooleanfalseAdds a leading checkbox column, pinned to the start.
valuestring[][]Keys of the selected rows (see row-key): an array in the property, ;-separated in the attribute. Entries are stored as strings, so [1, 2] selects the rows whose key field holds 1 and 2. To select by row rather than by key, use selectRows().
sortSortModel[][]The sort, in priority order: SortModel[] in the property, field:asc;other:desc in the sort attribute.
multi-sortbooleanfalseLets shift-click add a column to the sort instead of replacing it.
sortablebooleanfalseMakes every column sortable; a column's own sortable still wins.
resizablebooleantrueColumns are resizable by default; resizable="false" turns it off. A column's own resizable still wins.
stripebooleanfalseTints odd rows with --c2-table__row__odd--background.
animate-updatesbooleanfalseSmoothly interpolates changed finite numbers when rows is replaced. Rows are matched by row-key, or by index.
update-durationnumber400Duration of an animated rows update in milliseconds.
highlight-updatesbooleanfalsePulses changed row backgrounds: green for additions/increases, red for removals/decreases, blue otherwise.
update-highlight-fieldstring—Numeric field that determines whether a modified row highlights as increased or decreased. Defaults to its first changed number.
virtualTableVirtualModeautoauto virtualizes past virtual-threshold rows; always and never force it. wrap overrides it with never.
wrapbooleanfalseWraps body cell text onto several lines: rows grow to their content (at least --c2-table__row--height) and cells are top-aligned and no longer clipped. Rows of different heights cannot be windowed, so this turns virtualization off — every row is rendered, whatever virtual says.
row-heightnumber36Row height in pixels used before the first row has been measured.
overscannumber6Rows rendered above and below the viewport while virtualizing.
virtual-thresholdnumber100Row count past which virtual="auto" starts windowing.
block-sizenumber100Number of rows the table asks a dataSource for at a time.
loadingbooleanfalseShows the loading state; implied while a dataSource resolves its first block.
errorstring—Shows the error state with this message.
empty-messagestringNo rowsMessage shown when there are no rows.
pagenumber1The page on show, 1-based. Only meaningful while the table is paginated; clamped to pageCount.
page-sizenumber0Rows per page. 0 leaves paging off; a c2-pagination slotted into the footer sets it from its own page-size when the table has none, which is what makes the nested form work with no configuration. With rows the page is sliced in place; with a dataSource each page is one request.
summary-valuesRecord<string, unknown> | undefined—Values of the summary row keyed by column id (its field unless set), such as totals computed by a server. An entry wins over the column's summary aggregate. An object in the property, JSON in the attribute.
summary-scopeTableSummaryScopeallRows the summary aggregates cover: all rows, or only the page on show. A dataSource is only aggregated per page.
group-by(string | TableGroupBy)[][]Groups the rows by these fields, outermost first: group-by="region,status" in the attribute, and field names or TableGroupBy objects in the property. Not applied to a dataSource, which only holds the rows it fetched.
group-displayTableGroupDisplayrowrow gives each group a row of the grid with its column aggregates; band draws a full-width band per group.
expanded-groupsstring[] | undefined—Keys of the open groups (region=EMEA/status=Paid). While unset, every group follows groups-collapsed; the first toggle writes the full list here, so it can be read, stored and handed back. ;-separated in the attribute.
groups-collapsedbooleanfalseStarts every group closed while expandedGroups is unset.
empty-group-labelstringNo valueLabel of the group of rows whose value is empty.

Slots

NameDescription
defaultThe column definitions: c2-table-column elements. They render nothing themselves.
toolbarBar above the header, for a title, filters or a column menu. Hidden when empty.
footerBar below the rows, for a row count or a c2-pagination. Hidden when empty.
emptyReplaces the built-in "no rows" message.
loadingReplaces the built-in spinner shown while the first rows load.
errorReplaces the built-in message shown when error is set.
fallbackMeaningful server-rendered table content. It remains visible before custom-element upgrade and is retained in the light DOM but hidden after the interactive grid mounts, avoiding duplicate client content.
group:{groupKey}Label of one group, e.g. slot="group:region=EMEA", in place of its formatted value and row count. The copy of the group kept under the header while its rows scroll shows the built-in label.
cell:{line}:{field}Body of one cell of a column marked cell-slot, e.g. slot="cell:0:change" for the first displayed row. line is the cell's display line, counted across the whole dataset after sort, filter and grouping with the page offset included — the numbering of range-change. Lets a framework render a cell with its own template language instead of a renderCell function; the column's renderCell or formatted value stays as the fallback. Children are needed only for the lines range-change reports (map detail.rows, or renderedRange.rows, each { line, key, row }); a child whose line is outside the rendered window is left unassigned. After a sort, filter or page change the same line holds a different row, so re-render the children from the next range-change.

Events

NameTypeDescription
page-changeCustomEvent<TablePageChangeEventDetail>Fired after the shown page changes, while paginated. detail.start and detail.count are the slice of the whole dataset now shown — with a dataSource, the getRows request that follows. A pager slotted in the footer does not fire its own: the table speaks for it.
range-changeCustomEvent<TableRangeChangeEventDetail>Fired after the rendered body rows change — the window scrolled, or the rows, sort, page or grouping changed. detail.start/detail.end are the display lines rendered (end exclusive), detail.rows one { line, key, row } entry per rendered data row in display order (group rows and rows a dataSource has not delivered are left out) and detail.keys their keys. Those lines are the only ones whose cell:{line}:{field} slots exist. Fires again when the same keys move to other lines. Does not bubble.
group-toggleCustomEvent<TableGroupToggleEventDetail>Fired after the user opens or closes a group, with its key, whether it is now expanded, and the group itself (its rows and aggregates). expandedGroups already holds the new state. Does not bubble.
sort-changeCustomEvent<TableSortChangeEventDetail>Fired after the user clicks a sortable header. detail.sort is the new sort model, in priority order.
row-clickCustomEvent<TableRowEventDetail>Fired when a row is clicked, before the selection is applied.
row-activateCustomEvent<TableRowEventDetail>Fired when the user opens a row: a pointer click on it, or Enter on one of its focused cells — so one listener serves a table used for navigation from the mouse and the keyboard alike. Not fired by a click or Enter that belongs to a control inside a cell (a button, link or input), and fired before the selection is applied. Does not bubble: a table nested in another table's cell would otherwise open the outer row too, so the listener belongs on the element itself.
cell-clickCustomEvent<TableCellEventDetail>Fired when a cell is clicked; adds detail.column and detail.value.
selection-changeCustomEvent<TableSelectionChangeEventDetail>Fired after the user changes the selection. detail.value is the array of selected row keys, detail.rows the matching rows. Does not bubble: several components fire selection-change, so a listener belongs on the element itself rather than on an ancestor.
column-resizeCustomEvent<TableColumnResizeEventDetail>Fired when the user releases a column's resize handle.

CSS parts

Shadow DOM styling hooks used with ::part(name). Prefer CSS custom properties when they cover the change.

NameDescription
toolbarRow above the grid containing the toolbar slot.
viewportScrollable container around the grid.
gridThe ARIA grid containing the header and body rows.
footerRow below the grid containing the footer slot.
stateShared cell containing the empty, loading, or error slot and its fallback state.
header-rowThe grid header row.
header-cellEvery column header cell.
selection-header-cellThe header cell containing the select-all checkbox.
resizerThe pointer target used to resize a column.
sort-iconThe sort-direction indicator in a sortable header.
cellEvery body grid cell.
selection-cellA body cell containing a row-selection checkbox.
skeletonPlaceholder displayed while a remote row is loading.
cell-contentThe content wrapper inside a body cell.
rowEvery rendered body row. Also carries the names rowPart returns for it, such as row-failed.
row-selectedA body row while it is selected; exposed in addition to row.
summary-rowThe totals row kept at the bottom of the grid.
summary-cellEvery cell of the summary row. Each also carries summary-cell-<id>, named after its column.
summary-contentThe content wrapper inside a summary cell; also summary-content-<id>.
group-rowEvery group row. Also group-row-level-<n> (0 for the outermost level), group-band with group-display="band", and group-row-echo on a copy kept under the header.
group-cellEvery cell of a group row. Each also carries group-cell-<id>, named after its column.
group-toggleThe chevron of a group row.
group-labelThe group's value, or what renderGroup returned.
group-countThe number of rows in the group.

CSS custom properties

Grouped by semantic target and state from --c2-<component>__<target>__<state>--<property>. Click a group to collapse it; click a name to copy it.

NameTypeDefaultDescription
c2-table
--c2-table--backgroundcolor#ffffff
--c2-table--colorcolor#18181b
--c2-table--font-sizefont-size14px
--c2-table--max-heightpixelnoneCaps the height when the host is not sized itself; the body scrolls.
--c2-table--border-topborder1px solid #e4e4e7
--c2-table--border-rightborder1px solid #e4e4e7
--c2-table--border-bottomborder1px solid #e4e4e7
--c2-table--border-leftborder1px solid #e4e4e7
--c2-table--border-top-left-radiusborder-radius8px
--c2-table--border-top-right-radiusborder-radius8px
--c2-table--border-bottom-left-radiusborder-radius8px
--c2-table--border-bottom-right-radiusborder-radius8px
--c2-table--box-shadowbox-shadownone
c2-table > header
--c2-table__header--backgroundcolor#fafafa
--c2-table__header--colorcolor#71717a
--c2-table__header--heightpixel36px
--c2-table__header--font-sizefont-size12px
--c2-table__header--font-weightfont-weight600
--c2-table__header--letter-spacingletter-spacing0.02em
--c2-table__header--border-bottomborder1px solid #e4e4e7
c2-table > header-cell
--c2-table__header-cell--paddingpadding0 12px
--c2-table__header-cell--gappixel6px
c2-table > header-cell > hover
--c2-table__header-cell__hover--backgroundcolor#f4f4f5
c2-table > header-cell > sorted
--c2-table__header-cell__sorted--colorcolor#18181b
c2-table > sort-icon
--c2-table__sort-icon--widthpixel14px
--c2-table__sort-icon--heightpixel14px
--c2-table__sort-icon--colorcolor#a1a1aa
c2-table > sort-icon > active
--c2-table__sort-icon__active--colorcolorrgb(2, 101, 220)
c2-table > resizer
--c2-table__resizer--widthpixel9pxWidth of the grab area, not of the visible line.
--c2-table__resizer--heightpixel56%Height of the resting divider, as a share of the header.
--c2-table__resizer--line-widthpixel1px
--c2-table__resizer--colorcolor#e4e4e7The divider drawn at a resizable column's edge.
c2-table > resizer > hover
--c2-table__resizer__hover--heightpixel100%
--c2-table__resizer__hover--line-widthpixel2px
--c2-table__resizer__hover--colorcolorrgb(2, 101, 220)
c2-table > row
--c2-table__row--heightpixel36pxRow height; virtualization measures it, so keep it uniform.
--c2-table__row--border-bottomborder1px solid #e4e4e7
c2-table > row > hover
--c2-table__row__hover--backgroundcolor#f4f4f5
c2-table > row > odd
--c2-table__row__odd--backgroundcolor#fafafaApplies with the stripe attribute.
c2-table > row > selected
--c2-table__row__selected--backgroundcolor#edf1fe
--c2-table__row__selected--colorcolor#18181b
c2-table > row > selected > hover
--c2-table__row__selected__hover--backgroundcolor#e2e9fdA selected row under the pointer.
c2-table > row > added
--c2-table__row__added--backgroundcolorrgba(22,163,74,0.16)Highlight used while a realtime row expands into the table.
c2-table > row > removed
--c2-table__row__removed--backgroundcolorrgba(220,38,38,0.14)Highlight used while a realtime row collapses out of the table.
c2-table > row > increased
--c2-table__row__increased--backgroundcolorrgba(22,163,74,0.14)Pulse used when the watched numeric value increases.
c2-table > row > decreased
--c2-table__row__decreased--backgroundcolorrgba(220,38,38,0.12)Pulse used when the watched numeric value decreases.
c2-table > row > modified
--c2-table__row__modified--backgroundcolorrgba(2,101,220,0.1)Pulse used when a change has no numeric direction.
c2-table > cell
--c2-table__cell--paddingpadding0 12px
--c2-table__cell--gappixel8px
--c2-table__cell--font-sizefont-size14px
--c2-table__cell--colorcolor#18181b
--c2-table__cell--border-rightbordernoneVertical grid lines; applies to header cells too.
c2-table > cell > wrap
--c2-table__cell__wrap--paddingpadding8px 12pxBody cell padding with wrap, where content is top-aligned.
c2-table > cell > focus
--c2-table__cell__focus--outlineoutline2px solid rgba(2, 101, 220, 0.4)
--c2-table__cell__focus--outline-offsetpixel-2px
c2-table > pinned-start
--c2-table__pinned-start--box-shadowbox-shadow1px 0 0 0 #e4e4e7Separator on the last column pinned to the start.
c2-table > pinned-end
--c2-table__pinned-end--box-shadowbox-shadow-1px 0 0 0 #e4e4e7Separator on the first column pinned to the end.
c2-table > summary
--c2-table__summary--heightpixel36px
--c2-table__summary--backgroundcolor#fafafa
--c2-table__summary--colorcolor#18181b
--c2-table__summary--font-sizefont-size14px
--c2-table__summary--font-weightfont-weight600
--c2-table__summary--box-shadowbox-shadow0 -1px 0 0 #e4e4e7Separator above the summary row; a shadow rather than a border so it lands on the last row's own border instead of doubling it.
c2-table > group-row
--c2-table__group-row--backgroundcolor#fafafa
--c2-table__group-row--colorcolor#18181b
--c2-table__group-row--font-weightfont-weight600
c2-table > group-row > hover
--c2-table__group-row__hover--backgroundcolor#f4f4f5
c2-table > group-row > echo
--c2-table__group-row__echo--box-shadowbox-shadow0 1px 0 0 #e4e4e7Separator under a group row kept under the header.
c2-table > group-band
--c2-table__group-band--backgroundcolor#f4f4f5Background of a group with group-display="band".
c2-table > group
--c2-table__group--indentpixel24pxIndentation per group level; the default lines rows up with their group's label.
c2-table > group-toggle
--c2-table__group-toggle--sizepixel16px
--c2-table__group-toggle--colorcolor#71717a
--c2-table__group-toggle--transition-durationtime150msChevron turn when a group opens or closes; respects reduced motion.
c2-table > group-count
--c2-table__group-count--backgroundcolor#f4f4f5
--c2-table__group-count--colorcolor#52525b
--c2-table__group-count--font-sizefont-size12px
--c2-table__group-count--font-weightfont-weight600
--c2-table__group-count--paddingpadding1px 7px
--c2-table__group-count--border-radiusborder-radius999px
c2-table > selection-cell
--c2-table__selection-cell--widthpixel44pxWidth of the checkbox-selection column.
c2-table > skeleton
--c2-table__skeleton--backgroundcolor#f4f4f5Placeholder shown in cells whose dataSource block is still loading.
--c2-table__skeleton--border-radiusborder-radius4px
c2-table > state
--c2-table__state--colorcolor#71717aColour of the empty and loading messages.
--c2-table__state--paddingpadding32px 12px
--c2-table__state--font-sizefont-size14px
c2-table > state > error
--c2-table__state__error--colorcolorrgb(211, 21, 16)
c2-table > toolbar
--c2-table__toolbar--backgroundcolortransparent
--c2-table__toolbar--paddingpadding8px 12px
--c2-table__toolbar--border-bottomborder1px solid #e4e4e7
c2-table > footer
--c2-table__footer--backgroundcolortransparent
--c2-table__footer--paddingpadding8px 12px
--c2-table__footer--border-topborder1px solid #e4e4e7

c2-table-column

One column of a c2-table, declared as a light-DOM child. The element renders nothing: it is a definition the table reads, the same way c2-select reads its c2-list-item children. Everything it exposes as an attribute can also be set as a property, and the function-valued properties (renderCell, renderHeader, comparator) are property-only.

<c2-table rows='[{ "name": "Ada", "score": 12 }]'>
  <c2-table-column field="name" header="Name" width="2fr" sortable pinned="start"></c2-table-column>
  <c2-table-column field="score" header="Score" width="120px" align="end" format="number" sortable></c2-table-column>
</c2-table>

Attributes

NameTypeDefaultDescription
column-idstring—Stable identity of the column; defaults to field. Set it when two columns show the same field, or for a computed column with no field. Widths, pinning, the cell-<id> parts and the summary row are keyed by it. Not the HTML id, which has to be unique in the whole document rather than in one table.
fieldstring—Key of the value in the row object; may be a dotted path such as user.name.
headerstring | undefined—Header label. Falls back to the field name.
widthstring1frGrid track for the column: 1fr, 160px, minmax(120px, 1fr)…
min-widthnumber64Lower bound in pixels: the floor of a flexible (fr) track on a narrow table, and while the column is resized.
alignColumnAlignstartHorizontal alignment of the header and the cells.
sortableboolean | undefined—Lets the user sort by this column. Absent inherits the table's sortable; sortable="false" opts out.
resizableboolean | undefined—Lets the user drag the column's trailing edge. Absent inherits the table's resizable; resizable="false" opts out.
pinnedColumnPin | undefined—Freezes the column against the leading or trailing edge while scrolling horizontally.
hiddenbooleanfalseLeaves the column out of the table without removing the definition.
formatColumnFormattextBuilt-in Intl formatting applied when no renderCell is set.
format-optionsRecord<string, unknown> | undefined—Options handed to the Intl formatter of format, as JSON in the attribute.
currencystring | undefined—Currency code used by format="currency".
localestring | undefined—BCP 47 locale used by format. Defaults to the browser locale.
cell-classstring | undefined—Class set on every cell of this column, so light-DOM CSS can target it through ::part(cell).
cell-slotbooleanfalseRenders each cell from a light-DOM child of the table rather than from renderCell: the cell holds a <slot name="cell:<line>:<field>">, line being the row's display line, so a framework can build the body with its own template language. Render children only for the lines the table's range-change reports (detail.rows); after a sort, filter or page change the same line holds another row, so re-render from the next range-change.
summaryTableSummaryAggregate | TableSummaryFunction | undefined—Value of the column in the table's summary row: sum, avg, min, max or count, or a function of the rows (property only).
summary-labelstring | undefined—Text shown in the column's summary cell when it has no value, such as Total.
summary-alignColumnAlign | undefined—Alignment of the summary cell. Defaults to align.
summary-spannumber | undefined—Number of columns the summary cell spans, starting at this one; the spanned columns' summaries are not shown.
group-columnbooleanfalsePuts the group tree (chevron, group label and count, indentation) in this column while the table is grouped. Defaults to the first column.
AccordionConnected, animated panels with shared borders and single or multiple expansion.LayoutAction BarA floating bar for the current selection: the count, the bulk actions and a button that clears it.LayoutApp ShellThe frame of an application: header, navigation, main, an optional details panel, banner and footer, laid out from its own width.LayoutArea chartA line chart with the region under each line filled — every line-chart attribute, plus a fill opacity.ChartAttachmentFile and image attachments with metadata, upload progress, failure states, and actions.Data displayAutocompleteSearchable combobox for local or remote items with customizable list rows.InputsAvatarImage, initials or icon for a person, with status dot and badge.Data displayBadgeTinted pill for status text, counts and dots, optionally pinned to a corner of another element.Data displayBannerA persistent, full-width message in the page flow for system notices, outages and account status.FeedbackBar chartBars over categories or time buckets, with several series drawn side by side within each band.ChartBar ListA ranked list whose rows carry their own bar: top pages, referrers, countries, or the changes between two periods.Data displayBorder BeamA decorative beam that travels around the border of any positioned container.LayoutBottom NavThe mobile tab bar: three to five destinations along the bottom of the screen, each an icon over a short label with a count or dot badge.NavigationBreadcrumbNavigation trail of link buttons with separators, a current page and optional collapsing.NavigationBubble chartAn ECharts scatter plot with a third measure encoded as bubble area, for comparing how two measures relate while showing how much each point weighs.ChartButterfly chartTwo series back to back on a shared category axis, the categories named between them. The population pyramid is the classic case.ChartButtonThemeable button with slots for text, prefix, suffix and running icons.ButtonsButton GroupJoined actions and polished segmented controls with single or multiple selection.ButtonsCandlestick chartAn ECharts OHLC chart for market sessions and other open-close ranges, with semantic positive and negative colours.ChartCardGroups related content and actions on a single bordered surface.LayoutCard InputCard number, expiry date and security code in one field, formatted as the brand prints them and checked as they are typed.InputsCarouselA swipeable slideshow with previous/next controls, indicators, looping and optional autoplay.LayoutCascaderSelect a value from related, multi-level data in one floating panel.InputsChat InputAuto-growing message composer with keyboard submission, toolbar actions and native form support.ChatChat MessageFlexible message row for conversations, assistant answers and activity updates.ChatChat Message ListScrolling conversation log that follows new messages, counts unread ones and loads older history.ChatCheckboxNative checkbox behaviour in a quiet, themeable box with an opt-in hover layer.InputsCheckbox groupCheckboxes grouped into one form control with a value array, a group label and an at-least-one rule.InputsChipA compact pill for a filter, a choice or an entered value: selectable as a toggle, removable with a button or the keyboard.InputsChip GroupA single row of chips or badges that collapses whatever does not fit into a +N indicator, recomputed as the row or its items change size.Data displayChoice MatrixRows × columns of checkboxes or radio buttons in one form control: permissions, notification settings, agreement scales.InputsChord chartFlows between groups around a circle, where one row is one flow from a source to a target.ChartCitationA numbered inline marker that names its source, with a hover preview of the page it cites.ChatCode EditorEditable, syntax-highlighted source field on CodeMirror 6, themed entirely through CSS variables.Editors & viewersCode ViewerSyntax-highlighted code with line numbers, copy button and dark mode, powered by shiki.Editors & viewersColor AreaTwo-dimensional area for picking saturation and value of a colour.InputsColor SelectColour swatch that opens a full picker built from area and slider.InputsColor SliderHorizontal slider for choosing a hue from 0 to 360.InputsCommandA searchable list of commands: type to filter, arrows to highlight, Enter to run. The core of a ⌘K palette.NavigationComparison BarSegmented ratio bar comparing two or three quantities, such as the bid/ask balance of an order book.Data displayConfirm DialogAsks the user to confirm an action: await show() or confirm() for a true/false answer, with a destructive variant and an async confirm action.FeedbackContext MenuA menu opened by right-clicking or long-pressing an area, built from a slotted c2-menu or a render function per clicked spot.NavigationCopy ButtonButton that copies text to the clipboard — the element it sits in, another element by id, or a literal string.ButtonsCountdownTime left until a date, or through a timer, drawn as segments, a clock or a phrase, and kept current to the second.Data displayDashboardGrid of resizable panes, dragged by the edges they share.LayoutDate InputForm-associated single-date input with native picker, constraints, helper text and error states.InputsDate SelectorAccessible one- or two-month calendar for choosing a date range.InputsDate StripA row of days to pick one from, a week at a time, with dots on the days that have something on them.InputsDate Time PickerForm-associated date-and-time field with a calendar and time popup, min/max/step constraints and an IANA time zone.InputsDepth chartCumulative bid and ask size around the mid price of an order book, as trading screens show market depth.ChartDescription ListRead-only label and value pairs for a detail page, in columns that wrap with the available width.Data displayDetailsCollapsible disclosure built on native details and summary.LayoutDiff ViewerRead-only line diff of two texts, unified or side by side, with folded unchanged lines and word highlights.Editors & viewersDistribution BarOne 100% stacked bar of a breakdown, with a legend of shares and the hovered part brought forward.Data displayEmoji PickerA searchable grid of emoji in categories, with skin tones and the emoji used last.InputsFacet ListOne facet of a filter sidebar: an attribute’s values with counts, to include or exclude from a search.InputsFieldsetGroups related controls under a legend, with a description, a group-level error and a disabled state that reaches every control inside.InputsFilter BuilderA filter bar of sentence chips (Status is any of Active), an add-filter picker and an editor for each part; it reports a plain JSON filter tree.InputsFloat ButtonA floating action button for the main action of a screen, which can expand into a speed dial of related actions.ButtonsFlowA pipeline, dependency graph or database schema on a pannable canvas: steps with a status, smooth edges, rows joined row to row, auto layout, draggable nodes saved to localStorage, a hover card and a context menu.Editors & viewersFormForm container with validation timing, an error summary, server errors, dirty tracking and async submit.InputsForm FieldLabel, hint, error, warning and character counter around any form control, wired for assistive technology.InputsFormat DateA date and time formatted for the reader's language and, optionally, a fixed time zone.Data displayFormat NumberA number formatted for its locale: currency, percent, units, compact counts and byte sizes, from Intl.NumberFormat.Data displayGanttA read-only project timeline: tasks, groups, milestones and dependencies on a day, week or month scale.PlanningGauge chartA focused radial KPI gauge drawn by ECharts, with a configurable scale, progress arc and pointer.ChartGoogle MapGoogle Maps with markers, a road route from A to B, and Street View, loaded once per page from a browser key.Data displayHeaderArranges brand, navigation, actions and a mobile trigger in a reusable site shell.LayoutHeatmap chartRows binned into cells by two keys, aggregated, and coloured by a sequential, diverging or stepped scale: a currency matrix, pair × tenor, hour × weekday, or a calendar of days. Drawn by ECharts, with a colour key that counts, marks and filters.ChartHighlightMarks the parts of a text that match a search query.Data displayHover CardInteractive preview card shown when a link or mention is hovered or focused, rendered in the top layer.FeedbackIcon ButtonRound, hoverable button wrapping a slotted SVG icon.ButtonsImageImage with lazy loading, a loading placeholder, an error fallback, click-to-load for untrusted URLs and a full-screen preview.Data displayImage CropperChoose the part of an image to keep by moving and resizing a selection, then read it back as a canvas or a blob.Editors & viewersIndicatorSolid dot or count pinned to an edge or corner of any element, with an accessible name for the count.Data displayInline EditText that turns into a field on click: Enter (Ctrl/⌘+Enter when multiline) commits, Escape cancels, and any control with a value that fires change can be the editor.InputsJSON FormA form generated from a JSON Schema, laid out by the schema, a UI schema or your own markup.InputsJSON ViewerBrowse a JSON value as a collapsible tree, search it, and copy any path or value.Editors & viewersKanbanBoard layout and card movement by pointer or keyboard, with cards drawn by your own renderItem.PlanningKbdKeyboard key label for shortcuts and command hints, with the semantics of the native kbd element.Data displayKey Value EditorEditable KEY=value rows for environment variables and headers: paste a .env file to split it into rows, mask secret values, and flag duplicate or malformed keys.InputsLabelCaption that names and activates the control referenced by its for attribute, with a required marker.InputsLine chartA line chart over a time or numeric x axis, drawn on canvas by uPlot, with series declared as children.ChartLink ButtonText-styled control for link and navigation actions, rendered as a real anchor or a button.NavigationListVertical list container with single or multiple selection.Data displayList ItemSelectable row with icon slots, used on its own or as the option of list and select.Data displayLoading OverlayCovers a region while it loads: the content stays in place, dimmed and blocked, with a spinner and an announced label.FeedbackLog ViewerExplore large logs with variable-height virtual scrolling and sticky tabular attributes.Editors & viewersMap chartA choropleth and point map on vector outlines, drawn by ECharts: regions shaded by a value, with layers of sized points and flow lines, on the bundled world and US maps or your own GeoJSON, TopoJSON or SVG.ChartMarkdownSafe markdown renderer that streams: chat answers and READMEs, with code, math and diagrams.ChatMarkerAn inline marker that highlights, underlines, strikes through, boxes or circles a run of text.Data displayMask InputA text input that fits what is typed to a pattern, for postcodes, IBANs, tax IDs, expiry dates and other fixed formats.InputsMasonryAutomatically pack differently sized dashboard tiles, then move or resize them in edit mode.LayoutMaster DetailA list beside the record it opens, one pane at a time with a Back step when the element is narrow.LayoutMathTeX formulas rendered as native MathML: no font CSS, readable by screen readers, safe for untrusted input.Data displayMenuCommands, links, checkboxes and submenus in a popover anchored to a trigger.NavigationMenubarDesktop-style File, Edit and View menus in one bar, with the arrow-key and hover movement of an application menu bar.NavigationMermaidMermaid text diagrams drawn in your theme colours, loaded on demand and safe for untrusted sources.Data displayMeterA measurement inside a known range — storage, quota, strength — with native meter thresholds and an optional segmented breakdown.Data displayModalDialog built on the native dialog element: focus trap, backdrop, Escape, title, body and footer.FeedbackMoney InputCurrency amount field that groups digits as you type, follows the locale and stores an integer count of minor units.InputsMonth PickerPick a month, or a year: billing periods, reports and card expiry.InputsMonth PlannerMonth calendar that draws events and trips as bars across the days they cover.PlanningNavigation MenuSite navigation bar whose triggers open panels of links below the header.NavigationNotepadA rich-text notepad that looks like paper: handwriting on ruled lines, a formatting toolbar over the selection, checklists and tear-off pages.PlanningNotification CenterAn inbox panel of notifications grouped by day, with read and unread states and mark all as read.FeedbackNumber InputForm-associated numeric input with native validation, step controls, adornments and helper states.InputsOrg ChartA hierarchy drawn as connected cards that collapse and expand: an organization chart, a reporting line or a team structure.Data displayOTP InputForm-associated one-time-code field with one cell per character, paste and SMS autofill, grouping and masking.InputsOverflow ListOne row of actions or links that shows what fits and folds the rest into a "More" menu, refitting as its width changes.LayoutOverlap chartA Venn diagram of two or three sets, where each circle is a set and each shared area counts the members of exactly that combination.ChartOverlayAnchored popup built on the browser Popover API, positioned with floating-ui.FeedbackPage EditorA Notion-style editor for long text: Markdown shortcuts while you type, a / menu for blocks, a toolbar over selected text, code blocks with syntax colours and eight named colours.Editors & viewersPage HeaderThe top of a page: breadcrumb or parent link, your heading with status badges, description, metadata, page actions that fold into a menu, tabs and a toolbar.LayoutPaginationPage navigation in three layouts: numbered pages, a simple page status, or a table-footer row with rows-per-page.NavigationPassword FieldA password input with a show/hide toggle, a strength meter, a requirements checklist and a Caps Lock warning.InputsPhone InputA phone number field with a searchable country picker, as-you-type grouping and an E.164 value.InputsPie chartA pie or donut chart drawn by ECharts, where one row is one slice and label-field names it.ChartPopconfirmA small "Are you sure?" popup anchored to the button that asked for it.FeedbackProgressProgress bar or ring, indeterminate or filling to a value, with an optional label and count.FeedbackPyramid chartRanked levels of a whole, stacked from a narrow apex to a wide base, where one row is one level.ChartQR CodeGenerate accessible, themeable QR codes locally as crisp SVG graphics.Data displayQuery InputA key:value query field whose filters are chips you can switch off or remove, with syntax highlighting and field and value suggestions, as in Datadog, GitHub and Sentry.InputsQuestionnaireA multi-step single- and multiple-choice flow with validation, shortcuts and form submission.InputsRadar chartCompare several profiles across the same set of normalized indicators.ChartRadioRadio options built on native inputs, grouped into one value with keyboard navigation.InputsRateAccessible star rating input with hover preview, keyboard control and optional half values.InputsReaction BarEmoji reactions with counts under a message or comment, toggled by the current user, with a picker to add more.ChatRelative TimeTime relative to now, such as "3 minutes ago" or "in 2 days", that keeps itself current and shows the full date on hover.Data displayReorder ListReorder a vertical queue with pointer or keyboard input while the application owns persistence.Data displayRich Text EditorA compact formatted-text field for comments, replies and email bodies: bold, links, lists, quotes and code, a one-tab-stop toolbar, and a Markdown value.InputsSankey chartQuantities moving through stages, where one row is one flow and each band is as wide as what it carries.ChartSave BarA floating bar that appears while a form has unsaved changes, with Discard and Save.LayoutScatter chartAn ECharts scatter plot for finding relationships, clusters and outliers across two numeric measures.ChartSearch FieldA search box with a debounced search event, a clear button, a keyboard shortcut hint and recent searches.InputsSecret FieldShows an API key or other secret masked, with buttons to reveal it, copy it and ask for a new one.InputsSelectDropdown that pairs a themeable trigger with an anchored list of c2-list-item options.InputsSeparatorHorizontal or vertical rule with an optional label, for dividing content and toolbars.LayoutSheetDialog pinned to an edge of the screen, for content that complements the page rather than interrupting it.FeedbackShortcutKeyboard shortcuts for a whole application from one element: each binding fires an action event, runs a handler or activates a target.InputsSide NavResponsive navigation drawer beside the page: pushes the content on large screens, slides over it with a backdrop on small ones.NavigationSkeletonPlaceholder block standing in for content that has not arrived, in three shapes and three animations.FeedbackSkip LinkA "Skip to main content" link that appears when a keyboard user tabs onto it and moves focus into the main content.NavigationSliderRange input with a themeable track, thumb, step ticks and value bubble.InputsSparklineA chromeless trend line sized for a table cell, a list row or the trend slot of a c2-stat.ChartSpinnerCircular progress indicator, indeterminate or showing a value, with optional text.FeedbackSplit ButtonA main action with a caret menu of alternatives, such as "Send ▾", or a remembered choice like a merge method.ButtonsSplit PanelTwo panels separated by a divider the user drags, or moves with the keyboard, to resize them.LayoutSpreadsheetA small editable grid with basic formulas, for budgets, quotes, price lists and score sheets.Editors & viewersStatDisplays a KPI with an optional icon, trend and supporting description.Data displayState TimelineOne band per series, coloured by the discrete state it was in over time: service health, CI runs, host power.ChartStatus LightColoured dot plus a short label for the state of something, such as Live, Building or Failed.Data displayStatus PanelCommunicate empty states, operation outcomes and recoverable errors with clear next steps.FeedbackStepsThe trace of a task as it runs, or a stepper across the top of a view: statuses, durations, stages that open while they work, and steps the reader can select.Data displayStickyPins content to the top or bottom of its scroll container and tells you when it is stuck, optionally hiding it while the reader scrolls down.LayoutStreaming TextPlain text that arrives in bursts, such as an LLM answer, revealed at a steady pace behind a caret.ChatSwipe ActionA list row that slides sideways to reveal actions behind it, as in a mail or task list on a phone.LayoutSwitchOn/off toggle on a native switch input, with label, description and thumb icons.InputsTableVirtualized data grid with declarative columns, sorting, selection, pinning and resizing.Data displayTable Of ContentsAn "On this page" navigation that lists the headings of a document, nests them by level and highlights the section being read.NavigationTabsTab strip that shows one content panel at a time.NavigationTag InputTurns typed or pasted text into removable tags — recipients, keywords, labels — with configurable delimiters, parsing and validation.InputsText FieldSingle-line input with icon slots, clear button, helper and error text, and a character counter.InputsTextareaMultiline text input with resizing, helper and error text, and a character counter.InputsTheme SelectColour-theme switcher: click to step to the next mode, hover for the full menu.InputsTime InputForm-associated time-of-day input with a scroll-wheel picker, step and range constraints, helper text and error states.InputsTime Range PickerDashboard time range control: searchable quick ranges, an absolute range typed or picked on a calendar, time zone, shift and zoom, and auto-refresh.InputsTime Slot PickerPick a free time from someone's calendar: a row of days, then that day's times grouped into morning, afternoon and evening.InputsTimelineA vertical sequence of dated events on a connected rail: order history, activity feeds, changelogs.Data displayToastNotification cards and a manager for stacked, queued notifications with independent lifetimes.FeedbackTodo ListA to-do list with the feel of paper: hand-drawn ticks, notes, highlighters, swipe and drag, and a remembered look.PlanningToggletipA small ⓘ button that opens a help bubble on click or tap; the bubble can hold links and is announced to screen readers.FeedbackTooltipContextual hint shown when its target is hovered or focused, rendered in the top layer.FeedbackTourA guided product tour that spotlights one element at a time and explains it in a panel beside it.FeedbackTrace WaterfallShow the spans of a distributed trace as a tree, each with a duration bar on one shared time axis.Data displayTreeHierarchical tree view with expansion, selection, checkboxes and lazy loading.Data displayTree SelectA dropdown for picking one or several rows from a hierarchy, with checkboxes, search and a form value.InputsTreemap chartA whole split into nested rectangles, each sized by its value: market maps, budgets and disk usage.ChartTruncateClamps text to a number of lines, with an optional Show more button.Data displayUploadDrag-and-drop file selection with validation, upload progress, retry, cancellation, and attachment results.InputsView OptionsThe Display popover of a collection: layout, grouping, ordering on several levels, Show switches and visible properties, reported as one plain value.InputsVirtual ListWindowed list with built-in search, sorting, selection and an async data source.Data displayVisually HiddenText for screen readers only: kept in the accessibility tree, drawn nowhere, optionally shown while it holds focus.LayoutWaterfall chartA running total bridged by the steps that move it, where one row is one step and totals mark where the bridge lands.ChartWeek PlannerWeekly schedule with time blocks: a typical week with optional odd and even weeks, or a dated week the user edits.PlanningWorking IndicatorA live "work in progress" line: animated mark, shimmering label, trailing dots and elapsed time.FeedbackFeather Icons287 open-source Feather icons, one web component each.IconsMat Icon2,234 Material Icons ligatures rendered through a single element.IconsPhosphor Icons1,512 flexible icons in six weights, one web component each.IconsSymbols157 themeable spot illustrations for empty states, status panels, onboarding and error pages.IconsTask icons191 duotone icons for to-do items: work, home, health, sport, learning, food, money, travel and more.IconsThemingTheme every c2n component from a handful of design tokens with @c2n/theme, or reach for any component variable directly.GuideLanguagesComponents show their text in English; add your app’s languages as one JSON object, picked by the nearest lang.GuideFrameworksUse the components from React, Vue, Angular, Svelte, Lit or plain HTML — typed events, generated template types, and the one piece of configuration each framework needs.GuideUsing c2n in an applicationThe workflow behind every c2n app: load the theme once, use c2-* tags directly, and turn every repeated pattern into a small variant or composed component.GuideAI toolsGive Claude Code, Codex, Google Antigravity or GitHub Copilot the c2n skill, live component APIs, examples and application conventions.GuideNo components match.