From 1de6e91ba3951694d883a19517c7537af47953aa Mon Sep 17 00:00:00 2001 From: Pouzor Date: Fri, 3 Jul 2026 11:07:48 +0200 Subject: [PATCH] feat: colour device-inventory role badge by node-type accent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The role/type badge on each inventory tile was always flat grey (bg-[#21262d] text-muted-foreground), which read as disabled and gave no visual cue about the device kind. Colour it with the same per-type accent the node uses on the canvas — resolved through the active theme / style section via resolveNodeColors — so a zigbee_coordinator, zwave_router, etc. gets its style-section colour (translucent background + solid text). Applies to every source (IP, zigbee, zwave) since all node types carry an accent in the theme. Test: role badge renders with the node-type accent colour, not the grey muted class. ha-relevant: yes --- .../src/components/modals/PendingDevicesModal.tsx | 14 ++++++++++++-- .../modals/__tests__/PendingDevicesModal.test.tsx | 12 ++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/modals/PendingDevicesModal.tsx b/frontend/src/components/modals/PendingDevicesModal.tsx index 926c947..6d3af0d 100644 --- a/frontend/src/components/modals/PendingDevicesModal.tsx +++ b/frontend/src/components/modals/PendingDevicesModal.tsx @@ -7,6 +7,8 @@ import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle } from '@ import { scanApi } from '@/api/client' import { useCanvasStore } from '@/stores/canvasStore' import { useDesignStore } from '@/stores/designStore' +import { useThemeStore } from '@/stores/themeStore' +import { resolveNodeColors } from '@/utils/nodeColors' import { toast } from 'sonner' import { PendingDeviceModal, type PendingDevice } from '@/components/modals/PendingDeviceModal' import type { NodeType, ServiceInfo } from '@/types' @@ -657,7 +659,12 @@ interface DeviceCardProps { function DeviceCard({ device, selected, selectMode, highlighted, onClick, cardRef }: DeviceCardProps) { const source = inferSource(device) - const Icon = TYPE_ICONS[device.suggested_type ?? 'generic'] ?? Circle + const roleType = (device.suggested_type ?? 'generic') as NodeType + const Icon = TYPE_ICONS[roleType] ?? Circle + const activeTheme = useThemeStore((s) => s.activeTheme) + // Colour the role badge with the same accent the node uses on the canvas + // (from the active theme / style section), instead of a flat grey. + const roleColor = resolveNodeColors({ type: roleType, custom_colors: undefined }, activeTheme).border const label = deviceLabel(device) const sourceColor = source === 'zigbee' ? '#00d4ff' : source === 'zwave' ? '#ff6e00' : '#a855f7' const sourceLabel = @@ -734,7 +741,10 @@ function DeviceCard({ device, selected, selectMode, highlighted, onClick, cardRe {sourceLabel} {device.suggested_type && ( - + {device.suggested_type} )} diff --git a/frontend/src/components/modals/__tests__/PendingDevicesModal.test.tsx b/frontend/src/components/modals/__tests__/PendingDevicesModal.test.tsx index 25b27be..ae322fc 100644 --- a/frontend/src/components/modals/__tests__/PendingDevicesModal.test.tsx +++ b/frontend/src/components/modals/__tests__/PendingDevicesModal.test.tsx @@ -153,6 +153,18 @@ describe('PendingDevicesModal', () => { expect(screen.getByText('Z-WAVE')).toBeInTheDocument() }) + it('colours the role badge with the node-type accent, not flat grey', async () => { + mockPending.mockResolvedValue({ data: [DEVICE_ZWAVE] }) + render() + const card = await waitFor(() => screen.getByTestId('pending-card-dev-c')) + // zwave_router accent from the default theme = #e3b341 (amber), applied to + // both the text colour and a translucent background. + const badge = within(card).getByText('zwave_router') + // #e3b341 → rgb(227, 179, 65) once jsdom normalises the inline colour. + expect(badge).toHaveStyle({ color: 'rgb(227, 179, 65)' }) + expect(badge.className).not.toContain('text-muted-foreground') + }) + it('filters by source (zwave only)', async () => { mockPending.mockResolvedValue({ data: [DEVICE_IP, DEVICE_ZWAVE] }) render()