Files

113 lines
3.8 KiB
TypeScript
Raw Permalink Normal View History

import { getDirection, type Locale } from "../LanguageSwitcher";
/* Exported from Figma assets/eu-en (224:11275) and assets/eu-en - darkBg
(238:2325). The source files are downscaled copies of the Figma exports. */
const EMBLEM_SRC = {
light: "/assets/eu-flag.png",
dark: "/assets/eu-flag-dark.png",
} as const;
const EMBLEM_INTRINSIC_WIDTH = 192;
const EMBLEM_INTRINSIC_HEIGHT = 128;
/**
* Drawn emblem box per size. "md" is the 48x32 the navigation and the drawer
* use; "sm" is the 36x24 the home hero draws above the wordmark (478:15951).
* Only the emblem changes - see the note on the statement below.
*/
const EMBLEM_BOX = {
md: "h-[32px] w-[48px]",
sm: "h-[24px] w-[36px]",
} as const;
export type EuBadgeSize = keyof typeof EMBLEM_BOX;
/** Which tier-2 surface the badge is sitting on. `:root` is the dark one. */
export type EuBadgeSurface = keyof typeof EMBLEM_SRC;
export interface EuBadgeProps {
/** "Funded by the European Union", already in the reader's language. */
statement: string;
/** Alt text for the emblem. Empty when the statement is rendered beside it. */
emblemAlt?: string;
/** Language of `statement` - drives the font switch and the text direction. */
locale: Locale;
surface: EuBadgeSurface;
/** "md" (48x32) by default; "sm" (36x24) for the hero lockup. */
size?: EuBadgeSize;
className?: string;
}
/**
* The mandatory EU visibility lockup: emblem + funding statement.
*
* The lockup itself is pinned to `dir="ltr"` so the emblem always leads, which
* is how the Arabic navigation frame (334:526) draws it; only the statement
* carries the reader's own direction. A mirroring ancestor still moves the
* whole badge from the inline start to the inline end in Arabic.
*
* DEVIATION FROM FIGMA (colour): the design sets the statement in EU reflex
* blue (hex 0f2a8e). A raw hex is not permitted in a component here, and there
* is no semantic token for a third-party brand colour, so the statement uses
* --text-primary. It stays legible on both surfaces and the emblem still
* carries the EU colours. Add a tier-2 token if the blue has to come back.
*
* DEVIATION FROM FIGMA (type): the hero badge sets the statement at 10px. The
* type scale has no 10px role and a raw font-size is not permitted, so both
* sizes render the statement at `label-md` (12px). The lockup is then a little
* taller than the 24px emblem at "sm"; it is also more legible, which EU
* visibility guidance asks for. Add a tier-2 role if 10px is required.
*/
export function EuBadge({
statement,
emblemAlt = "",
locale,
surface,
size = "md",
className,
}: EuBadgeProps) {
return (
<div
dir="ltr"
className={["flex shrink-0 items-center gap-2xs", className]
.filter(Boolean)
.join(" ")}
>
<img
src={EMBLEM_SRC[surface]}
alt={emblemAlt}
width={EMBLEM_INTRINSIC_WIDTH}
height={EMBLEM_INTRINSIC_HEIGHT}
loading="eager"
decoding="async"
draggable={false}
className={`block shrink-0 ${EMBLEM_BOX[size]}`}
/>
<span
lang={locale}
dir={getDirection(locale)}
className="label-md block w-[96px] text-[var(--text-primary)]"
>
{statement}
</span>
</div>
);
}
export default EuBadge;
/* ---------------------------------------------------------------------------
USAGE
---------------------------------------------------------------------------
// In the mobile drawer, on the dark surface:
<EuBadge statement={t("site.euStatement")} locale="en" surface="dark" />
// Above the home hero wordmark, at the smaller emblem size:
<EuBadge
size="sm"
statement={t("site.euStatement")}
locale={locale}
surface="dark"
/>
------------------------------------------------------------------------ */