mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix(desktop): convert px text literals to rem so zoom scales app-wide
Cmd +/- zoom scales the root html font-size (rem-only by design), but text-[Npx] font literals froze text in pixels and broke zoom outside the timeline. Convert the 63 non-overlapping UI surfaces to rem so text scales proportionally everywhere. Mapping: 12px -> stock text-xs token; sizes with no clean stock home (7-11px micro-text on avatars, badges, chips) -> 1:1 rem literals to preserve exact visual hierarchy with zero pixel shift. Also converts the 2 stray leading-[100px] line-height literals to rem. Deliberately defers the 3 render-path files (MessageRow.tsx, markdown.tsx, mentionChip.ts) to PR #1052, which already converts them and is awaiting merge — touching them here on a main base would manufacture a conflict. The check:px-text guard lands with #1052; once it merges, the guard covers this branch's 63 files plus #1052's 3. Co-authored-by: Taylor Ho <taylorkmho@gmail.com> Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
co-authored by
Taylor Ho
parent
9ee5aeebd9
commit
2951bf5351
@@ -253,8 +253,8 @@ function MemoryGraphView({
|
||||
className="text-xs italic text-muted-foreground"
|
||||
data-testid="agent-memory-no-core"
|
||||
>
|
||||
No <code className="font-mono text-[10px]">core</code> memory yet —
|
||||
agent identity is unrooted.
|
||||
No <code className="font-mono text-[0.625rem]">core</code> memory yet
|
||||
— agent identity is unrooted.
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ export function AddTeamToChannelDialog({
|
||||
>
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-5 w-5 text-[9px]"
|
||||
className="h-5 w-5 text-[0.5625rem]"
|
||||
label={persona.displayName}
|
||||
/>
|
||||
<span className="text-xs font-medium">
|
||||
|
||||
@@ -198,7 +198,7 @@ function ToolTimestamp({
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="shrink-0 cursor-default text-[11px] text-muted-foreground/60">
|
||||
<span className="shrink-0 cursor-default text-[0.6875rem] text-muted-foreground/60">
|
||||
{time}
|
||||
{duration ? ` · ${duration}` : null}
|
||||
</span>
|
||||
@@ -260,7 +260,7 @@ function BuzzToolInlineAction({
|
||||
if (action.onClick) {
|
||||
return (
|
||||
<button
|
||||
className="inline-flex max-w-[14rem] shrink min-w-0 items-center gap-1 rounded-full border border-primary/20 bg-primary/[0.05] px-1.5 py-0.5 text-[11px] font-normal leading-none text-primary/90 transition-colors hover:border-primary/35 hover:bg-primary/10 hover:text-primary"
|
||||
className="inline-flex max-w-[14rem] shrink min-w-0 items-center gap-1 rounded-full border border-primary/20 bg-primary/[0.05] px-1.5 py-0.5 text-[0.6875rem] font-normal leading-none text-primary/90 transition-colors hover:border-primary/35 hover:bg-primary/10 hover:text-primary"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -279,7 +279,7 @@ function BuzzToolInlineAction({
|
||||
|
||||
return (
|
||||
<span
|
||||
className="inline-flex max-w-[14rem] shrink min-w-0 items-center gap-1 rounded-full border border-border/60 bg-muted/40 px-1.5 py-0.5 text-[11px] font-normal leading-none text-muted-foreground"
|
||||
className="inline-flex max-w-[14rem] shrink min-w-0 items-center gap-1 rounded-full border border-border/60 bg-muted/40 px-1.5 py-0.5 text-[0.6875rem] font-normal leading-none text-muted-foreground"
|
||||
title={action.title}
|
||||
>
|
||||
{action.avatar}
|
||||
|
||||
@@ -112,7 +112,7 @@ function MessageItem({
|
||||
{!isAssistant ? (
|
||||
<UserAvatar
|
||||
avatarUrl={authorProfile?.avatarUrl ?? null}
|
||||
className="mr-2 mt-1 h-5 w-5 shrink-0 text-[8px]"
|
||||
className="mr-2 mt-1 h-5 w-5 shrink-0 text-[0.5rem]"
|
||||
displayName={authorLabel}
|
||||
size="xs"
|
||||
/>
|
||||
@@ -198,7 +198,7 @@ function MetadataItem({
|
||||
<span className="truncate">{section.title}</span>
|
||||
<ChevronDown className="h-3.5 w-3.5 shrink-0 text-muted-foreground transition-transform group-open/section:rotate-180" />
|
||||
</summary>
|
||||
<pre className="mt-2 max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/50 px-3 py-2 font-mono text-[11px] leading-5 text-muted-foreground">
|
||||
<pre className="mt-2 max-h-56 overflow-auto whitespace-pre-wrap break-words rounded-md bg-muted/50 px-3 py-2 font-mono text-[0.6875rem] leading-5 text-muted-foreground">
|
||||
{section.body.trim() || "No metadata."}
|
||||
</pre>
|
||||
</details>
|
||||
@@ -248,7 +248,7 @@ function TranscriptTimestamp({ timestamp }: { timestamp: string }) {
|
||||
return (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<span className="shrink-0 cursor-default text-[11px] text-muted-foreground/60">
|
||||
<span className="shrink-0 cursor-default text-[0.6875rem] text-muted-foreground/60">
|
||||
{formatted}
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
|
||||
@@ -64,8 +64,8 @@ export function ManagedAgentLogPanel({
|
||||
<Skeleton className="mt-2 h-4 w-3/4" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="mt-4 overflow-hidden rounded-xl border border-border/70 bg-[#17171d] text-[12px] text-zinc-100">
|
||||
<div className="flex items-center justify-between border-b border-white/10 px-4 py-2 text-[11px] uppercase tracking-[0.18em] text-zinc-400">
|
||||
<div className="mt-4 overflow-hidden rounded-xl border border-border/70 bg-[#17171d] text-xs text-zinc-100">
|
||||
<div className="flex items-center justify-between border-b border-white/10 px-4 py-2 text-[0.6875rem] uppercase tracking-[0.18em] text-zinc-400">
|
||||
<span>{selectedAgent.name}</span>
|
||||
<span>{selectedAgent.status}</span>
|
||||
</div>
|
||||
|
||||
@@ -349,7 +349,7 @@ function StatusBlock({
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-1 lg:pt-0.5">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground lg:hidden">
|
||||
<p className="text-[0.6875rem] font-semibold uppercase tracking-[0.16em] text-muted-foreground lg:hidden">
|
||||
Status
|
||||
</p>
|
||||
<AgentStatusBadge
|
||||
@@ -385,7 +385,7 @@ function RuntimeBlock({
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-1 lg:pt-0.5">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground lg:hidden">
|
||||
<p className="text-[0.6875rem] font-semibold uppercase tracking-[0.16em] text-muted-foreground lg:hidden">
|
||||
Runtime
|
||||
</p>
|
||||
<p className="truncate font-mono text-xs text-foreground">
|
||||
|
||||
@@ -152,7 +152,7 @@ export function ModelPicker({
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
{needsRestart ? (
|
||||
<span className="text-[10px] text-warning">restart to apply</span>
|
||||
<span className="text-[0.625rem] text-warning">restart to apply</span>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -14,7 +14,7 @@ export function PersonaCatalogSelectionBadge({
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 whitespace-nowrap rounded-full px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.14em]",
|
||||
"inline-flex items-center gap-1 whitespace-nowrap rounded-full px-2.5 py-1 text-[0.625rem] font-semibold uppercase tracking-[0.14em]",
|
||||
isActive
|
||||
? "bg-primary text-primary-foreground shadow-xs"
|
||||
: "border border-border/70 bg-background/85 text-muted-foreground",
|
||||
|
||||
@@ -12,7 +12,7 @@ export function RawEventRail({ events }: { events: ObserverEvent[] }) {
|
||||
<aside className="rounded-lg border border-border/70 bg-[#17171d] text-zinc-100">
|
||||
<div className="flex items-center justify-between border-b border-white/10 px-3 py-2">
|
||||
<div>
|
||||
<p className="text-[11px] font-semibold uppercase tracking-[0.16em] text-zinc-400">
|
||||
<p className="text-[0.6875rem] font-semibold uppercase tracking-[0.16em] text-zinc-400">
|
||||
Raw ACP
|
||||
</p>
|
||||
<p className="text-xs text-zinc-500">JSON-RPC payloads</p>
|
||||
@@ -40,7 +40,7 @@ export function RawEventRail({ events }: { events: ObserverEvent[] }) {
|
||||
<span className="font-mono text-zinc-500">#{event.seq}</span>{" "}
|
||||
{describeRawEvent(event)}
|
||||
</summary>
|
||||
<pre className="mt-2 max-h-72 overflow-auto whitespace-pre-wrap break-words text-[11px] leading-5 text-zinc-300">
|
||||
<pre className="mt-2 max-h-72 overflow-auto whitespace-pre-wrap break-words text-[0.6875rem] leading-5 text-zinc-300">
|
||||
{JSON.stringify(event.payload, null, 2)}
|
||||
</pre>
|
||||
</details>
|
||||
|
||||
@@ -95,7 +95,7 @@ export function RelayDirectorySection({
|
||||
className="w-full border-collapse text-left text-sm"
|
||||
data-testid="relay-directory-table"
|
||||
>
|
||||
<thead className="bg-muted/35 text-[11px] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
|
||||
<thead className="bg-muted/35 text-[0.6875rem] font-semibold uppercase tracking-[0.16em] text-muted-foreground">
|
||||
<tr>
|
||||
<th className="px-4 py-3">Agent</th>
|
||||
<th className="px-4 py-3">Status</th>
|
||||
@@ -121,7 +121,7 @@ export function RelayDirectorySection({
|
||||
</td>
|
||||
<td className="px-4 py-3 align-top">
|
||||
<PresenceBadge
|
||||
className="px-2.5 py-0.5 text-[11px]"
|
||||
className="px-2.5 py-0.5 text-[0.6875rem]"
|
||||
status={agent.status}
|
||||
/>
|
||||
</td>
|
||||
|
||||
@@ -211,7 +211,7 @@ function AllowlistPicker({
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="text-sm font-medium">Allowed pubkeys</span>
|
||||
<span className="rounded-full bg-background px-2 py-1 text-[11px] font-medium leading-none text-muted-foreground">
|
||||
<span className="rounded-full bg-background px-2 py-1 text-[0.6875rem] font-medium leading-none text-muted-foreground">
|
||||
{allowlist.length} selected
|
||||
</span>
|
||||
</div>
|
||||
@@ -241,7 +241,7 @@ function AllowlistPicker({
|
||||
<div className="flex flex-wrap gap-1.5 border-t border-border/70 px-2.5 py-2">
|
||||
{allowlist.map((pubkey) => (
|
||||
<div
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-border/80 bg-muted/60 px-2.5 py-1 text-[11px] leading-none"
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-border/80 bg-muted/60 px-2.5 py-1 text-[0.6875rem] leading-none"
|
||||
data-testid={`agent-respond-to-chip-${pubkey}`}
|
||||
key={pubkey}
|
||||
>
|
||||
|
||||
@@ -422,7 +422,7 @@ export function TeamDialog({
|
||||
/>
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-6 w-6 text-[10px]"
|
||||
className="h-6 w-6 text-[0.625rem]"
|
||||
label={persona.displayName}
|
||||
/>
|
||||
<span className="text-sm">{persona.displayName}</span>
|
||||
|
||||
@@ -172,7 +172,7 @@ export function TeamsSection({
|
||||
</Tooltip>
|
||||
) : null}
|
||||
{team.version ? (
|
||||
<span className="shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
||||
<span className="shrink-0 rounded-full bg-muted px-1.5 py-0.5 text-[0.625rem] font-medium text-muted-foreground">
|
||||
v{team.version}
|
||||
</span>
|
||||
) : null}
|
||||
@@ -199,13 +199,13 @@ export function TeamsSection({
|
||||
{visible.map((persona) => (
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-6 w-6 border-2 border-card text-[10px]"
|
||||
className="h-6 w-6 border-2 border-card text-[0.625rem]"
|
||||
key={persona.id}
|
||||
label={persona.displayName}
|
||||
/>
|
||||
))}
|
||||
{overflow > 0 ? (
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded-full border-2 border-card bg-muted text-[10px] font-medium text-muted-foreground">
|
||||
<span className="flex h-6 w-6 items-center justify-center rounded-full border-2 border-card bg-muted text-[0.625rem] font-medium text-muted-foreground">
|
||||
+{overflow}
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -49,7 +49,7 @@ function SelectionChipButton({
|
||||
<ProfileAvatar
|
||||
avatarUrl={avatarUrl}
|
||||
className={cn(
|
||||
"h-6 w-6 text-[10px]",
|
||||
"h-6 w-6 text-[0.625rem]",
|
||||
selected
|
||||
? "bg-primary/20 text-primary ring-1 ring-primary/20"
|
||||
: "bg-background/80 text-muted-foreground ring-1 ring-border/70",
|
||||
@@ -73,7 +73,7 @@ function RuntimeBadge({
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-full px-1.5 py-0.5 text-[10px] font-medium leading-none",
|
||||
"inline-flex items-center rounded-full px-1.5 py-0.5 text-[0.625rem] font-medium leading-none",
|
||||
isOverridden
|
||||
? "bg-warning/15 text-warning"
|
||||
: "bg-muted/60 text-muted-foreground",
|
||||
@@ -174,7 +174,7 @@ export function AddChannelBotPersonasSection({
|
||||
{isInChannel ? (
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[10px] font-medium leading-none",
|
||||
"inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[0.625rem] font-medium leading-none",
|
||||
isSelected
|
||||
? "bg-primary/15 text-primary"
|
||||
: "bg-muted/60 text-muted-foreground",
|
||||
@@ -192,18 +192,18 @@ export function AddChannelBotPersonasSection({
|
||||
<div className="flex items-center gap-2">
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-7 w-7 text-[10px] bg-primary-foreground/20 text-primary-foreground"
|
||||
className="h-7 w-7 text-[0.625rem] bg-primary-foreground/20 text-primary-foreground"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
label={persona.displayName}
|
||||
/>
|
||||
<p className="font-medium">{persona.displayName}</p>
|
||||
</div>
|
||||
{isInChannel ? (
|
||||
<p className="text-[11px] font-medium text-emerald-300">
|
||||
<p className="text-[0.6875rem] font-medium text-emerald-300">
|
||||
✓ Already in this channel
|
||||
</p>
|
||||
) : null}
|
||||
<p className="text-[11px] text-primary-foreground">
|
||||
<p className="text-[0.6875rem] text-primary-foreground">
|
||||
{promptPreview(persona.systemPrompt)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -124,7 +124,7 @@ export function AddChannelBotTeamsSection({
|
||||
{inChannelCount > 0 ? (
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[10px] font-medium leading-none",
|
||||
"inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 text-[0.625rem] font-medium leading-none",
|
||||
allSelected
|
||||
? "bg-primary/15 text-primary"
|
||||
: "bg-muted/60 text-muted-foreground",
|
||||
@@ -143,7 +143,7 @@ export function AddChannelBotTeamsSection({
|
||||
<div className="space-y-1.5">
|
||||
<p className="font-medium">{team.name}</p>
|
||||
{team.description ? (
|
||||
<p className="text-[11px] text-primary-foreground/80">
|
||||
<p className="text-[0.6875rem] text-primary-foreground/80">
|
||||
{team.description}
|
||||
</p>
|
||||
) : null}
|
||||
@@ -158,10 +158,10 @@ export function AddChannelBotTeamsSection({
|
||||
>
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-4 w-4 text-[8px] bg-primary-foreground/20 text-primary-foreground"
|
||||
className="h-4 w-4 text-[0.5rem] bg-primary-foreground/20 text-primary-foreground"
|
||||
label={persona.displayName}
|
||||
/>
|
||||
<span className="text-[10px] text-primary-foreground">
|
||||
<span className="text-[0.625rem] text-primary-foreground">
|
||||
{persona.displayName}
|
||||
</span>
|
||||
{personaInChannel ? (
|
||||
|
||||
@@ -80,7 +80,7 @@ export function AgentSessionThreadPanel({
|
||||
<div className="ml-auto flex shrink-0 items-center gap-2">
|
||||
{isLive && isWorking ? (
|
||||
<Badge
|
||||
className="shrink-0 gap-1 px-2 py-0 text-[10px]"
|
||||
className="shrink-0 gap-1 px-2 py-0 text-[0.625rem]"
|
||||
variant="default"
|
||||
>
|
||||
<CircleDot className="h-2.5 w-2.5" />
|
||||
@@ -92,7 +92,7 @@ export function AgentSessionThreadPanel({
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
aria-label="Stop current agent turn"
|
||||
className="h-6 px-2 text-[11px]"
|
||||
className="h-6 px-2 text-[0.6875rem]"
|
||||
data-testid="agent-session-stop-turn"
|
||||
disabled={!canInterruptTurn}
|
||||
onClick={() => {
|
||||
|
||||
@@ -184,8 +184,8 @@ export function BotActivityComposerAction({
|
||||
className={cn(
|
||||
"border border-background",
|
||||
isInline
|
||||
? "!h-[18px] !w-[18px] shadow-xs ring-1 ring-primary/25 text-[7px]"
|
||||
: "!h-5 !w-5 text-[8px]",
|
||||
? "!h-[18px] !w-[18px] shadow-xs ring-1 ring-primary/25 text-[0.4375rem]"
|
||||
: "!h-5 !w-5 text-[0.5rem]",
|
||||
)}
|
||||
displayName={agent.name}
|
||||
key={agent.pubkey}
|
||||
@@ -193,7 +193,7 @@ export function BotActivityComposerAction({
|
||||
))}
|
||||
</span>
|
||||
{typingAgents.length > 2 ? (
|
||||
<span className="text-[11px] leading-none">
|
||||
<span className="text-[0.6875rem] leading-none">
|
||||
+{typingAgents.length - 2}
|
||||
</span>
|
||||
) : null}
|
||||
@@ -240,7 +240,7 @@ export function BotActivityComposerAction({
|
||||
>
|
||||
<UserAvatar
|
||||
avatarUrl={agentAvatarUrl(agent)}
|
||||
className="!h-6 !w-6 shrink-0 text-[9px]"
|
||||
className="!h-6 !w-6 shrink-0 text-[0.5625rem]"
|
||||
displayName={agent.name}
|
||||
/>
|
||||
<span className="min-w-0 flex-1 truncate">{agent.name}</span>
|
||||
|
||||
@@ -184,7 +184,7 @@ export function ChannelMemberInviteCard({
|
||||
<span>Add members</span>
|
||||
</div>
|
||||
{inviteTargets.length > 0 ? (
|
||||
<span className="rounded-full bg-background px-2 py-1 text-[11px] font-medium leading-none text-muted-foreground">
|
||||
<span className="rounded-full bg-background px-2 py-1 text-[0.6875rem] font-medium leading-none text-muted-foreground">
|
||||
{inviteTargets.length} selected
|
||||
</span>
|
||||
) : null}
|
||||
@@ -210,7 +210,7 @@ export function ChannelMemberInviteCard({
|
||||
<div className="flex flex-wrap gap-1.5 border-t border-border/70 px-2.5 py-2">
|
||||
{selectedInvitees.map((invitee) => (
|
||||
<div
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-border/80 bg-muted/60 px-2.5 py-1 text-[11px] leading-none"
|
||||
className="inline-flex items-center gap-1.5 rounded-full border border-border/80 bg-muted/60 px-2.5 py-1 text-[0.6875rem] leading-none"
|
||||
data-testid={`selected-invitee-${invitee.pubkey}`}
|
||||
key={invitee.pubkey}
|
||||
>
|
||||
|
||||
@@ -92,7 +92,7 @@ export function ChannelScreenHeader({
|
||||
activeChannel?.channelType === "dm" ? (
|
||||
<ProfileAvatar
|
||||
avatarUrl={activeDmAvatarUrl}
|
||||
className="h-6 w-6 rounded-full text-[10px]"
|
||||
className="h-6 w-6 rounded-full text-[0.625rem]"
|
||||
iconClassName="h-3.5 w-3.5"
|
||||
label={activeChannelTitle}
|
||||
testId="chat-header-dm-avatar"
|
||||
|
||||
@@ -264,7 +264,7 @@ export function MembersSidebar({
|
||||
<section className="space-y-2.5">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<h2 className="text-sm font-semibold tracking-tight">People</h2>
|
||||
<span className="rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
|
||||
<span className="rounded-full bg-muted px-2 py-0.5 text-[0.6875rem] font-medium text-muted-foreground">
|
||||
{people.length}
|
||||
</span>
|
||||
</div>
|
||||
@@ -284,7 +284,7 @@ export function MembersSidebar({
|
||||
<section className="space-y-2.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<h2 className="text-sm font-semibold tracking-tight">Bots</h2>
|
||||
<span className="rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
|
||||
<span className="rounded-full bg-muted px-2 py-0.5 text-[0.6875rem] font-medium text-muted-foreground">
|
||||
{bots.length}
|
||||
</span>
|
||||
{hasControllableManagedBots ? (
|
||||
@@ -329,7 +329,7 @@ export function MembersSidebar({
|
||||
Archived
|
||||
</h2>
|
||||
<span
|
||||
className="rounded-full bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground"
|
||||
className="rounded-full bg-muted px-2 py-0.5 text-[0.6875rem] font-medium text-muted-foreground"
|
||||
data-testid="members-sidebar-archived-count"
|
||||
>
|
||||
{archived.length}
|
||||
|
||||
@@ -119,7 +119,7 @@ export function MembersSidebarMemberCard({
|
||||
<div className="relative shrink-0">
|
||||
<ProfileAvatar
|
||||
avatarUrl={profileAvatarUrl ?? null}
|
||||
className="h-9 w-9 text-[11px] shadow-none"
|
||||
className="h-9 w-9 text-[0.6875rem] shadow-none"
|
||||
iconClassName="h-4 w-4"
|
||||
label={memberAvatarLabel}
|
||||
/>
|
||||
@@ -159,7 +159,7 @@ export function MembersSidebarMemberCard({
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<p className="truncate font-mono text-[10px] text-muted-foreground/50">
|
||||
<p className="truncate font-mono text-[0.625rem] text-muted-foreground/50">
|
||||
{truncatePubkey(member.pubkey)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,7 @@ export function QuickBotBar({ personas, pending, onAdd }: QuickBotBarProps) {
|
||||
src={rewriteRelayUrl(persona.avatarUrl)}
|
||||
/>
|
||||
) : (
|
||||
<span className="text-[9px] font-semibold text-primary">
|
||||
<span className="text-[0.5625rem] font-semibold text-primary">
|
||||
{initials}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -187,11 +187,11 @@ export function FeedSection({
|
||||
|
||||
<div className="pointer-events-none relative flex min-w-0 items-center gap-2">
|
||||
<span
|
||||
className={`text-[13px] font-medium ${isDone ? "line-through text-muted-foreground" : ""}`}
|
||||
className={`text-[0.8125rem] font-medium ${isDone ? "line-through text-muted-foreground" : ""}`}
|
||||
>
|
||||
{feedHeadline(item)}
|
||||
</span>
|
||||
<span className="inline-flex items-center gap-1 text-[11px] text-muted-foreground">
|
||||
<span className="inline-flex items-center gap-1 text-[0.6875rem] text-muted-foreground">
|
||||
<UserAvatar
|
||||
avatarUrl={
|
||||
profiles?.[item.pubkey.toLowerCase()]?.avatarUrl ?? null
|
||||
@@ -212,18 +212,18 @@ export function FeedSection({
|
||||
})}
|
||||
</span>
|
||||
{item.channelName ? (
|
||||
<span className="text-[11px] text-primary/80">
|
||||
<span className="text-[0.6875rem] text-primary/80">
|
||||
#{item.channelName}
|
||||
</span>
|
||||
) : null}
|
||||
<span className="ml-auto shrink-0 text-[11px] text-muted-foreground/60">
|
||||
<span className="ml-auto shrink-0 text-[0.6875rem] text-muted-foreground/60">
|
||||
{formatRelativeTime(item.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="pointer-events-none relative mt-0.5 line-clamp-2">
|
||||
<Markdown
|
||||
className="max-w-none text-[13px] leading-snug text-muted-foreground"
|
||||
className="max-w-none text-[0.8125rem] leading-snug text-muted-foreground"
|
||||
compact
|
||||
content={feedContent(item)}
|
||||
mentionNames={mentionNames}
|
||||
|
||||
@@ -319,7 +319,7 @@ export function InboxDetailPane({
|
||||
<div className="min-h-0 flex-1 overflow-y-auto overscroll-contain pb-32">
|
||||
<div>
|
||||
{isThreadContextLoading ? (
|
||||
<div className="px-6 pb-3 text-[11px] text-muted-foreground">
|
||||
<div className="px-6 pb-3 text-[0.6875rem] text-muted-foreground">
|
||||
Loading context...
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
@@ -67,7 +67,7 @@ export function InboxListPane({
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
className="inline-flex shrink-0 items-center gap-1.5 rounded-full border-border/70 bg-background/70 px-2.5 text-[11px] font-medium leading-none text-muted-foreground shadow-xs backdrop-blur-sm hover:bg-muted/60 hover:text-foreground"
|
||||
className="inline-flex shrink-0 items-center gap-1.5 rounded-full border-border/70 bg-background/70 px-2.5 text-[0.6875rem] font-medium leading-none text-muted-foreground shadow-xs backdrop-blur-sm hover:bg-muted/60 hover:text-foreground"
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="outline"
|
||||
@@ -153,7 +153,7 @@ export function InboxListPane({
|
||||
{item.senderLabel}
|
||||
</p>
|
||||
{item.isActionRequired ? (
|
||||
<span className="inline-flex shrink-0 items-center text-[10px] font-semibold uppercase tracking-[0.14em] text-amber-600 dark:text-amber-300">
|
||||
<span className="inline-flex shrink-0 items-center text-[0.625rem] font-semibold uppercase tracking-[0.14em] text-amber-600 dark:text-amber-300">
|
||||
Needs action
|
||||
</span>
|
||||
) : null}
|
||||
@@ -189,7 +189,7 @@ export function InboxListPane({
|
||||
<div className="mt-1 flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
|
||||
<span
|
||||
className={cn(
|
||||
"text-[11px] text-muted-foreground",
|
||||
"text-[0.6875rem] text-muted-foreground",
|
||||
isDone ? "font-normal" : "font-semibold",
|
||||
)}
|
||||
>
|
||||
|
||||
@@ -76,11 +76,11 @@ export function RecentNotesSection({
|
||||
{displayName}
|
||||
</span>
|
||||
{isAgent ? (
|
||||
<span className="inline-flex h-3.5 items-center rounded bg-muted px-1 text-[9px] font-medium text-muted-foreground">
|
||||
<span className="inline-flex h-3.5 items-center rounded bg-muted px-1 text-[0.5625rem] font-medium text-muted-foreground">
|
||||
bot
|
||||
</span>
|
||||
) : null}
|
||||
<span className="shrink-0 text-[10px] text-muted-foreground">
|
||||
<span className="shrink-0 text-[0.625rem] text-muted-foreground">
|
||||
{formatRelativeTime(note.createdAt)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -363,7 +363,7 @@ export function HuddleBar({ className }: HuddleBarProps) {
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{isPttMode && (
|
||||
<kbd className="rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground">
|
||||
<kbd className="rounded bg-muted px-1.5 py-0.5 text-[0.625rem] text-muted-foreground">
|
||||
{navigator.platform?.includes("Mac") ? "⌃Space" : "Ctrl+Space"}
|
||||
</kbd>
|
||||
)}
|
||||
|
||||
@@ -321,7 +321,7 @@ export function HuddleIndicator({
|
||||
<span className="absolute inset-0 animate-pulse rounded-lg ring-2 ring-border/70" />
|
||||
{/* Participant count badge */}
|
||||
{participantCount > 0 && (
|
||||
<span className="absolute -right-1 -top-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full border border-border bg-background px-0.5 text-[9px] font-bold text-muted-foreground">
|
||||
<span className="absolute -right-1 -top-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full border border-border bg-background px-0.5 text-[0.5625rem] font-bold text-muted-foreground">
|
||||
{participantCount}
|
||||
</span>
|
||||
)}
|
||||
|
||||
@@ -216,7 +216,7 @@ export function DeviceList({
|
||||
})}
|
||||
</ul>
|
||||
{showChangeHint && (
|
||||
<p className="mt-1 text-[10px] text-muted-foreground">
|
||||
<p className="mt-1 text-[0.625rem] text-muted-foreground">
|
||||
Change takes effect on next huddle
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -52,7 +52,7 @@ export function ParticipantList({
|
||||
avatarUrl={profile.avatarUrl ?? null}
|
||||
label={profile.displayName || pubkey.slice(0, 6)}
|
||||
className={cn(
|
||||
"h-7 w-7 rounded-lg text-[9px]",
|
||||
"h-7 w-7 rounded-lg text-[0.5625rem]",
|
||||
isActive &&
|
||||
"ring-2 ring-green-500 ring-offset-1 ring-offset-background",
|
||||
)}
|
||||
@@ -83,7 +83,7 @@ export function ParticipantList({
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="absolute -bottom-1 -right-1 text-[9px] leading-none"
|
||||
className="absolute -bottom-1 -right-1 text-[0.5625rem] leading-none"
|
||||
>
|
||||
🤖
|
||||
</span>
|
||||
@@ -121,7 +121,7 @@ function HexAvatar({
|
||||
aria-label={ariaLabel ?? `Participant ${pubkey.slice(0, 8)}`}
|
||||
role="img"
|
||||
className={cn(
|
||||
"flex h-7 w-7 items-center justify-center rounded-lg text-[9px] font-semibold shadow-xs",
|
||||
"flex h-7 w-7 items-center justify-center rounded-lg text-[0.5625rem] font-semibold shadow-xs",
|
||||
isActive &&
|
||||
"ring-2 ring-green-500 ring-offset-1 ring-offset-background",
|
||||
)}
|
||||
|
||||
@@ -136,7 +136,7 @@ export const ComposerAttachments = React.memo(function ComposerAttachments({
|
||||
>
|
||||
<div className="flex h-5 max-w-[10rem] items-center gap-1 rounded border border-border/70 bg-muted px-1.5">
|
||||
<FileText className="h-3 w-3 shrink-0 text-muted-foreground" />
|
||||
<span className="truncate text-[10px] text-muted-foreground">
|
||||
<span className="truncate text-[0.625rem] text-muted-foreground">
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ export function DayDivider({ label }: { label: string }) {
|
||||
data-testid="message-timeline-day-divider"
|
||||
data-day-label={label}
|
||||
>
|
||||
<p className="relative z-10 shrink-0 rounded-lg border border-border/70 bg-background/95 px-2 py-1 text-[10px] font-medium tracking-[0.02em] text-muted-foreground/70 shadow-xs backdrop-blur-sm">
|
||||
<p className="relative z-10 shrink-0 rounded-lg border border-border/70 bg-background/95 px-2 py-1 text-[0.625rem] font-medium tracking-[0.02em] text-muted-foreground/70 shadow-xs backdrop-blur-sm">
|
||||
{label}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
@@ -36,7 +36,7 @@ function FileChangeBadge({
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"rounded-md px-1.5 py-0.5 font-mono text-[10px] font-semibold",
|
||||
"rounded-md px-1.5 py-0.5 font-mono text-[0.625rem] font-semibold",
|
||||
tone === "positive"
|
||||
? "bg-emerald-500/10 text-status-added"
|
||||
: "bg-rose-500/10 text-status-deleted",
|
||||
@@ -97,10 +97,10 @@ export function DiffViewer({
|
||||
>
|
||||
{showFileHeader ? (
|
||||
<div className="flex items-center gap-2 border-b border-border/60 bg-muted/35 px-3 py-2">
|
||||
<span className="truncate font-mono text-[11px] text-foreground/85">
|
||||
<span className="truncate font-mono text-[0.6875rem] text-foreground/85">
|
||||
{label}
|
||||
</span>
|
||||
<span className="rounded-md border border-border/60 px-1.5 py-0.5 text-[10px] uppercase tracking-[0.14em] text-muted-foreground">
|
||||
<span className="rounded-md border border-border/60 px-1.5 py-0.5 text-[0.625rem] uppercase tracking-[0.14em] text-muted-foreground">
|
||||
{DIFF_TYPE_LABELS[diffType]}
|
||||
</span>
|
||||
<div className="ml-auto flex items-center gap-1.5">
|
||||
|
||||
@@ -773,7 +773,7 @@ export function MessageComposer({
|
||||
data-testid="edit-target"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
<p className="text-[0.6875rem] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
Editing message
|
||||
</p>
|
||||
<p className="truncate text-sm text-foreground/80">
|
||||
@@ -796,7 +796,7 @@ export function MessageComposer({
|
||||
data-testid="reply-target"
|
||||
>
|
||||
<div className="min-w-0">
|
||||
<p className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
<p className="text-[0.6875rem] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
Replying to {replyTarget.author}
|
||||
</p>
|
||||
<p className="truncate text-sm text-foreground/80">
|
||||
|
||||
@@ -286,7 +286,7 @@ export function MessageThreadPanel({
|
||||
{!isAtBottom ? (
|
||||
<div className="pointer-events-none absolute inset-x-0 bottom-36 z-20 flex justify-center px-4">
|
||||
<Button
|
||||
className="pointer-events-auto h-7 min-h-7 gap-1.5 rounded-full border-border/50 bg-background/85 px-2.5 text-[11px] font-medium text-muted-foreground shadow-xs backdrop-blur-sm hover:bg-muted/70 hover:text-foreground [&_svg]:size-3.5"
|
||||
className="pointer-events-auto h-7 min-h-7 gap-1.5 rounded-full border-border/50 bg-background/85 px-2.5 text-[0.6875rem] font-medium text-muted-foreground shadow-xs backdrop-blur-sm hover:bg-muted/70 hover:text-foreground [&_svg]:size-3.5"
|
||||
data-testid="thread-scroll-to-latest"
|
||||
onClick={() => scrollToBottom("smooth")}
|
||||
size="sm"
|
||||
|
||||
@@ -32,7 +32,7 @@ function ParticipantAvatar({
|
||||
>
|
||||
<UserAvatar
|
||||
avatarUrl={participant.avatarUrl}
|
||||
className="h-7 w-7 text-[10px]"
|
||||
className="h-7 w-7 text-[0.625rem]"
|
||||
displayName={participant.author}
|
||||
size="sm"
|
||||
/>
|
||||
|
||||
@@ -400,7 +400,7 @@ export const MessageTimeline = React.memo(function MessageTimeline({
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
className="pointer-events-auto h-7 min-h-7 gap-1.5 rounded-full border-border/50 bg-background/85 px-2.5 text-[11px] font-medium text-muted-foreground shadow-xs backdrop-blur-sm hover:bg-muted/70 hover:text-foreground [&_svg]:size-3.5"
|
||||
className="pointer-events-auto h-7 min-h-7 gap-1.5 rounded-full border-border/50 bg-background/85 px-2.5 text-[0.6875rem] font-medium text-muted-foreground shadow-xs backdrop-blur-sm hover:bg-muted/70 hover:text-foreground [&_svg]:size-3.5"
|
||||
data-testid="message-scroll-to-latest"
|
||||
onClick={() => {
|
||||
scrollToBottom("smooth");
|
||||
|
||||
@@ -129,7 +129,7 @@ function SystemMessageAvatar({
|
||||
const avatar = (
|
||||
<UserAvatar
|
||||
avatarUrl={resolveAvatarUrl(singlePubkey, profiles)}
|
||||
className="!h-9 !w-9 shrink-0 text-[10px]"
|
||||
className="!h-9 !w-9 shrink-0 text-[0.625rem]"
|
||||
displayName={actorLabel}
|
||||
testId="system-message-avatar"
|
||||
/>
|
||||
@@ -165,12 +165,12 @@ function SystemMessageAvatar({
|
||||
>
|
||||
<UserAvatar
|
||||
avatarUrl={resolveAvatarUrl(actorPubkey, profiles)}
|
||||
className="!h-7 !w-7 border-2 border-background text-[9px]"
|
||||
className="!h-7 !w-7 border-2 border-background text-[0.5625rem]"
|
||||
displayName={actorLabel}
|
||||
/>
|
||||
<UserAvatar
|
||||
avatarUrl={resolveAvatarUrl(targetPubkey, profiles)}
|
||||
className="!absolute !bottom-0 !right-0 !h-7 !w-7 border-2 border-background text-[9px]"
|
||||
className="!absolute !bottom-0 !right-0 !h-7 !w-7 border-2 border-background text-[0.5625rem]"
|
||||
displayName={targetLabel}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -113,8 +113,8 @@ export function TypingIndicatorRow({
|
||||
label={label}
|
||||
className={cn(
|
||||
isActivityVariant
|
||||
? "h-[18px] w-[18px] text-[7px]"
|
||||
: "h-5 w-5 text-[8px]",
|
||||
? "h-[18px] w-[18px] text-[0.4375rem]"
|
||||
: "h-5 w-5 text-[0.5rem]",
|
||||
)}
|
||||
iconClassName={
|
||||
isActivityVariant ? "h-2.5 w-2.5" : "h-3 w-3"
|
||||
|
||||
@@ -86,7 +86,7 @@ function AvatarPreview({
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"buzz-avatar-emoji-glyph flex h-full w-full items-center justify-center text-[6rem] leading-[100px]",
|
||||
"buzz-avatar-emoji-glyph flex h-full w-full items-center justify-center text-[6rem] leading-[6.25rem]",
|
||||
avatarSquishKey > 0 && "buzz-avatar-squish",
|
||||
)}
|
||||
data-testid="onboarding-avatar-preview-emoji"
|
||||
|
||||
@@ -177,7 +177,7 @@ export function MembershipDenied({
|
||||
<p className="font-medium text-foreground">
|
||||
This will use this Nostr identity:
|
||||
</p>
|
||||
<p className="break-all font-mono text-[11px] text-muted-foreground">
|
||||
<p className="break-all font-mono text-[0.6875rem] text-muted-foreground">
|
||||
{shortenNpub(previewNpub)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -227,7 +227,7 @@ export function NostrKeyImportForm({
|
||||
<p className="font-medium text-foreground">
|
||||
This will use this Nostr identity:
|
||||
</p>
|
||||
<p className="break-all font-mono text-[11px] text-muted-foreground">
|
||||
<p className="break-all font-mono text-[0.6875rem] text-muted-foreground">
|
||||
{shortenNpub(previewNpub)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -216,7 +216,7 @@ export function UserProfilePopover({
|
||||
</p>
|
||||
) : null}
|
||||
{profile?.displayName ? (
|
||||
<p className="truncate font-mono text-[10px] text-muted-foreground/50">
|
||||
<p className="truncate font-mono text-[0.625rem] text-muted-foreground/50">
|
||||
{truncatePubkey(pubkey)}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
@@ -75,7 +75,7 @@ export function AgentActivityCard({
|
||||
{displayName}
|
||||
</span>
|
||||
{agentStatus ? <StatusDot status={agentStatus} /> : null}
|
||||
<span className="shrink-0 text-[11px] text-muted-foreground">
|
||||
<span className="shrink-0 text-[0.6875rem] text-muted-foreground">
|
||||
{formatRelativeTime(group.latestAt)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -113,7 +113,7 @@ export function AgentActivityCard({
|
||||
</span>
|
||||
<div className="min-w-0 flex-1 text-sm">
|
||||
<Markdown content={note.content} />
|
||||
<p className="mt-1 text-[10px] text-muted-foreground">
|
||||
<p className="mt-1 text-[0.625rem] text-muted-foreground">
|
||||
{formatRelativeTime(note.createdAt)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -191,7 +191,7 @@ export function NoteCard({
|
||||
</button>
|
||||
</UserProfilePopover>
|
||||
{isAgent ? (
|
||||
<span className="inline-flex h-4 items-center rounded bg-muted px-1 text-[10px] font-medium text-muted-foreground">
|
||||
<span className="inline-flex h-4 items-center rounded bg-muted px-1 text-[0.625rem] font-medium text-muted-foreground">
|
||||
bot
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -103,7 +103,7 @@ export function PulseTabBar({
|
||||
>
|
||||
Agents
|
||||
{relayAgents.length > 0 ? (
|
||||
<span className="ml-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-muted px-1 text-[10px] font-medium text-muted-foreground">
|
||||
<span className="ml-0.5 inline-flex h-4 min-w-4 items-center justify-center rounded-full bg-muted px-1 text-[0.625rem] font-medium text-muted-foreground">
|
||||
{relayAgents.length}
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -201,7 +201,7 @@ export function TopbarSearch({
|
||||
placeholder="Search everything"
|
||||
value={query}
|
||||
/>
|
||||
<kbd className="shrink-0 text-[10px] text-muted-foreground/70">
|
||||
<kbd className="shrink-0 text-[0.625rem] text-muted-foreground/70">
|
||||
⌘K
|
||||
</kbd>
|
||||
</div>
|
||||
@@ -212,7 +212,7 @@ export function TopbarSearch({
|
||||
data-testid="search-results"
|
||||
>
|
||||
{debouncedQuery.length < MIN_SEARCH_QUERY_LENGTH ? (
|
||||
<div className="px-3 py-3 text-[11px] text-muted-foreground">
|
||||
<div className="px-3 py-3 text-[0.6875rem] text-muted-foreground">
|
||||
<p>Type at least two characters for live suggestions.</p>
|
||||
</div>
|
||||
) : searchQuery.isLoading && results.length === 0 ? (
|
||||
@@ -291,7 +291,7 @@ export function TopbarSearch({
|
||||
: truncateResultText(result.hit.content)}
|
||||
</span>
|
||||
</span>
|
||||
<span className="shrink-0 text-[11px] text-muted-foreground/75">
|
||||
<span className="shrink-0 text-[0.6875rem] text-muted-foreground/75">
|
||||
{result.kind === "channel"
|
||||
? "Channel"
|
||||
: `${describeSearchHit(result.hit)} · ${formatRelativeTime(result.hit.createdAt)}`}
|
||||
|
||||
@@ -216,7 +216,10 @@ function TemplateRow({
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="truncate text-sm font-medium">{template.name}</span>
|
||||
{template.isBuiltin ? (
|
||||
<Badge className="shrink-0 text-[10px] uppercase" variant="outline">
|
||||
<Badge
|
||||
className="shrink-0 text-[0.625rem] uppercase"
|
||||
variant="outline"
|
||||
>
|
||||
built-in
|
||||
</Badge>
|
||||
) : null}
|
||||
@@ -756,7 +759,7 @@ function RuntimeRow({
|
||||
) : (
|
||||
<ProfileAvatar
|
||||
avatarUrl={avatarUrl ?? null}
|
||||
className="h-5 w-5 shrink-0 text-[8px] bg-muted text-muted-foreground ring-1 ring-border/50"
|
||||
className="h-5 w-5 shrink-0 text-[0.5rem] bg-muted text-muted-foreground ring-1 ring-border/50"
|
||||
label={label}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -109,7 +109,7 @@ function RuntimeRow({
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<p className="text-sm font-medium">{runtime.label}</p>
|
||||
{runtime.command ? (
|
||||
<code className="rounded bg-muted px-1.5 py-0.5 text-[11px]">
|
||||
<code className="rounded bg-muted px-1.5 py-0.5 text-[0.6875rem]">
|
||||
{runtime.command}
|
||||
</code>
|
||||
) : null}
|
||||
@@ -134,21 +134,21 @@ function RuntimeRow({
|
||||
{runtime.underlyingCliPath &&
|
||||
runtime.underlyingCliPath !== runtime.binaryPath ? (
|
||||
<div className="mt-1 space-y-0.5">
|
||||
<p className="break-all font-mono text-[11px] text-muted-foreground/80">
|
||||
<p className="break-all font-mono text-[0.6875rem] text-muted-foreground/80">
|
||||
<span className="text-muted-foreground">CLI:</span>{" "}
|
||||
{runtime.underlyingCliPath}
|
||||
</p>
|
||||
<p className="break-all font-mono text-[11px] text-muted-foreground/80">
|
||||
<p className="break-all font-mono text-[0.6875rem] text-muted-foreground/80">
|
||||
<span className="text-muted-foreground">ACP adapter:</span>{" "}
|
||||
{runtime.binaryPath}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<p className="mt-1 break-all font-mono text-[11px] text-muted-foreground/80">
|
||||
<p className="mt-1 break-all font-mono text-[0.6875rem] text-muted-foreground/80">
|
||||
{runtime.binaryPath}
|
||||
</p>
|
||||
<p className="mt-1 text-[11px] text-muted-foreground/60">
|
||||
<p className="mt-1 text-[0.6875rem] text-muted-foreground/60">
|
||||
ACP support built-in — no separate adapter needed.
|
||||
</p>
|
||||
</>
|
||||
@@ -158,7 +158,7 @@ function RuntimeRow({
|
||||
<>
|
||||
<p className="mt-1 text-sm font-normal text-muted-foreground">
|
||||
CLI detected at{" "}
|
||||
<code className="rounded bg-muted px-1 py-0.5 text-[11px]">
|
||||
<code className="rounded bg-muted px-1 py-0.5 text-[0.6875rem]">
|
||||
{runtime.underlyingCliPath ?? "unknown path"}
|
||||
</code>{" "}
|
||||
but ACP adapter not found.
|
||||
@@ -176,7 +176,7 @@ function RuntimeRow({
|
||||
<>
|
||||
<p className="mt-1 text-sm font-normal text-muted-foreground">
|
||||
ACP adapter found at{" "}
|
||||
<code className="rounded bg-muted px-1 py-0.5 text-[11px]">
|
||||
<code className="rounded bg-muted px-1 py-0.5 text-[0.6875rem]">
|
||||
{runtime.binaryPath ?? "unknown path"}
|
||||
</code>{" "}
|
||||
but the {runtime.label} CLI is not installed.
|
||||
|
||||
@@ -179,7 +179,7 @@ export function NotificationSettingsCard({
|
||||
<span className="flex items-center gap-2 text-sm font-medium">
|
||||
{SLOT_LABELS[slot]}
|
||||
{comingSoon ? (
|
||||
<span className="rounded-full bg-muted/70 px-2 py-0.5 text-[10px] font-normal uppercase tracking-wide text-muted-foreground">
|
||||
<span className="rounded-full bg-muted/70 px-2 py-0.5 text-[0.625rem] font-normal uppercase tracking-wide text-muted-foreground">
|
||||
Coming soon
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -429,7 +429,7 @@ export function ProfileSettingsCard({
|
||||
>
|
||||
<span
|
||||
className={cn(
|
||||
"buzz-avatar-emoji-glyph flex h-full w-full items-center justify-center text-[6rem] leading-[100px]",
|
||||
"buzz-avatar-emoji-glyph flex h-full w-full items-center justify-center text-[6rem] leading-[6.25rem]",
|
||||
avatarSquishKey > 0 && "buzz-avatar-squish",
|
||||
)}
|
||||
data-testid="profile-avatar-preview-emoji"
|
||||
|
||||
@@ -113,7 +113,7 @@ export function SoundPicker({
|
||||
<span>{name}</span>
|
||||
<span className="flex items-center gap-2">
|
||||
{name === recommended ? (
|
||||
<span className="text-[10px] uppercase tracking-wide text-muted-foreground">
|
||||
<span className="text-[0.625rem] uppercase tracking-wide text-muted-foreground">
|
||||
rec.
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -444,7 +444,7 @@ export function AppSidebar({
|
||||
</SidebarMenuButton>
|
||||
{homeBadgeCount > 0 ? (
|
||||
<SidebarMenuBadge
|
||||
className="right-2 rounded-full bg-primary/15 px-1.5 text-[11px] text-primary peer-data-[active=true]/menu-button:bg-sidebar-active-foreground/20 peer-data-[active=true]/menu-button:text-sidebar-active-foreground"
|
||||
className="right-2 rounded-full bg-primary/15 px-1.5 text-[0.6875rem] text-primary peer-data-[active=true]/menu-button:bg-sidebar-active-foreground/20 peer-data-[active=true]/menu-button:text-sidebar-active-foreground"
|
||||
data-testid="sidebar-home-count"
|
||||
>
|
||||
{Math.min(homeBadgeCount, 99)}
|
||||
@@ -492,7 +492,7 @@ export function AppSidebar({
|
||||
</SidebarMenuButton>
|
||||
{shouldShowAgentCount ? (
|
||||
<SidebarMenuBadge
|
||||
className="right-2 rounded-full bg-sidebar-accent/70 px-1.5 text-[11px] text-sidebar-foreground/75 peer-data-[active=true]/menu-button:bg-sidebar-active-foreground/20 peer-data-[active=true]/menu-button:text-sidebar-active-foreground"
|
||||
className="right-2 rounded-full bg-sidebar-accent/70 px-1.5 text-[0.6875rem] text-sidebar-foreground/75 peer-data-[active=true]/menu-button:bg-sidebar-active-foreground/20 peer-data-[active=true]/menu-button:text-sidebar-active-foreground"
|
||||
data-testid="sidebar-agents-count"
|
||||
>
|
||||
{totalAgentCount}
|
||||
|
||||
@@ -3,7 +3,7 @@ import type * as React from "react";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
|
||||
const MORE_UNREAD_BUTTON_CLASS =
|
||||
"h-7 min-h-7 gap-1.5 rounded-full border-0 bg-primary px-2.5 text-[11px] font-medium text-primary-foreground shadow-md hover:bg-primary/90 [&_svg]:size-3.5";
|
||||
"h-7 min-h-7 gap-1.5 rounded-full border-0 bg-primary px-2.5 text-[0.6875rem] font-medium text-primary-foreground shadow-md hover:bg-primary/90 [&_svg]:size-3.5";
|
||||
|
||||
export function MoreUnreadButton({
|
||||
bottomClassName = "bottom-0",
|
||||
|
||||
@@ -180,7 +180,7 @@ export function NewDirectMessageDialog({
|
||||
>
|
||||
<ProfileAvatar
|
||||
avatarUrl={user.avatarUrl}
|
||||
className="h-5 w-5 text-[10px] shadow-none"
|
||||
className="h-5 w-5 text-[0.625rem] shadow-none"
|
||||
iconClassName="h-3 w-3"
|
||||
label={formatUserName(user)}
|
||||
/>
|
||||
|
||||
@@ -78,7 +78,10 @@ export function SidebarProfileCard({
|
||||
const workspaceLabel = activeWorkspace?.name ?? "No workspace";
|
||||
const readonlyWorkspaceLabel = (
|
||||
<span className="flex min-w-0 cursor-pointer items-center gap-1 text-xs leading-snug text-sidebar-foreground/70">
|
||||
<span aria-hidden="true" className="shrink-0 text-[10px] leading-none">
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="shrink-0 text-[0.625rem] leading-none"
|
||||
>
|
||||
🐝
|
||||
</span>
|
||||
<span className="truncate">{workspaceLabel}</span>
|
||||
|
||||
@@ -70,7 +70,7 @@ function DmChannelIcon({
|
||||
<span className="relative flex h-5 w-5 shrink-0 items-center justify-center">
|
||||
<ProfileAvatar
|
||||
avatarUrl={primaryParticipant.avatarUrl}
|
||||
className="h-5 w-5 rounded-full border border-sidebar-border/80 bg-sidebar-accent/80 text-[9px] text-sidebar-foreground shadow-none"
|
||||
className="h-5 w-5 rounded-full border border-sidebar-border/80 bg-sidebar-accent/80 text-[0.5625rem] text-sidebar-foreground shadow-none"
|
||||
iconClassName="h-3 w-3"
|
||||
label={primaryParticipant.label}
|
||||
/>
|
||||
@@ -91,18 +91,18 @@ function DmChannelIcon({
|
||||
<span className="relative flex h-5 w-7 shrink-0 items-center">
|
||||
<ProfileAvatar
|
||||
avatarUrl={primaryParticipant.avatarUrl}
|
||||
className="absolute left-0 top-0 h-[18px] w-[18px] rounded-full border-2 border-sidebar bg-sidebar-accent/80 text-[8px] text-sidebar-foreground shadow-none"
|
||||
className="absolute left-0 top-0 h-[18px] w-[18px] rounded-full border-2 border-sidebar bg-sidebar-accent/80 text-[0.5rem] text-sidebar-foreground shadow-none"
|
||||
iconClassName="h-2.5 w-2.5"
|
||||
label={primaryParticipant.label}
|
||||
/>
|
||||
<ProfileAvatar
|
||||
avatarUrl={secondaryParticipant.avatarUrl}
|
||||
className="absolute bottom-0 right-0 h-[18px] w-[18px] rounded-full border-2 border-sidebar bg-sidebar-accent/80 text-[8px] text-sidebar-foreground shadow-none"
|
||||
className="absolute bottom-0 right-0 h-[18px] w-[18px] rounded-full border-2 border-sidebar bg-sidebar-accent/80 text-[0.5rem] text-sidebar-foreground shadow-none"
|
||||
iconClassName="h-2.5 w-2.5"
|
||||
label={secondaryParticipant.label}
|
||||
/>
|
||||
{participants && participants.length > 2 ? (
|
||||
<span className="absolute -bottom-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-sidebar-primary px-1 text-[8px] font-semibold text-sidebar-primary-foreground">
|
||||
<span className="absolute -bottom-1 -right-1 flex h-3.5 min-w-3.5 items-center justify-center rounded-full bg-sidebar-primary px-1 text-[0.5rem] font-semibold text-sidebar-primary-foreground">
|
||||
{participants.length}
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -120,7 +120,7 @@ export function SetStatusDialog({
|
||||
{emoji ? (
|
||||
<button
|
||||
aria-label="Clear status emoji"
|
||||
className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full border border-background bg-muted text-[10px] leading-none text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
className="absolute -right-1 -top-1 flex h-4 w-4 items-center justify-center rounded-full border border-background bg-muted text-[0.625rem] leading-none text-muted-foreground hover:bg-accent hover:text-foreground"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
setEmoji("");
|
||||
|
||||
@@ -85,7 +85,7 @@ export function WorkflowCard({
|
||||
</span>
|
||||
<StatusBadge status={displayStatus} />
|
||||
</div>
|
||||
<div className="mt-1.5 flex items-center gap-3 pl-6 text-[11px] text-muted-foreground">
|
||||
<div className="mt-1.5 flex items-center gap-3 pl-6 text-[0.6875rem] text-muted-foreground">
|
||||
{channelName ? <span>{channelName}</span> : null}
|
||||
{triggerSummary ? <span>{triggerSummary}</span> : null}
|
||||
<span className="flex items-center gap-1">
|
||||
|
||||
@@ -186,7 +186,7 @@ export function WorkflowDetailPanel({
|
||||
</span>
|
||||
<RunStatusBadge status={run.status} />
|
||||
</div>
|
||||
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 pl-6 text-[11px] text-muted-foreground">
|
||||
<div className="mt-2 flex flex-wrap items-center gap-x-3 gap-y-1 pl-6 text-[0.6875rem] text-muted-foreground">
|
||||
<span>
|
||||
{new Date(
|
||||
run.createdAt * 1000,
|
||||
@@ -216,10 +216,10 @@ export function WorkflowDetailPanel({
|
||||
|
||||
{isSelected ? (
|
||||
<div className="border-t border-border/60 bg-background/60 px-4 py-4">
|
||||
<div className="mb-3 flex items-center gap-2 text-[11px] font-medium uppercase tracking-[0.18em] text-muted-foreground">
|
||||
<div className="mb-3 flex items-center gap-2 text-[0.6875rem] font-medium uppercase tracking-[0.18em] text-muted-foreground">
|
||||
<span>Execution Trace</span>
|
||||
{approvalsQuery.isFetching ? (
|
||||
<span className="text-[10px] tracking-[0.12em] text-muted-foreground/80">
|
||||
<span className="text-[0.625rem] tracking-[0.12em] text-muted-foreground/80">
|
||||
Refreshing approvals...
|
||||
</span>
|
||||
) : null}
|
||||
|
||||
@@ -94,7 +94,7 @@ export function WorkflowRunTrace({
|
||||
</div>
|
||||
{Object.keys(step.output).length > 0 ? (
|
||||
<div className="mt-3">
|
||||
<p className="mb-1 text-[11px] font-medium uppercase tracking-[0.16em] text-muted-foreground">
|
||||
<p className="mb-1 text-[0.6875rem] font-medium uppercase tracking-[0.16em] text-muted-foreground">
|
||||
Output
|
||||
</p>
|
||||
<pre className="max-h-32 overflow-auto rounded-lg bg-muted/40 px-3 py-2 font-mono text-xs text-muted-foreground">
|
||||
@@ -104,7 +104,7 @@ export function WorkflowRunTrace({
|
||||
) : null}
|
||||
{step.error ? (
|
||||
<div className="mt-3">
|
||||
<p className="mb-1 text-[11px] font-medium uppercase tracking-[0.16em] text-red-400">
|
||||
<p className="mb-1 text-[0.6875rem] font-medium uppercase tracking-[0.16em] text-red-400">
|
||||
Error
|
||||
</p>
|
||||
<pre className="max-h-32 overflow-auto rounded-lg bg-red-500/10 px-3 py-2 font-mono text-xs text-red-400">
|
||||
@@ -114,7 +114,7 @@ export function WorkflowRunTrace({
|
||||
) : null}
|
||||
{pendingApproval ? (
|
||||
<div className="mt-3">
|
||||
<p className="mb-2 text-[11px] font-medium uppercase tracking-[0.16em] text-amber-600">
|
||||
<p className="mb-2 text-[0.6875rem] font-medium uppercase tracking-[0.16em] text-amber-600">
|
||||
Pending approval
|
||||
</p>
|
||||
<WorkflowApprovalCard approval={pendingApproval} />
|
||||
|
||||
@@ -132,7 +132,7 @@ export function WorkspaceSwitcher({
|
||||
<span
|
||||
className={
|
||||
isProfileVariant
|
||||
? "flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-sidebar-border/70 bg-sidebar-accent/40 text-[10px] leading-none"
|
||||
? "flex h-5 w-5 shrink-0 items-center justify-center rounded-md border border-sidebar-border/70 bg-sidebar-accent/40 text-[0.625rem] leading-none"
|
||||
: "flex h-5 w-5 shrink-0 items-center justify-center text-xs leading-none"
|
||||
}
|
||||
>
|
||||
|
||||
@@ -6,8 +6,8 @@ import { Avatar, AvatarFallback, AvatarImage } from "@/shared/ui/avatar";
|
||||
type UserAvatarSize = "xs" | "sm" | "md";
|
||||
|
||||
const sizeClasses: Record<UserAvatarSize, string> = {
|
||||
xs: "h-5 w-5 text-[8px]",
|
||||
sm: "h-6 w-6 text-[9px]",
|
||||
xs: "h-5 w-5 text-[0.5rem]",
|
||||
sm: "h-6 w-6 text-[0.5625rem]",
|
||||
md: "h-10 w-10 text-xs",
|
||||
};
|
||||
|
||||
|
||||
@@ -531,7 +531,7 @@ function VideoScrubber({
|
||||
style={{ left: `${hoverRatio * 100}%` }}
|
||||
>
|
||||
<div className="h-5 w-0.5 rounded-full bg-white shadow-[0_0_0_0.5px_rgba(0,0,0,0.25)]" />
|
||||
<span className="absolute -top-6 left-1/2 -translate-x-1/2 whitespace-nowrap text-[11px] font-medium tabular-nums text-white/90">
|
||||
<span className="absolute -top-6 left-1/2 -translate-x-1/2 whitespace-nowrap text-[0.6875rem] font-medium tabular-nums text-white/90">
|
||||
{formatTimecode(hoverRatio * duration)} / {formatTimecode(duration)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -918,7 +918,7 @@ export function VideoPlayer({
|
||||
)}
|
||||
</button>
|
||||
<span
|
||||
className="shrink-0 text-[10px] font-medium tabular-nums leading-none text-white"
|
||||
className="shrink-0 text-[0.625rem] font-medium tabular-nums leading-none text-white"
|
||||
data-testid="video-inline-time"
|
||||
>
|
||||
{formatTimecode(currentTime)}
|
||||
@@ -932,7 +932,7 @@ export function VideoPlayer({
|
||||
testIdPrefix="video-inline"
|
||||
/>
|
||||
<span
|
||||
className="shrink-0 text-[10px] font-medium tabular-nums leading-none text-white/70"
|
||||
className="shrink-0 text-[0.625rem] font-medium tabular-nums leading-none text-white/70"
|
||||
data-testid="video-inline-duration"
|
||||
>
|
||||
{formatTimecode(duration)}
|
||||
@@ -1716,12 +1716,12 @@ function VideoReviewDialog({
|
||||
{formatTimecode(currentTime)}
|
||||
</span>
|
||||
{replyTarget ? (
|
||||
<span className="text-[11px] text-muted-foreground">
|
||||
<span className="text-[0.6875rem] text-muted-foreground">
|
||||
Replying to {replyTarget.comment.author}
|
||||
</span>
|
||||
) : (
|
||||
<label
|
||||
className="flex cursor-pointer select-none items-center gap-1.5 text-[11px] text-muted-foreground"
|
||||
className="flex cursor-pointer select-none items-center gap-1.5 text-[0.6875rem] text-muted-foreground"
|
||||
htmlFor="video-review-frame-toggle"
|
||||
>
|
||||
<Checkbox
|
||||
@@ -1874,7 +1874,7 @@ function VideoReviewCommentBody({
|
||||
item.seconds !== null && item.timecode ? (
|
||||
<button
|
||||
aria-label={`Jump to ${item.timecode}`}
|
||||
className="inline-flex h-5 shrink-0 items-center rounded bg-amber-400/15 px-1.5 align-middle font-mono text-[11px] font-semibold text-amber-300 outline-hidden transition-colors hover:bg-amber-400/30 focus-visible:ring-2 focus-visible:ring-white/60"
|
||||
className="inline-flex h-5 shrink-0 items-center rounded bg-amber-400/15 px-1.5 align-middle font-mono text-[0.6875rem] font-semibold text-amber-300 outline-hidden transition-colors hover:bg-amber-400/30 focus-visible:ring-2 focus-visible:ring-white/60"
|
||||
data-testid="video-review-comment-timecode"
|
||||
type="button"
|
||||
onClick={() => onSeek(item.seconds ?? 0)}
|
||||
@@ -1892,7 +1892,7 @@ function VideoReviewCommentBody({
|
||||
displayName={item.comment.author}
|
||||
size="xs"
|
||||
/>
|
||||
<p className="truncate text-[13px] font-semibold text-foreground">
|
||||
<p className="truncate text-[0.8125rem] font-semibold text-foreground">
|
||||
{item.comment.author}
|
||||
</p>
|
||||
<p className="shrink-0 text-xs text-muted-foreground">
|
||||
|
||||
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
|
||||
const badgeVariants = cva(
|
||||
"inline-flex items-center rounded-full px-2 pb-[3px] pt-[5px] text-[10px] font-semibold uppercase leading-none tracking-[0.18em]",
|
||||
"inline-flex items-center rounded-full px-2 pb-[3px] pt-[5px] text-[0.625rem] font-semibold uppercase leading-none tracking-[0.18em]",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
|
||||
Reference in New Issue
Block a user