Skip to content
BigBang

Popular

    ↑↓Navigate↵OpenEscClose
    TR

    Templates

    AuthShell

    The shared shell of sign-in, one-time code and password screens.

    AuthShell puts the screens seen before sign-in into one centred card. There is no navigation, so the user’s attention goes to the form only.

    The brand and mode switches in the page header restyle the live preview too. The second preview shows the second brand in dark mode.

    Live example, StorybookOpen in Storybook
    Live example, StorybookOpen in Storybook
    Region Element Note
    Brand brand Logo or product name; a neutral product name when left out.
    Content card main The page’s only h1 (title), a description and the form. At most 400 px wide.
    Footer footer Privacy and help links; replace them with footer.
    Side panel aside Decorative only; hidden from screen readers.
    Width Layout
    Below 1024 px One column; the card is centred and the side panel hidden.
    1024 px and up Side panel on the left, a 448 px form column on the right. With aside={false} the card centres on the full width.

    The card’s padding comes from space.2xl, its border from border.subtle and its shadow from shadow.raised.

    • The page has a single main landmark, named by its title (aria-labelledby).
    • There is one h1; headings inside the form start at h2.
    • The footer is a named footer (contentinfo).
    • The side panel has aria-hidden and holds nothing focusable.
    • On load, focus stays at the start of the document; the first field does not take autoFocus, so screen readers read the title first.
    import { Heading, Inline, Link, Stack, Text } from '@bigbang/ui';
    import type { ReactNode } from 'react';
    import { type Lang, LangProvider } from '../../patterns/lang';
    const copy = {
    tr: { product: 'Ürün adı', privacy: 'Gizlilik', help: 'Yardım', footer: 'Yasal bilgiler', aside: 'Ekibinizin işleri tek yerde.' },
    en: { product: 'Product name', privacy: 'Privacy', help: 'Help', footer: 'Legal', aside: "Your team's work in one place." },
    };
    export type AuthShellProps = {
    /** The page's only h1, such as "Giriş yapın". */
    title: string;
    /** One sentence under the title. */
    description?: ReactNode;
    /** The form. */
    children: ReactNode;
    /** Links under the card; defaults to privacy and help. */
    footer?: ReactNode;
    /** Logo or product name; defaults to a neutral product name. */
    brand?: ReactNode;
    /** Shows the decorative side panel from `lg` up. */
    aside?: boolean;
    lang?: Lang;
    };
    /**
    * Template for sign-in, one-time code and password screens: one centred card in a `main` landmark,
    * the brand above it and the footer links below. No navigation, so nothing competes with the form.
    */
    export function AuthShell({ title, description, children, footer, brand, aside = true, lang = 'tr' }: AuthShellProps) {
    const t = copy[lang];
    return (
    <LangProvider lang={lang}>
    <div className="grid min-h-[40rem] w-full bg-surface-default lg:grid-cols-[1fr_minmax(0,28rem)]" data-template="auth-shell">
    {aside ? (
    <div className="hidden items-end bg-surface-layer-1 p-4xl lg:flex" aria-hidden="true">
    <Text size="lg" tone="subtle">
    {t.aside}
    </Text>
    </div>
    ) : null}
    <div className={`flex flex-col items-center justify-between gap-3xl px-lg py-3xl ${aside ? '' : 'lg:col-span-2'}`}>
    <div className="w-full max-w-[25rem]" data-part="brand">
    {brand ?? (
    <Text weight="medium">
    {t.product}
    </Text>
    )}
    </div>
    <main className="w-full max-w-[25rem] rounded-lg border border-line-subtle bg-surface-raised p-2xl shadow-raised" aria-labelledby={`auth-title-${lang}`}>
    <Stack gap="xl">
    <Stack gap="sm">
    <Heading level={1} size="lg" id={`auth-title-${lang}`}>
    {title}
    </Heading>
    {description ? <Text tone="subtle">{description}</Text> : null}
    </Stack>
    {children}
    </Stack>
    </main>
    <footer className="w-full max-w-[25rem]" aria-label={t.footer}>
    {footer ?? (
    <Inline gap="lg">
    <Link href="#" size="sm">
    {t.privacy}
    </Link>
    <Link href="#" size="sm">
    {t.help}
    </Link>
    </Inline>
    )}
    </footer>
    </div>
    </div>
    </LangProvider>
    );
    }

    Heading, Text, Stack, Inline, Link. Blocks built on this shell: Sign-in, One-time code.