Collapsed toolbar: Slack chip + separator + raised-chip action group
Match WorkClaw's collapsed action cluster. Left-to-right now reads
Slack → Sessions → New → │ separator │ → Computer (coral):
- New Slack quick-launch chip (brand /services/slack.svg) as the first
action, opening the Computer → Slack app via setParams({app:'slack'})
(same handler as the panel home tile; connect-gated there).
- Slack/Sessions/New wrapped in their own md+ sub-group and given the
raised-chip treatment (bg-neutral-900 + ring-1 ring-inset ring-white/8
+ shadow-bubble), preserving hover/active.
- Thin 24px vertical separator (w-px h-6 bg-white/12) before the coral
Computer toggle, which stays size-[42px]/shadow-launcher and always
visible (mobile-reachable; the action group hides <md per WorkClaw).
Handlers/aria-labels/icons of Sessions/New/Computer unchanged. The
header 'Slack' button doesn't collide with the panel-scoped Slack tests.
Verified live: cluster order Slack→Sessions→New→Computer; Slack opens
?app=slack.
86 unit + 31 functional E2E green.
Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Fable 5
parent
e0a59e3b95
commit
35d0754b8d
@@ -1,5 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
import { List, Monitor, SquarePen, X } from "lucide-react";
|
import { List, Monitor, SquarePen, X } from "lucide-react";
|
||||||
import { useQueryStates } from "nuqs";
|
import { useQueryStates } from "nuqs";
|
||||||
|
|
||||||
@@ -8,6 +9,11 @@ import { Avatar } from "@/components/ui/Avatar";
|
|||||||
import { DeviceSizeToggle } from "@/components/computer/DeviceSizeToggle";
|
import { DeviceSizeToggle } from "@/components/computer/DeviceSizeToggle";
|
||||||
import { panelParsers } from "@/lib/url/panel-params";
|
import { panelParsers } from "@/lib/url/panel-params";
|
||||||
|
|
||||||
|
/* WorkClaw's raised-chip treatment for the collapsed action buttons:
|
||||||
|
dark fill, inset hairline ring, bubble shadow (dark-only app). */
|
||||||
|
const CHIP =
|
||||||
|
"inline-flex size-9 items-center justify-center rounded-full bg-neutral-900 shadow-bubble ring-1 ring-white/[0.08] transition-colors duration-(--duration-normal) ease-app ring-inset";
|
||||||
|
|
||||||
/** Chat header (measured): a two-zone toolbar. The identity sits left; the
|
/** Chat header (measured): a two-zone toolbar. The identity sits left; the
|
||||||
* action cluster (Sessions / New / Computer) is centered as its own group;
|
* action cluster (Sessions / New / Computer) is centered as its own group;
|
||||||
* and the device-size toggles + Close are a separate, absolutely-positioned
|
* and the device-size toggles + Close are a separate, absolutely-positioned
|
||||||
@@ -42,17 +48,28 @@ export function ChatHeader({
|
|||||||
<p className="truncate text-sm text-[#7d7d7d]">{agent.job_title}</p>
|
<p className="truncate text-sm text-[#7d7d7d]">{agent.job_title}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action cluster — centered, standalone group. */}
|
{/* Action cluster — centered, standalone group (measured): the
|
||||||
<div className="absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center gap-3">
|
chipped action group (Slack / Sessions / New), a vertical
|
||||||
|
separator, then the coral Computer toggle. */}
|
||||||
|
<div className="absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center gap-2.5">
|
||||||
|
<div className="hidden items-center gap-3 md:flex">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
aria-label="Slack"
|
||||||
|
onClick={() => setParams({ app: "slack" })}
|
||||||
|
className={`${CHIP} text-foreground hover:bg-neutral-800`}
|
||||||
|
>
|
||||||
|
<Image src="/services/slack.svg" alt="" width={18} height={18} />
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Sessions"
|
aria-label="Sessions"
|
||||||
aria-pressed={sessions}
|
aria-pressed={sessions}
|
||||||
onClick={() => setParams({ sessions: !sessions })}
|
onClick={() => setParams({ sessions: !sessions })}
|
||||||
className={`inline-flex size-9 items-center justify-center rounded-full transition-colors duration-(--duration-normal) ease-app ${
|
className={`${CHIP} ${
|
||||||
sessions
|
sessions
|
||||||
? "bg-surface-warm-muted text-foreground"
|
? "text-foreground"
|
||||||
: "text-muted-foreground hover:bg-hover-bg hover:text-foreground"
|
: "text-muted-foreground hover:bg-neutral-800 hover:text-foreground"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<List aria-hidden size={18} />
|
<List aria-hidden size={18} />
|
||||||
@@ -61,10 +78,15 @@ export function ChatHeader({
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label="New"
|
aria-label="New"
|
||||||
onClick={onNewSession}
|
onClick={onNewSession}
|
||||||
className="inline-flex size-9 items-center justify-center rounded-full text-muted-foreground transition-colors duration-(--duration-normal) ease-app hover:bg-hover-bg hover:text-foreground"
|
className={`${CHIP} text-muted-foreground hover:bg-neutral-800 hover:text-foreground`}
|
||||||
>
|
>
|
||||||
<SquarePen aria-hidden size={18} />
|
<SquarePen aria-hidden size={18} />
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
aria-hidden
|
||||||
|
className="hidden h-6 w-px shrink-0 bg-white/[0.12] md:block"
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="Computer"
|
aria-label="Computer"
|
||||||
|
|||||||
Reference in New Issue
Block a user