Skip to content
2 changes: 1 addition & 1 deletion desktop/src/app/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ export function AppShell() {
<HuddleProvider>
<div className="flex h-dvh flex-col overflow-hidden overscroll-none">
<SidebarProvider className="min-h-0 flex-1 overflow-hidden">
<div className="fixed left-[80px] top-[8px] z-50 flex items-center gap-1.5">
<div className="fixed left-[80px] top-[8px] z-50 flex items-center gap-0.5">
<SidebarTrigger className="h-6 w-6 text-muted-foreground/70 hover:bg-muted/60 hover:text-foreground" />
<Button
aria-label="Go back"
Expand Down
9 changes: 5 additions & 4 deletions desktop/src/features/agents/ui/AgentsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ export function AgentsScreen() {
<ChatHeader
description="Choose personas from Persona Catalog, create local ACP workers, and monitor the relay-visible agent directory."
mode="agents"
overlaysContent
title="Agents"
/>

<React.Suspense fallback={<ViewLoadingFallback kind="agents" />}>
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
<React.Suspense fallback={<ViewLoadingFallback kind="agents" />}>
<AgentsView />
</div>
</React.Suspense>
</React.Suspense>
</div>
</>
);
}
2 changes: 1 addition & 1 deletion desktop/src/features/agents/ui/AgentsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function AgentsView() {

return (
<>
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 py-4 sm:px-6">
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 pb-4 pt-14 sm:px-6">
<div className="mx-auto flex w-full max-w-6xl flex-col gap-6">
<div className="flex flex-col gap-6">
<PersonasSection
Expand Down
17 changes: 9 additions & 8 deletions desktop/src/features/channels/ui/ChannelMembersBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,10 @@ export function ChannelMembersBar({

return (
<React.Fragment>
<div className="flex items-center gap-2">
<div className="flex items-center gap-1.5">
<Button
aria-label="Add agent"
className="h-9 w-9 rounded-full"
className="h-8 w-8 rounded-full"
data-testid="channel-add-bot-trigger"
disabled={!canAddAgents}
onClick={() => {
Expand All @@ -99,10 +99,11 @@ export function ChannelMembersBar({
type="button"
variant="outline"
>
<Plus className="h-4 w-4" />
<Plus className="h-3.5 w-3.5" />
</Button>

<HuddleIndicator
className="h-8 w-8"
channelId={channel.id}
onStart={async () => {
try {
Expand All @@ -119,28 +120,28 @@ export function ChannelMembersBar({

<Button
aria-label={`View channel members (${memberCount})`}
className="h-9 gap-1.5 rounded-full px-3"
className="h-8 gap-1.5 rounded-full px-2.5"
data-testid="channel-members-trigger"
onClick={onToggleMembers}
type="button"
variant="outline"
>
<Users className="h-4 w-4" />
<span className="min-w-[1ch] text-sm font-medium tabular-nums">
<Users className="h-3.5 w-3.5" />
<span className="min-w-[1ch] text-xs font-medium tabular-nums">
{memberCount}
</span>
</Button>

<Button
aria-label="Manage channel"
className="h-9 w-9 rounded-full"
className="h-8 w-8 rounded-full"
data-testid="channel-management-trigger"
onClick={onManageChannel}
size="icon"
type="button"
variant="outline"
>
<Settings2 className="h-4 w-4" />
<Settings2 className="h-3.5 w-3.5" />
</Button>
</div>

Expand Down
1 change: 1 addition & 0 deletions desktop/src/features/channels/ui/ChannelScreenHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export function ChannelScreenHeader({
}
channelType={activeChannel?.channelType}
description={getChannelDescription(activeChannel)}
overlaysContent
statusBadge={
<ChannelHeaderStatusBadge
channelType={activeChannel?.channelType}
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/features/channels/ui/EphemeralChannelBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ export function EphemeralChannelBadge({
className={cn(
"inline-flex items-center gap-1 rounded-full font-medium text-slate-500 dark:text-slate-400",
isHeader
? "h-5 w-5 justify-center border border-sky-500/20 bg-sky-500/5 p-0 text-xs"
? "h-[18px] w-[18px] justify-center border border-border/70 bg-muted/35 p-0 text-xs text-muted-foreground"
: "shrink-0 h-4 w-4 justify-center border border-sky-500/15 bg-slate-500/5 p-0 text-slate-500/80 dark:text-slate-400/80",
)}
data-testid={testId}
title={display.tooltipLabel}
>
<Clock className={cn(isHeader ? "h-3 w-3" : "h-2.5 w-2.5")} />
<Clock className={cn(isHeader ? "h-2.5 w-2.5" : "h-2.5 w-2.5")} />
</span>
);
}
36 changes: 24 additions & 12 deletions desktop/src/features/chat/ui/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
import type * as React from "react";

import type { ChannelType, ChannelVisibility } from "@/shared/api/types";
import { cn } from "@/shared/lib/cn";
import { useSidebar } from "@/shared/ui/sidebar";

type ChatHeaderProps = {
actions?: React.ReactNode;
Expand All @@ -19,9 +21,12 @@ type ChatHeaderProps = {
channelType?: ChannelType;
visibility?: ChannelVisibility;
mode?: "home" | "channel" | "agents" | "workflows" | "pulse";
overlaysContent?: boolean;
statusBadge?: React.ReactNode;
};

const HEADER_ICON_CLASS = "h-4 w-4 text-muted-foreground";

function ChannelIcon({
channelType,
visibility,
Expand All @@ -32,34 +37,34 @@ function ChannelIcon({
mode?: "home" | "channel" | "agents" | "workflows" | "pulse";
}) {
if (mode === "home") {
return <Home className="h-5 w-5 text-primary" />;
return <Home className={HEADER_ICON_CLASS} />;
}

if (mode === "agents") {
return <Bot className="h-5 w-5 text-primary" />;
return <Bot className={HEADER_ICON_CLASS} />;
}

if (mode === "workflows") {
return <Zap className="h-5 w-5 text-primary" />;
return <Zap className={HEADER_ICON_CLASS} />;
}

if (mode === "pulse") {
return <Activity className="h-5 w-5 text-primary" />;
return <Activity className={HEADER_ICON_CLASS} />;
}

if (channelType === "dm") {
return <CircleDot className="h-5 w-5 text-primary" />;
return <CircleDot className={HEADER_ICON_CLASS} />;
}

if (visibility === "private") {
return <Lock className="h-5 w-5 text-primary" />;
return <Lock className={HEADER_ICON_CLASS} />;
}

if (channelType === "forum") {
return <FileText className="h-5 w-5 text-primary" />;
return <FileText className={HEADER_ICON_CLASS} />;
}

return <Hash className="h-5 w-5 text-primary" />;
return <Hash className={HEADER_ICON_CLASS} />;
}

export function ChatHeader({
Expand All @@ -69,32 +74,39 @@ export function ChatHeader({
channelType,
visibility,
mode = "channel",
overlaysContent = false,
statusBadge,
}: ChatHeaderProps) {
const trimmedDescription = description.trim();
const { state: sidebarState } = useSidebar();
const reserveGlobalControls = sidebarState === "collapsed";

return (
<header
className="relative z-20 flex min-w-0 shrink-0 items-center gap-3 bg-background/25 px-4 pb-2 pt-6 shadow-[0_4px_24px_rgba(0,0,0,0.06)] backdrop-blur-xl supports-[backdrop-filter]:bg-background/20 dark:shadow-[0_4px_24px_rgba(0,0,0,0.25)] sm:px-6"
className={cn(
"relative z-30 flex min-h-11 min-w-0 shrink-0 items-center gap-3 bg-background/70 px-4 py-1.5 shadow-[0_4px_24px_rgba(0,0,0,0.06)] backdrop-blur-xl transition-[margin,padding] duration-200 ease-linear supports-[backdrop-filter]:bg-background/55 dark:shadow-[0_4px_24px_rgba(0,0,0,0.25)] sm:px-6",
overlaysContent && "-mb-11",
reserveGlobalControls && "md:pl-40",
)}
data-testid="chat-header"
data-tauri-drag-region
>
<div className="min-w-0 flex-1">
<div className="flex min-w-0 flex-wrap items-center gap-2">
<div className="flex min-w-0 flex-wrap items-center gap-1.5">
<ChannelIcon
channelType={channelType}
mode={mode}
visibility={visibility}
/>
<h1
className="min-w-0 truncate text-lg font-semibold tracking-tight"
className="min-w-0 truncate text-base font-semibold leading-5 tracking-tight"
data-testid="chat-title"
title={trimmedDescription || undefined}
>
{title}
</h1>
{statusBadge ? (
<div className="flex shrink-0 flex-wrap items-center gap-2">
<div className="flex shrink-0 flex-wrap items-center gap-1.5">
{statusBadge}
</div>
) : null}
Expand Down
1 change: 1 addition & 0 deletions desktop/src/features/home/ui/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function HomeScreen({
<ChatHeader
description="Personalized activity feed for mentions, reminders, channel activity, and agent work."
mode="home"
overlaysContent
title="Home"
/>

Expand Down
6 changes: 3 additions & 3 deletions desktop/src/features/home/ui/HomeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type FeedFilter =

function HomeLoadingState() {
return (
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 py-3 sm:px-6">
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 pb-3 pt-14 sm:px-6">
<div className="mx-auto flex w-full max-w-5xl flex-col gap-4">
<div className="grid gap-4">
{["mentions", "actions"].map((section) => (
Expand Down Expand Up @@ -138,7 +138,7 @@ export function HomeView({

if (!feed) {
return (
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 py-3 sm:px-6">
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 pb-3 pt-14 sm:px-6">
<div className="mx-auto flex w-full max-w-3xl flex-col gap-4">
<div className="rounded-md border border-destructive/30 bg-destructive/5 px-4 py-5">
<p className="text-base font-semibold tracking-tight">
Expand All @@ -162,7 +162,7 @@ export function HomeView({
const showActivity = filter === "all" || filter === "activity";
const showAgentActivity = filter === "all" || filter === "agent_activity";
return (
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 py-3 sm:px-6">
<div className="flex-1 overflow-y-auto overflow-x-hidden overscroll-contain px-4 pb-3 pt-14 sm:px-6">
<div className="mx-auto flex w-full max-w-5xl flex-col gap-4">
<div className="flex items-center gap-1.5">
{FILTER_OPTIONS.map((option) => (
Expand Down
13 changes: 6 additions & 7 deletions desktop/src/features/huddle/components/HuddleIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,15 @@ export function HuddleIndicator({
return (
<Button
aria-label="Start huddle"
className={cn("h-9 w-9 rounded-full", className)}
className={cn("h-8 w-8 rounded-full", className)}
data-testid="channel-start-huddle-trigger"
disabled={startDisabled || isStarting}
onClick={() => onStart()}
size="icon"
type="button"
variant="outline"
>
<Headphones className="h-4 w-4" />
<Headphones className="h-3.5 w-3.5" />
</Button>
);
}
Expand Down Expand Up @@ -246,19 +246,18 @@ export function HuddleIndicator({
<TooltipTrigger asChild>
<Button
aria-label={`Join active huddle (${participantCount} participant${participantCount !== 1 ? "s" : ""})`}
className={cn("h-9 w-9 rounded-full relative", className)}
className={cn("relative h-8 w-8 rounded-full", className)}
disabled={isJoining || isStarting}
onClick={() => void handleJoin()}
size="icon"
type="button"
variant="outline"
>
<Headphones className="h-4 w-4 text-green-500" />
{/* Green glow effect */}
<span className="absolute inset-0 animate-pulse rounded-full ring-2 ring-green-500/40" />
<Headphones className="h-3.5 w-3.5 text-muted-foreground" />
<span className="absolute inset-0 animate-pulse rounded-full ring-2 ring-border/70" />
{/* Participant count badge */}
{participantCount > 0 && (
<span className="absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-green-500 px-0.5 text-[10px] font-bold text-white">
<span className="absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-full border border-border bg-background px-0.5 text-[10px] font-bold text-muted-foreground">
{participantCount}
</span>
)}
Expand Down
6 changes: 5 additions & 1 deletion desktop/src/features/messages/ui/MessageThreadPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,11 @@ export function MessageThreadPanel({
<>
{isOverlay && <OverlayPanelBackdrop onClose={onClose} />}
<aside
className={cn(PANEL_BASE_CLASS, isOverlay && PANEL_OVERLAY_CLASS)}
className={cn(
PANEL_BASE_CLASS,
!isOverlay && "pt-11",
isOverlay && PANEL_OVERLAY_CLASS,
)}
data-testid="message-thread-panel"
style={{ width: `${widthPx}px` }}
>
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/features/messages/ui/MessageTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const MessageTimeline = React.memo(function MessageTimeline({
ref={scrollContainerRef}
>
<div
className="mx-auto flex w-full max-w-4xl flex-col gap-2 pb-10 pt-14"
className="mx-auto flex w-full max-w-4xl flex-col gap-2 pb-10 pt-16"
ref={contentRef}
>
<div ref={topSentinelRef} aria-hidden className="h-px" />
Expand Down
5 changes: 4 additions & 1 deletion desktop/src/features/pulse/ui/PulseScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ export function PulseScreen() {
<ChatHeader
description="Notes from people and agents you follow"
mode="pulse"
overlaysContent
title="Pulse"
/>
<PulseView currentPubkey={identityQuery.data?.pubkey} />
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
<PulseView currentPubkey={identityQuery.data?.pubkey} />
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion desktop/src/features/pulse/ui/PulseView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ export function PulseView({ currentPubkey }: PulseViewProps) {
className="flex min-h-0 flex-1 flex-col overflow-hidden"
>
{/* Tab bar */}
<div className="flex items-center gap-1 border-b border-border/60 px-4 sm:px-6">
<div className="flex items-center gap-1 border-b border-border/60 px-4 pt-11 sm:px-6">
<TabsList className="h-auto gap-1 rounded-none border-none bg-transparent p-0">
<TabsTrigger value="foryou" className={tabTriggerClassName}>
For You
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function WorkflowDetailPanel({

return (
<div
className="flex h-full flex-col border-l bg-background"
className="flex h-full flex-col border-l bg-background pt-11"
data-testid="workflow-detail-panel"
>
<div className="flex items-center justify-between border-b px-4 py-3">
Expand Down
9 changes: 5 additions & 4 deletions desktop/src/features/workflows/ui/WorkflowsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,20 @@ export function WorkflowsScreen({
<ChatHeader
description="Create, manage, and monitor automated workflows across your channels."
mode="workflows"
overlaysContent
title="Workflows"
/>

<React.Suspense fallback={<ViewLoadingFallback kind="workflows" />}>
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
<React.Suspense fallback={<ViewLoadingFallback kind="workflows" />}>
<WorkflowsView
channels={channels}
onCloseWorkflow={onCloseWorkflow}
onSelectWorkflow={onSelectWorkflow}
selectedWorkflowId={selectedWorkflowId}
/>
</div>
</React.Suspense>
</React.Suspense>
</div>
</>
);
}
2 changes: 1 addition & 1 deletion desktop/src/features/workflows/ui/WorkflowsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export function WorkflowsView({
data-testid="workflows-view"
>
<div
className="flex min-h-0 flex-1 flex-col overflow-y-auto p-4"
className="flex min-h-0 flex-1 flex-col overflow-y-auto px-4 pb-4 pt-14"
data-scroll-restoration-id="workflows-list"
>
<div className="mb-4 flex items-center justify-between">
Expand Down
Loading
Loading