Files
community-rule/app/components/asset/Logo/Logo.tsx
T
adilalloandCursor 33cdaf135c Match Home, top nav, hero, and logo wall to the current marketing frames.
Puts Workshops in the header, pairs the hero with a static rule card and breakpoint CTAs, and shows the three pilot marks with no wall label.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-11-02 18:50:32 -07:00

144 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { memo } from "react";
import Link from "next/link";
import { useTranslation } from "../../../contexts/MessagesContext";
import { getAssetPath, ASSETS } from "../../../../lib/assetUtils";
interface LogoProps {
size?:
| "default"
| "footer"
| "createFlow"
| "topNavFolderTop"
| "topNavHeader";
/**
* Visual style: default (dark on light) or inverse (e.g. black/white on teal).
* @default "default"
*/
palette?: "default" | "inverse";
/**
* Whether to show the "CommunityRule" wordmark.
* @default true
*/
wordmark?: boolean;
}
interface SizeConfig {
containerHeight: string;
gap: string;
textSize: string;
lineHeight: string;
iconSize: string;
}
const Logo = memo<LogoProps>(
({ size = "default", palette = "default", wordmark = true }) => {
const t = useTranslation("controlsChrome");
// Figma: "Asset / Logo" (4002:6735) — 40×6×27 at 1x; nav/footer/create-flow
// instances scale that lockup.
const sizes: Record<string, SizeConfig> = {
default: {
containerHeight: "h-[var(--space-1000)]",
gap: "gap-[var(--space-150)]",
textSize: "text-[21.97px]",
lineHeight: "leading-[27.05px]",
iconSize: "w-[27px] h-[27px]",
},
footer: {
containerHeight: "h-[41px] md:h-[56px] lg:h-[82px]",
gap: "gap-[6.21px] md:gap-[8.49px] lg:gap-[12.43px]",
textSize:
"text-[22.75px] md:text-[31.08px] lg:text-[45.51px]",
lineHeight:
"leading-[28px] md:leading-[38.25px] lg:leading-[56.01px]",
iconSize:
"w-[27.96px] h-[27.96px] md:w-[38.18px] md:h-[38.18px] lg:w-[55.91px] lg:h-[55.91px]",
},
createFlow: {
containerHeight: "h-[30px] md:h-[var(--space-1000)]",
gap: "gap-[4.5px] md:gap-[var(--space-150)]",
textSize: "text-[16.48px] md:text-[21.97px]",
lineHeight: "leading-[20.28px] md:leading-[27.05px]",
iconSize: "w-[20.25px] h-[20.25px] md:w-[27px] md:h-[27px]",
},
topNavFolderTop: {
containerHeight:
"h-[14.1px] sm:h-[21.35px] md:h-[var(--space-800)] lg:h-[var(--space-1000)] xl:h-[50.35px]",
gap: "gap-0 sm:gap-[3.2px] md:gap-[4.8px] lg:gap-[var(--space-150)] xl:gap-[7.5px]",
textSize:
"text-[11.57px] sm:text-[11.72px] md:text-[17.58px] lg:text-[21.97px] xl:text-[27.47px]",
lineHeight:
"leading-[14.24px] sm:leading-[14.42px] md:leading-[21.64px] lg:leading-[27.05px] xl:leading-[33.81px]",
iconSize:
"w-[14.1px] h-[14.1px] sm:w-[14.4px] sm:h-[14.4px] md:w-[21.6px] md:h-[21.6px] lg:w-[27px] lg:h-[27px] xl:w-[33.75px] xl:h-[33.75px]",
},
topNavHeader: {
containerHeight:
"h-[14.2px] sm:h-[21.22px] md:h-[var(--space-800)] lg:h-[40.69px] xl:h-[50.35px]",
gap: "gap-0 sm:gap-[3.18px] md:gap-[4.85px] lg:gap-[6.06px] xl:gap-[7.5px]",
textSize:
"text-[11.57px] sm:text-[11.66px] md:text-[17.76px] lg:text-[22.2px] xl:text-[27.47px]",
lineHeight:
"leading-[14.24px] sm:leading-[14.35px] md:leading-[21.86px] lg:leading-[27.32px] xl:leading-[33.81px]",
iconSize:
"w-[14.2px] h-[14.2px] sm:w-[14.33px] sm:h-[14.33px] md:w-[21.82px] md:h-[21.82px] lg:w-[27.27px] lg:h-[27.27px] xl:w-[33.75px] xl:h-[33.75px]",
},
};
const config = sizes[size || "default"] || sizes.default;
const isInverse = palette === "inverse";
const textColorClass = isInverse
? "text-[var(--color-content-invert-primary)]"
: "text-[var(--color-content-default-primary)]";
const wordmarkVisibilityClass =
size === "topNavHeader"
? wordmark
? "hidden sm:block"
: "hidden"
: size === "topNavFolderTop"
? wordmark
? "hidden md:block"
: "hidden"
: wordmark
? ""
: "hidden";
return (
<Link href="/" className="group block" aria-label={t("logoAlt")}>
<div
className={`flex items-center ${config.containerHeight} ${
wordmark ? config.gap : ""
} cursor-pointer`}
>
{/* Logo Text - responsive visibility for topNav sizes */}
<div
className={`font-bricolage-grotesque ${textColorClass} ${config.textSize} ${config.lineHeight} font-normal tracking-[0px] transition-opacity duration-200 ease-out group-hover:opacity-80 ${wordmarkVisibilityClass}`}
aria-label={t("logoText")}
>
{t("logoText")}
</div>
{/* Vector Icon */}
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
src={getAssetPath(ASSETS.LOGO)}
alt={t("logoAlt")}
width={27}
height={27}
className={`flex-shrink-0 ${config.iconSize} origin-center transition-transform duration-200 ease-out group-hover:scale-110 ${
isInverse ? "brightness-0" : ""
}`}
aria-hidden="true"
/>
</div>
</Link>
);
},
);
Logo.displayName = "Logo";
export default Logo;