Skip to content

Commit e31e096

Browse files
Quickbeardclaude
andcommitted
feat(ui): draw the codev C in Splash and Mark
The icon/wordmark rebrand only reached `Logo`, so upstream's square "o" still shipped in the last two glyphs that render it: the desktop boot splash, the app loading overlay, the connection-error screen, the two session side-panel watermarks and the v1 new-session view. Both glyphs now draw the codev C — the block art `█▀▀▀ / █ / ▀▀▀▀` on a 4x5 grid with a one-unit stroke, the same geometry the app icon and the `codev --mini` badge use — as one full-bleed path each. Upstream's second path, which shaded the lower half of the "o"'s enclosed counter, is dropped: the C is open on the right so there is no counter to shade, and the TUI badge is a flat outline for the same reason. The two split on color. `Splash` is brand-locked through a new `--logo-splash: #ee0033`, declared once with no dark-mode swap — red clears 4:1 against both the light and dark `background-base`, unlike the wordmark's navy half. `Mark` keeps `var(--icon-strong-base)` because two of its three call sites are `opacity-10` watermarks, where brand red reads as a pink wash rather than a neutral texture. The static `opacity-50` on the two splash call sites is left as is: this fork's `animate-pulse` is `pulse-opacity` (0.4 -> 1 -> 0.4), which overrides the declared opacity for the whole animation, so removing it would be a no-op in two upstream files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 477aee1 commit e31e096

3 files changed

Lines changed: 27 additions & 5 deletions

File tree

