Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions app/frontend/src/components/sidebar/icons.ts

This file was deleted.

43 changes: 43 additions & 0 deletions app/frontend/src/components/sidebar/icons.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/** Shared sidebar icons. */

/** Icon column treatment shared by the sidebar info panels (Pane, Host):
* brighter token, bold weight, +2px size. leading-none keeps the taller
* glyph inside the row's 16px line box (no row-height change). */
export const ICON_CLASS = "text-accent-bright font-bold text-[14px] leading-none";

/** Small palette icon for color-picker triggers — an artist's palette
* silhouette with four paint blobs. Line-art to match the sidebar's other
* line icons (e.g. the window-row pin); replaces the former U+25A0 glyph,
* which read as a media "stop" button rather than a color control. Blobs are
* pure fills (stroke="none") so they read as dots, not stroked rings.
*
* Shared by the window-row, session-row, and server-panel color triggers so
* the affordance is identical everywhere. `size` defaults to 13px (sidebar
* rows); the compact server tile passes a smaller size.
*
* strokeWidth is 2 (not the lucide-default 1.7) so the *effective* stroke
* weight matches the window-row pin: 2 ÷ 24-viewBox × 13px ≈ 1.08px vs the
* pin's 1.5 ÷ 16 × 12 ≈ 1.125px. A thinner stroke reads as a lighter color
* even with the same `currentColor` token, so weight parity is what makes the
* icons look like the same color in a cluster. */
export function PaletteIcon({ size = 13 }: { size?: number }) {
return (
<svg
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<circle cx="13.5" cy="6.5" r="1.4" fill="currentColor" stroke="none" />
<circle cx="17.5" cy="10.5" r="1.4" fill="currentColor" stroke="none" />
<circle cx="8.5" cy="7.5" r="1.4" fill="currentColor" stroke="none" />
<circle cx="6.5" cy="12.5" r="1.4" fill="currentColor" stroke="none" />
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.93 0 1.65-.75 1.65-1.69 0-.44-.18-.83-.44-1.12-.29-.29-.44-.65-.44-1.13a1.64 1.64 0 0 1 1.67-1.67h2c3.05 0 5.56-2.5 5.56-5.55C21.96 6.01 17.46 2 12 2z" />
</svg>
);
}
5 changes: 3 additions & 2 deletions app/frontend/src/components/sidebar/server-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createPortal } from "react-dom";
import { CollapsiblePanel } from "./collapsible-panel";
import { LogoSpinner } from "@/components/logo-spinner";
import { SwatchPopover } from "@/components/swatch-popover";
import { PaletteIcon } from "./icons";
import { UNCOLORED_SELECTED_KEY, type RowTint } from "@/themes";
import type { ServerInfo } from "@/api/client";

Expand Down Expand Up @@ -291,9 +292,9 @@ function ServerTile({
type="button"
aria-label={`Set color for server ${name}`}
onClick={onColorClick}
className="text-text-secondary hover:text-text-primary text-[11px] leading-none px-0.5 py-0.5"
className="text-text-secondary hover:text-text-primary leading-none px-0.5 py-0.5 flex items-center justify-center"
>
&#x25A0;
<PaletteIcon size={12} />
</button>
)}
{onKill && (
Expand Down
5 changes: 3 additions & 2 deletions app/frontend/src/components/sidebar/session-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { ProjectSession } from "@/types";
import type { MergedSession } from "@/contexts/optimistic-context";
import type { RowTint } from "@/themes";
import { SwatchPopover } from "@/components/swatch-popover";
import { PaletteIcon } from "./icons";

type SessionRowProps = {
/** Tmux server this session belongs to — bound into the identity-arg
Expand Down Expand Up @@ -194,9 +195,9 @@ function SessionRowInner({
setShowColorPicker((v) => !v);
}}
aria-label={`Set color for ${session.name}`}
className="text-text-secondary hover:text-text-primary transition-opacity opacity-0 group-hover:opacity-100 coarse:opacity-100 text-[12px] px-0.5 min-h-[36px] flex items-center justify-center"
className="text-text-secondary hover:text-text-primary transition-opacity opacity-0 group-hover:opacity-100 coarse:opacity-100 px-0.5 min-h-[36px] flex items-center justify-center"
>
&#x25A0;
<PaletteIcon />
</button>
)}
<button
Expand Down
35 changes: 1 addition & 34 deletions app/frontend/src/components/sidebar/window-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { UNCOLORED_SELECTED_KEY, type RowTint } from "@/themes";
import { SwatchPopover } from "@/components/swatch-popover";
import { StatusDot } from "@/components/status-dot";
import { PinPopover } from "./pin-popover";
import { PaletteIcon } from "./icons";

type ProjectWindow = ProjectSession["windows"][number];
type GhostWindow = MergedSession["windows"][number];
Expand Down Expand Up @@ -448,37 +449,3 @@ function PinIcon({ filled }: { filled: boolean }) {
</svg>
);
}

/** Small palette icon for the color-picker trigger — an artist's palette
* silhouette with four paint blobs. Line-art to match PinIcon's stroke style;
* rendered at 13px so the blobs stay legible at sidebar scale. Replaces the
* former U+25A0 glyph, which read as a media "stop" button rather than a color
* control. Blobs are pure fills (stroke="none") so they read as dots, not
* stroked rings.
*
* strokeWidth is 2 (not the lucide-default 1.7) so the *effective* stroke
* weight matches PinIcon: 2 ÷ 24-viewBox × 13px ≈ 1.08px, vs the pin's
* 1.5 ÷ 16 × 12 ≈ 1.125px. A thinner stroke reads as a lighter color even
* though both inherit the same `currentColor` token, so weight parity is what
* makes the two icons look like the same color in the cluster. */
function PaletteIcon() {
return (
<svg
width={13}
height={13}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
>
<circle cx="13.5" cy="6.5" r="1.4" fill="currentColor" stroke="none" />
<circle cx="17.5" cy="10.5" r="1.4" fill="currentColor" stroke="none" />
<circle cx="8.5" cy="7.5" r="1.4" fill="currentColor" stroke="none" />
<circle cx="6.5" cy="12.5" r="1.4" fill="currentColor" stroke="none" />
<path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.93 0 1.65-.75 1.65-1.69 0-.44-.18-.83-.44-1.12-.29-.29-.44-.65-.44-1.13a1.64 1.64 0 0 1 1.67-1.67h2c3.05 0 5.56-2.5 5.56-5.55C21.96 6.01 17.46 2 12 2z" />
</svg>
);
}
Loading