mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-19 02:06:38 +00:00
## Summary Adds a **sitewide announcement banner** to the website, rendered above the navbar on every page. It has a two-layer visibility model: - **Build-time gate** — a pure, unit-tested `evaluateBannerVisibility()` decides whether the banner mounts at all (active flag + optional date window + locale/section targeting), driven by a typed config (`src/config/banner.ts`). No CMS; copy resolves through i18n. - **Client-side dismissal** — persisted in `localStorage`, keyed by a **content hash** so editing the copy re-shows the banner (per-locale, so an en edit doesn't re-show it for zh-CN). Current content points the CTA at **Comfy MCP** (`/mcp`). ## Highlights - **Full-width branded bar** above a now-`sticky` navbar; reuses the design system (`Button`, gradient tokens, new reusable `IconButton`). - **Flash-free** on load: an inline pre-hydration script hides an already-dismissed banner before paint (no pop-in, no layout shift); `close()` sets the same signal after the leave animation to stay flash-free across ClientRouter navigations. - **Open/close transition**: grid-rows height collapse + fade, respecting `prefers-reduced-motion`. - **i18n**: copy in `en` + `zh-CN`. ## Where to edit later - **Copy**: `apps/website/src/i18n/translations.ts` → `launches.banner.text` / `launches.banner.cta` - **Link / on-off / dates / targeting**: `apps/website/src/config/banner.ts` (`bannerConfig`) ## Notes - On a static site the `startsAt`/`endsAt` window is evaluated at **build time** (documented in `banner.ts`). - Changing the copy or link changes the content hash, so previously-dismissed visitors will see the banner again — by design. ## Test plan - `pnpm test:unit` — evaluator + version-hash unit tests pass. - `pnpm typecheck` + lint clean. - On the preview: banner shows on `/`, `/launches`, and a `zh-CN` page; CTA -> `/mcp`; dismiss animates and stays dismissed on reload (no flash); reduced-motion disables the animation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
86 lines
2.4 KiB
Vue
86 lines
2.4 KiB
Vue
<script setup lang="ts">
|
|
import type { Locale } from '../../../i18n/translations.ts'
|
|
import { t } from '../../../i18n/translations.ts'
|
|
import { externalLinks, getRoutes } from '../../../config/routes.ts'
|
|
import GitHubStarBadge from '../GitHubStarBadge.vue'
|
|
import HeaderMainDesktop from './HeaderMainDesktop.vue'
|
|
import HeaderMainMobile from './HeaderMainMobile.vue'
|
|
import Button from '@/components/ui/button/Button.vue'
|
|
|
|
const { locale = 'en', githubStars = '' } = defineProps<{
|
|
locale?: Locale
|
|
githubStars?: string
|
|
}>()
|
|
const routes = getRoutes(locale)
|
|
|
|
const ctaButtons = [
|
|
{
|
|
prefix: t('nav.ctaDesktopPrefix', locale),
|
|
core: t('nav.ctaDesktopCore', locale),
|
|
ariaLabel: t('nav.downloadLocal', locale),
|
|
href: routes.download,
|
|
primary: false
|
|
},
|
|
{
|
|
prefix: t('nav.ctaCloudPrefix', locale),
|
|
core: t('nav.ctaCloudCore', locale),
|
|
ariaLabel: t('nav.launchCloud', locale),
|
|
href: externalLinks.cloud,
|
|
primary: true
|
|
}
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<nav
|
|
class="sticky top-0 z-50 flex items-center justify-between gap-4 bg-primary-comfy-ink px-6 py-5 lg:gap-4 lg:px-[clamp(0.25rem,4vw,5rem)] lg:py-8"
|
|
aria-label="Main navigation"
|
|
>
|
|
<a
|
|
:href="routes.home"
|
|
class="inline-grid h-10 shrink-0 grid-cols-1 grid-rows-1 transition-[width]"
|
|
aria-label="Comfy home"
|
|
>
|
|
<img
|
|
src="/icons/logomark.svg"
|
|
alt="Comfy"
|
|
class="col-span-full row-span-full h-8"
|
|
/>
|
|
<div
|
|
class="relative col-span-full row-span-full h-10 w-0 overflow-clip transition-[width] xl:w-36"
|
|
>
|
|
<img
|
|
src="/icons/logo.svg"
|
|
alt="Comfy"
|
|
class="absolute top-0 left-0 h-10 w-36 max-w-none object-contain object-left"
|
|
/>
|
|
</div>
|
|
</a>
|
|
|
|
<!-- Desktop nav links -->
|
|
<HeaderMainDesktop :locale class="hidden lg:block" />
|
|
<HeaderMainMobile :locale class="lg:hidden" />
|
|
|
|
<!-- Desktop CTA buttons -->
|
|
<div
|
|
data-testid="desktop-nav-cta"
|
|
class="hidden shrink-0 items-center gap-2 lg:flex"
|
|
>
|
|
<GitHubStarBadge v-if="githubStars" :stars="githubStars" />
|
|
<Button
|
|
v-for="cta in ctaButtons"
|
|
:key="cta.href"
|
|
as="a"
|
|
:href="cta.href"
|
|
:variant="cta.primary ? 'default' : 'outline'"
|
|
:aria-label="cta.ariaLabel"
|
|
>
|
|
<span
|
|
><span class="hidden xl:inline-block">{{ cta.prefix }} </span
|
|
>{{ cta.core }}</span
|
|
>
|
|
</Button>
|
|
</div>
|
|
</nav>
|
|
</template>
|