MDK Logo

Container components

Components for displaying and controlling Bitcoin mining containers

Components for viewing, navigating, and controlling Bitcoin mining containers, racks, and associated hardware.

Prerequisites

Vendor-specific components

Hardware-specific UI is split by vendor:

All container components

Every component in this category, including shared chrome and vendor-specific widgets.

ComponentDescription
DeviceExplorerHierarchical view of containers, racks, and miners
ContainerControlsBoxBatch container operations panel
TanksBoxImmersion tank status display
SupplyLiquidBoxCooling liquid supply monitoring
MinersSummaryBoxContainer miner summary widget
EnabledDisableToggleTank circulation toggle control
GenericDataBoxGeneric label-value-unit datatable
SocketPDU socket tile with power and miner state
TankRowSingle tank stats row
ContainerFanLegendSingle container fan status badge
ContainerFansCardGrid of container fan indicators
DryCoolerDry cooler units with fans and pumps
PumpBoxSingle pump running/off indicator
BitdeerPumpsBitdeer exhaust fan status indicator
BitdeerSettingsBitdeer container settings and thresholds
BitdeerTankPressureChartsBitdeer tank pressure time-series chart
BitdeerTankTempChartsBitdeer tank oil and water temperature chart
BitMainBasicSettingsBitmain cooling, power and positioning view
BitMainCoolingSystemBitmain cooling pump and fan statuses
BitMainHydroLiquidTemperatureChartsBitmain hydro secondary liquid temp chart
BitMainHydroSettingsBitmain hydro settings and thresholds
BitMainLiquidPressureChartsBitmain supply/return liquid pressure chart
BitMainLiquidTempChartsBitmain supply/return liquid temp chart
BitMainPowerAndPositioningBitmain distribution power and GPS panel
BitMainPowerChartsBitmain total and per-box power chart
BitMainSupplyLiquidFlowChartsBitmain supply liquid flow chart
StatusItemLabeled status indicator row
BitMainControlsTabBitmain immersion controls tab view
BitMainImmersionControlBoxTwo-column immersion control box container
BitMainImmersionPumpStationControlBoxPump station alarm and state card
BitMainImmersionSettingsBitmain immersion threshold settings form
BitMainImmersionSummaryBoxBitmain immersion pumps and liquid temps
BitMainImmersionSystemStatusImmersion server start and connection status
BitMainImmersionUnitControlBoxImmersion unit status and frequency card
FireStatusBoxMicroBT fire and environmental sensors
GaugeChartComponentLabeled gauge chart with value and unit
MicroBTCoolingMicroBT cooling system detail panel
MicroBTSettingsMicroBT container settings and thresholds
MicroBTWidgetBoxMicroBT cycle pump and cooling fan widget
PowerMetersMicroBT power meter readings panels

Shared components

Components that are generic across container vendors. They work with any container device record and are the building blocks used inside the vendor-specific pages above.

DeviceExplorer

Hierarchical view of containers, racks, and miners with filtering, search, and selection capabilities.

Import

import { DeviceExplorer } from '@mdk/foundation'

Props

PropTypeDefaultDescription
deviceType'container' | 'miner' | 'cabinet'requiredCurrent view type
dataDevice[]requiredArray of devices to display
filterOptionsDeviceExplorerFilterOption[]requiredCascader filter options
searchOptionsDeviceExplorerSearchOption[]requiredSearch autocomplete options
searchTagsstring[]requiredCurrent search tags
onSearchTagsChange(tags: string[]) => voidrequiredSearch tags change handler
onDeviceTypeChange(type: DeviceExplorerDeviceType) => voidrequiredDevice type tab change handler
onFiltersChange(value: LocalFilters) => voidrequiredFilter change handler
selectedDevicesDataTableRowSelectionState{}Selected row state
onSelectedDevicesChange(selections: DataTableRowSelectionState) => voidnoneSelection change handler
renderAction(device: Device) => ReactNodenoneCustom action column renderer
getFormattedDate(date: Date) => stringrequiredDate formatter function
classNamestringnoneAdditional CSS class

Basic usage

