MDK Logo

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 '@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

PropTypeDefaultDescription
classNamestringnoneAdditional CSS class
onClickfunctionnoneClick handler (adds clickable styling)
childrenReactNodenoneCard 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 when onClick is 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

PropTypeDefaultDescription
titlestring''Accordion header title
isOpenedbooleanfalseInitially expanded
isRowbooleanfalseRow layout for content
unpaddedbooleanfalseRemove content padding
noBorderbooleanfalseRemove trigger border
solidBackgroundbooleanfalseSolid background color
showToggleIconbooleantrueShow expand/collapse icon
toggleIconPosition'left' | 'right''left'Icon position
customLabelReactNodenoneCustom label next to title
onValueChangefunctionnoneCallback 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

PropTypeDefaultDescription
countnumber0Number to display
overflowCountnumber99Max count before showing "99+"
showZerobooleanfalseShow badge when count is 0
dotbooleanfalseShow as dot instead of number
textstringnoneCustom text content
colorColorVariant'primary'Badge color
size'sm' | 'md' | 'lg''md'Badge size
status'success' | 'processing' | 'error' | 'warning' | 'default'noneStatus variant
squarebooleanfalseSquare 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

PropTypeDefaultDescription
currentnumber1Current page number
totalnumber0Total number of items
pageSizenumber20Items per page
pageSizeOptionsnumber[][10, 20, 50, 100]Page size options
showSizeChangerbooleantrueShow page size dropdown
showTotalbooleanfalseShow total count text
disabledbooleanfalseDisable pagination
size'sm' | 'md' | 'lg''sm'Size variant
onChangefunctionnonePage/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

PropTypeDefaultDescription
descriptionReactNodenoneRequired. 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" />

On this page