diff --git a/.fork/customizations.yaml b/.fork/customizations.yaml index 8b850468e963..f6a1956534bd 100644 --- a/.fork/customizations.yaml +++ b/.fork/customizations.yaml @@ -1083,7 +1083,7 @@ - apps/web/src/custom/SidebarV2ChromeRows.tsx - apps/web/src/custom/useScrollGutterWidth.ts - apps/web/src/custom/SidebarStageDitherArt.tsx - - apps/web/src/custom/assets/sidebar-brand-mark.png + - apps/web/src/custom/assets/sidebar-brand-mark.svg - apps/web/src/custom/assets/sidebar-stage-dither-dev.png shadows: [] watch: diff --git a/apps/web/src/__fork_guards__/forkSidebarChrome.test.ts b/apps/web/src/__fork_guards__/forkSidebarChrome.test.ts index bcf08fe6f7ab..7a81b85a0171 100644 --- a/apps/web/src/__fork_guards__/forkSidebarChrome.test.ts +++ b/apps/web/src/__fork_guards__/forkSidebarChrome.test.ts @@ -182,13 +182,35 @@ describe("fork guard: fork-sidebar-chrome", () => { expect(chrome).toMatch(/sidebar-brand[^"]*ml-auto/u); expect(chrome).not.toContain("ml-[var(--workspace-titlebar-content-left)]"); expect(chrome).toMatch(/sidebar-brand[^"]*text-sidebar-foreground/u); - expect(chrome).toContain("size-6 shrink-0 [image-rendering:pixelated]"); + expect(chrome).toContain("size-6 shrink-0"); expect(chrome).toContain("text-[0.875rem] leading-4 font-medium"); + // The pixelated hack lived on the component, not the asset — a substring + // check on the class list would not notice it coming back beside it. + expect(chrome).not.toContain("image-rendering"); + // The mark's art is a 23x23 pixel grid drawn at a 24px slot. A bitmap can + // only get there by resampling 23 cells onto 24 pixels, which blends every + // cell into its neighbours — the blur the vector mark replaced. Keep it + // vector, keep the viewBox on the 23-unit grid, and keep crispEdges so the + // cells stay hard-edged at every DPR instead of antialiasing back to mush. const mark = NodeFS.readFileSync( - NodeURL.fileURLToPath(new URL("../custom/assets/sidebar-brand-mark.png", import.meta.url)), + NodeURL.fileURLToPath(new URL("../custom/assets/sidebar-brand-mark.svg", import.meta.url)), + "utf8", ); - expect(mark.readUInt32BE(16)).toBe(24); - expect(mark.readUInt32BE(20)).toBe(24); + expect(mark).toContain('viewBox="0 0 23 23"'); + expect(mark).toContain('shape-rendering="crispEdges"'); + expect(mark).not.toMatch(/image-rendering| check pins the + // geometry to plain rect attributes — an svgo pass or Figma re-export that + // moves it into transforms or path data would otherwise hide fractional + // coordinates from this guard entirely. + const coords = [...mark.matchAll(/\s(?:x|y|width|height)="([^"]+)"/gu)]; + expect(coords.length).toBeGreaterThan(100); + for (const coord of coords) { + expect(coord[1]).toMatch(/^\d+$/u); + } + expect(mark).not.toMatch(/transform=| { diff --git a/apps/web/src/components/sidebar/SidebarChrome.tsx b/apps/web/src/components/sidebar/SidebarChrome.tsx index 0f01ec5e9fc3..39dd976f31cc 100644 --- a/apps/web/src/components/sidebar/SidebarChrome.tsx +++ b/apps/web/src/components/sidebar/SidebarChrome.tsx @@ -11,7 +11,7 @@ import { } from "../SidebarStageBackdrop"; import { Badge } from "../ui/badge"; /* fork:begin fork-sidebar-chrome — see .fork/customizations.yaml#fork-sidebar-chrome */ -import sidebarBrandMarkUrl from "~/custom/assets/sidebar-brand-mark.png"; +import sidebarBrandMarkUrl from "~/custom/assets/sidebar-brand-mark.svg"; /* fork:end fork-sidebar-chrome */ import { SidebarFooter, @@ -92,12 +92,14 @@ function SidebarBrand() { {/* fork:begin fork-app-identity — see .fork/customizations.yaml#fork-app-identity The borrowed T3 wordmark stays gone. The fork's own exported mark and APP_BASE_NAME form the exact 24px / 4px / 14px lockup from the design, - while the injected desktop name and bridge-less fallback still agree. */} - + while the injected desktop name and bridge-less fallback still agree. + The mark is vector: its art is a 23x23 pixel grid, which no bitmap can + resample into a 24px box without smearing every cell. crispEdges lives + in the asset, so cells stay hard-edged at every DPR. The 23-into-24 fit + still renders the center row and column of cells 2px at DPR 1 — one + heavy line, accepted over either blurring all of them or drawing the + art at 23px, which centers on a half-pixel. */} + {APP_BASE_NAME} {/* fork:end fork-app-identity */} diff --git a/apps/web/src/custom/assets/sidebar-brand-mark.png b/apps/web/src/custom/assets/sidebar-brand-mark.png deleted file mode 100644 index a131487d08e5..000000000000 Binary files a/apps/web/src/custom/assets/sidebar-brand-mark.png and /dev/null differ diff --git a/apps/web/src/custom/assets/sidebar-brand-mark.svg b/apps/web/src/custom/assets/sidebar-brand-mark.svg new file mode 100644 index 000000000000..a5fe465a51b5 --- /dev/null +++ b/apps/web/src/custom/assets/sidebar-brand-mark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + +