bottom_panel_open

Footer

Bottom area for links and meta content.

Footer Examples

Copy-ready examples with live previews.

Basic usage

The simplest footer: brand text + subtitle.

Live preview

Basic

import Footer from "@/_components/footer/Footer";

export default function Example() {
  return (
    <Footer
      brandTitle="cssnt_components"
      brandSubtitle="Material-ish components"
    />
  );
}

With action buttons

Use `actionButtons` to render an actions column (only when `variant !== minimal).

Action buttons accept any ReactNode: Button, Link-wrapped Button, anchors, etc.

Live preview

Actions

import Link from "next/link";
import Footer from "@/packages/ui/src/_components/footer/Footer";
import { Button } from "@/packages/ui/src/_components/buttons_variants/buttons/Button";

export default function Example() {
  return (
    <Footer
      brandTitle="cssnt_components"
      brandSubtitle="Material-ish components"
      links={[
        { label: "Docs", href: "/docs" },
        { label: "Changelog", href: "/changelog" },
        { label: "GitHub", href: "https://github.com/...", external: true },
      ]}
      actionButtons={[
        <Link key="getting-started" href="/docs/getting-started">
          <Button variant="primary" ripple variantRadio="sm">
            Getting started
          </Button>
        </Link>,
        <a key="github" href="https://github.com/..." target="_blank" rel="noreferrer">
          <Button variant="transparent" ripple variantRadio="sm">
            GitHub
          </Button>
        </a>,
      ]}
    />
  );
}

Variant and alignment

Use `variant` to control layout density and `align` to control horizontal alignment.

Live preview

Documentation

Extras

Standard vs minimal

import Footer from "@/packages/ui/src/_components/footer/Footer";
import { Button } from "@/packages/ui/src/_components/buttons_variants/buttons/Button";

export default function Example() {
  return (
    <div style={{ display: "grid", gap: 14 }}>
      <Footer
        variant="standard"
        align="start"
        brandTitle="Standard / start"
        brandSubtitle="Shows brand + links + actions (when provided)."
        links={[
          { label: "Docs", href: "/docs" },
          { label: "GitHub", href: "https://github.com/...", external: true },
        ]}
        actionButtons={[
          <Button key="contact" variant="primary" ripple variantRadio="sm">
            Contact
          </Button>,
        ]}
      />

      <Footer
        variant="minimal"
        align="center"
        brandTitle="Minimal / center"
        brandSubtitle="Minimal disables the actions column."
        links={[
          { label: "Docs", href: "/docs" },
          { label: "GitHub", href: "https://github.com/...", external: true },
        ]}
        actionButtons={[
          <Button key="hidden" variant="primary" ripple variantRadio="sm">
            (Hidden)
          </Button>,
        ]}
      />
    </div>
  );
}

Custom bottom bar

Override `bottomLeft` to customize the footer bar text.

Live preview

Custom bottomLeft

import Footer from "@/packages/ui/src/_components/footer/Footer";

export default function Example() {
  const year = new Date().getFullYear();

  return (
    <Footer
      brandTitle="cssnt_components"
      brandSubtitle="Material-ish components"
      links={[
        { label: "Docs", href: "/docs" },
        { label: "GitHub", href: "https://github.com/...", external: true },
      ]}
      bottomLeft={
        <span style={{ display: "inline-flex", gap: 8, alignItems: "center" }}>
          <span>© {year}</span>
          <span style={{ opacity: 0.75 }}>CSSN&apos;T</span>
        </span>
      }
    />
  );
}

Playground

Quickly validate combinations and edge cases in a single place.

Live preview

Interactive playground

import { useState } from "react";
import Link from "next/link";
import Footer from "@/_components/footer/Footer";
import { Button } from "@/_components/buttons_variants/buttons/Button";

export default function Example() {
  const [variant, setVariant] = useState<"standard" | "minimal">("standard");
  const [align, setAlign] = useState<"start" | "center">("start");
  const [showLogo, setShowLogo] = useState(true);
  const [useLongLinks, setUseLongLinks] = useState(false);

  const links = useLongLinks
    ? [
        { label: "Docs", href: "/docs" },
        { label: "Components", href: "/components" },
        { label: "Tokens", href: "/tokens" },
        { label: "Changelog", href: "/changelog" },
        { label: "Roadmap", href: "/roadmap" },
        { label: "GitHub", href: "https://github.com/...", external: true },
      ]
    : [
        { label: "Docs", href: "/docs" },
        { label: "Changelog", href: "/changelog" },
        { label: "GitHub", href: "https://github.com/...", external: true },
      ];

  return (
    <div style={{ display: "grid", gap: 12 }}>
      <div style={{ display: "flex", flexWrap: "wrap", gap: 8, alignItems: "center" }}>
        <Button
          variant="primary"
          ripple
          variantRadio="sm"
          onClick={() => setVariant(v => (v === "standard" ? "minimal" : "standard"))}
        >
          Variant: {variant}
        </Button>

        <Button
          variant="transparent"
          ripple
          variantRadio="sm"
          onClick={() => setAlign(a => (a === "start" ? "center" : "start"))}
        >
          Align: {align}
        </Button>

        <Button
          variant="transparent"
          ripple
          variantRadio="sm"
          onClick={() => setShowLogo(v => !v)}
        >
          Logo: {showLogo ? "on" : "off"}
        </Button>

        <Button
          variant="transparent"
          ripple
          variantRadio="sm"
          onClick={() => setUseLongLinks(v => !v)}
        >
          Links: {useLongLinks ? "long" : "basic"}
        </Button>
      </div>

      <Footer
        variant={variant}
        align={align}
        showLogo={showLogo}
        brandTitle={
          <span style={{ display: "inline-flex", gap: 8, alignItems: "baseline" }}>
            <span>cssnt_components</span>
            <span style={{ opacity: 0.65, fontSize: 12 }}>v1.0</span>
          </span>
        }
        brandSubtitle="Tweak variant/align/logo and validate layout."
        links={links}
        actionButtons={[
          <Link key="docs" href="/docs">
            <Button variant="primary" ripple variantRadio="sm">
              Docs
            </Button>
          </Link>,
          <a key="repo" href="https://github.com/..." target="_blank" rel="noreferrer">
            <Button variant="transparent" ripple variantRadio="sm">
              Repository
            </Button>
          </a>,
        ]}
        bottomLeft="© cssnt_components"
      />
    </div>
  );
}

On this page

Footer Props

Footer — Props
PropTypeRequiredDefaultDescription
classNamestringNoundefinedExtra class names for the <footer> root.
customStylesReact.CSSPropertiesNoundefinedInline styles for the <footer> root.
variant"standard" | "minimal"No"standard"Layout density. "minimal" reduces columns and disables the actions column.
align"start" | "center"No"start"Alignment class applied to the root.
showLogobooleanNotrueToggles the brand logo rendering.
logoSrcstringNo"/images/cssnt_logo.png"Brand logo source.
logoAltstringNo"Logo"Brand logo alt text.
logoSizestringNo"72px"Brand logo size (passed as height/width to Image).
brandTitleReact.ReactNode | stringNoundefinedBrand text (rendered as a Title h3).
brandSubtitleReact.ReactNode | stringNoundefinedBrand subtitle (rendered as a Paragraph).
linksArray<{ label: string; href: string; external?: boolean }>No[]Navigation links. Renders a "Documentation" column when non-empty.
actionButtonsReact.ReactNode[]No[]Custom nodes. Renders an "Extras" column when non-empty and variant !== "minimal".
bottomLeftReact.ReactNodeNo"© current year"Bottom-left content for the footer bar. Defaults to © current year.
bottomRightReact.ReactNodeNoundefinedDeclared in types but not currently rendered by Footer.tsx (no effect today).