Differentiate portal callout colors and width

When both banners stack they read as one band if they share
gold. Use sky (info) for locale and amber (warning) for NDA,
and keep content inside the same max-w-5xl column as TopBar.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-07-30 15:17:29 +02:00
parent 1e8690aaae
commit 51ba02cedd
4 changed files with 109 additions and 97 deletions

View File

@@ -109,61 +109,63 @@ export function LocaleMismatchCallout({ identityKey }: LocaleMismatchCalloutProp
return (
<aside className={slots.root()} role="status">
<div className={slots.content()}>
<GlobeIcon weight="fill" className={slots.icon()} aria-hidden />
<Text size={2} color="neutral" highContrast className={slots.message()}>
{t("locale.mismatch.message", { language: urlLabel })}
</Text>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("locale.mismatch.dismiss")}
disabled={busy}
className={slots.dismissMobile()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
</div>
<div className={slots.actions()}>
<Button
size={1}
variant="solid"
color="gold"
disabled={busy}
className={slots.action()}
onClick={switchToSaved}
>
{t("locale.mismatch.switchToMine", {
language: savedLabel,
// Label this action in the user's saved locale so it reads as
// "switch back to my language", not the page they're visiting.
lng: savedLanguage,
})}
</Button>
<Button
size={1}
variant="solid"
color="neutral"
highContrast
disabled={busy}
className={slots.action()}
onClick={adoptUrlLocale}
>
{t("locale.mismatch.useThis", { language: urlLabel })}
</Button>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("locale.mismatch.dismiss")}
disabled={busy}
className={slots.dismissDesktop()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
<div className={slots.inner()}>
<div className={slots.content()}>
<GlobeIcon weight="fill" className={slots.icon()} aria-hidden />
<Text size={2} color="neutral" highContrast className={slots.message()}>
{t("locale.mismatch.message", { language: urlLabel })}
</Text>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("locale.mismatch.dismiss")}
disabled={busy}
className={slots.dismissMobile()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
</div>
<div className={slots.actions()}>
<Button
size={1}
variant="outline"
color="sky"
disabled={busy}
className={slots.action()}
onClick={switchToSaved}
>
{t("locale.mismatch.switchToMine", {
language: savedLabel,
// Label this action in the user's saved locale so it reads as
// "switch back to my language", not the page they're visiting.
lng: savedLanguage,
})}
</Button>
<Button
size={1}
variant="solid"
color="neutral"
highContrast
disabled={busy}
className={slots.action()}
onClick={adoptUrlLocale}
>
{t("locale.mismatch.useThis", { language: urlLabel })}
</Button>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("locale.mismatch.dismiss")}
disabled={busy}
className={slots.dismissDesktop()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
</div>
</div>
</aside>
);

View File

@@ -21,12 +21,16 @@
import { tv } from "tailwind-variants/lite";
// Full-bleed locale-mismatch banner under the TopBar: message row + actions,
// stacking on small screens.
// stacking on small screens. Sky (info) so it reads apart from the amber
// unsigned-NDA callout when both are visible. Content column matches TopBar /
// page layout (px-8 + centered max-w-5xl).
export const localeMismatchCallout = tv({
slots: {
root: "flex w-full items-center gap-3 bg-gold-3 px-8 py-2.5 max-md:flex-col max-md:items-stretch max-md:gap-3 max-md:px-4 max-md:py-3",
root: "w-full bg-sky-3 px-8 py-2.5 max-md:px-4 max-md:py-3",
inner:
"mx-auto flex w-full max-w-5xl items-center gap-3 max-md:flex-col max-md:items-stretch max-md:gap-3",
content: "flex min-w-0 flex-1 items-start gap-2",
icon: "mt-0.5 size-4 shrink-0 text-gold-11",
icon: "mt-0.5 size-4 shrink-0 text-sky-11",
message: "min-w-0 flex-1",
dismissMobile: "md:hidden",
actions: "flex shrink-0 items-center gap-2 max-md:flex-col max-md:items-stretch",

View File

@@ -66,42 +66,44 @@ export function UnsignedNDACallout({ compliancePortalKey }: UnsignedNDACalloutPr
return (
<aside className={slots.root()} role="status">
<div className={slots.content()}>
<FileTextIcon weight="fill" className={slots.icon()} aria-hidden />
<Text size={2} color="neutral" highContrast className={slots.message()}>
{t("nda.unsignedBanner.message")}
</Text>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("nda.unsignedBanner.dismiss")}
className={slots.dismissMobile()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
</div>
<div className={slots.actions()}>
<Link
to={ndaHref}
size={1}
variant="solid"
color="gold"
className={slots.cta()}
>
{t("nda.unsignedBanner.sign")}
</Link>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("nda.unsignedBanner.dismiss")}
className={slots.dismissDesktop()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
<div className={slots.inner()}>
<div className={slots.content()}>
<FileTextIcon weight="fill" className={slots.icon()} aria-hidden />
<Text size={2} color="neutral" highContrast className={slots.message()}>
{t("nda.unsignedBanner.message")}
</Text>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("nda.unsignedBanner.dismiss")}
className={slots.dismissMobile()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
</div>
<div className={slots.actions()}>
<Link
to={ndaHref}
size={1}
variant="solid"
color="amber"
className={slots.cta()}
>
{t("nda.unsignedBanner.sign")}
</Link>
<IconButton
size={1}
variant="ghost"
color="neutral"
aria-label={t("nda.unsignedBanner.dismiss")}
className={slots.dismissDesktop()}
onClick={() => setDismissed(true)}
>
<XIcon />
</IconButton>
</div>
</div>
</aside>
);

View File

@@ -21,12 +21,16 @@
import { tv } from "tailwind-variants/lite";
// Full-bleed unsigned-NDA banner under the TopBar: message row + CTA/dismiss,
// stacking on small screens like the locale-mismatch callout.
// stacking on small screens. Amber (warning) so it reads apart from the sky
// locale-mismatch callout when both are visible. Content column matches TopBar /
// page layout (px-8 + centered max-w-5xl).
export const unsignedNDACallout = tv({
slots: {
root: "flex w-full items-center gap-3 bg-gold-3 px-8 py-2.5 max-md:flex-col max-md:items-stretch max-md:gap-3 max-md:px-4 max-md:py-3",
root: "w-full bg-amber-3 px-8 py-2.5 max-md:px-4 max-md:py-3",
inner:
"mx-auto flex w-full max-w-5xl items-center gap-3 max-md:flex-col max-md:items-stretch max-md:gap-3",
content: "flex min-w-0 flex-1 items-start gap-2",
icon: "mt-0.5 size-4 shrink-0 text-gold-11",
icon: "mt-0.5 size-4 shrink-0 text-amber-11",
message: "min-w-0 flex-1",
dismissMobile: "md:hidden",
actions: "flex shrink-0 items-center gap-2 max-md:flex-col max-md:items-stretch",