‎DIVERGENCES.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ from the squash message first, or use a plain merge.
9292
| `packages/opencode/script/postinstall.mjs` | `base` prefix `opencode-` → `codev-code-`; source/target binary names `opencode`/`opencode.exe` → `codev`/`codev.exe` (matches build.ts's `bin/codev` and publish.ts's `bin/codev.exe` stub); temp-dir prefix and failure message rebranded | Install-time platform-binary fetch must match the published package and binary names. | Keep our prefix and binary names. |
9393
| `packages/tui/src/logo.ts` | Pixel glyphs "open"+"code" → "co"+"dev"; added a `brand` export (`navy` `#19224c` / `red` `#ee0033`, the landing page's `--color-brand-navy`/`--color-brand-red`), a `wordmarkHalves` export (each row's "co" and "dev" halves with the shadow marks substituted to glyphs, so each half can take its own brand color), the composed `wordmark` (plain lines, built from `wordmarkHalves`) and `ansiWordmark` (bold, no shadow: "co" in the terminal's default foreground, "dev" in brand red truecolor) exports for CLI banners; added a `badge` export (the "c" of the wordmark — `logo.left` rows 1-3 sliced to the first glyph, with the `_` shadow-fill marks stripped to spaces so it renders as a flat outline) for the `--mini` splashes | Branded wordmark art; `ansiWordmark` feeds the CLI help banner and session epilogue. | Keep our glyphs + exports; take upstream's surrounding changes. |
9494
| `packages/tui/src/component/logo.tsx` | Renders the lowercase codev wordmark from `wordmarkHalves` — one bold `<text>` per half, no per-char shadow cells — with "co" in `brand.navy` on light / `theme.text` on dark and "dev" in `brand.red`, instead of upstream's two-tone "open"+"code" | Banner is pixel-identical to the landing page wordmark (`codev-landing-page` `app/components/PixelWordmark.tsx`: `text-brand-navy dark:text-foreground` + `text-brand-red`), so the marketing site and the TUI read as one brand. Deliberately fixed brand colors rather than the theme's `secondary`, and no drop shadow — the landing wordmark has neither. | Keep our version wholesale. If upstream restructures the component, re-apply the two-half brand coloring rather than reverting to a theme color. |
95-
| `packages/ui/src/components/logo.tsx`, `packages/ui/src/components/logo.css` | `Logo` renders the lowercase "codev" wordmark instead of upstream's "opencode": the `wordmarkHalves` pixel glyphs of `packages/tui/src/logo.ts` resolved to a 24x6 grid at one unit per pixel (viewBox `0 0 24 6`, was `0 0 234 42`), as two `<path>`s — `data-slot="logo-wordmark-co"` and `…-dev` — with no drop-shadow paths. Colors come from two custom properties defined in logo.css on `[data-component="logo-wordmark"]`: `--logo-wordmark-dev` is always brand red `#ee0033`, `--logo-wordmark-co` is brand navy `#19224c` on light and `var(--icon-strong-base)` on dark. The dark swap is declared three times — under `prefers-color-scheme: dark` for surfaces that never stamp a theme, then under both `[data-color-scheme="light"]` and `[data-color-scheme="dark"]` so the app's explicit choice (`packages/ui/src/theme/context.tsx` sets it on `<html>`) beats the OS preference in both directions. Brand hexes are literals, not theme tokens — same reasoning as the TUI component row. `Mark` and `Splash` (the square "o") are untouched. | The web/desktop banner is the same art the TUI home banner and the landing page wordmark draw, so every surface reads as one brand. | Keep our version wholesale. If upstream restructures the component, re-apply the two-half brand coloring rather than reverting to `--icon-*` tokens. |
95+
| `packages/ui/src/components/logo.tsx`, `packages/ui/src/components/logo.css` | `Logo` renders the lowercase "codev" wordmark instead of upstream's "opencode": the `wordmarkHalves` pixel glyphs of `packages/tui/src/logo.ts` resolved to a 24x6 grid at one unit per pixel (viewBox `0 0 24 6`, was `0 0 234 42`), as two `<path>`s — `data-slot="logo-wordmark-co"` and `…-dev` — with no drop-shadow paths. Colors come from two custom properties defined in logo.css on `[data-component="logo-wordmark"]`: `--logo-wordmark-dev` is always brand red `#ee0033`, `--logo-wordmark-co` is brand navy `#19224c` on light and `var(--icon-strong-base)` on dark. The dark swap is declared three times — under `prefers-color-scheme: dark` for surfaces that never stamp a theme, then under both `[data-color-scheme="light"]` and `[data-color-scheme="dark"]` so the app's explicit choice (`packages/ui/src/theme/context.tsx` sets it on `<html>`) beats the OS preference in both directions. Brand hexes are literals, not theme tokens — same reasoning as the TUI component row. `Mark` and `Splash` likewise drop upstream's square "o" for the codev "C": the block art `█▀▀▀ / █ / ▀▀▀▀` on a 4x5 grid with a one-unit stroke — the same geometry `packages/desktop/icons/icon.svg` and the `codev --mini` badge (`badge` in `packages/tui/src/logo.ts`) draw — as one full-bleed `<path>` each, `data-slot="logo-mark-c"` at viewBox `0 0 16 20` and `logo-splash-c` at `0 0 80 100`. Upstream's second path on each glyph, which shaded the lower half of the "o"'s enclosed counter in `--icon-weak-base` / `--icon-base`, is dropped: the C is open on the right so there is no counter to shade, and the TUI badge is a flat outline for the same reason. The two split on color. `Splash` is brand-locked through `--logo-splash: #ee0033`, declared once on `[data-component="logo-splash"]` with no dark-mode swap — red clears 4:1 against both the light and dark `background-base`, unlike the wordmark's navy half. `Mark` keeps `var(--icon-strong-base)` because two of its three call sites are `opacity-10` watermarks in the session side panel, where brand red reads as a pink wash instead of a neutral texture. | The web/desktop banner is the same art the TUI home banner and the landing page wordmark draw, so every surface reads as one brand. Same for the marks: the desktop boot splash, the app icon, the landing page icon and the `--mini` badge are one glyph in one red, so the splash should not be the only surface still drawing upstream's "o" in theme grey. | Keep our version wholesale. If upstream restructures the component, re-apply the two-half brand coloring rather than reverting to `--icon-*` tokens, and re-apply the C rather than taking back the "o". Keep `Splash` brand-locked and `Mark` tokenized — do not "unify" them, the split is load-bearing for the `opacity-10` watermarks. |
9696
| `packages/ui/src/v2/components/wordmark-v2.tsx` (+ fork-only `wordmark-v2.css`) | `WordmarkV2` — the watermark behind the v2 new-session composer (`packages/app/src/components/session/session-new-design-view.tsx`) — draws the codev wordmark from the same 24x6 pixel grid as `Logo` instead of upstream's 720x129 "opencode", as two `<path>`s (`data-slot="wordmark-v2-co"` / `…-dev`). Upstream's watermark treatment is kept verbatim: the `0.6` outer opacity and the alpha mask whose gradient fades the mark out over its bottom half (converted to the new viewBox: gradient `y1` 68/129 → 3.163/6). "co" keeps `fill="currentColor"` so it still follows the caller's `text-*` class; "dev" takes brand red `#ee0033`. Per-half opacities live in the new `wordmark-v2.css`, following the one-CSS-file-per-v2-component convention: `co` is `0.112` (upstream's own `0.16 × 0.7` nesting, flattened), `dev` is boosted to `0.224` on light and `0.336` on dark via `--wordmark-v2-dev-opacity`, declared under `prefers-color-scheme` and both `[data-color-scheme]` values like components/logo.css. The boost is deliberate and measured: at upstream's weight a saturated red composites to within a few levels of the grey "co" half against the dark background and the two-tone disappears entirely, while the same value already reads pink against the light one. | The component is currently **not rendered** — the new-session view drops it (see the row below) — but it stays rebranded and exported so reinstating the watermark does not bring the upstream mark back with it. | Keep our version wholesale, including the per-theme `dev` opacity. If upstream retunes the watermark opacities, re-derive the `dev` boost from the new base rather than adopting a single flat value. |
9797
| `packages/app/src/components/session/session-new-design-view.tsx`, `packages/app/src/pages/new-session.tsx` | Drops the `WordmarkV2` watermark from the v2 new-session screen and centres the composer. Upstream absolutely positions the content block at `top-[25.375%]` to leave room for the wordmark above it; with the mark gone that offset just parks the composer high in an empty pane, so the outer element becomes `flex items-center justify-center` over `size-full` (carrying the `px-6` inset across) and the `mt-8` spacer under the wordmark goes away. The pane also takes the same raised card every session sits on: `bg-v2-background-bg-deep` → `bg-v2-background-bg-base` in the view, and `new-session.tsx`'s `rounded-[10px]` wrapper gains `bg-v2-background-bg-base shadow-[var(--v2-elevation-raised)]` — the exact pair `SessionPanelFrame` (`pages/session.tsx`) applies with `newLayout raised`. Verified equal at runtime: same background, same eight-layer shadow, same 10px radius. | The wordmark reads as clutter on the desktop new-session screen; without it the pane should be balanced, not top-weighted. And with the sidebar always on screen, upstream's `bg-deep` made the draft screen read as an extension of the window chrome while every session floated on a card — the two screens have to match. | Keep our centred layout and the card. If upstream restyles this view, re-apply the drop + centring rather than restoring `top-[25.375%]`, and re-check the background against whatever `SessionPanelFrame` then uses rather than hardcoding `bg-base`. Reinstating the watermark means restoring the offset too, or it will sit centred with the composer. |
9898
| `packages/app/src/pages/home.tsx`, `packages/app/src/pages/error.tsx`, `packages/enterprise/src/routes/share/[shareID].tsx` | `Logo` width utilities retuned for the codev wordmark's 4:1 box (upstream's is 5.57:1): home `md:w-xl` → `md:w-104`, error `w-58.5` → `w-42`, share (both call sites) `w-58.5` → `w-42` | Each value is the width at which the new wordmark renders at exactly the height the upstream one did, so no surrounding layout shifts. | Keep our widths; take upstream's surrounding changes. Recompute rather than restore if upstream changes the size. |

