From c4da4847440c613fcb5dd9a208d75854bdeeb141 Mon Sep 17 00:00:00 2001 From: Vivek Date: Mon, 10 Aug 2026 22:21:12 +0530 Subject: [PATCH 1/9] feat(gallery): brand the gallery shell like the website gallery.webjs.dev and webjs.dev read as two different products. The favicon was reconciled recently, but everything below the tab strip still diverged: a cool-grey palette, Bricolage Grotesque off the Google Fonts CDN, no logo, no footer, and an in-flow header. Port the website's visual system to the gallery-only surfaces: the warm oklch palette, the self-hosted Inter Tight / Inter / JetBrains Mono stack, the ambient glow background, the fixed blurred header, the brand lockup, and a reduced footer. Both themes, and the logo swaps correctly with JavaScript off. The scaffold keeps shipping the neutral look. gallery/ is the single source of the feature gallery that webjs create copies into every generated app, and the neutral palette there is deliberate: an app-building agent reads the demos for idioms, and a vividly branded example outweighs a prose instruction to pick its own design. Only app/layout.ts, app/page.ts, components/theme-toggle.ts and public/ are gallery-only, so the change is confined to those and every demo, module and ui primitive is untouched. The shadcn token NAMES are kept and only their VALUES move, which is what makes that confinement possible: every payload demo is written against bg-card, text-muted-foreground and border-border, so they render branded with zero payload edits. shadcn's --accent stays neutral on purpose, since it is a hover surface rather than the brand accent despite sharing the website's name. Also fixes a live bug the port surfaced. The toggle wrote localStorage webjs_theme while the layout's bootstrap read theme, so a reader who picked a theme got a first paint in the other one. --- gallery/app/layout.ts | 177 ++++++++++++++---- gallery/app/page.ts | 2 +- gallery/components/theme-toggle.ts | 10 +- gallery/public/brand/webjs-lockup-on-dark.svg | 10 + .../public/brand/webjs-lockup-on-light.svg | 10 + gallery/public/fonts/inter-tight.woff2 | Bin 0 -> 44872 bytes gallery/public/fonts/inter.woff2 | Bin 0 -> 48256 bytes gallery/public/fonts/jetbrains-mono.woff2 | Bin 0 -> 40404 bytes gallery/public/input.css | 38 +++- 9 files changed, 196 insertions(+), 51 deletions(-) create mode 100644 gallery/public/brand/webjs-lockup-on-dark.svg create mode 100644 gallery/public/brand/webjs-lockup-on-light.svg create mode 100644 gallery/public/fonts/inter-tight.woff2 create mode 100644 gallery/public/fonts/inter.woff2 create mode 100644 gallery/public/fonts/jetbrains-mono.woff2 diff --git a/gallery/app/layout.ts b/gallery/app/layout.ts index d049da73f..d1a293659 100644 --- a/gallery/app/layout.ts +++ b/gallery/app/layout.ts @@ -57,67 +57,162 @@ export default function RootLayout({ children }: { children: unknown }) { })(); - - - + + + + -
- - - WebJs Gallery - - + + +
+
-
- ${children} -
+ +
+
+ ${children} +
+ + + +
`; diff --git a/gallery/app/page.ts b/gallery/app/page.ts index 0b3dbeef0..8c57cb74f 100644 --- a/gallery/app/page.ts +++ b/gallery/app/page.ts @@ -24,7 +24,7 @@ export default function Home() {
-

+

Explore the gallery

diff --git a/gallery/components/theme-toggle.ts b/gallery/components/theme-toggle.ts index e2b65195b..69a4693ce 100644 --- a/gallery/components/theme-toggle.ts +++ b/gallery/components/theme-toggle.ts @@ -3,7 +3,7 @@ import { WebComponent, html, signal } from '@webjsdev/core'; /** * ``: three-state theme switcher: system → light → dark → system. * - * State is mirrored to localStorage (`webjs_theme`) and reflected as + * State is mirrored to localStorage (`theme`) and reflected as * ``. The initial theme is set by the synchronous bootstrap * script in layout.js so there's no FOUC on page load. */ @@ -15,7 +15,7 @@ export class ThemeToggle extends WebComponent { connectedCallback() { super.connectedCallback(); let saved: string | null = null; - try { saved = localStorage.getItem('webjs_theme'); } catch {} + try { saved = localStorage.getItem('theme'); } catch {} this.theme.set(saved === 'light' || saved === 'dark' ? saved : 'system'); } @@ -26,8 +26,8 @@ export class ThemeToggle extends WebComponent { : t === 'light' ? 'dark' : 'system'; this.theme.set(next); try { - if (next === 'system') localStorage.removeItem('webjs_theme'); - else localStorage.setItem('webjs_theme', next); + if (next === 'system') localStorage.removeItem('theme'); + else localStorage.setItem('theme', next); } catch {} if (next === 'system') delete document.documentElement.dataset.theme; else document.documentElement.dataset.theme = next; @@ -45,7 +45,7 @@ export class ThemeToggle extends WebComponent { const icon = t === 'light' ? ICONS.sun : t === 'dark' ? ICONS.moon : ICONS.system; return html`