Skip to content

Commit 81245d9

Browse files
ersinkocclaude
andcommitted
refactor(ui): compact PairingBanner layout for Channels page
Redesign the PairingBanner component to be more space-efficient: - Collapse unclaimed channels into a single expandable section - Show compact grid (1-3 columns) for unclaimed setup instructions - Display count summary instead of full boxes (e.g., "6 channels need setup") - Move detailed /connect commands behind "Show setup instructions" toggle - Keep claimed channels as compact horizontal rows Before: Each unclaimed channel had its own large banner box (6 boxes = lots of scrolling) After: Single compact banner with grid layout, expandable when needed This reduces vertical space usage significantly while keeping all functionality. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 08fe207 commit 81245d9

File tree

1 file changed

+59
-46
lines changed

1 file changed

+59
-46
lines changed

packages/ui/src/pages/channels-detail.tsx

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ export function PairingBanner() {
512512
const [channels, setChannels] = useState<PairingChannel[]>([]);
513513
const [copiedId, setCopiedId] = useState<string | null>(null);
514514
const [revokingId, setRevokingId] = useState<string | null>(null);
515+
const [showUnclaimed, setShowUnclaimed] = useState(false);
515516
const toast = useToast();
516517
const dialog = useDialog();
517518

@@ -565,59 +566,71 @@ export function PairingBanner() {
565566
const claimedChannels = channels.filter((ch) => ch.claimed);
566567

567568
return (
568-
<div className="mx-6 mt-4 space-y-2">
569-
{/* Unclaimed channels — prominent warning */}
570-
{unclaimedChannels.map((ch) => (
571-
<div key={ch.pluginId} className="p-4 rounded-lg border border-warning/40 bg-warning/5">
572-
<div className="flex items-start gap-3">
573-
<Key className="w-5 h-5 text-warning mt-0.5 shrink-0" />
574-
<div className="flex-1 min-w-0">
575-
<p className="text-sm font-semibold text-text-primary dark:text-dark-text-primary">
576-
Claim ownership — {ch.name}
577-
</p>
578-
<p className="text-xs text-text-secondary dark:text-dark-text-secondary mt-0.5">
579-
Send this command on <span className="capitalize">{ch.platform}</span> to become the
580-
owner of this channel.
581-
</p>
582-
<div className="mt-2 flex items-center gap-2">
583-
<div className="flex-1 flex items-center gap-2 px-3 py-2 bg-bg-tertiary dark:bg-dark-bg-tertiary rounded-md border border-border dark:border-dark-border font-mono text-sm">
584-
<span className="text-text-muted dark:text-dark-text-muted text-xs">
585-
/connect
586-
</span>
587-
<span className="font-bold text-text-primary dark:text-dark-text-primary tracking-widest">
588-
{ch.key}
589-
</span>
590-
</div>
591-
<button
592-
onClick={() => handleCopy(ch.pluginId, `/connect ${ch.key}`)}
593-
className="flex items-center gap-1.5 px-3 py-2 text-xs font-medium border border-border dark:border-dark-border rounded-md hover:bg-bg-tertiary dark:hover:bg-dark-bg-tertiary transition-colors text-text-primary dark:text-dark-text-primary"
569+
<div className="mx-6 mt-4 space-y-3">
570+
{/* Unclaimed channels — compact grid layout */}
571+
{unclaimedChannels.length > 0 && (
572+
<div className="p-3 rounded-lg border border-warning/30 bg-warning/5">
573+
<button
574+
onClick={() => setShowUnclaimed(!showUnclaimed)}
575+
className="w-full flex items-center justify-between"
576+
>
577+
<div className="flex items-center gap-2">
578+
<Key className="w-4 h-4 text-warning" />
579+
<span className="text-sm font-medium text-text-primary dark:text-dark-text-primary">
580+
{unclaimedChannels.length} channel{unclaimedChannels.length !== 1 ? 's' : ''} need setup
581+
</span>
582+
</div>
583+
<span className="text-xs text-text-muted dark:text-dark-text-muted">
584+
{showUnclaimed ? 'Hide' : 'Show'} setup instructions
585+
</span>
586+
</button>
587+
588+
{showUnclaimed && (
589+
<div className="mt-3 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2">
590+
{unclaimedChannels.map((ch) => (
591+
<div
592+
key={ch.pluginId}
593+
className="p-2.5 rounded-md border border-warning/20 bg-bg-primary dark:bg-dark-bg-primary"
594594
>
595-
{copiedId === ch.pluginId ? (
596-
<>
597-
<CheckCircle2 className="w-3.5 h-3.5 text-success" />
598-
Copied!
599-
</>
600-
) : (
601-
<>
602-
<Copy className="w-3.5 h-3.5" />
603-
Copy
604-
</>
605-
)}
606-
</button>
607-
</div>
608-
<p className="text-[11px] text-text-muted dark:text-dark-text-muted mt-1.5">
609-
Key rotates after each successful claim.
610-
</p>
595+
<div className="flex items-center gap-2 mb-1.5">
596+
<span className="text-xs font-medium text-text-primary dark:text-dark-text-primary">
597+
{ch.name}
598+
</span>
599+
<span className="text-[10px] text-text-muted dark:text-dark-text-muted capitalize">
600+
{ch.platform}
601+
</span>
602+
</div>
603+
<div className="flex items-center gap-1.5">
604+
<div className="flex-1 flex items-center gap-1.5 px-2 py-1 bg-bg-tertiary dark:bg-dark-bg-tertiary rounded font-mono text-xs">
605+
<span className="text-text-muted text-[10px]">/connect</span>
606+
<span className="font-bold text-text-primary dark:text-dark-text-primary">
607+
{ch.key}
608+
</span>
609+
</div>
610+
<button
611+
onClick={() => handleCopy(ch.pluginId, `/connect ${ch.key}`)}
612+
className="p-1.5 text-xs border border-border dark:border-dark-border rounded hover:bg-bg-tertiary dark:hover:bg-dark-bg-tertiary transition-colors"
613+
title="Copy command"
614+
>
615+
{copiedId === ch.pluginId ? (
616+
<CheckCircle2 className="w-3.5 h-3.5 text-success" />
617+
) : (
618+
<Copy className="w-3.5 h-3.5 text-text-muted dark:text-dark-text-muted" />
619+
)}
620+
</button>
621+
</div>
622+
</div>
623+
))}
611624
</div>
612-
</div>
625+
)}
613626
</div>
614-
))}
627+
)}
615628

616-
{/* Claimed channels — compact row with revoke option */}
629+
{/* Claimed channels — compact row */}
617630
{claimedChannels.map((ch) => (
618631
<div
619632
key={ch.pluginId}
620-
className="p-3 rounded-lg border border-success/30 bg-success/5 flex items-center gap-3"
633+
className="p-2.5 rounded-lg border border-success/30 bg-success/5 flex items-center gap-3"
621634
>
622635
<ShieldCheck className="w-4 h-4 text-success shrink-0" />
623636
<div className="flex-1 min-w-0">

0 commit comments

Comments
 (0)