<DeviceExplorer
  deviceType="container"
  data={containers}
  filterOptions={[
    { value: 'site-a', label: 'Site A' },
    { value: 'site-b', label: 'Site B' },
  ]}
  searchOptions={[
    { value: 'container-001', label: 'Container 001' },
  ]}
  searchTags={searchTags}
  onSearchTagsChange={setSearchTags}
  onDeviceTypeChange={setDeviceType}
  onFiltersChange={handleFilters}
  getFormattedDate={(date) => date.toLocaleDateString()}
/>

With selection

<DeviceExplorer
  deviceType="miner"
  data={miners}
  filterOptions={filterOptions}
  searchOptions={searchOptions}
  searchTags={[]}
  onSearchTagsChange={setSearchTags}
  onDeviceTypeChange={setDeviceType}
  onFiltersChange={handleFilters}
  selectedDevices={selected}
  onSelectedDevicesChange={setSelected}
  getFormattedDate={formatDate}
  renderAction={(device) => (
    <Button size="sm" onClick={() => viewDetails(device.id)}>
      View
    </Button>
  )}
/>

Styling

  • .mdk-device-explorer: Root element
  • .mdk-device-explorer__toolbar: Toolbar container
  • .mdk-device-explorer__toolbar__filter: Filter Cascader
  • .mdk-device-explorer__toolbar__search: Search input
  • .mdk-device-explorer__toolbar__tabs: Device type tabs
  • .mdk-device-explorer__toolbar__tabs-list: Tabs list container
  • .mdk-device-explorer__toolbar__tab-trigger: Individual tab trigger

ContainerControlsBox

Batch container operations panel with start/stop, cooling controls, power management, and alarm reset functionality. Adapts UI based on container type (Bitdeer, Bitmain, MicroBT).

Import

import { ContainerControlsBox } from '@mdk/foundation'

Props

PropTypeDefaultDescription
dataDevicenoneContainer device data
isBatchbooleanfalseEnable batch operations mode
selectedDevicesDevice[][]Selected devices for batch operations
pendingSubmissionsPendingSubmission[][]Pending action submissions
alarmsDataItemsTimelineItemData[][]Active alarms to display
tailLogDataUnknownRecord[]noneTail log data for power modes
onNavigate(path: string) => voidrequiredNavigation handler

Basic usage

<ContainerControlsBox
  data={container}
  onNavigate={(path) => router.push(path)}
/>

Batch operations

<ContainerControlsBox
  isBatch
  selectedDevices={selectedContainers}
  pendingSubmissions={pending}
  alarmsDataItems={alarms}
  onNavigate={handleNavigate}
/>

Container type features

The component automatically adapts based on container type:

  • Bitdeer: Start/Stop, Reset Alarm, Tank 1/2 toggles, Air Exhaust toggle, Socket controls
  • Bitmain Hydro: Start/Stop Cooling, PID Mode display
  • Bitmain Immersion: Start/Stop Cooling, PID Mode, Running Mode, System Status
  • MicroBT: Start/Stop Cooling, Socket controls

Styling

  • .mdk-container-controls-box: Root element
  • .mdk-container-controls-box__buttons-row: Action buttons row
  • .mdk-container-controls-box__toggles-row: Toggle switches row
  • .mdk-container-controls-box__toggle: Individual toggle container
  • .mdk-container-controls-box__bulk-row: Bulk action buttons row

TanksBox

Displays immersion tank status with temperature, pressure, and pump indicators for each tank.

Import

import { TanksBox } from '@mdk/foundation'

Props

PropTypeDefaultDescription
dataTanksBoxDatanoneTank data object

TanksBoxData type

type Tank = {
  cold_temp_c: number
  enabled: boolean
  color?: string      // Visual indicator color
  flash?: boolean     // Enable flash animation
  tooltip?: string    // Tooltip text
}

type TanksBoxData = {
  oil_pump: Tank[]
  water_pump: { enabled: boolean }[]
  pressure: { value?: number; flash?: boolean; color?: string; tooltip?: string }[]
}

Basic usage

<TanksBox
  data={{
    oil_pump: [
      { cold_temp_c: 45, enabled: true },
      { cold_temp_c: 42, enabled: true },
    ],
    water_pump: [
      { enabled: true },
      { enabled: false },
    ],
    pressure: [
      { value: 1.2 },
      { value: 1.1 },
    ],
  }}
/>

With visual alerts

