+
@@ -118,7 +118,7 @@ export function CAStatusCard({ ca, canWrite: writable, tenantId }: CAStatusCardP
return (
diff --git a/frontend/src/components/certificates/CertificatesPage.tsx b/frontend/src/components/certificates/CertificatesPage.tsx
index c9b4a80..386039c 100644
--- a/frontend/src/components/certificates/CertificatesPage.tsx
+++ b/frontend/src/components/certificates/CertificatesPage.tsx
@@ -74,7 +74,7 @@ export function CertificatesPage() {
Certificate Authority
-
+
)
}
diff --git a/frontend/src/components/certificates/DeviceCertTable.tsx b/frontend/src/components/certificates/DeviceCertTable.tsx
index 02c30d1..f25bca5 100644
--- a/frontend/src/components/certificates/DeviceCertTable.tsx
+++ b/frontend/src/components/certificates/DeviceCertTable.tsx
@@ -189,7 +189,7 @@ export function DeviceCertTable({
}
if (loading) {
- return
+ return
}
return (
diff --git a/frontend/src/components/command-palette/CommandPalette.tsx b/frontend/src/components/command-palette/CommandPalette.tsx
index 7cec592..119c3ed 100644
--- a/frontend/src/components/command-palette/CommandPalette.tsx
+++ b/frontend/src/components/command-palette/CommandPalette.tsx
@@ -204,7 +204,7 @@ export function CommandPalette() {
const visiblePages = pageCommands.filter((p) => p.visible)
const itemClass =
- 'flex items-center gap-3 px-2 py-2 rounded-lg text-sm text-text-secondary cursor-pointer data-[selected=true]:bg-accent-muted data-[selected=true]:text-accent'
+ 'flex items-center gap-3 px-2 py-2 rounded-lg text-sm text-text-secondary cursor-pointer data-[selected=true]:bg-accent-soft data-[selected=true]:text-accent'
const groupHeadingClass =
'[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:text-text-muted [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-wider'
@@ -216,7 +216,7 @@ export function CommandPalette() {
overlayClassName="fixed inset-0 z-50 bg-background/80 backdrop-blur-sm"
contentClassName="fixed left-1/2 top-[20%] -translate-x-1/2 z-50 w-full max-w-lg"
>
-
+
0 && (
{results.map((r, i) => (
-
+
{r.timestamp}
{r.command}
diff --git a/frontend/src/components/config-editor/ConfigEditorPage.tsx b/frontend/src/components/config-editor/ConfigEditorPage.tsx
index 9569788..ab7211d 100644
--- a/frontend/src/components/config-editor/ConfigEditorPage.tsx
+++ b/frontend/src/components/config-editor/ConfigEditorPage.tsx
@@ -325,7 +325,7 @@ export function ConfigEditorPage() {
{/* Delete Confirmation Dialog */}
!o && setDeleteConfirmOpen(false)}>
-
+
Confirm Delete
diff --git a/frontend/src/components/config-editor/EntryForm.tsx b/frontend/src/components/config-editor/EntryForm.tsx
index 9f7b0b5..464cab1 100644
--- a/frontend/src/components/config-editor/EntryForm.tsx
+++ b/frontend/src/components/config-editor/EntryForm.tsx
@@ -143,7 +143,7 @@ export function EntryForm({ open, onClose, mode, entry, columns, onSubmit }: Ent
return (
!o && onClose()}>
-
+
{mode === 'add' ? 'Add New Entry' : 'Edit Entry'}
diff --git a/frontend/src/components/config-editor/EntryTable.tsx b/frontend/src/components/config-editor/EntryTable.tsx
index efe4d91..7e72629 100644
--- a/frontend/src/components/config-editor/EntryTable.tsx
+++ b/frontend/src/components/config-editor/EntryTable.tsx
@@ -42,7 +42,7 @@ export function EntryTable({
className={cn(
'rounded-lg border p-4 text-sm',
isContainerPath
- ? 'border-border bg-surface text-text-secondary'
+ ? 'border-border bg-panel text-text-secondary'
: 'border-error/30 bg-error/10 text-error',
)}
>
@@ -64,14 +64,8 @@ export function EntryTable({
if (isLoading) {
return (
-
-
- {Array.from({ length: 5 }).map((_, i) => (
-
- ))}
+
+ Loading…
)
}
@@ -128,7 +122,7 @@ export function EntryTable({
diff --git a/frontend/src/components/config-editor/MenuTree.tsx b/frontend/src/components/config-editor/MenuTree.tsx
index b1b21b5..f0bc924 100644
--- a/frontend/src/components/config-editor/MenuTree.tsx
+++ b/frontend/src/components/config-editor/MenuTree.tsx
@@ -265,7 +265,7 @@ function TreeItem({
className={cn(
'flex items-center gap-1.5 w-full px-2 py-1 text-xs rounded transition-colors',
isActive
- ? 'bg-[hsl(var(--accent-muted))] text-accent'
+ ? 'bg-[hsl(var(--accent-soft))] text-accent'
: 'text-text-secondary hover:text-text-primary hover:bg-elevated/50',
)}
style={{ paddingLeft: `${depth * 12 + 8}px` }}
diff --git a/frontend/src/components/config/AddressListPanel.tsx b/frontend/src/components/config/AddressListPanel.tsx
index 147f636..b95cef3 100644
--- a/frontend/src/components/config/AddressListPanel.tsx
+++ b/frontend/src/components/config/AddressListPanel.tsx
@@ -145,7 +145,7 @@ export function AddressListPanel({ tenantId, deviceId, active }: ConfigPanelProp
-
+
diff --git a/frontend/src/components/config/AddressPanel.tsx b/frontend/src/components/config/AddressPanel.tsx
index 90072f5..aad49d2 100644
--- a/frontend/src/components/config/AddressPanel.tsx
+++ b/frontend/src/components/config/AddressPanel.tsx
@@ -282,7 +282,7 @@ function AddressTable({
return (
<>
{/* Table */}
-
+
diff --git a/frontend/src/components/config/ArpPanel.tsx b/frontend/src/components/config/ArpPanel.tsx
index 442e799..b54ff46 100644
--- a/frontend/src/components/config/ArpPanel.tsx
+++ b/frontend/src/components/config/ArpPanel.tsx
@@ -193,8 +193,8 @@ export function ArpPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
className={cn(
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
filterTab === tab.key
- ? 'bg-surface text-text-primary shadow-sm'
- : 'text-text-secondary hover:text-text-primary hover:bg-surface/50',
+ ? 'bg-panel text-text-primary shadow-sm'
+ : 'text-text-secondary hover:text-text-primary hover:bg-panel/50',
)}
>
{tab.label}
@@ -290,7 +290,7 @@ function ArpTable({
return (
<>
{/* Table */}
-
+
diff --git a/frontend/src/components/config/BandwidthTestTool.tsx b/frontend/src/components/config/BandwidthTestTool.tsx
index c055062..61ed058 100644
--- a/frontend/src/components/config/BandwidthTestTool.tsx
+++ b/frontend/src/components/config/BandwidthTestTool.tsx
@@ -82,7 +82,7 @@ export function BandwidthTestTool({ tenantId, deviceId }: ConfigPanelProps) {
return (
-
+
Target Address
@@ -99,7 +99,7 @@ export function BandwidthTestTool({ tenantId, deviceId }: ConfigPanelProps) {
setDirection(e.target.value)}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
Both
Send
@@ -111,7 +111,7 @@ export function BandwidthTestTool({ tenantId, deviceId }: ConfigPanelProps) {
setProtocol(e.target.value)}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
TCP
UDP
@@ -170,7 +170,7 @@ export function BandwidthTestTool({ tenantId, deviceId }: ConfigPanelProps) {
)}
{results.length > 0 && (
-
+
Bandwidth Test Results
diff --git a/frontend/src/components/config/BatchConfigPanel.tsx b/frontend/src/components/config/BatchConfigPanel.tsx
index f0136e1..649dfe2 100644
--- a/frontend/src/components/config/BatchConfigPanel.tsx
+++ b/frontend/src/components/config/BatchConfigPanel.tsx
@@ -180,11 +180,11 @@ function DeviceSelector({
onSelectionChange(new Set())
}
- if (isLoading) return
+ if (isLoading) return
if (devices.length === 0) {
return (
-
+
No devices found for this tenant.
)
@@ -208,7 +208,7 @@ function DeviceSelector({
-
+
@@ -327,7 +327,7 @@ function ChangeDefiner({
{operationType && (
-
+
{operationType === 'add-firewall-rule' && (
<>
Firewall Rule
@@ -605,7 +605,7 @@ function ExecutionPanel({
return (
{/* Change description */}
-
+
Change to Apply
{change.description}
@@ -626,7 +626,7 @@ function ExecutionPanel({
{/* Summary */}
{isComplete && (
-
+
{successCount} succeeded
@@ -641,7 +641,7 @@ function ExecutionPanel({
)}
{/* Device status table */}
-
+
diff --git a/frontend/src/components/config/BridgePortPanel.tsx b/frontend/src/components/config/BridgePortPanel.tsx
index 9c8f3bc..2f2bf61 100644
--- a/frontend/src/components/config/BridgePortPanel.tsx
+++ b/frontend/src/components/config/BridgePortPanel.tsx
@@ -138,11 +138,11 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
{ports.entries.length === 0 ? (
-
+
No bridge ports configured.
) : (
-
+
@@ -212,7 +212,7 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, interface: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary font-mono"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary font-mono"
>
Select...
{ifaceNames.map((name) => {name} )}
@@ -223,7 +223,7 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, bridge: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary font-mono"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary font-mono"
>
{bridgeNames.map((name) => {name} )}
@@ -243,7 +243,7 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, 'frame-types': e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
{FRAME_TYPES.map((ft) => {ft} )}
@@ -253,7 +253,7 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, 'ingress-filtering': e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
Yes
No
@@ -264,7 +264,7 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, hw: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
Yes
No
@@ -297,7 +297,7 @@ export function BridgePortPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, edge: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
Auto
Yes
diff --git a/frontend/src/components/config/BridgeVlanPanel.tsx b/frontend/src/components/config/BridgeVlanPanel.tsx
index bb1c465..9da0e40 100644
--- a/frontend/src/components/config/BridgeVlanPanel.tsx
+++ b/frontend/src/components/config/BridgeVlanPanel.tsx
@@ -140,7 +140,7 @@ export function BridgeVlanPanel({ tenantId, deviceId, active }: ConfigPanelProps
{/* VLAN Filtering status per bridge */}
{bridges.entries.length > 0 && (
-
+
Bridge VLAN Filtering
@@ -170,11 +170,11 @@ export function BridgeVlanPanel({ tenantId, deviceId, active }: ConfigPanelProps
{/* VLAN Table */}
{vlans.entries.length === 0 ? (
-
+
No bridge VLAN entries configured.
) : (
-
+
@@ -247,7 +247,7 @@ export function BridgeVlanPanel({ tenantId, deviceId, active }: ConfigPanelProps
setFormData((f) => ({ ...f, bridge: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary font-mono"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary font-mono"
>
{bridgeNames.map((name) => {name} )}
diff --git a/frontend/src/components/config/ConfigDiffViewer.tsx b/frontend/src/components/config/ConfigDiffViewer.tsx
index 8bfc1cb..17d016a 100644
--- a/frontend/src/components/config/ConfigDiffViewer.tsx
+++ b/frontend/src/components/config/ConfigDiffViewer.tsx
@@ -81,9 +81,9 @@ export function ConfigDiffViewer({
const isLoading = loadingOld || loadingNew
return (
-
+
{/* Header */}
-
+
{isEncrypted && (
@@ -126,8 +126,8 @@ export function ConfigDiffViewer({
{/* Diff content */}
{isLoading ? (
-
- Loading diff...
+
+ Loading…
) : !diffFile ? (
diff --git a/frontend/src/components/config/ConfigHistorySection.tsx b/frontend/src/components/config/ConfigHistorySection.tsx
index 2c4e1de..ce0fc6b 100644
--- a/frontend/src/components/config/ConfigHistorySection.tsx
+++ b/frontend/src/components/config/ConfigHistorySection.tsx
@@ -65,7 +65,7 @@ export function ConfigHistorySection({ tenantId, deviceId, deviceName }: ConfigH
})
return (
-
+
Configuration History
@@ -83,7 +83,7 @@ export function ConfigHistorySection({ tenantId, deviceId, deviceName }: ConfigH
)}
{isLoading ? (
-
+
) : !changes || changes.length === 0 ? (
No configuration changes recorded yet.
diff --git a/frontend/src/components/config/ConfigTab.tsx b/frontend/src/components/config/ConfigTab.tsx
index 3fdc853..7b86620 100644
--- a/frontend/src/components/config/ConfigTab.tsx
+++ b/frontend/src/components/config/ConfigTab.tsx
@@ -158,16 +158,11 @@ export function ConfigTab({
{/* Timeline panel */}
{isLoading ? (
-
- {[0, 1, 2].map((i) => (
-
- ))}
+
+ Loading…
) : !backups || backups.length === 0 ? (
-
+
No backups yet. Click ‘Backup Now’ to create the first backup.
) : (
@@ -201,7 +196,7 @@ export function ConfigTab({
}
/>
) : (
-
+
{selectedShas.length < 2
? 'Select two backups from the timeline to compare'
: 'Click "Compare selected" to view the diff'}
diff --git a/frontend/src/components/config/ConnTrackPanel.tsx b/frontend/src/components/config/ConnTrackPanel.tsx
index 159e5f6..6e75d9a 100644
--- a/frontend/src/components/config/ConnTrackPanel.tsx
+++ b/frontend/src/components/config/ConnTrackPanel.tsx
@@ -104,7 +104,7 @@ export function ConnTrackPanel({ tenantId, deviceId, active }: ConfigPanelProps)
{/* Active connections count */}
-
+
@@ -120,7 +120,7 @@ export function ConnTrackPanel({ tenantId, deviceId, active }: ConfigPanelProps)
{/* Tracking settings */}
-
+
Connection Tracking Settings
@@ -154,7 +154,7 @@ export function ConnTrackPanel({ tenantId, deviceId, active }: ConfigPanelProps)
setFormData((f) => ({ ...f, enabled: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>
Auto
Yes
diff --git a/frontend/src/components/config/DhcpClientPanel.tsx b/frontend/src/components/config/DhcpClientPanel.tsx
index 95ca2db..d2ea949 100644
--- a/frontend/src/components/config/DhcpClientPanel.tsx
+++ b/frontend/src/components/config/DhcpClientPanel.tsx
@@ -206,7 +206,7 @@ export function DhcpClientPanel({ tenantId, deviceId, active }: ConfigPanelProps
{/* DHCP Client table */}
-
+
diff --git a/frontend/src/components/config/DhcpPanel.tsx b/frontend/src/components/config/DhcpPanel.tsx
index 9f0cf47..4f5ed96 100644
--- a/frontend/src/components/config/DhcpPanel.tsx
+++ b/frontend/src/components/config/DhcpPanel.tsx
@@ -240,8 +240,8 @@ export function DhcpPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
className={cn(
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
activeTab === tab.key
- ? 'bg-surface text-text-primary shadow-sm'
- : 'text-text-secondary hover:text-text-primary hover:bg-surface/50',
+ ? 'bg-panel text-text-primary shadow-sm'
+ : 'text-text-secondary hover:text-text-primary hover:bg-panel/50',
)}
>
{tab.icon}
@@ -400,7 +400,7 @@ function ServersTab({
}, [form, editing, panel])
return (
-
+
DHCP Servers
@@ -651,7 +651,7 @@ function PoolsTab({
}, [form, editing, panel])
return (
-
+
Address Pools
@@ -860,7 +860,7 @@ function LeasesTab({
}
return (
-
+
DHCP Leases
@@ -1112,7 +1112,7 @@ function NetworksTab({
}, [form, editing, panel])
return (
-
+
DHCP Networks
diff --git a/frontend/src/components/config/DiffViewer.tsx b/frontend/src/components/config/DiffViewer.tsx
index e9e79b8..e8f51dd 100644
--- a/frontend/src/components/config/DiffViewer.tsx
+++ b/frontend/src/components/config/DiffViewer.tsx
@@ -10,10 +10,10 @@ interface DiffViewerProps {
}
function classifyLine(line: string): string {
- if (line.startsWith('@@')) return 'bg-blue-900/20 text-blue-300'
+ if (line.startsWith('@@')) return 'bg-info/10 text-info'
if (line.startsWith('+++') || line.startsWith('---')) return 'text-text-muted'
- if (line.startsWith('+')) return 'bg-green-900/30 text-green-300'
- if (line.startsWith('-')) return 'bg-red-900/30 text-red-300'
+ if (line.startsWith('+')) return 'bg-success/10 text-success'
+ if (line.startsWith('-')) return 'bg-error/10 text-error'
return 'text-text-primary'
}
@@ -24,7 +24,7 @@ export function DiffViewer({ tenantId, deviceId, snapshotId, onClose }: DiffView
})
return (
-
+
{/* Header */}
@@ -47,10 +47,8 @@ export function DiffViewer({ tenantId, deviceId, snapshotId, onClose }: DiffView
{/* Content */}
{isLoading ? (
-
- {[75, 90, 65, 85, 70, 80].map((w, i) => (
-
- ))}
+
+ Loading…
) : isError || !diff ? (
diff --git a/frontend/src/components/config/DnsPanel.tsx b/frontend/src/components/config/DnsPanel.tsx
index 2fc53db..d54af71 100644
--- a/frontend/src/components/config/DnsPanel.tsx
+++ b/frontend/src/components/config/DnsPanel.tsx
@@ -302,7 +302,7 @@ export function DnsPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
{/* Section 1: Resolver Settings */}
-
+
@@ -393,7 +393,7 @@ export function DnsPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
{/* Section 2: Static DNS Entries */}
-
+
diff --git a/frontend/src/components/config/FirewallPanel.tsx b/frontend/src/components/config/FirewallPanel.tsx
index c965478..7b87341 100644
--- a/frontend/src/components/config/FirewallPanel.tsx
+++ b/frontend/src/components/config/FirewallPanel.tsx
@@ -23,7 +23,7 @@ import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Checkbox } from '@/components/ui/checkbox'
-import { Skeleton } from '@/components/ui/skeleton'
+import { LoadingText } from '@/components/ui/skeleton'
import {
Dialog,
DialogContent,
@@ -643,7 +643,7 @@ function FilterRulesTable({
-
+
@@ -836,7 +836,7 @@ function NatRulesTable({
-
+
@@ -1340,16 +1340,10 @@ function CellEmpty() {
function LoadingRows({ cols }: { cols: number }) {
return (
- <>
- {Array.from({ length: 5 }).map((_, i) => (
-
- {Array.from({ length: cols }).map((_, j) => (
-
-
-
- ))}
-
- ))}
- >
+
+
+
+
+
)
}
diff --git a/frontend/src/components/config/InterfacesPanel.tsx b/frontend/src/components/config/InterfacesPanel.tsx
index af57409..969bceb 100644
--- a/frontend/src/components/config/InterfacesPanel.tsx
+++ b/frontend/src/components/config/InterfacesPanel.tsx
@@ -24,7 +24,7 @@ import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Checkbox } from '@/components/ui/checkbox'
-import { Skeleton } from '@/components/ui/skeleton'
+import { LoadingText } from '@/components/ui/skeleton'
import {
Select,
SelectContent,
@@ -71,14 +71,14 @@ const SUB_TABS: { key: SubTab; label: string; icon: React.ElementType }[] = [
// ---------------------------------------------------------------------------
const TYPE_COLORS: Record = {
- ether: '#3B82F6',
- bridge: '#8B5CF6',
- vlan: '#F59E0B',
- bonding: '#10B981',
- pppoe: '#EF4444',
- l2tp: '#EC4899',
- ovpn: '#06B6D4',
- wlan: '#84CC16',
+ ether: 'hsl(var(--accent))',
+ bridge: 'hsl(var(--info))',
+ vlan: 'hsl(var(--warning))',
+ bonding: 'hsl(var(--success))',
+ pppoe: 'hsl(var(--error))',
+ l2tp: 'hsl(var(--error))',
+ ovpn: 'hsl(var(--info))',
+ wlan: 'hsl(var(--success))',
}
// ---------------------------------------------------------------------------
@@ -228,23 +228,13 @@ export function InterfacesPanel({ tenantId, deviceId, active }: ConfigPanelProps
}
// ---------------------------------------------------------------------------
-// Loading skeleton
+// Loading state
// ---------------------------------------------------------------------------
-function TableSkeleton({ rows = 5 }: { rows?: number }) {
+function TableLoading() {
return (
-
-
-
-
- {Array.from({ length: rows }).map((_, i) => (
-
-
-
-
-
-
- ))}
+
+
)
}
@@ -260,18 +250,18 @@ function InterfacesTable({
entries: Record
[]
isLoading: boolean
}) {
- if (isLoading) return
+ if (isLoading) return
if (entries.length === 0) {
return (
-
+
No interfaces found on this device.
)
}
return (
-
+
@@ -362,7 +352,7 @@ function IpAddressesTab({ entries, isLoading, interfaceNames, addChange }: IpAdd
})
}
- if (isLoading) return
+ if (isLoading) return
return (
@@ -374,11 +364,11 @@ function IpAddressesTab({ entries, isLoading, interfaceNames, addChange }: IpAdd
{entries.length === 0 ? (
-
+
No IP addresses configured.
) : (
-
+
@@ -621,7 +611,7 @@ function VlansTab({ entries, isLoading, interfaceNames, addChange }: VlansTabPro
})
}
- if (isLoading) return
+ if (isLoading) return
return (
@@ -633,11 +623,11 @@ function VlansTab({ entries, isLoading, interfaceNames, addChange }: VlansTabPro
{entries.length === 0 ? (
-
+
No VLANs configured.
) : (
-
+
@@ -926,7 +916,7 @@ function BridgesTab({
})
}
- if (isLoading) return
+ if (isLoading) return
return (
@@ -941,11 +931,11 @@ function BridgesTab({
{bridges.length === 0 ? (
-
+
No bridges configured.
) : (
-
+
@@ -1015,11 +1005,11 @@ function BridgesTab({
{bridgePorts.length === 0 ? (
-
+
No bridge ports configured.
) : (
-
+
diff --git a/frontend/src/components/config/IpsecPanel.tsx b/frontend/src/components/config/IpsecPanel.tsx
index f4525a3..34e2223 100644
--- a/frontend/src/components/config/IpsecPanel.tsx
+++ b/frontend/src/components/config/IpsecPanel.tsx
@@ -87,7 +87,7 @@ export function IpsecPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
{SUB_TABS.map((tab) => (
setActiveTab(tab.key)}
className={cn('flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
- activeTab === tab.key ? 'bg-surface text-text-primary shadow-sm' : 'text-text-secondary hover:text-text-primary hover:bg-surface/50')}>
+ activeTab === tab.key ? 'bg-panel text-text-primary shadow-sm' : 'text-text-secondary hover:text-text-primary hover:bg-panel/50')}>
{tab.icon}{tab.label}
))}
@@ -147,11 +147,11 @@ function PeersTab({ entries, panel }: { entries: PeerEntry[]; panel: PanelHook }
Address setForm((f) => ({ ...f, address: e.target.value }))} placeholder="0.0.0.0/0" className="h-8 text-sm font-mono" />
Auth Method
- setForm((f) => ({ ...f, 'auth-method': e.target.value }))} className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary">
+ setForm((f) => ({ ...f, 'auth-method': e.target.value }))} className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary">
Pre-Shared Key RSA Key RSA Signature
Exchange Mode
- setForm((f) => ({ ...f, 'exchange-mode': e.target.value }))} className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary">
+ setForm((f) => ({ ...f, 'exchange-mode': e.target.value }))} className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary">
Main Aggressive IKEv2
@@ -208,8 +208,8 @@ function PoliciesTab({ entries, panel }: { entries: PolicyEntry[]; panel: PanelH
Dst Address setForm((f) => ({ ...f, 'dst-address': e.target.value }))} placeholder="10.0.0.0/24" className="h-8 text-sm font-mono" />
-
Tunnel setForm((f) => ({ ...f, tunnel: e.target.value }))} className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary">Yes No
-
Action setForm((f) => ({ ...f, action: e.target.value }))} className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary">Encrypt None
+
Tunnel setForm((f) => ({ ...f, tunnel: e.target.value }))} className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary">Yes No
+
Action setForm((f) => ({ ...f, action: e.target.value }))} className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary">Encrypt None
Proposal setForm((f) => ({ ...f, proposal: e.target.value }))} className="h-8 text-sm" />
@@ -275,7 +275,7 @@ function ProposalsTab({ entries, panel }: { entries: ProposalEntry[]; panel: Pan
function SasTab({ entries }: { entries: SaEntry[] }) {
return (
-
+
Installed SAs ({entries.length})
{entries.length === 0 ?
No active security associations.
: (
@@ -301,7 +301,7 @@ function SasTab({ entries }: { entries: SaEntry[] }) {
function TableWrapper({ title, count, onAdd, children }: { title: string; count: number; onAdd: () => void; children: React.ReactNode }) {
return (
-
+
{title} ({count})
Add
diff --git a/frontend/src/components/config/ManglePanel.tsx b/frontend/src/components/config/ManglePanel.tsx
index fd11f9d..b97d5a1 100644
--- a/frontend/src/components/config/ManglePanel.tsx
+++ b/frontend/src/components/config/ManglePanel.tsx
@@ -127,7 +127,7 @@ export function ManglePanel({ tenantId, deviceId, active }: ConfigPanelProps) {
onClick={() => setChainFilter(chain)}
className={cn(
'px-3 py-1.5 rounded-md text-sm font-medium transition-colors capitalize',
- chainFilter === chain ? 'bg-surface text-text-primary shadow-sm' : 'text-text-secondary hover:text-text-primary hover:bg-surface/50',
+ chainFilter === chain ? 'bg-panel text-text-primary shadow-sm' : 'text-text-secondary hover:text-text-primary hover:bg-panel/50',
)}
>
{chain}
@@ -193,7 +193,7 @@ function MangleTable({ entries, panel }: { entries: MangleEntry[]; panel: PanelH
return (
<>
-
+
diff --git a/frontend/src/components/config/PingTool.tsx b/frontend/src/components/config/PingTool.tsx
index f3621a3..40eab89 100644
--- a/frontend/src/components/config/PingTool.tsx
+++ b/frontend/src/components/config/PingTool.tsx
@@ -90,7 +90,7 @@ export function PingTool({ tenantId, deviceId }: ConfigPanelProps) {
return (
{/* Input form */}
-
+
Target IP / Hostname
@@ -166,7 +166,7 @@ export function PingTool({ tenantId, deviceId }: ConfigPanelProps) {
)}
{results.length > 0 && (
-
+
Ping Results
@@ -189,7 +189,7 @@ export function PingTool({ tenantId, deviceId }: ConfigPanelProps) {
{/* Stats summary */}
{stats && (
-
+
diff --git a/frontend/src/components/config/PoolPanel.tsx b/frontend/src/components/config/PoolPanel.tsx
index 4fb674d..62a0530 100644
--- a/frontend/src/components/config/PoolPanel.tsx
+++ b/frontend/src/components/config/PoolPanel.tsx
@@ -275,7 +275,7 @@ function PoolTable({
return (
<>
{/* Table */}
-
+
diff --git a/frontend/src/components/config/PppPanel.tsx b/frontend/src/components/config/PppPanel.tsx
index c10f7d9..7e6e562 100644
--- a/frontend/src/components/config/PppPanel.tsx
+++ b/frontend/src/components/config/PppPanel.tsx
@@ -98,7 +98,7 @@ export function PppPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
{SUB_TABS.map((tab) => (
setActiveTab(tab.key)}
className={cn('flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
- activeTab === tab.key ? 'bg-surface text-text-primary shadow-sm' : 'text-text-secondary hover:text-text-primary hover:bg-surface/50')}>
+ activeTab === tab.key ? 'bg-panel text-text-primary shadow-sm' : 'text-text-secondary hover:text-text-primary hover:bg-panel/50')}>
{tab.icon}{tab.label}
{tab.key === 'active' && activeConns.entries.length > 0 && (
{activeConns.entries.length}
@@ -146,7 +146,7 @@ function ProfilesTab({ entries, panel }: { entries: ProfileEntry[]; panel: Panel
return (
<>
-
+
PPP Profiles ({entries.length})
Add Profile
@@ -219,7 +219,7 @@ function SecretsTab({ entries, panel, profileNames }: { entries: SecretEntry[];
return (
<>
-
+
PPP Secrets ({entries.length})
Add Secret
@@ -252,7 +252,7 @@ function SecretsTab({ entries, panel, profileNames }: { entries: SecretEntry[];
Service
- setForm((f) => ({ ...f, service: e.target.value }))} className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary">
+ setForm((f) => ({ ...f, service: e.target.value }))} className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary">
{PPP_SERVICES.map((s) => {s} )}
Profile setForm((f) => ({ ...f, profile: e.target.value }))} placeholder="default" className="h-8 text-sm" list="profile-names" />
@@ -281,7 +281,7 @@ function ActiveTab({ entries, tenantId, deviceId, refetch }: { entries: ActiveEn
})
return (
-
+
Active Connections ({entries.length})
diff --git a/frontend/src/components/config/RestorePreview.tsx b/frontend/src/components/config/RestorePreview.tsx
index fc040de..8d38146 100644
--- a/frontend/src/components/config/RestorePreview.tsx
+++ b/frontend/src/components/config/RestorePreview.tsx
@@ -52,10 +52,8 @@ export function RestorePreview({
if (isLoading) {
return (
-
-
-
-
+
+ Loading…
)
}
@@ -100,7 +98,7 @@ export function RestorePreview({
)}
{/* Summary bar */}
-
+
+{diff.added}
-{diff.removed}
@@ -125,7 +123,7 @@ export function RestorePreview({
{changedCategories.map((cat) => (
togglePath(cat.path)}
>
diff --git a/frontend/src/components/config/RoutesPanel.tsx b/frontend/src/components/config/RoutesPanel.tsx
index f7fd29a..0ad07e1 100644
--- a/frontend/src/components/config/RoutesPanel.tsx
+++ b/frontend/src/components/config/RoutesPanel.tsx
@@ -170,8 +170,8 @@ export function RoutesPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
className={cn(
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
filterTab === tab.key
- ? 'bg-surface text-text-primary shadow-sm'
- : 'text-text-secondary hover:text-text-primary hover:bg-surface/50',
+ ? 'bg-panel text-text-primary shadow-sm'
+ : 'text-text-secondary hover:text-text-primary hover:bg-panel/50',
)}
>
{tab.label}
@@ -313,7 +313,7 @@ function RoutesTable({
return (
<>
{/* Table */}
-
+
diff --git a/frontend/src/components/config/ScriptsPanel.tsx b/frontend/src/components/config/ScriptsPanel.tsx
index d49bc69..fd4a378 100644
--- a/frontend/src/components/config/ScriptsPanel.tsx
+++ b/frontend/src/components/config/ScriptsPanel.tsx
@@ -148,8 +148,8 @@ export function ScriptsPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
className={cn(
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors',
activeTab === tab.key
- ? 'bg-surface text-text-primary shadow-sm'
- : 'text-text-secondary hover:text-text-primary hover:bg-surface/50',
+ ? 'bg-panel text-text-primary shadow-sm'
+ : 'text-text-secondary hover:text-text-primary hover:bg-panel/50',
)}
>
{tab.icon}
@@ -275,7 +275,7 @@ function ScriptsTab({
return (
<>
-
+
@@ -477,7 +477,7 @@ function SchedulerTab({
return (
<>
-
+
diff --git a/frontend/src/components/config/ServicesPanel.tsx b/frontend/src/components/config/ServicesPanel.tsx
index c4f275b..b62454d 100644
--- a/frontend/src/components/config/ServicesPanel.tsx
+++ b/frontend/src/components/config/ServicesPanel.tsx
@@ -230,7 +230,7 @@ function ServiceTable({
return (
<>
-
+
@@ -337,7 +337,7 @@ function ServiceTable({
setForm((f) => ({ ...f, disabled: e.target.value }))}
- className="h-8 w-full rounded-md border border-border bg-surface px-3 text-sm text-text-primary"
+ className="h-8 w-full rounded-md border border-border bg-panel px-3 text-sm text-text-primary"
>