Interactive mission board
Search, sort, select rows, and turn the page. Select-all only affects this page.
| Rescue the moon | Ready | 90 | |
| Find the missing ink | In progress | 40 | |
| Catch the plot twist | Ready | 75 |
searchable selectable pageSize={3}
WelkUI!Explore live variants, compare states, and learn every prop. Pick a component to start.
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.
| Rescue the moon | Ready | 90 | |
| Find the missing ink | In progress | 40 | |
| Catch the plot twist | Ready | 75 |
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.
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.
Search, sort, select rows, and turn the page. Select-all only affects this page.
| Rescue the moon | Ready | 90 | |
| Find the missing ink | In progress | 40 | |
| Catch the plot twist | Ready | 75 |
searchable selectable pageSize={3}A display-only table without search, sorting, selection boxes, stripes, or pagination.
| Mission | Status | Points |
|---|---|---|
| Rescue the moon | Ready | 90 |
| Find the missing ink | In progress | 40 |
| Catch the plot twist | Ready | 75 |
| Deliver the punchline | Complete | 100 |
| Save the last panel | In progress | 60 |
density="compact" striped={false} pagination={false} searchable={false} sortable={false} selectable={false}A loading message replaces rows and disables controls.
loadingAn empty dataset receives a friendly, customizable message.
data={[]} emptyMessage="No missions. Time for a coffee!"Required props are marked in the default column. Other props are optional. ReactNode accepts text or JSX.
| Prop | Type | Default | Description |
|---|---|---|---|
caption | ReactNode | Required | Visible, accessible table title. |
data | readonly T[] | Required | Client-side records. Keep row ids stable when records update. |
columns | readonly WelkDataTableColumn<T>[] | Required | Unique id, header, accessor; optional cell, compare, sortable, searchable, align, and width. |
getRowId | (row: T) => string | number | Required | Unique, stable, non-empty row identity. Duplicate ids throw. |
getRowLabel | (row: T) => string | Row id | Accessible row-selection label. |
searchable | boolean | false | Enables text search across column accessor values. |
searchLabel | string | "Search table" | Visible search-field label. |
searchPlaceholder | string | "Find your next clue..." | Search-field hint. |
search / defaultSearch | string | "" | Controlled or initial query. Controlled search requires updating it in onSearchChange. |
onSearchChange | (search: string) => void | Unset | Receives search-field changes. |
sortable | boolean | true | Enables sorting table-wide. False hides sort controls and ignores sort/defaultSort; column sortable=false still disables individual columns. |
sort / defaultSort | WelkDataTableSort | null | Unsorted | Sort columnId and asc/desc direction; null clears controlled sorting. defaultSort accepts an initial sort. |
onSortChange | (sort: WelkDataTableSort | null) => void | Unset | Receives requested sorting. |
pagination | boolean | true | Shows client-side page controls; false renders all matching rows. |
pageSize | number | 10 | Positive integer number of rows per page. Invalid values throw. |
selectable | boolean | false | Adds row checkboxes and select-all for the current page. |
selectedRowIds / defaultSelectedRowIds | readonly (string | number)[] | [] | Controlled or initial selected ids. Selection survives search, sorting, and page changes. |
onSelectionChange | (ids: (string | number)[]) => void | Unset | Receives selected ids from the current dataset, including other pages. |
loading | boolean | false | Replaces rows with loading status and disables table controls. |
loadingMessage | ReactNode | "Loading the next chapter..." | Loading content. |
emptyMessage | ReactNode | "No rows yet. The story starts here." | Content for an empty dataset. |
noResultsMessage | ReactNode | "No matching rows. Try another clue." | Content when search finds no matching records. |
striped | boolean | true | Alternating row backgrounds. |
density | "comfortable" | "compact" | "comfortable" | Cell spacing. |
getRowClassName | (row: T) => string | undefined | Unset | Additional class on each data row. |
className | string | Unset | Additional CSS class on the component root. |
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.
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.