<TanksBox
  data={{
    oil_pump: [
      { cold_temp_c: 85, enabled: true, color: 'red', flash: true, tooltip: 'High temp!' },
    ],
    water_pump: [{ enabled: true }],
    pressure: [{ value: 2.5, color: 'orange', flash: true }],
  }}
/>

Styling

  • .mdk-tanks-box: Root element
  • Uses TankRow internally for each tank display

SupplyLiquidBox

Displays cooling liquid supply metrics including temperature, set temperature, and pressure.

Import

import { SupplyLiquidBox } from '@mdk/foundation'

Props

PropTypeDefaultDescription
dataDevicenoneContainer device data
containerSettingsSupplyLiquidBoxContainerSettingsnullThreshold configuration

Basic usage

<SupplyLiquidBox data={containerDevice} />

With threshold settings

<SupplyLiquidBox
  data={containerDevice}
  containerSettings={{
    thresholds: {
      supply_liquid_temp: { warning: 35, critical: 40 },
      supply_liquid_pressure: { warning: 1.8, critical: 2.0 },
    },
  }}
/>

Features

The component displays three SingleStatCard items:

  • Supply Liquid Temp: Current liquid temperature
  • Supply Liquid Set Temp: Target temperature
  • Supply Liquid Pressure: Current pressure

Each stat automatically shows color and flash indicators based on threshold settings.

Styling

  • .mdk-supply-liquid-box: Root element
  • .mdk-supply-liquid-box__stats: Stats container

MinersSummaryBox

Displays mining summary parameters in a 2-column grid layout.

Import

import { MinersSummaryBox } from '@mdk/foundation'

Props

PropTypeDefaultDescription
paramsMinersSummaryParam[]requiredArray of label-value pairs
classNamestringnoneAdditional CSS class

MinersSummaryParam type

type MinersSummaryParam = {
  label: string   // Parameter name
  value: string   // Pre-formatted display value (including units)
}

Basic usage

<MinersSummaryBox
  params={[
    { label: 'Efficiency', value: '32.5 W/TH/S' },
    { label: 'Hash Rate', value: '1.24 PH/s' },
    { label: 'Max Temp', value: '72 °C' },
    { label: 'Avg Temp', value: '65 °C' },
  ]}
/>

Notes

  • Values must be pre-formatted strings (the component does not format data)
  • Text size automatically adjusts for long values (>12 or >15 characters)

Styling

  • .mdk-miners-summary-box: Root element
  • .mdk-miners-summary-box__param: Individual parameter row
  • .mdk-miners-summary-box__label: Parameter label
  • .mdk-miners-summary-box__label--small: Smaller text for long values
  • .mdk-miners-summary-box__label--tiny: Tiny text for very long values
  • .mdk-miners-summary-box__value: Parameter value

EnabledDisableToggle

Toggle control to enable/disable tank circulation or the air exhaust system. Disabled when the container is offline.

Import

import { EnabledDisableToggle } from '@mdk/foundation'

Props

PropTypeDefaultDescription
valueunknownrequiredCurrent toggle value; boolean enables switch display
tankNumbernumber | stringrequiredTank identifier; empty falls back to "Air Exhaust System"
isButtonDisabledbooleanrequiredDisables both Enable and Disable buttons
isOfflinebooleanrequiredMarks container offline and disables controls
onToggle(params: { tankNumber, isOn: boolean }) => voidrequiredFires when user clicks Enable or Disable

Basic usage

<EnabledDisableToggle
  value={tank.circulationEnabled}
  tankNumber={1}
  isButtonDisabled={false}
  isOffline={false}
  onToggle={({ tankNumber, isOn }) => submitToggle(tankNumber, isOn)}
/>

Air exhaust variant

<EnabledDisableToggle
  value={exhaustEnabled}
  tankNumber=""
  isButtonDisabled={false}
  isOffline={false}
  onToggle={({ isOn }) => setExhaust(isOn)}
/>

Styling

  • .mdk-enabled-disable-toggle: Root element
  • .mdk-enabled-disable-toggle__toggle: Label and Switch row shown when value is boolean

GenericDataBox

Renders a table of label/value/unit rows with optional highlighting, color, and flash states, using a shared fallback when a value is missing.

Import

import { GenericDataBox } from '@mdk/foundation'

