16 KiB
DemoBMS — UI/UX Improvement Plan
Generated from full page-by-page review (16 pages + shared layout). Work through phases in order — each phase builds on the previous.
Phase 1 — Foundation Fixes
Goal: Fix broken/incomplete global chrome and shared infrastructure before touching individual pages. Effort: ~1–2 days | Risk: Low
1.1 Topbar title map — complete it
- Add missing entries for: generator, leak, fire, network, energy, maintenance
- Replace pathname-based map with a route config object shared with sidebar
1.2 Topbar — replace placeholder avatar with Clerk UserButton
- Swap the blue circle for
<UserButton />from@clerk/nextjs - Removes the hardcoded placeholder and provides sign-out, profile link for free
1.3 Topbar — remove or disable the site selector
- The dropdown is hardcoded with 3 fake sites and does nothing
- Either wire it to real site context, or remove it entirely until it's real
- A non-functional control erodes trust
1.4 Topbar — consolidate the alarm badge
- Remove the alarm count badge from the sidebar nav item
- Keep it only on the topbar bell icon (single canonical location)
1.5 Sidebar — add section groupings with dividers
- Split 15 nav items into labelled groups:
- OVERVIEW — Dashboard, Floor Map
- INFRASTRUCTURE — Power, Generator, Cooling, Environmental
- SAFETY — Leak Detection, Fire & Safety, Network
- OPERATIONS — Assets, Alarms, Capacity
- MANAGEMENT — Reports, Energy & CO₂, Maintenance, Settings
- Render section headers as small ALL-CAPS muted labels with a horizontal rule above
- Collapsed sidebar: show only icons, hide section headers
1.6 Sidebar — move collapse toggle to bottom
- Currently the toggle is an absolutely-positioned button that's easy to miss
- Move it to the bottom of the sidebar as a regular icon button above Settings
- Add a tooltip: "Collapse menu" / "Expand menu"
1.7 Centralise threshold constants
- Create
/lib/thresholds.tsexporting a single const object:export const THRESHOLDS = { temp: { warn: 26, critical: 28 }, humidity: { warn: 65, critical: 80 }, power: { warn: 0.75, critical: 0.85 }, // fraction of capacity filter: { warn: 80, critical: 120 }, // Pa compressor: { warn: 0.80, critical: 0.95 }, battery: { warn: 30, critical: 20 }, fuel: { warn: 30, critical: 15 }, } - Replace all hardcoded threshold values across every page with imports from this file
1.8 Global spacing standardisation
- Audit and enforce: all page wrappers use
space-y-6, all cards usep-6, all card headers usepb-3 - Create a
<PageShell title="">wrapper component used by every page to ensure consistent top padding and title rendering
1.9 Empty state and error boundary
- Create a reusable
<ErrorCard message="">component shown when a fetch fails - Create a reusable
<EmptyCard message="">for no-data states - Wrap every data-dependent card in a try/catch that renders
<ErrorCard>instead of crashing - Add a top-level React error boundary in the dashboard layout
Phase 2 — Alarms Page
Goal: Make the alarm page genuinely usable under operational pressure. Effort: ~1 day | Risk: Low
2.1 Sticky filter bar
- Make the filter row (state tabs + severity dropdown)
sticky top-0 z-10so it stays visible while scrolling through long alarm lists
2.2 Bulk action at top
- Move the "Bulk Resolve" button into the filter/action row at the top, not below the table
- Add a "Select All" checkbox in the table header
2.3 Swap Critical stat card for Avg Age
- Replace the "Critical" count card with "Avg Age" — the mean time alarms have been open
- Display as "Xh Ym" format
- Colour red if avg age > 1h, amber if > 15 min, green if < 15 min
2.4 Column priority on small screens
- On mobile/tablet, keep: Severity | Message | Escalation timer | Actions
- Drop: Sensor ID, State (already conveyed by row colour)
- Escalation timer must always be visible — it is the most operationally critical column
2.5 Pagination
- Add simple page controls: Previous / Page X of Y / Next
- Default page size: 25 rows
- Show total count above the table: "Showing 1–25 of 142 alarms"
2.6 Embed sparkline in stat cards
- Remove the standalone 24-hour sparkline chart
- Embed a micro line chart (24 data points, 40px tall) inside each stat card below the number
- Net result: less vertical space used, same information
Phase 3 — Dashboard Page
Goal: Reduce clutter, improve at-a-glance legibility. Effort: ~1 day | Risk: Low
3.1 Uniform KPI card grid
- Standardise all 6 KPI cards to the same height and same layout template
- Use a 3×2 grid (3 cols on lg, 2 on md, 1 on sm) consistently
3.2 Replace mini floor map
- The mini floor map widget is too small to be useful
- Replace with a "Room Quick Status" card:
- Two rows: Hall A / Hall B
- Each row: health badge (OK / Warning / Critical), avg temp, total power, CRAC state
- Link to /floor-map for full view
3.3 Data freshness pill in topbar
- Move the "last updated" indicator from the dashboard page into the topbar (right side, before the bell)
- Make it global — show the last successful API poll timestamp for any page
- Colour: green if < 60s, amber if 60–120s, red if > 120s (stale)
3.4 Alarm feed / Room status layout
- Change the bottom row from 2-col + 1-col to 50/50
- Alarm Feed: left panel
- Room Quick Status: right panel (replaces mini floor map)
Phase 4 — Power Page
Goal: Tame the long scroll, improve information hierarchy. Effort: ~1.5 days | Risk: Low–Medium
4.1 Page-internal anchor navigation
- Add a sticky sub-nav bar below the topbar with anchor links:
Site Overview | UPS | Generator | Transfer Switch | Phase Analysis - Each section gets an
id=""and smooth-scroll on click
4.2 Power path diagram
- Add a simple horizontal flow diagram at the top of the page:
Grid → [ATS: feed A/B] → [UPS: battery/online] → Rack Distribution - Use coloured nodes (green = live, amber = degraded, red = fault)
- No library needed — a flex row of icon + connector line components
4.3 Always-visible Phase Summary card
- Show a collapsed "Phase Balance" summary card at all times (Phase A / B / C current kW in a 3-col grid)
- Expand to full Phase Imbalance Table on click or if violations exist
4.4 Per-rack bar chart — full width
- The per-rack chart needs more horizontal room to show 10 bars legibly
- Move it to full width above the history chart (stack them, not side by side)
Phase 5 — Cooling Page
Goal: Reduce card density, surface critical maintenance items earlier. Effort: ~1 day | Risk: Low
5.1 Standardise fleet summary bar
- Replace the horizontal KPI tile flex row with proper KPI cards matching dashboard style
5.2 Promote filter replacement alert
- If any CRAC unit is within 14 days of filter replacement threshold, show a dismissible alert banner at the top of the page
- Move the Predictive Filter Replacement card to the top of the page (above CRAC cards)
5.3 CRAC card — progressive disclosure
- The current CRAC card has 6 stacked sections
- Keep: thermal hero (supply/return/ΔT), capacity bar, fan speed
- Collapse into a "Details" accordion: compressor pressures + electrical readings
- The thermal hero section should be 30% larger — it is the most important readout
5.4 Thermal hero — increase visual weight
- Increase supply/return temp font to text-3xl
- ΔT value in a coloured pill (green/amber/red based on threshold)
- Add a small up/down arrow showing trend (last 5 min)
Phase 6 — Environmental Page
Goal: Unify interactive state across sections, reduce redundancy. Effort: ~1 day | Risk: Low
6.1 Shared room tab state
- All sections on the page (heatmap, dew point, trend chart) should react to a single room tab selector at the top of the page, not per-section tabs
- Add one prominent "Hall A / Hall B" tab switcher at the page level
6.2 Dual-axis chart — clarify axes
- Add unit labels on the Y-axis: left axis "Temperature (°C)", right axis "Humidity (%)"
- Change the humidity line to a dashed style (already done) but also add a subtle fill under it to visually distinguish it from the temperature line
- Add a brief legend note: "Shaded areas = ASHRAE A1 safe zone"
6.3 VESDA and Leak panels — link to dedicated pages
- Label both panels clearly as "Summary — see Leak Detection / Fire & Safety for detail"
- Add a "View full page →" link in each panel header
- This avoids duplicating full detail here
Phase 7 — Floor Map Page
Goal: Improve overlay controls and map legibility. Effort: ~1 day | Risk: Low–Medium
7.1 Overlay controls — proper segmented control
- Replace the 4 overlay buttons with a shadcn
<Tabs>style segmented control - Active tab: filled background, not just a subtle border change
7.2 Hot/cold aisle labels — improve visibility
- Increase aisle divider label font size and weight
- Add icon: 🔴 Hot Aisle / 🔵 Cold Aisle (or Lucide Flame / Snowflake)
- Increase divider bar height slightly
7.3 Rack tile — secondary metric on hover only
- In Temperature overlay: show °C as main value; power bar appears on hover tooltip only
- In Power overlay: show % as main value; temp appears in tooltip
- Reduces visual clutter in the tile grid
7.4 CRAC strip — move above rack grid
- The CRAC strip is currently below the rack grid and easy to miss
- Move it above the grid with a stronger visual separator (border + label "Cooling Unit")
7.5 Leak sensor panel — add zone labels
- Add a brief location description to each sensor: "Hall A — under floor, near CRAC" etc.
- Use consistent zone label chips rather than free text
Phase 8 — Assets Page
Goal: Make each tab genuinely useful and distinct from other pages. Effort: ~1 day | Risk: Low
8.1 Rack Grid tab → Rack Summary Table
- Replace the visual rack grid (duplicates Floor Map) with a sortable table:
- Columns: Rack ID | Room | Temp (°C) | Power (kW) | Power % | Alarms | Status
- Sortable by any column
- Row click opens RackDetailSheet
8.2 Device List — sort headers
- Add click-to-sort on every column header with a sort direction indicator (chevron icon)
- Default sort: Type then Name
8.3 Device type legend
- Add a compact colour legend row above the device table explaining the dot colours
- One row of: ● Server ● Switch ● PDU ● Storage ● Firewall ● KVM
8.4 CRAC / UPS cards → inventory rows
- Replace the large card components with compact inventory table rows:
- ID | Type | Status | Room | Rack | Last Maintenance
- Link to full detail on click (CracDetailSheet / UpsCard modal)
Phase 9 — Remaining Pages
Goal: Individual page improvements that don't interact with other phases. Effort: ~1.5 days | Risk: Low
9.1 Generator page — add fuel runtime estimate
- Add "Est. runtime at current load: X hours" as the hero stat in each generator card
- Show a small fuel consumption trend chart (last 24h) if data is available
- Clearly differentiate this page from the generator section in Power page by adding: last start log, maintenance schedule table
9.2 Capacity page — radial gauge values
- Ensure a large centered text value (e.g. "74%") is always visible inside the gauge arc
- Add "Headroom: X kW" as a sub-label below the gauge
9.3 Capacity page — runway in months
- Display runway as "~2.3 months" alongside weeks
- Add a 90-day forecast line on the per-rack chart (dotted line extrapolating current growth)
9.4 Fire & Safety page — fire state improvements
- Fire-level cards: increase border to 4px, add a very faint red background overlay (
bg-red-950/30) - Replace small status dots with a proper status row: icon + label + state text (e.g. ✓ Detector 1 — Online)
- Show raw obscuration value (%/m) on the bar, not just the bar fill
9.5 Leak Detection page — add history
- Add "Last triggered: X days ago" to each sensor card
- Add a 30-day trigger count badge: "0 events" / "3 events"
- This keeps the page useful when all sensors are clear
9.6 Network page — improve port display
- Change port headline from "72%" to "36 / 48 ports active" — then show % as sub-label
- Group card metrics: top 3 bold (state, ports, bandwidth) + secondary row (CPU, memory, temp)
9.7 Reports page — promote export to top
- Move the 3 export buttons to a prominent action bar at the top of the page
- Add a page-level date range picker that controls all KPIs on the page simultaneously
- Always show numeric % labels on CRAC/UPS uptime bars
9.8 Maintenance page — modal for create form
- Move "Create window" form into a shadcn
<Dialog>modal triggered by the header button - In the target selector, group options: Site / Hall A racks / Hall B racks / Cooling / Power
- Add a 7-day horizontal timeline strip below the active windows list showing when each window falls
9.9 Settings page — skeleton structure
- Replace "Coming soon" with a tabbed layout: Profile | Notifications | Thresholds | Site Config
- Thresholds tab: shows the values from
lib/thresholds.tsas editable fields (even if not persisted to backend yet) - This makes the page look intentional rather than unfinished
Phase 10 — Polish & Accessibility
Goal: Final consistency pass, mobile, keyboard navigation. Effort: ~1–2 days | Risk: Low
10.1 Mobile audit
- Test every page at 375px and 768px width
- Fix broken chart widths (use
ResponsiveContainereverywhere, check it's set) - Ensure touch targets are ≥44px tall
- Test sidebar sheet on mobile
10.2 Focus rings and keyboard nav
- Add
focus-visible:ring-2 focus-visible:ring-primaryto all interactive elements that are missing it - Verify logical tab order on every page (left-to-right, top-to-bottom)
- Add
aria-labelto icon-only buttons (alarm bell, collapse toggle, overlay buttons)
10.3 Chart skeleton height matching
- Measure actual rendered chart heights for each chart type
- Set skeleton
h-[]to match exactly, preventing layout shift on load
10.4 Dark/light mode toggle
- Add a theme toggle button in the topbar (Moon / Sun icon)
- The ThemeProvider is already wired — just needs a toggle button and
localStoragepersistence
10.5 Loading state audit
- Every card that fetches data must show a
<Skeleton>during initial load - No card should show an empty white box or flash unstyled content
10.6 Toast notification consistency
- Audit all
toast.error()/toast.success()calls across pages - Ensure every user action (acknowledge alarm, bulk resolve, create maintenance window, export) has a corresponding success/error toast
Summary Table
| Phase | Focus | Pages Touched | Est. Effort |
|---|---|---|---|
| 1 | Foundation fixes (nav, thresholds, errors) | All (shared) | 1–2 days |
| 2 | Alarms page | Alarms | 1 day |
| 3 | Dashboard page | Dashboard | 1 day |
| 4 | Power page | Power | 1.5 days |
| 5 | Cooling page | Cooling | 1 day |
| 6 | Environmental page | Environmental | 1 day |
| 7 | Floor Map page | Floor Map | 1 day |
| 8 | Assets page | Assets | 1 day |
| 9 | Remaining pages | Generator, Capacity, Fire, Leak, Network, Reports, Maintenance, Settings | 1.5 days |
| 10 | Polish & accessibility | All | 1–2 days |
| Total | ~11–13 days |
Dependency Order
Phase 1 (foundation)
└─► Phase 2 (alarms)
└─► Phase 3 (dashboard)
└─► Phase 4 (power)
└─► Phase 5 (cooling)
└─► Phase 6 (environmental)
└─► Phase 7 (floor map)
└─► Phase 8 (assets)
└─► Phase 9 (remaining pages)
└─► Phase 10 (polish — last, after all pages stable)
Phases 2–9 are independent of each other and can be parallelised once Phase 1 is complete.