Data Display
Components

Data Display

Components for showing structured data and user-generated content: tables, trees, code, logs, kanban, and timelines.

Components in this category

Table

Standard data table with sortable headers and footers.

TableContainer

Scrollable container for wide tables.

DataGrid

Feature-rich data grid with sorting, filtering and cell editing.

VirtualList

Virtualised scrolling list for large datasets.

List

Standard list with selectable, clickable items.

ListItem

Single row in a List, ListSection or standalone.

ListSection

Categorized section within a List.

ListDivider

Horizontal divider between list items.

DescriptionList

Label–value pair list, like a spec sheet.

ResourceRow

Compact row for a cloud/IT resource with icon and meta.

TagList

Horizontal list of tags or keywords.

Truncate

Text clipping with line limits, middle ellipsis, and an overflow tooltip.

Image

Lazy image with a reserved box, a placeholder and a failure fallback.

TreeView

Hierarchical tree with expand/collapse.

TreeTable

TreeView rendered as a table with columns.

JsonViewer

Interactive JSON tree with syntax highlighting.

CodeBlock

Syntax-highlighted code block with copy.

InlineCode

Inline code snippet within running text.

DiffViewer

Unified or split diff viewer.

LogViewer

Scrollable log viewer with severity badges and search.

KanbanBoard

Drag-and-drop kanban board.

KanbanColumn

Single column in a KanbanBoard.

KanbanCard

Card inside a KanbanColumn.

Pagination

Page-number pagination with first/last shortcuts.

PageButton

Individual page button used inside Pagination.

Timeline

Ordered event rows with configurable styles and content slots.

TimelineItem

One event, composed by hand.

ActivityFeed

Activity rows with actor, action, target, and timestamp.

CommentThread

Threaded comment system with reactions.

CommentView

Single comment display.

CommentComposer

Rich text comment input.

Tables & Grids

Table / Th / Td / Tr / TableFooter

Table, Th, Td, Tr, and TableFooter are the standard table primitives. Th has a num prop for right-aligned numeric headers; Td adds num, name (bold), and mono variants. Tr supports hover, attn (highlighted), sel (selected), and dimmed.

Table
ImportTSX
import {
  Table,
  TableContainer,
  Th,
  Td,
  Tr,
  TableFooter,
} from "@solarius/onset";

DataGrid

DataGrid provides sortable columns, row selection, cell editing, virtual scrolling, zebra striping, and a sticky footer summary. Built on useVirtualRange for performance on large datasets.

DataGridProps props
PropTypeDefaultDescription
rowsT[]—The data rows.
columnsDataGridColumn<T>[]—Column definitions.
getRowId(row: T, index: number) => string—Stable row identity.
rowHeightnumber—Fixed row height in px.
sortDataGridSort | null—Current sort state.
onSortChange(sort: DataGridSort | null) => void—Sort change handler.
selectedIdsstring[]—Selected row ids.
onSelectionChange(ids: string[]) => void—Selection change handler.
onCellEdit(edit: CellEdit<T>) => void—Cell edit commit handler.
onRowClick(row: T, index: number) => void—Row click handler.
stripedboolean—Zebra striping.
borderedboolean—Border and corner radius around the grid.
ImportTSX
import { DataGrid } from "@solarius/onset";
import type { DataGridColumn, DataGridSort, CellEdit } from "@solarius/onset";

const columns: DataGridColumn<MyRow>[] = [
  { key: "name", header: "Name", sortable: true },
  { key: "status", header: "Status", numeric: true },
  {
    key: "actions",
    header: "",
    render: (row) => <Button size="sm">View</Button>,
  },
];

<DataGrid
  rows={data}
  columns={columns}
  getRowId={(row) => row.id}
  rowHeight={36}
  height={400}
  sort={sort}
  onSortChange={setSort}
  selectedIds={selected}
  onSelectionChange={setSelected}
/>;

VirtualList

VirtualList renders only the visible slice of a long list, using the useVirtualRange hook for windowing math. Supports both fixed and variable row heights.

ImportTSX
import { VirtualList, useVirtualRange } from "@solarius/onset";

<VirtualList
  data={items}
  itemHeight={40}
  height={300}
  renderItem={(item, index) => <div>{item.name}</div>}
  overscan={8}
/>;

List / ListItem / ListSection / ListDivider

Generic vertical list primitive. The base under ActivityFeed, InboxPanel, and ad hoc row layouts. ListItem has slots for media, title, description, meta, and actions.

List

DescriptionList

Key/value fact sheet, as in a "Details" card. Rows are DescriptionRow objects with key, value, optional mono font, and optional onClick.

DescriptionList

ResourceRow

ResourceRow renders a cloud resource row with an icon, title, subtitle, and right-aligned meta/value pair. Exported from DescriptionList.

TagList

TagList renders a horizontal list of Tag components from a string array.

Trees & JSON

TreeView

Hierarchical explorer (account trees, resource groups, file paths) with disclosure carets and single selection.

TreeView
ImportTSX
import { TreeView } from "@solarius/onset";
import type { TreeNode } from "@solarius/onset";

TreeTable

TreeTable combines the hierarchical disclosure of TreeView with the column grid of a table — expandable rows with per-column values. Exported from JsonViewer.