Props

PropTypeDefaultDescription
dataDataItem[][]Rows to render as label, value, and units
fallbackValueunknownnoneValue used when a row's value is undefined

DataItem type

type DataItem = {
  label?: string
  value?: unknown
  units?: string
  unit?: string          // Alternative unit field
  isHighlighted?: boolean
  color?: string
  flash?: boolean
}

Basic usage

<GenericDataBox
  data={[
    { label: 'Temperature', value: 45, units: '°C' },
    { label: 'Pressure', value: 2.5, units: 'bar', isHighlighted: true },
    { label: 'Status', value: 'Running', color: 'green' },
  ]}
/>

Styling

  • .mdk-generic-data-box: Root element
  • Renders each row through DataRow

Socket

Visualizes a single PDU socket with power, current, miner status, cooling fan indicator, and heatmap coloring for temperature or hashrate, plus an add-miner affordance in edit mode.

Import

import { Socket } from '@mdk/foundation'

Props

PropTypeDefaultDescription
socketnumber | nullnullSocket index shown in the cell
enabledbooleanfalseWhether the socket is powered
selectedbooleanfalseApplies selected visual state
current_anumber | nullnullCurrent draw in amperes
power_wnumber | nullnullPower draw in watts
minerMiner | nullnullMiner mounted in the socket
heatmapHeatmap | nullnullHeatmap configuration; see type below
coolingboolean | undefinedundefinedShows cooling fan state when set
isEditFlowbooleanfalseRenders the add-miner flow UI
clickDisabledbooleanfalseDisables socket click interactions
isEmptyPowerDashedbooleanfalseShows zero power with dashed border
isContainerControlSupportedbooleanfalseAffects tooltip copy for controls
pdu{ pdu?: string | number }nonePDU metadata used for data-pdu-index
innerRefForwardedRef<HTMLDivElement>noneForwarded ref to the root element

Heatmap type

type Heatmap = {
  isHeatmapMode?: boolean
  mode?: string       // e.g. 'hashrate' or a temperature field
  ranges?: Record<string, { min?: number; max?: number }>
}

Basic usage

<Socket
  socket={1}
  enabled
  power_w={3250}
  current_a={14.5}
  miner={minerData}
/>

With heatmap

<Socket
  socket={1}
  enabled
  miner={minerData}
  heatmap={{
    isHeatmapMode: true,
    mode: 'chip_avg',
    ranges: { chip_avg: { min: 40, max: 85 } },
  }}
/>

Styling

  • .mdk-socket: Root element
  • .mdk-socket--has-cooling: Cooling fan visible
  • .mdk-socket--heatmap: Heatmap mode active
  • .mdk-socket--selected: Selected state
  • .mdk-socket--disabled: Click disabled
  • .mdk-socket__wrapper: Content wrapper
  • .mdk-socket__consumption-box: Power and current readouts
  • .mdk-socket__fan-icon / --on: Cooling fan icon
  • .mdk-socket__value: Individual power or current cell
  • .mdk-socket__index: Socket number badge
  • .mdk-socket__add-icon: Add-miner icon shown in edit flow
  • .mdk-socket__connection-icon: Clock icon shown while connecting

TankRow

Row showing a tank's temperature, optional pressure, and oil/water pump running indicators, with color and flash hints for alerts.

Import

import { TankRow } from '@mdk/foundation'

Props

PropTypeDefaultDescription
labelstringrequiredRow label shown on the left
temperaturenumberrequiredTemperature reading displayed in the row
unitstringrequiredUnit suffix appended to the temperature
oilPumpEnabledbooleanrequiredDrives the oil pump indicator state
waterPumpEnabledbooleanrequiredDrives the water pump indicator state
colorstringrequiredAccent color for the temperature cell
flashbooleannoneEnables flash animation on the temp cell
tooltipstringnoneOverrides the default temperature tooltip
pressureTankRowPressurerequiredPressure readout block; see type below

TankRowPressure type

type TankRowPressure = Partial<{
  value: number
  flash: boolean
  color: string
  tooltip: string
}>

Basic usage

<TankRow
  label="Tank 1"
  temperature={45}
  unit="°C"
  oilPumpEnabled
  waterPumpEnabled={false}
  color=""
  pressure={{ value: 1.2 }}