‎packages/ui/src/components/logo.css‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
aspect-ratio: 4/5;
44
}
55

6+
/* Fork: the splash "C" is brand-locked, matching the `codev --mini` badge
7+
(BRAND_MARK in packages/opencode/src/cli/cmd/run/theme.ts), the landing page
8+
icon and the desktop app icon — the same glyph in the same red on every
9+
surface. Unlike the wordmark's navy half this needs no dark-mode swap: red
10+
clears 4:1 against both the light and dark background-base, so one
11+
unconditional declaration covers every theme. `Mark` deliberately stays on
12+
--icon-strong-base; see the note on the component. */
13+
[data-component="logo-splash"] {
14+
--logo-splash: #ee0033;
15+
}
16+
617
/* Fork: the codev wordmark's two halves. Literal hex rather than theme tokens —
718
these are the landing page's brand colors (codev-landing-page app/globals.css
819
--color-brand-navy / --color-brand-red, mirrored in packages/tui/src/logo.ts

‎packages/ui/src/components/logo.tsx‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
import { type ComponentProps } from "solid-js"
22

3+
// Fork: the codev "C" instead of upstream's square "o" — the block art
4+
// `█▀▀▀ / █ / ▀▀▀▀` on a 4x5 grid with a one-unit stroke, the same geometry the
5+
// app icon (packages/desktop/icons/icon.svg) and the `codev --mini` badge draw.
6+
// The C has no enclosed counter, so upstream's second path — which shaded the
7+
// lower half of the "o"'s hole — has nowhere to live and is dropped, matching
8+
// the TUI badge's flat outline (packages/tui/src/logo.ts `badge`).
9+
//
10+
// Stays on --icon-strong-base rather than the brand red `Splash` uses: two of
11+
// this component's three call sites are opacity-10 watermarks in the session
12+
// side panel, where brand red renders as a pink wash instead of a neutral
13+
// texture.
314
export const Mark = (props: { class?: string }) => {
415
return (
516
<svg
@@ -9,12 +20,13 @@ export const Mark = (props: { class?: string }) => {
920
fill="none"
1021
xmlns="http://www.w3.org/2000/svg"
1122
>
12-
<path data-slot="logo-logo-mark-shadow" d="M12 16H4V8H12V16Z" fill="var(--icon-weak-base)" />
13-
<path data-slot="logo-logo-mark-o" d="M12 4H4V16H12V4ZM16 20H0V0H16V20Z" fill="var(--icon-strong-base)" />
23+
<path data-slot="logo-mark-c" d="M0 0H16V4H4V16H16V20H0Z" fill="var(--icon-strong-base)" />
1424
</svg>
1525
)
1626
}
1727

28+
// Fork: the same codev "C" as `Mark`, at 80x100 (unit 20), brand-locked rather
29+
// than tokenized — see --logo-splash in logo.css.
1830
export const Splash = (props: Pick<ComponentProps<"svg">, "ref" | "class">) => {
1931
return (
2032
<svg
@@ -25,8 +37,7 @@ export const Splash = (props: Pick<ComponentProps<"svg">, "ref" | "class">) => {
2537
fill="none"
2638
xmlns="http://www.w3.org/2000/svg"
2739
>
28-
<path d="M60 80H20V40H60V80Z" fill="var(--icon-base)" />
29-
<path d="M60 20H20V80H60V20ZM80 100H0V0H80V100Z" fill="var(--icon-strong-base)" />
40+
<path data-slot="logo-splash-c" d="M0 0H80V20H20V80H80V100H0Z" fill="var(--logo-splash)" />
3041
</svg>
3142
)
3243
}

0 commit comments

Comments
 (0)