ImportTSX
import { TreeTable } from "@solarius/onset";
import type { TreeTableColumn, TreeTableNode } from "@solarius/onset";

JsonViewer

Interactive JSON tree with collapsible nodes, search highlighting, and a copy button. Accepts any plain object, array, or primitive.

JsonViewer
ImportTSX
import { JsonViewer } from "@solarius/onset";

Code & Logs

CodeBlock

Syntax-highlighted code block with line numbers and a copy button. Supports ts, tsx, js, json, bash, sql, css, yaml, and text. Highlighting uses a small rule-based tokenizer, not a parser.

CodeBlockProps props
PropTypeDefaultDescription
languageCodeLanguage—"ts" | "tsx" | "js" | "json" | "bash" | "sql" | "css" | "yaml" | "text"
codestring—The source code string.
copyablebooleantrueShow the copy button.
CodeBlock

InlineCode

InlineCode wraps a short code fragment in a styled <code> element for use inside running text.

npm install @solarius/onset
InlineCode

DiffViewer

DiffViewer renders a unified diff with colored add/delete lines, line-number gutters, and a collapsed-file-header row. Pass a raw diff string or pre-parsed DiffLine[]. The exported parseUnifiedDiff helper converts unified diff text into typed lines.

ImportTSX
import { DiffViewer, parseUnifiedDiff } from "@solarius/onset";

<DiffViewer
  diff={`--- a/file.ts
+++ b/file.ts
@@ -1,3 +1,3 @@
-const old = true;
+const updated = false;
 unchanged;`}
/>;

LogViewer

Live-tailing log stream with time, level, and unit columns. Renders from an array of LogEntry objects.

LogViewerProps props
PropTypeDefaultDescription
entriesLogEntry[]—Log entries with time, level, unit, and message fields.
LogViewer
ImportTSX
import { LogViewer } from "@solarius/onset";
import type { LogEntry } from "@solarius/onset";

Kanban

KanbanBoard, KanbanColumn, and KanbanCard form a drag-and-drop board. Cards are draggable between columns via HTML drag-and-drop. Each KanbanColumn receives dropped cards through onDropCard.

KanbanColumnProps props
PropTypeDefaultDescription
titleReactNode—Column heading.
countnumber—Mono count next to the title.
metaReactNode—Right-aligned header meta.
onDropCard(cardId: string, index: number) => void—Card drop handler. Omit to make a no-drop column.
footerReactNode—Pinned under the card list.
Kanban
ImportTSX
import { KanbanBoard, KanbanColumn, KanbanCard } from "@solarius/onset";

<KanbanBoard>
  <KanbanColumn
    title="Backlog"
    count={items.length}
    onDropCard={(cardId, index) => moveCard(cardId, "backlog", index)}
  >
    {items.map((item) => (
      <KanbanCard key={item.id} id={item.id} title={item.title} />
    ))}
  </KanbanColumn>
</KanbanBoard>;

Text & media

Truncate

Truncate supports line clamping, middle ellipsis, and tooltips for clipped text. Use Text truncate for a single trailing ellipsis. See Truncate for props.

Truncate

Image

An <img> that reserves its layout box before loading, shows a placeholder while loading, and renders a fallback when the URL fails. It lazy-loads by default. Full props on its page.

Image
ImportTSX
import { Truncate, Image } from "@solarius/onset";

<Truncate tooltip>{row.message}</Truncate>
<Image src={asset.url} alt={asset.name} ratio={16 / 9} rounded="md" />

Other

Pagination / PageButton

Numbered pager built on PageButton; pair with TableFooter for the standard table footer.

PaginationProps props
PropTypeDefaultDescription
pagenumber—Controlled 1-based page.
defaultPagenumber1Initial uncontrolled page.
pageCountnumber—Total pages.
onChange(page: number) => void—Page change handler.
maxButtonsnumber7Max numbered buttons before collapsing to ellipses.
Pagination

Timeline / TimelineItem

Timeline displays ordered events with optional title, meta, time, description, detail, and actions slots. It accepts items or TimelineItem children, three variants, three densities, and configurable timestamp placement. See Timeline.

Timeline

ActivityFeed

ActivityFeed displays actor, action, target, and timestamp fields using Timeline rows. Optional day headings use the client timezone after hydration.

ActivityFeed
ImportTSX
import { ActivityFeed } from "@solarius/onset";
import type { ActivityItem } from "@solarius/onset";

CommentThread / CommentView / CommentComposer

Threaded comment system with avatars, reactions, badges, replies, and a composer. CommentView renders a single comment with nested replies; CommentComposer provides the text input for new comments and replies. Supports pending (optimistic) posts.

ImportTSX
import { CommentThread, CommentView, CommentComposer } from "@solarius/onset";
import type { Comment, CommentReaction } from "@solarius/onset";

const comments: Comment[] = [
  {
    id: "1",
    author: "Alice",
    body: "Looks good to me. Ship it.",
    time: new Date(),
    reactions: [{ emoji: "🚀", count: 2, reacted: true }],
    replies: [
      { id: "2", author: "Bob", body: "Agreed, let's go.", time: new Date() },
    ],
  },
];

<CommentThread
  comments={comments}
  onReply={(parentId, body) => createReply(parentId, body)}
  onReact={(commentId, emoji) => toggleReaction(commentId, emoji)}
/>;