Container components
Components for displaying and controlling Bitcoin mining containers
Components for viewing, navigating, and controlling Bitcoin mining containers, racks, and associated hardware.
Prerequisites
- Complete the @mdk/foundation installation and add the dependency
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.
| Component | Description |
|---|---|
DeviceExplorer | Hierarchical view of containers, racks, and miners |
ContainerControlsBox | Batch container operations panel |
TanksBox | Immersion tank status display |
SupplyLiquidBox | Cooling liquid supply monitoring |
MinersSummaryBox | Container miner summary widget |
EnabledDisableToggle | Tank circulation toggle control |
GenericDataBox | Generic label-value-unit datatable |
Socket | PDU socket tile with power and miner state |
TankRow | Single tank stats row |
ContainerFanLegend | Single container fan status badge |
ContainerFansCard | Grid of container fan indicators |
DryCooler | Dry cooler units with fans and pumps |
PumpBox | Single pump running/off indicator |
BitdeerPumps | Bitdeer exhaust fan status indicator |
BitdeerSettings | Bitdeer container settings and thresholds |
BitdeerTankPressureCharts | Bitdeer tank pressure time-series chart |
BitdeerTankTempCharts | Bitdeer tank oil and water temperature chart |
BitMainBasicSettings | Bitmain cooling, power and positioning view |
BitMainCoolingSystem | Bitmain cooling pump and fan statuses |
BitMainHydroLiquidTemperatureCharts | Bitmain hydro secondary liquid temp chart |
BitMainHydroSettings | Bitmain hydro settings and thresholds |
BitMainLiquidPressureCharts | Bitmain supply/return liquid pressure chart |
BitMainLiquidTempCharts | Bitmain supply/return liquid temp chart |
BitMainPowerAndPositioning | Bitmain distribution power and GPS panel |
BitMainPowerCharts | Bitmain total and per-box power chart |
BitMainSupplyLiquidFlowCharts | Bitmain supply liquid flow chart |
StatusItem | Labeled status indicator row |
BitMainControlsTab | Bitmain immersion controls tab view |
BitMainImmersionControlBox | Two-column immersion control box container |
BitMainImmersionPumpStationControlBox | Pump station alarm and state card |
BitMainImmersionSettings | Bitmain immersion threshold settings form |
BitMainImmersionSummaryBox | Bitmain immersion pumps and liquid temps |
BitMainImmersionSystemStatus | Immersion server start and connection status |
BitMainImmersionUnitControlBox | Immersion unit status and frequency card |
FireStatusBox | MicroBT fire and environmental sensors |
GaugeChartComponent | Labeled gauge chart with value and unit |
MicroBTCooling | MicroBT cooling system detail panel |
MicroBTSettings | MicroBT container settings and thresholds |
MicroBTWidgetBox | MicroBT cycle pump and cooling fan widget |
PowerMeters | MicroBT 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
| Prop | Type | Default | Description |
|---|---|---|---|
deviceType | 'container' | 'miner' | 'cabinet' | required | Current view type |
data | Device[] | required | Array of devices to display |
filterOptions | DeviceExplorerFilterOption[] | required | Cascader filter options |
searchOptions | DeviceExplorerSearchOption[] | required | Search autocomplete options |
searchTags | string[] | required | Current search tags |
onSearchTagsChange | (tags: string[]) => void | required | Search tags change handler |
onDeviceTypeChange | (type: DeviceExplorerDeviceType) => void | required | Device type tab change handler |
onFiltersChange | (value: LocalFilters) => void | required | Filter change handler |
selectedDevices | DataTableRowSelectionState | {} | Selected row state |
onSelectedDevicesChange | (selections: DataTableRowSelectionState) => void | none | Selection change handler |
renderAction | (device: Device) => ReactNode | none | Custom action column renderer |
getFormattedDate | (date: Date) => string | required | Date formatter function |
className | string | none | Additional 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: FilterCascader.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
| Prop | Type | Default | Description |
|---|---|---|---|
data | Device | none | Container device data |
isBatch | boolean | false | Enable batch operations mode |
selectedDevices | Device[] | [] | Selected devices for batch operations |
pendingSubmissions | PendingSubmission[] | [] | Pending action submissions |
alarmsDataItems | TimelineItemData[] | [] | Active alarms to display |
tailLogData | UnknownRecord[] | none | Tail log data for power modes |
onNavigate | (path: string) => void | required | Navigation 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
| Prop | Type | Default | Description |
|---|---|---|---|
data | TanksBoxData | none | Tank 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
TankRowinternally for each tank display
SupplyLiquidBox
Displays cooling liquid supply metrics including temperature, set temperature, and pressure.
Import
import { SupplyLiquidBox } from '@mdk/foundation'Props
| Prop | Type | Default | Description |
|---|---|---|---|
data | Device | none | Container device data |
containerSettings | SupplyLiquidBoxContainerSettings | null | Threshold 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
| Prop | Type | Default | Description |
|---|---|---|---|
params | MinersSummaryParam[] | required | Array of label-value pairs |
className | string | none | Additional 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
| Prop | Type | Default | Description |
|---|---|---|---|
value | unknown | required | Current toggle value; boolean enables switch display |
tankNumber | number | string | required | Tank identifier; empty falls back to "Air Exhaust System" |
isButtonDisabled | boolean | required | Disables both Enable and Disable buttons |
isOffline | boolean | required | Marks container offline and disables controls |
onToggle | (params: { tankNumber, isOn: boolean }) => void | required | Fires 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 andSwitchrow shown whenvalueis 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
| Prop | Type | Default | Description |
|---|---|---|---|
data | DataItem[] | [] | Rows to render as label, value, and units |
fallbackValue | unknown | none | Value 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
| Prop | Type | Default | Description |
|---|---|---|---|
socket | number | null | null | Socket index shown in the cell |
enabled | boolean | false | Whether the socket is powered |
selected | boolean | false | Applies selected visual state |
current_a | number | null | null | Current draw in amperes |
power_w | number | null | null | Power draw in watts |
miner | Miner | null | null | Miner mounted in the socket |
heatmap | Heatmap | null | null | Heatmap configuration; see type below |
cooling | boolean | undefined | undefined | Shows cooling fan state when set |
isEditFlow | boolean | false | Renders the add-miner flow UI |
clickDisabled | boolean | false | Disables socket click interactions |
isEmptyPowerDashed | boolean | false | Shows zero power with dashed border |
isContainerControlSupported | boolean | false | Affects tooltip copy for controls |
pdu | { pdu?: string | number } | none | PDU metadata used for data-pdu-index |
innerRef | ForwardedRef<HTMLDivElement> | none | Forwarded 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
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | required | Row label shown on the left |
temperature | number | required | Temperature reading displayed in the row |
unit | string | required | Unit suffix appended to the temperature |
oilPumpEnabled | boolean | required | Drives the oil pump indicator state |
waterPumpEnabled | boolean | required | Drives the water pump indicator state |
color | string | required | Accent color for the temperature cell |
flash | boolean | none | Enables flash animation on the temp cell |
tooltip | string | none | Overrides the default temperature tooltip |
pressure | TankRowPressure | required | Pressure 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
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | null | none | Fan number shown in the badge |
enabled | boolean | false | Renders on/off styling and icon color |
className | string | none | Additional 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
| Prop | Type | Default | Description |
|---|---|---|---|
fansData | PumpItem[] | none | Fan 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
ContainerFanLegendper 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
| Prop | Type | Default | Description |
|---|---|---|---|
data | UnknownRecord | none | Container 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
| Prop | Type | Default | Description |
|---|---|---|---|
pumpTitle | string | required | Pump label prefix (e.g. "Oil", "Water") |
pumpItem | PumpItem | none | Pump 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