/>

With alert state

<TankRow
  label="Tank 2"
  temperature={82}
  unit="°C"
  oilPumpEnabled
  waterPumpEnabled
  color="red"
  flash
  tooltip="Oil temperature above threshold"
  pressure={{ value: 2.4, color: 'orange', flash: true }}
/>

Styling

  • .mdk-tanks-box__row: Root row element
  • .mdk-tanks-box__params: Temperature and pressure group
  • .mdk-tanks-box__param / __param-label / __param-value: Individual readouts
  • .mdk-tanks-box__pump-statuses: Pump indicator group
  • .mdk-tanks-box__pump-status / __pump-status-title: Per-pump indicator

ContainerFanLegend

Small badge displaying a numbered fan with an on/off styled fan icon. Used as a legend tile within fan grids.

Import

import { ContainerFanLegend } from '@mdk/foundation'

Props

PropTypeDefaultDescription
indexnumber | nullnoneFan number shown in the badge
enabledbooleanfalseRenders on/off styling and icon color
classNamestringnoneAdditional CSS class on the root element

Basic usage

<ContainerFanLegend index={1} enabled />
<ContainerFanLegend index={2} enabled={false} />

Styling

  • .mdk-container-fan-legend: Root element
  • .mdk-container-fan-legend--on / --off: On/off state modifier
  • .mdk-container-fan-legend__number: Fan number badge
  • .mdk-container-fan-legend__icon / --on / --off: Fan icon container

ContainerFansCard

Renders a grid of ContainerFanLegend entries from a fans data array, showing each fan's number and on/off state.

Import

import { ContainerFansCard } from '@mdk/foundation'

Props

PropTypeDefaultDescription
fansDataPumpItem[]noneFan entries; returns null when omitted

PumpItem type

type PumpItem = {
  enabled?: boolean
  index: number
}

Basic usage

<ContainerFansCard
  fansData={[
    { enabled: true, index: 0 },
    { enabled: false, index: 1 },
    { enabled: true, index: 2 },
  ]}
/>

Styling

  • .mdk-container-fans-card: Root grid element
  • Renders one ContainerFanLegend per entry

DryCooler

Displays two dry cooler segments, each with a running/off indicator, fan grid, and associated oil and water pump boxes, backfilling empty slots when data is partial.

Import

import { DryCooler } from '@mdk/foundation'

Props

PropTypeDefaultDescription
dataUnknownRecordnoneContainer device record with cooling system stats

Basic usage

<DryCooler data={containerDevice} />

Expected data shape

The component reads the following path from data:

// data.container_specific_stats.cooling_system
{
  dry_cooler: [
    { index: 0, enabled: true, fans: [{ enabled: true, index: 0 }] },
    { index: 1, enabled: false, fans: [] },
  ],
  oil_pump:   [{ enabled: true, index: 0 }, { enabled: false, index: 1 }],
  water_pump: [{ enabled: true, index: 0 }, { enabled: true,  index: 1 }],
}

Styling

  • .mdk-dry-cooler: Root element
  • .mdk-dry-cooler__segment: Per-cooler group
  • .mdk-dry-cooler__card: Cooler card with status and fans
  • .mdk-dry-cooler__status: Title and indicator row
  • .mdk-dry-cooler__title: Cooler title
  • .mdk-dry-cooler__pumps: Oil and water pump column

PumpBox

Compact box showing a named, numbered pump with a running or off indicator. Renders nothing when the pump has no boolean enabled state.

Import

import { PumpBox } from '@mdk/foundation'

Props

PropTypeDefaultDescription
pumpTitlestringrequiredPump label prefix (e.g. "Oil", "Water")
pumpItemPumpItemnonePump entry; returns null without a boolean enabled

PumpItem type

type PumpItem = {
  enabled?: boolean
  index: number        // zero-based; shown as index + 1
}

Basic usage

<PumpBox pumpTitle="Oil" pumpItem={{ enabled: true, index: 0 }} />
<PumpBox pumpTitle="Water" pumpItem={{ enabled: false, index: 1 }} />

Styling

  • .mdk-pump-box: Root element
  • .mdk-pump-box__status: Title and indicator row
  • .mdk-pump-box__title: Pump title text

On this page