fix(ai): onboarding welcome uses each brand's own logo (no hardcoded Hanzo H / tagline)
Read brandConfig.logo inside OnboardingLayout (was a module-level useBrand()
frozen on the default brand, forcing visor.svg's Hanzo "H" onto Zoo/Lux).
Drop the broken right-column hero preview; tagline is now opt-in via
brandConfig.tagline (empty default — removes the old hardcoded "the way, the
truth, the life"). Welcome title uses {{appName}} so no brand name leaks.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -10,17 +10,21 @@ export type OnboardingLayoutProps = React.PropsWithChildren<
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>;
|
||||
|
||||
const logoSrc =
|
||||
useBrand().brand === 'zoo' ? './zoo-logo.svg' : './visor.svg';
|
||||
// TODO: zoo-onboarding.png is currently the rounded app icon as a stand-in.
|
||||
// Replace with a proper Zoo onboarding hero image when art is available.
|
||||
const heroSrc =
|
||||
useBrand().brand === 'zoo' ? './zoo-onboarding.png' : './onboarding.png';
|
||||
|
||||
const OnboardingLayout = ({ className, ...props }: OnboardingLayoutProps) => {
|
||||
const { tapCount, setTapCount, setShowLocalNodeOption } =
|
||||
useContext(LogoTapContext);
|
||||
|
||||
// Brand-driven logo + (optional) tagline. Read INSIDE the component so each
|
||||
// app's injected brand (set by <HanzoAI {...brandConfig}/> before mount) is
|
||||
// honored — the previous module-level useBrand() froze on the default brand
|
||||
// and forced the Hanzo "H" (visor.svg) onto Zoo/Lux. The brand ships its own
|
||||
// mark via brandConfig.logo; nothing brand-specific is hardcoded here.
|
||||
const brand = useBrand();
|
||||
const logoSrc = brand.logo?.dark ?? brand.logo?.light ?? '/app-logo.png';
|
||||
// Tagline is opt-in: only brands that set brandConfig.tagline show one. No
|
||||
// brand carries the old hardcoded "the way, the truth, the life" copy.
|
||||
const tagline = (brand as { tagline?: string }).tagline;
|
||||
|
||||
const handleLogoTap = () => {
|
||||
const newCount = tapCount + 1;
|
||||
setTapCount(newCount);
|
||||
@@ -33,39 +37,34 @@ const OnboardingLayout = ({ className, ...props }: OnboardingLayoutProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'bg-bg-dark relative mx-auto grid h-full grid-cols-2 flex-col-reverse items-center px-[48px]',
|
||||
'bg-bg-dark relative mx-auto flex h-full items-center justify-center px-[48px]',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<UpdateBanner />
|
||||
<div className="flex h-[calc(100dvh-100px)] items-center justify-center">
|
||||
<div className="flex h-[calc(100dvh-100px)] w-full items-center justify-center">
|
||||
<div className="mx-auto flex h-[600px] w-full max-w-lg flex-col gap-12">
|
||||
<img
|
||||
alt={`${useBrand().name} logo`}
|
||||
className="w-24 cursor-pointer"
|
||||
data-cy="hanzo-logo"
|
||||
onClick={handleLogoTap}
|
||||
src={logoSrc}
|
||||
/>
|
||||
<div className="flex flex-col gap-3">
|
||||
<img
|
||||
alt={`${brand.name} logo`}
|
||||
className="w-24 cursor-pointer"
|
||||
data-cy="app-logo"
|
||||
onClick={handleLogoTap}
|
||||
src={logoSrc}
|
||||
/>
|
||||
{tagline ? (
|
||||
<p className="text-xs uppercase tracking-[0.2em] text-white/60">
|
||||
{tagline}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="flex-1">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid h-full place-items-center">
|
||||
<div className="relative size-full">
|
||||
<div className="absolute left-14 z-10 flex aspect-square size-full items-center object-left bg-blend-darken">
|
||||
<img
|
||||
alt={`${useBrand().name} onboarding`}
|
||||
className="size-full max-h-[70vh] object-cover object-left"
|
||||
data-cy="onboarding-logo"
|
||||
src={heroSrc}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,6 +13,10 @@ export interface BrandConfig {
|
||||
productName: string;
|
||||
identifier: string; // bundle id, e.g. com.lux.desktop
|
||||
logo: { light: string; dark: string; favicon: string };
|
||||
/** Optional small-caps tagline under the onboarding logo. Empty/absent for
|
||||
* every brand by default — set it per-brand to opt in. (Replaces the old
|
||||
* hardcoded "the way, the truth, the life".) */
|
||||
tagline?: string;
|
||||
colors: { primary: string; bg: string; fg: string };
|
||||
hosts: string[];
|
||||
storeUrl: { mac: string; win: string; ios: string; android: string };
|
||||
|
||||
@@ -14,7 +14,7 @@ export default {
|
||||
enterToSend: '<span>Enter</span> to send',
|
||||
},
|
||||
desktop: {
|
||||
welcome: 'Welcome to Hanzo',
|
||||
welcome: 'Welcome to {{appName}}',
|
||||
welcomeDescription:
|
||||
'<b>Hanzo lets you build AI agents in minutes — fast, private, and secure.</b> Run locally, collaborate through a decentralized network, and create AI workflows effortlessly. ',
|
||||
localAI: 'Hanzo Local AI',
|
||||
|
||||
Reference in New Issue
Block a user