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:
npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w
2026-06-14 23:19:57 -07:00
co-authored by Taylor Ho
parent 9ee5aeebd9
commit 2951bf5351
65 changed files with 139 additions and 133 deletions
@@ -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>
)}
+5 -5
View File
@@ -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>
+1 -1
View File
@@ -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">
&#x2318;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"
}
>
+2 -2
View File
@@ -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",
};
+7 -7
View File
@@ -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">
+1 -1
View File
@@ -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: {