Component field guide

Explore live variants, compare states, and learn every prop. Pick a component to start.

LIVE COMPONENT

WelkDataTable

A typed, comic-inspired data table with client-side sorting, search, pagination, row selection, and custom cells. Native table semantics, bold headers, dashed rules, uneven corners, and hard shadows keep data readable and playful.

Mission board
Rescue the moonReady90
Find the missing inkIn progress40
Catch the plot twistReady75

Usage

React / TSX
import { WelkDataTable } from "@welkui/react";

const missions = [
  { id: "M1", name: "Rescue the moon", points: 90 },
  { id: "M2", name: "Find the missing ink", points: 40 },
  { id: "M3", name: "Catch the plot twist", points: 75 },
];

<WelkDataTable
  caption="Mission board"
  data={missions}
  columns={[
    { id: "name", header: "Mission", accessor: (row) => row.name },
    { id: "points", header: "Points", accessor: (row) => row.points, align: "right" },
  ]}
  getRowId={(row) => row.id}
  getRowLabel={(row) => row.name}
  searchable
  selectable
  pageSize={2}
/>

Import @welkui/react/styles.css once in your app. Stateful snippets belong inside a React component.

Variants and behavior

  • Comfortable (default) or compact density, with optional alternating stripes.
  • Columns sort ascending, descending, then return to original order; set the table's sortable=false to disable all sorting or a column's sortable=false to disable just that column.
  • Search and selection are opt-in. Pagination defaults to ten rows per page.
  • Loading, empty-data, and no-search-results messages are customizable.

Visual variant gallery

These are real components, not screenshots. Compare their appearance and try the controls. Key props below each preview show what changes; use the usage example above for imports and component setup.

Interactive mission board

Search, sort, select rows, and turn the page. Select-all only affects this page.

Mission board
Rescue the moonReady90
Find the missing inkIn progress40
Catch the plot twistReady75
Key propssearchable selectable pageSize={3}

Compact

A display-only table without search, sorting, selection boxes, stripes, or pagination.

Mission board
MissionStatusPoints
Rescue the moonReady90
Find the missing inkIn progress40
Catch the plot twistReady75
Deliver the punchlineComplete100
Save the last panelIn progress60
Key propsdensity="compact" striped={false} pagination={false} searchable={false} sortable={false} selectable={false}

Loading

A loading message replaces rows and disables controls.

Mission board
Loading the next chapter...
Key propsloading

Empty

An empty dataset receives a friendly, customizable message.

Mission board
No missions. Time for a coffee!
Key propsdata={[]} emptyMessage="No missions. Time for a coffee!"

Usage notes and accessibility

  • Use a descriptive caption and unique, stable getRowId values. Column accessor values drive search and sorting; cell only changes rendering.
  • Sorting cycles ascending, descending, and unsorted. Numeric values sort numerically; provide compare for domain-specific ordering and sortable=false for action columns.
  • Select-all affects the current page only. Selection persists across filters and pages; process selected ids in your application and validate permissions before bulk actions.
  • All data processing is client-side. Supply a reasonably sized dataset; server-side querying and virtualization are not included. Pagination limits rendered rows, not data processing.
  • The table uses native headers and aria-sort. Search, sort buttons, selection, pagination, and horizontal overflow are keyboard accessible. Give custom action buttons descriptive accessible names.

Props

Required props are marked in the default column. Other props are optional. ReactNode accepts text or JSX.

WelkDataTable prop reference
PropTypeDefaultDescription
captionReactNodeRequiredVisible, accessible table title.
datareadonly T[]RequiredClient-side records. Keep row ids stable when records update.
columnsreadonly WelkDataTableColumn<T>[]RequiredUnique id, header, accessor; optional cell, compare, sortable, searchable, align, and width.
getRowId(row: T) => string | numberRequiredUnique, stable, non-empty row identity. Duplicate ids throw.
getRowLabel(row: T) => stringRow idAccessible row-selection label.
searchablebooleanfalseEnables text search across column accessor values.
searchLabelstring"Search table"Visible search-field label.
searchPlaceholderstring"Find your next clue..."Search-field hint.
search / defaultSearchstring""Controlled or initial query. Controlled search requires updating it in onSearchChange.
onSearchChange(search: string) => voidUnsetReceives search-field changes.
sortablebooleantrueEnables sorting table-wide. False hides sort controls and ignores sort/defaultSort; column sortable=false still disables individual columns.
sort / defaultSortWelkDataTableSort | nullUnsortedSort columnId and asc/desc direction; null clears controlled sorting. defaultSort accepts an initial sort.
onSortChange(sort: WelkDataTableSort | null) => voidUnsetReceives requested sorting.
paginationbooleantrueShows client-side page controls; false renders all matching rows.
pageSizenumber10Positive integer number of rows per page. Invalid values throw.
selectablebooleanfalseAdds row checkboxes and select-all for the current page.
selectedRowIds / defaultSelectedRowIdsreadonly (string | number)[][]Controlled or initial selected ids. Selection survives search, sorting, and page changes.
onSelectionChange(ids: (string | number)[]) => voidUnsetReceives selected ids from the current dataset, including other pages.
loadingbooleanfalseReplaces rows with loading status and disables table controls.
loadingMessageReactNode"Loading the next chapter..."Loading content.
emptyMessageReactNode"No rows yet. The story starts here."Content for an empty dataset.
noResultsMessageReactNode"No matching rows. Try another clue."Content when search finds no matching records.
stripedbooleantrueAlternating row backgrounds.
density"comfortable" | "compact""comfortable"Cell spacing.
getRowClassName(row: T) => string | undefinedUnsetAdditional class on each data row.
classNamestringUnsetAdditional CSS class on the component root.

Native props and refs

Native div attributes are forwarded to the outer panel. Generic T is inferred from data; no ref is exposed. Cells can contain links, badges, or action buttons.

Project setup, styling and Next.js

Import @welkui/react/styles.css once in your app entry or Next.js root layout. The previews use the default theme; override --welk-* CSS tokens in your app to customize it.

For Next.js, put hooks and event handlers in a component beginning with "use client". Keep state local to the component using the control. The library preserves its client boundaries and uses your installed React version.

Use defaultValue or defaultChecked for uncontrolled fields, or a state value and its change callback for controlled fields. Do not switch between these modes during the lifetime of a field.

Modal and notification examples start closed: use their Try buttons to see them. Disabled examples are deliberately non-interactive. Validate forms, uploads, authentication, and server responses in your application; these components only provide UI.