Data display
Cards, tables, tags, and data presentation components
Components for displaying data in cards, tables, badges, tags, and other visual formats.
Prerequisites
- Complete the @mdk/core installation and add the dependency
DataTable
Full-featured data table built on TanStack Table with sorting, pagination, and row selection.
Import
import { DataTable } from '@mdk/core'
// Types for column definitions
import type {
DataTableColumnDef,
DataTableSortingState,
DataTablePaginationState,
DataTableRowSelectionState,
} from '@mdk/core'Basic usage
import { DataTable } from '@mdk/core'
import type { DataTableColumnDef } from '@mdk/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 '@mdk/core'Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | none | Additional CSS class |
onClick | function | none | Click handler (adds clickable styling) |
children | 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 '@mdk/core'Accordion props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | '' | Accordion header title |
isOpened | boolean | false | Initially expanded |
isRow | boolean | false | Row layout for content |
unpadded | boolean | false | Remove content padding |
noBorder | boolean | false | Remove trigger border |
solidBackground | boolean | false | Solid background color |
showToggleIcon | boolean | true | Show expand/collapse icon |
toggleIconPosition | 'left' | 'right' | 'left' | Icon position |
customLabel | ReactNode | none | Custom label next to title |
onValueChange | 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 '@mdk/core'Props
| Prop | Type | Default | Description |
|---|---|---|---|
count | number | 0 | Number to display |
overflowCount | number | 99 | Max count before showing "99+" |
showZero | boolean | false | Show badge when count is 0 |
dot | boolean | false | Show as dot instead of number |
text | string | none | Custom text content |
color | ColorVariant | 'primary' | Badge color |
size | 'sm' | 'md' | 'lg' | 'md' | Badge size |
status | 'success' | 'processing' | 'error' | 'warning' | 'default' | none | Status variant |
square | boolean | false | Square badge (no border-radius) |
offset | [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 '@mdk/core'Props
| Prop | Type | Default | Description |
|---|---|---|---|
current | number | 1 | Current page number |
total | number | 0 | Total number of items |
pageSize | number | 20 | Items per page |
pageSizeOptions | number[] | [10, 20, 50, 100] | Page size options |
showSizeChanger | boolean | true | Show page size dropdown |
showTotal | boolean | false | Show total count text |
disabled | boolean | false | Disable pagination |
size | 'sm' | 'md' | 'lg' | 'sm' | Size variant |
onChange | 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 '@mdk/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 '@mdk/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 '@mdk/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 '@mdk/core'Props
| Prop | Type | Default | Description |
|---|---|---|---|
description | ReactNode | none | Required. Description text |
image | 'default' | 'simple' | ReactNode | 'default' | Image/icon to display |
size | '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 '@mdk/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 '@mdk/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 '@mdk/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 '@mdk/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 '@mdk/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>Divider
Visual separator between content sections.
Import
import { Divider } from '@mdk/core'Basic usage
<Divider />
<Divider orientation="vertical" />Separator
Horizontal or vertical dividing line.
Import
import { Separator } from '@mdk/core'Basic usage
<Separator />
<Separator orientation="vertical" />
