Data display
Cards, tables, tags, and data presentation components
Components for displaying data in cards, tables, badges, tags, and other visual formats.
Prerequisites
DataTable
Full-featured data table built on TanStack Table with sorting, pagination, and row selection.
Import
import { DataTable } from '@tetherto/mdk-react-devkit/core'
// Types for column definitions
import type {
DataTableColumnDef,
DataTableSortingState,
DataTablePaginationState,
DataTableRowSelectionState,
} from '@tetherto/mdk-react-devkit/core'Basic usage
import { DataTable } from '@tetherto/mdk-react-devkit/core'
import type { DataTableColumnDef } from '@tetherto/mdk-react-devkit/core'
type Miner = {
id: string
name: string
hashrate: number
status: string
}
const columns: DataTableColumnDef<Miner>[] = [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'hashrate',
header: 'Hashrate',
cell: ({ row }) => `${row.original.hashrate} TH/s`,
},
{
accessorKey: 'status',
header: 'Status',
},
]
function MinersTable() {
return <DataTable columns={columns} data={miners} />
}With sorting and pagination
const [sorting, setSorting] = useState<DataTableSortingState>([])
const [pagination, setPagination] = useState<DataTablePaginationState>({
pageIndex: 0,
pageSize: 10,
})
<DataTable
columns={columns}
data={miners}
sorting={sorting}
onSortingChange={setSorting}
pagination={pagination}
onPaginationChange={setPagination}
/>With row selection
const [rowSelection, setRowSelection] = useState<DataTableRowSelectionState>({})
<DataTable
columns={columns}
data={miners}
rowSelection={rowSelection}
onRowSelectionChange={setRowSelection}
enableRowSelection
/>Styling
.mdk-data-table: Root container.mdk-data-table__header: Header row.mdk-data-table__body: Table body.mdk-data-table__row: Data row.mdk-data-table__cell: Table cell
Card
Flexible container component with optional header, body, and footer slots.
Import
import { Card, CardHeader, CardBody, CardFooter } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
className | Optional | string | none | Additional CSS class |
onClick | Optional | function | none | Click handler (adds clickable styling) |
children | Optional | ReactNode | none | Card content |
Basic usage
<Card>
<Card.Header>Title</Card.Header>
<Card.Body>Content goes here</Card.Body>
<Card.Footer>Actions</Card.Footer>
</Card>Default children are automatically wrapped in the body slot:
<Card>
<Card.Header>Title</Card.Header>
This content goes to the body automatically
</Card>Clickable card
<Card onClick={() => navigate('/details')}>
<Card.Header>Click me</Card.Header>
<Card.Body>Navigates on click</Card.Body>
</Card>Styling
.mdk-card: Root container.mdk-card--clickable: Applied whenonClickis provided.mdk-card__header: Header slot.mdk-card__body: Body slot.mdk-card__footer: Footer slot
LabeledCard
Card variant that pairs a tiny label above the body - used for compact stat or metadata blocks. Supports an optional navigation link on the label and a set of layout modifiers.
A generic card container with a header label, an optional navigation link on the label, and a set of layout modifiers. Useful for compact stat or metadata blocks.
Import
import { LabeledCard } from '@tetherto/mdk-react-devkit/core'Props
All props are optional.
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
label | Optional | ReactNode | none | Header content shown above the card body |
children | Optional | ReactNode | none | Card body content |
getNavigateOptions | Optional | (label: string) => { href?: string; target?: string } | none | Returns a link href/target for the label; only activates when label is a plain string |
isDark | Optional | boolean | false | Applies a dark background modifier |
isFullWidth | Optional | boolean | false | Stretches the card to full container width |
isFullHeight | Optional | boolean | false | Stretches the card to full container height |
isRelative | Optional | boolean | false | Sets position: relative on the container |
isScrollable | Optional | boolean | false | Enables vertical scroll on the card body |
hasNoWrap | Optional | boolean | false | Prevents content from wrapping |
hasNoMargin | Optional | boolean | false | Removes default margin |
hasNoBorder | Optional | boolean | false | Removes the card border |
className | Optional | string | none | Additional class for the root element |
Basic usage
<LabeledCard label="Device Overview" isFullWidth>
<p>Content goes here.</p>
</LabeledCard>With a navigation link on the label
<LabeledCard
label="Miners with error"
getNavigateOptions={(label) => ({ href: '/miners?filter=error' })}
>
<MinerList />
</LabeledCard>When label is the string 'Miners with error', an informational tooltip is added automatically, explaining that minor errors not affecting hashrate are excluded.
Accordion
Collapsible content sections built on Radix UI primitives.
Import
import {
Accordion,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from '@tetherto/mdk-react-devkit/core'Accordion props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
title | Optional | string | '' | Accordion header title |
isOpened | Optional | boolean | false | Initially expanded |
isRow | Optional | boolean | false | Row layout for content |
unpadded | Optional | boolean | false | Remove content padding |
noBorder | Optional | boolean | false | Remove trigger border |
solidBackground | Optional | boolean | false | Solid background color |
showToggleIcon | Optional | boolean | true | Show expand/collapse icon |
toggleIconPosition | Optional | 'left' | 'right' | 'left' | Icon position |
customLabel | Optional | ReactNode | none | Custom label next to title |
onValueChange | Optional | function | none | Callback when state changes |
Basic usage
<Accordion title="FAQ Section">
<p>This content can be expanded or collapsed.</p>
</Accordion>With custom label
<Accordion
title="System Status"
customLabel={<Badge variant="success">Active</Badge>}
showToggleIcon={false}
>
<p>All systems operational.</p>
</Accordion>Multiple items
<AccordionRoot type="multiple">
<AccordionItem value="item-1">
<AccordionTrigger>Section 1</AccordionTrigger>
<AccordionContent>Content 1</AccordionContent>
</AccordionItem>
<AccordionItem value="item-2">
<AccordionTrigger>Section 2</AccordionTrigger>
<AccordionContent>Content 2</AccordionContent>
</AccordionItem>
</AccordionRoot>Styling
.mdk-accordion: Root container.mdk-accordion--solid-background: Solid background variant.mdk-accordion__item: Individual item.mdk-accordion__trigger: Clickable header.mdk-accordion__content: Collapsible content area
Badge
Numeric or status badge that can wrap content or stand alone.
Import
import { Badge } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
count | Optional | number | 0 | Number to display |
overflowCount | Optional | number | 99 | Max count before showing "99+" |
showZero | Optional | boolean | false | Show badge when count is 0 |
dot | Optional | boolean | false | Show as dot instead of number |
text | Optional | string | none | Custom text content |
color | Optional | ColorVariant | 'primary' | Badge color |
size | Optional | 'sm' | 'md' | 'lg' | 'md' | Badge size |
status | Optional | 'success' | 'processing' | 'error' | 'warning' | 'default' | none | Status variant |
square | Optional | boolean | false | Square badge (no border-radius) |
offset | Optional | [number, number] | [0, 0] | Position offset [x, y] |
Basic usage
// Number badge on content
<Badge count={5}>
<Button>Messages</Button>
</Badge>
// Overflow
<Badge count={100} overflowCount={99}>
<BellIcon />
</Badge>
// Shows "99+"Dot badge
<Badge dot>
<NotificationIcon />
</Badge>Status badge
<Badge status="success" text="Online" />
<Badge status="error" text="Offline" />
<Badge status="processing" text="Syncing" />
<Badge status="warning" text="Warning" />Standalone badge
<Badge count={25} />
<Badge text="NEW" color="primary" square />Styling
.mdk-badge: Badge element.mdk-badge--{color}: Color variant.mdk-badge--{size}: Size variant.mdk-badge--dot: Dot variant.mdk-badge--status: Status variant.mdk-badge-wrapper: Wrapper when wrapping content
Pagination
Page navigation with size selector.
Import
import { Pagination } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
current | Optional | number | 1 | Current page number |
total | Optional | number | 0 | Total number of items |
pageSize | Optional | number | 20 | Items per page |
pageSizeOptions | Optional | number[] | [10, 20, 50, 100] | Page size options |
showSizeChanger | Optional | boolean | true | Show page size dropdown |
showTotal | Optional | boolean | false | Show total count text |
disabled | Optional | boolean | false | Disable pagination |
size | Optional | 'sm' | 'md' | 'lg' | 'sm' | Size variant |
onChange | Optional | function | none | Page/size change callback |
Basic usage
const [page, setPage] = useState(1)
const [pageSize, setPageSize] = useState(20)
<Pagination
current={page}
total={500}
pageSize={pageSize}
onChange={(newPage, newSize) => {
setPage(newPage)
setPageSize(newSize)
}}
/>With total display
<Pagination
current={1}
total={100}
pageSize={20}
showTotal
/>
// Shows "1-20 of 100"Styling
.mdk-pagination: Root container.mdk-pagination__pages: Page buttons container.mdk-pagination__button: Navigation button.mdk-pagination__button--active: Active page.mdk-pagination__total: Total count text.mdk-pagination__size-changer: Page size select
Tag
Removable tag/chip component.
Import
import { Tag } from '@tetherto/mdk-react-devkit/core'Basic usage
<Tag>Default Tag</Tag>
<Tag color="primary">Primary</Tag>
<Tag color="success">Success</Tag>
<Tag onClose={() => handleRemove()}>Removable</Tag>Avatar
User avatar display component with fallback initials.
Import
import { Avatar } from '@tetherto/mdk-react-devkit/core'Basic usage
<Avatar src="/user.jpg" alt="User" />
<Avatar>JD</Avatar>
<Avatar src="/user.jpg" size="lg" />SkeletonBlock
Loading placeholder animation.
Import
import { SkeletonBlock } from '@tetherto/mdk-react-devkit/core'Basic usage
// Text skeleton
<SkeletonBlock className="h-4 w-48" />
// Circle skeleton
<SkeletonBlock className="h-12 w-12 rounded-full" />
// Card skeleton
<Card>
<Card.Body>
<SkeletonBlock className="h-4 w-full mb-2" />
<SkeletonBlock className="h-4 w-3/4" />
</Card.Body>
</Card>EmptyState
Placeholder component for empty data states.
Import
import { EmptyState } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
description | Optional | ReactNode | none | Required. Description text |
image | Optional | 'default' | 'simple' | ReactNode | 'default' | Image/icon to display |
size | Optional | 'sm' | 'md' | 'lg' | 'md' | Size variant |
Basic usage
<EmptyState description="No data available" />
<EmptyState
description="No miners found matching your search"
image="simple"
size="sm"
/>Custom image
<EmptyState
description="No alerts at this time"
image={<BellOffIcon size={48} />}
/>Styling
.mdk-empty-state: Root container.mdk-empty-state--{size}: Size variant.mdk-empty-state__image: Image container.mdk-empty-state__description: Description text
Typography
Text styling components for headings and paragraphs.
Import
import { Typography } from '@tetherto/mdk-react-devkit/core'Basic usage
<Typography variant="h1">Dashboard</Typography>
<Typography variant="h2">Miner status</Typography>
<Typography variant="body">
Primary site operations are running within expected parameters.
</Typography>
<Typography variant="caption">Updated 2 minutes ago</Typography>Indicator
Status dot for online/offline/warning states.
Import
import { Indicator } from '@tetherto/mdk-react-devkit/core'Basic usage
<Indicator status="online" />
<Indicator status="offline" />
<Indicator status="warning" />
<span className="flex items-center gap-2">
<Indicator status="online" />
Miner online
</span>CurrencyToggler
Toggle between different currency display formats.
Import
import { CurrencyToggler } from '@tetherto/mdk-react-devkit/core'Basic usage
<CurrencyToggler
value={currency}
onChange={setCurrency}
options={['USD', 'BTC', 'SAT']}
/>ListViewFilter
Filter controls for list and table views with search and category filtering.
Import
import { ListViewFilter } from '@tetherto/mdk-react-devkit/core'Basic usage
<ListViewFilter
search={search}
onSearchChange={setSearch}
filters={[
{ key: 'status', label: 'Status', options: ['online', 'offline'] },
{ key: 'site', label: 'Site', options: ['A', 'B', 'C'] },
]}
activeFilters={activeFilters}
onFilterChange={setActiveFilters}
/>Mosaic
Grid layout component for dashboard widgets and responsive content arrangements.
Import
import { Mosaic, MosaicItem } from '@tetherto/mdk-react-devkit/core'Basic usage
<Mosaic columns={3} gap={16}>
<MosaicItem>
<Card>Hashrate</Card>
</MosaicItem>
<MosaicItem span={2}>
<Card>Active miners</Card>
</MosaicItem>
<MosaicItem>
<Card>Power usage</Card>
</MosaicItem>
</Mosaic>