Device Card
The device card displays a store device (POS terminal, printer, scanner, RFID reader) with its status, key-value stats, and action links. Used on the store-admin "Perangkat Toko" page.
Ilustrasi POS
POS Kasir 1Online
IP Address192.168.1.42
Firmwarev2.4.1
SerialPOS-JKT-003
RestartKonfigurasiLog
Anatomy
+-----------------------------------------------+
| |
| [Isometric device illustration] |
| (120x120px) |
| |
| Device Name [Online] badge |
| |
| IP Address 192.168.1.42 |
| Terakhir Online 22 Mar, 14:32 |
| Firmware v2.4.1 |
| Serial POS-JKT-003 |
| |
| Restart | Konfigurasi | Log |
+-----------------------------------------------+Visual Specifications
| Element | Style |
|---|---|
| Card | bg-card, border, rounded-xl, padding 20px |
| Illustration | Isometric style (see Illustration), centered, 120x120px |
| Device name | 16px, font-semibold, text-1 |
| Status badge | Pill badge, same as data table badge variants |
| Key-value rows | Label: 13px text-2, left. Value: 13px font-mono, text-1, right |
| Action links | 13px, font-semibold, text-brand (#2D6B4A), hover underline |
| Action separator | 1px border vertical between links |
Status Badge Variants
| Status | Label | Badge Color |
|---|---|---|
| Online | Online | Green bg, green text |
| Offline | Offline | Red bg, red text |
| Maintenance | Maintenance | Amber bg, amber text |
| Updating | Updating | Blue bg, blue text |
React Component
tsx
interface DeviceStat {
label: string
value: string
}
interface DeviceAction {
label: string
onClick: () => void
}
interface DeviceCardProps {
name: string
illustration: React.ReactNode
status: 'online' | 'offline' | 'maintenance' | 'updating'
stats: DeviceStat[]
actions: DeviceAction[]
}
export function DeviceCard({ name, illustration, status, stats, actions }: DeviceCardProps) {
const statusStyles = {
online: 'bg-green-50 text-green-700',
offline: 'bg-red-50 text-red-700',
maintenance: 'bg-amber-50 text-amber-700',
updating: 'bg-blue-50 text-blue-700',
}
return (
<div className="bg-card border border-border rounded-xl p-5">
{/* Illustration */}
<div className="flex justify-center mb-4">
<div className="w-[120px] h-[120px]">{illustration}</div>
</div>
{/* Name + Status */}
<div className="flex items-center justify-between mb-4">
<h3 className="font-semibold text-1">{name}</h3>
<span className={cn('px-2 py-0.5 rounded-full text-[10px] uppercase font-semibold', statusStyles[status])}>
{status}
</span>
</div>
{/* Stats */}
<div className="space-y-2 mb-4">
{stats.map(stat => (
<div key={stat.label} className="flex justify-between text-[13px]">
<span className="text-2">{stat.label}</span>
<span className="font-mono text-1">{stat.value}</span>
</div>
))}
</div>
{/* Actions */}
<div className="flex items-center justify-center gap-0 border-t border-border pt-3">
{actions.map((action, i) => (
<Fragment key={action.label}>
{i > 0 && <div className="w-px h-4 bg-border mx-3" />}
<button
onClick={action.onClick}
className="text-[13px] font-semibold text-brand hover:underline"
>
{action.label}
</button>
</Fragment>
))}
</div>
</div>
)
}Grid Layout
Display device cards in a responsive grid:
| Breakpoint | Columns |
|---|---|
| Desktop (>1280px) | 4 columns |
| Laptop (1024--1280px) | 3 columns |
| Tablet (768--1024px) | 2 columns |
| Mobile (<768px) | 1 column |
Gap: 16px
Offline State
When a device is offline for more than 24 hours, add a subtle red tint to the card border (border-red-200) and show a warning icon next to the status badge.
Don't
- Don't use photographs of devices --- always use isometric illustrations
- Don't show real IP addresses in documentation examples
- Don't auto-refresh device status more frequently than every 30 seconds