feat(branding): optional per-app banner replacing logo + name in header
A brand may ship a wide banner (logo + wordmark in one image) that
replaces the brand-kit logo + app-name pair in a standalone's header.
Events is the first consumer.
Banners are optional and resolve at build time, mirroring the existing
@brand-app-logo chain:
- resolveAppBanner(app?) checks per-standalone override first
(branding/<dep>/icons/<app>/banner.{svg,png}) then the brand's primary
banner (branding/<dep>/banner.{svg,png}); returns null when absent
instead of throwing, so brands without a banner keep logo + name.
- brandAppBannerAliasEntry() always registers the @brand-app-banner
alias (falling back to the logo) so the static import resolves; whether
it renders is gated by the VITE_APP_BANNER build flag.
- EventsPage renders the banner when the flag is set, else logo + name.
Deployers override per-standalone without touching the component. SVG
banners must have their text outlined to paths (browsers lack designer
fonts) — documented in branding/README.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
138f9905bf
commit
8f2c401e00
5 changed files with 119 additions and 7 deletions
|
|
@ -67,6 +67,37 @@ Resolution at build time:
|
|||
|
||||
`<app>` is set via `BRAND_APP` env var (the standalone build script sets this; deployers don't touch it directly).
|
||||
|
||||
## Optional banner (logo + wordmark lockup)
|
||||
|
||||
A brand may ship a **banner** — a single wide image combining the logo and the wordmark — that replaces the logo + app-name pair in a standalone's header (currently the events page header). Banners are optional: brands without one keep the default logo + name rendering.
|
||||
|
||||
```
|
||||
branding/<dep>/
|
||||
banner.svg # preferred — crisp at any size, recolorable
|
||||
banner.png # fallback (wide, transparent background)
|
||||
icons/
|
||||
events/banner.svg # optional per-standalone override
|
||||
```
|
||||
|
||||
Resolution mirrors the logo chain (`resolveAppBanner` in `vite-branding.ts`):
|
||||
|
||||
1. `branding/<dep>/icons/<app>/banner.svg`
|
||||
2. `branding/<dep>/icons/<app>/banner.png`
|
||||
3. `branding/<dep>/banner.svg`
|
||||
4. `branding/<dep>/banner.png`
|
||||
5. No banner → header falls back to logo + name (no error).
|
||||
|
||||
SVG is strongly preferred — a banner is wide and rasterizes poorly when scaled. Components reference it via the build-time `@brand-app-banner` alias; whether it renders is driven by the `VITE_APP_BANNER` flag, so the component stays brand-agnostic.
|
||||
|
||||
> **⚠️ Outline text to paths in any SVG you ship.** The browser only has
|
||||
> web-safe fonts — if a banner/logo SVG keeps live `<text>` elements that
|
||||
> reference a designer font (e.g. a decorative display face), the browser
|
||||
> substitutes a default font and the glyphs render wrong (we hit this with
|
||||
> a mangled `!` in the "Oyez!" banner). In Inkscape: **Edit → Select All in
|
||||
> All Layers (Ctrl+Alt+A)** — plain Select All only covers the current
|
||||
> layer — then **Path → Object to Path (Shift+Ctrl+C)**, and save. Verify
|
||||
> with `grep -c '<text' banner.svg` → should be `0`.
|
||||
|
||||
## How to use
|
||||
|
||||
**Building with the default brand:**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue