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
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 | (page: number, pageSize: number) => void | none | Callback when the page number or page size changes |
onSizeChange | Optional | (current: number, size: number) => void | none | Callback when the page size changes |
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
BtcAveragePrice
Displays a formatted BTC/USD price with a configurable label. Shows a dash when the value is absent, non-finite, or negative.
Import
import { BtcAveragePrice } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
price | Optional | number | null | none | BTC price in USD; formatted with grouping and no decimal places. Shows - when null, undefined, non-finite, or negative |
label | Optional | string | 'BTC Average Price' | Label shown before the price |
Basic usage
<BtcAveragePrice price={97_500} />
<BtcAveragePrice price={null} />Typography
Text styling components for headings and paragraphs.
Import
import { Typography } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
variant | Optional | 'heading1' | 'heading2' | 'heading3' | 'body' | 'secondary' | 'caption' | none | Typography variant |
size | Optional | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | none | Text size |
weight | Optional | 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | none | Font weight |
align | Optional | TextAlign | none | Text alignment |
color | Optional | 'default' | 'muted' | 'primary' | 'success' | 'warning' | 'error' | none | Text color variant |
truncate | Optional | boolean | false | Truncate text with ellipsis |
className | Optional | string | none | Custom class name |
Basic usage
<Typography variant="heading1">Operations dashboard</Typography>
<Typography variant="heading2">Sites</Typography>
<Typography variant="body">
Primary site operations are running within expected parameters.
</Typography>
<Typography variant="secondary">Last refreshed 12 seconds ago.</Typography>
<Typography variant="caption" color="muted">Updated 2 minutes ago</Typography>
<Typography weight="semibold" align="center" truncate>Site #1</Typography>Indicator
Status dot for online/offline/warning states.
Import
import { Indicator } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
color | Optional | 'gray' | 'slate' | 'red' | 'amber' | 'yellow' | 'green' | 'blue' | 'purple' | none | Color variant of the indicator dot |
size | Optional | 'sm' | 'md' | 'lg' | none | Size variant of the indicator |
vertical | Optional | boolean | false | When true, adds extra spacing between child elements and stacks them vertically |
onClick | Optional | function | none | Click handler |
children | Optional | ReactNode | none | Label content (text, icons, or multiple elements) |
className | Optional | string | none | Custom class name |
Basic usage
<Indicator color="green">Online</Indicator>
<Indicator color="red">Offline</Indicator>
<Indicator color="amber">Maintenance</Indicator>
<Indicator color="green" size="sm">Running</Indicator>
<Indicator color="green" vertical>
<span>Running</span>
<span>142</span>
</Indicator>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'
import type { CascaderValue, LocalFilters } from '@tetherto/mdk-react-devkit/core'Props
| Prop | Status | Type | Default | Description |
|---|---|---|---|---|
options | Required | CascaderOption[] | none | Cascader options for filtering |
onChange | Required | (selections: CascaderValue[]) => void | none | Callback when filters change |
localFilters | Optional | LocalFilters | none | Current filter values as key-value pairs (e.g. { status: ['active'] }) |
filterKey | Optional | string | none | Key to force re-mounting the Cascader when filters change (resets its internal state) |
className | Optional | string | none | Custom class name for the filter button |
Basic usage
const FILTER_OPTIONS = [
{
value: 'type',
label: 'Type',
children: [
{ value: 'Antminer S19XP', label: 'Antminer S19XP' },
{ value: 'Avalon A1346', label: 'Avalon A1346' },
],
},
{
value: 'status',
label: 'Status',
children: [
{ value: 'active', label: 'Active' },
{ value: 'offline', label: 'Offline' },
],
},
]
const [filters, setFilters] = useState<LocalFilters>({})
<ListViewFilter
options={FILTER_OPTIONS}
localFilters={filters}
onChange={(selections) => setFilters(selectionToFilters(selections))}
/>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>