fix(ui): declutter device page header — compact tool buttons
- WinBox/RemoteWinBox/SSH: replace big accent CTAs with compact bordered tool buttons (text-[10px], h-3 icons, border-default) - SimpleModeToggle: shrink from pill-button group to inline segmented control (text-[10px], accent-soft active state) - Edit/Delete already icon-only ghost from previous commit - All tool buttons now visually consistent — small, bordered, receding - Result: header reads as a compact control strip, not a CTA row Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -162,26 +162,26 @@ export function RemoteWinBoxButton({ tenantId, deviceId }: RemoteWinBoxButtonPro
|
||||
if (state === 'idle' || state === 'failed' || state === 'terminated') {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center gap-1">
|
||||
<button
|
||||
onClick={handleOpen}
|
||||
disabled={createMutation.isPending}
|
||||
className="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-accent text-white hover:bg-accent/90 disabled:opacity-50"
|
||||
className="inline-flex items-center gap-1 px-2 py-1 rounded-[var(--radius-control)] text-[10px] text-text-secondary border border-border-default hover:border-accent transition-[border-color,color] duration-[50ms] disabled:opacity-50"
|
||||
title="Open Remote WinBox (browser)"
|
||||
>
|
||||
{createMutation.isPending ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<Globe className="h-4 w-4" />
|
||||
<Globe className="h-3 w-3" />
|
||||
)}
|
||||
{createMutation.isPending ? 'Starting...' : 'Remote WinBox'}
|
||||
{createMutation.isPending ? 'Starting' : 'Remote'}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleReset}
|
||||
className="inline-flex items-center gap-2 px-4 py-2 rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground"
|
||||
title="Reset all remote WinBox sessions for this device"
|
||||
className="inline-flex items-center px-1.5 py-1 rounded-[var(--radius-control)] text-text-muted border border-border-default hover:border-accent transition-[border-color] duration-[50ms]"
|
||||
title="Reset remote sessions"
|
||||
>
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
Reset
|
||||
<RefreshCw className="h-3 w-3" />
|
||||
</button>
|
||||
</div>
|
||||
{state === 'failed' && error && (
|
||||
|
||||
@@ -162,10 +162,11 @@ export function SSHTerminal({ tenantId, deviceId, deviceName }: SSHTerminalProps
|
||||
return (
|
||||
<button
|
||||
onClick={handleOpen}
|
||||
className="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-accent text-white hover:bg-accent/90"
|
||||
className="inline-flex items-center gap-1 px-2 py-1 rounded-[var(--radius-control)] text-[10px] text-text-secondary border border-border-default hover:border-accent transition-[border-color,color] duration-[50ms]"
|
||||
title="Open SSH Terminal"
|
||||
>
|
||||
<TerminalIcon className="h-4 w-4" />
|
||||
SSH Terminal
|
||||
<TerminalIcon className="h-3 w-3" />
|
||||
SSH
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -78,14 +78,15 @@ export function WinBoxButton({ tenantId, deviceId }: WinBoxButtonProps) {
|
||||
openMutation.mutate()
|
||||
}}
|
||||
disabled={openMutation.isPending}
|
||||
className="inline-flex items-center gap-2 px-4 py-2 rounded-md bg-accent text-white hover:bg-accent/90 disabled:opacity-50"
|
||||
className="inline-flex items-center gap-1 px-2 py-1 rounded-[var(--radius-control)] text-[10px] text-text-secondary border border-border-default hover:border-accent transition-[border-color,color] duration-[50ms] disabled:opacity-50"
|
||||
title="Open WinBox tunnel"
|
||||
>
|
||||
{openMutation.isPending ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
<Loader2 className="h-3 w-3 animate-spin" />
|
||||
) : (
|
||||
<Monitor className="h-4 w-4" />
|
||||
<Monitor className="h-3 w-3" />
|
||||
)}
|
||||
{openMutation.isPending ? 'Connecting...' : 'Open WinBox'}
|
||||
{openMutation.isPending ? 'Connecting' : 'WinBox'}
|
||||
</button>
|
||||
{error && <p className="mt-2 text-sm text-error">{error}</p>}
|
||||
</div>
|
||||
@@ -94,18 +95,17 @@ export function WinBoxButton({ tenantId, deviceId }: WinBoxButtonProps) {
|
||||
|
||||
if (state === 'ready' && tunnelInfo) {
|
||||
return (
|
||||
<div className="rounded-md border p-4 space-y-3">
|
||||
<p className="font-medium text-sm">WinBox tunnel ready</p>
|
||||
<p className="text-sm text-text-muted">
|
||||
Connect to: <code className="font-mono">{tunnelInfo.host}:{tunnelInfo.port}</code>
|
||||
<div className="rounded-sm border border-border-default bg-panel p-2.5 space-y-2">
|
||||
<p className="text-xs text-text-primary">
|
||||
Tunnel ready: <code className="font-mono text-[10px] text-text-secondary">{tunnelInfo.host}:{tunnelInfo.port}</code>
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex gap-1">
|
||||
<button
|
||||
onClick={copyAddress}
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm rounded-md border hover:bg-accent"
|
||||
className="inline-flex items-center gap-1 px-2 py-0.5 text-[10px] rounded-[var(--radius-control)] border border-border-default text-text-secondary hover:border-accent transition-[border-color] duration-[50ms]"
|
||||
>
|
||||
<Copy className="h-3 w-3" />
|
||||
{copied ? 'Copied!' : 'Copy Address'}
|
||||
<Copy className="h-2.5 w-2.5" />
|
||||
{copied ? 'Copied' : 'Copy'}
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
@@ -113,15 +113,13 @@ export function WinBoxButton({ tenantId, deviceId }: WinBoxButtonProps) {
|
||||
closeMutation.mutate()
|
||||
}}
|
||||
disabled={closeMutation.isPending}
|
||||
className="inline-flex items-center gap-2 px-3 py-1.5 text-sm rounded-md border hover:bg-accent disabled:opacity-50"
|
||||
className="inline-flex items-center gap-1 px-2 py-0.5 text-[10px] rounded-[var(--radius-control)] border border-border-default text-text-muted hover:border-accent disabled:opacity-50 transition-[border-color] duration-[50ms]"
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
Close Tunnel
|
||||
<X className="h-2.5 w-2.5" />
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
<p className="text-xs text-text-muted">
|
||||
Tunnel closes after 5 min of inactivity
|
||||
</p>
|
||||
<p className="text-[9px] text-text-muted">Closes after 5 min idle</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,31 +14,31 @@ interface SimpleModeToggleProps {
|
||||
|
||||
export function SimpleModeToggle({ mode, onModeChange }: SimpleModeToggleProps) {
|
||||
return (
|
||||
<div className="flex items-center gap-1 rounded-lg border border-border bg-elevated/50 p-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
<div className="flex items-center gap-px rounded-[var(--radius-control)] border border-border-default overflow-hidden">
|
||||
<button
|
||||
onClick={() => onModeChange('simple')}
|
||||
className={cn(
|
||||
'gap-1.5 h-7 px-2.5 text-xs',
|
||||
mode === 'simple' && 'bg-accent/20 text-accent',
|
||||
'flex items-center gap-1 px-1.5 py-0.5 text-[10px] transition-[background-color,color] duration-[50ms]',
|
||||
mode === 'simple'
|
||||
? 'bg-accent-soft text-text-primary font-medium'
|
||||
: 'text-text-muted hover:text-text-secondary',
|
||||
)}
|
||||
>
|
||||
<LayoutGrid className="h-3.5 w-3.5" />
|
||||
<LayoutGrid className="h-2.5 w-2.5" />
|
||||
Simple
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
</button>
|
||||
<button
|
||||
onClick={() => onModeChange('standard')}
|
||||
className={cn(
|
||||
'gap-1.5 h-7 px-2.5 text-xs',
|
||||
mode === 'standard' && 'bg-accent/20 text-accent',
|
||||
'flex items-center gap-1 px-1.5 py-0.5 text-[10px] transition-[background-color,color] duration-[50ms]',
|
||||
mode === 'standard'
|
||||
? 'bg-accent-soft text-text-primary font-medium'
|
||||
: 'text-text-muted hover:text-text-secondary',
|
||||
)}
|
||||
>
|
||||
<Sliders className="h-3.5 w-3.5" />
|
||||
<Sliders className="h-2.5 w-2.5" />
|
||||
Standard
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user