Overview
The C4 footer system is composed of three CORE-OWNED components:
| Component | Location | Purpose |
|---|---|---|
Footer.astro | src/core/components/nav/ | Footer composition shell with three stacked regions |
UtilityNav.astro | src/core/components/nav/ | Reusable utility-link list renderer |
SocialLinks.astro | src/core/components/nav/ | Config-driven social icon link renderer |
PageGridLayout.astro renders Footer.astro by default when no footer named slot is provided.
Who this is for
- Implementors building or extending footer/navigation components
- Developers who need to understand footer composition boundaries
- AI agents implementing C4+ work that depends on footer behavior
Footer Layout Contract
Footer.astro renders three regions in order:
- Main section (
site-footer__main) with three columns:
- Column 1:
SiteLogo+ contact block fromsiteConfig.contact - Column 2:
menuConfig.footerNav.footerNav1 - Column 3:
menuConfig.footerNav.footerNav2stacked above social icons
- Footer nav3 row (
site-footer__footer-nav3) frommenuConfig.footerNav.footerNav3 - Copyright line (
site-footer__copyright) fromsiteConfig.copyright
The optional footerNav.footerNavLinks array is intentionally not used in C4.
Configuration Sources
Footer data is consumed from existing config contracts only:
src/site/config/site.tssiteConfig.contact(legalName,contactEmail,contactEmailLabel,contactPhone,contactPhoneLabel,addressLines)siteConfig.footer(showFooterNav1Heading,footerNav1HeadingLabel,showFooterNav2Heading,footerNav2HeadingLabel,showFooterNav3Heading,footerNav3HeadingLabel)siteConfig.socialLinkssiteConfig.copyrightsrc/site/config/menu.tsmenuConfig.footerNav.footerNav1menuConfig.footerNav.footerNav2menuConfig.footerNav.footerNav3
Footer naming/label behavior is schema-driven.
Component API Reference
Footer.astro
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
class | string | — | Optional class hook on root footer element |
Behavior:
- Uses semantic
<footer role="contentinfo"> - Renders non-empty contact fields only
- Renders optional email/phone labels when configured
- Renders social links only when
siteConfig.socialLinks.length > 0 - Renders legal row only when legal links exist
- Resolves copyright year:
year: "auto"-> current yearyear: number-> explicit numeric year- Interpolates
{year},{holder},{suffix}placeholders from template
UtilityNav.astro
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
heading | string | required | Used for nav label and heading text |
items | Array<{label: string; href: string}> | required | Empty array suppresses rendering |
orientation | "vertical" | "horizontal" | "vertical" | Vertical for columns, horizontal for legal row |
headingVisible | boolean | false | false renders heading as .sr-only |
class | string | — | Optional class hook |
SocialLinks.astro
Props:
| Prop | Type | Default | Notes |
|---|---|---|---|
links | SocialLinksConfig | required | Empty array suppresses rendering |
class | string | — | Optional class hook |
Behavior:
- Icon-only links in UI (
titleused for hover label) - Screen-reader text included per icon label
- Same-tab link behavior
rel="noopener noreferrer"applied- Supports icon names and SVG path-like strings by deriving basename (example:
src/core/assets/icons/social/x-twitter.svg->x-twitter)
Usage Examples (Focused)
Default footer via layout
---
import PageGridLayout from "@core/components/layouts/PageGridLayout.astro";
---
<PageGridLayout title="Example" description="Example page">
<p>Page content.</p>
</PageGridLayout>
Footer slot override
---
import PageGridLayout from "@core/components/layouts/PageGridLayout.astro";
---
<PageGridLayout title="Custom footer" description="Slot override example">
<Fragment slot="footer">
<footer role="contentinfo">Custom footer content</footer>
</Fragment>
<p>Page content.</p>
</PageGridLayout>
Standalone utility-nav row
---
import UtilityNav from "@core/components/nav/UtilityNav.astro";
const legal = [
{ label: "Terms", href: "/terms/" },
{ label: "Privacy", href: "/privacy/" },
];
---
<UtilityNav heading="Legal" items={legal} orientation="horizontal" />
Accessibility Notes
- Footer root uses
contentinfolandmark semantics - Utility navs use
aria-labelfrom heading text - Link focus states are visible across utility, social, and contact links
- Social links include accessible names via
aria-labeland.sr-onlytext - Configurable resource/company heading visibility allows per-site heading presentation without component edits
Verification Checklist (Focused)
- Open
/theme-docs/showcase/showcase-footer/and confirm the three stacked footer regions render in order. - Confirm main section columns map to:
- logo + contact
- resources links
- company links + social icons
- Keyboard-tab through footer links and verify visible focus styles.
- Toggle light/dark mode and confirm footer text/link contrast remains readable.
- Set
socialLinksto[]and verify social icon row disappears cleanly. - Set
copyright.yearto"auto"and verify current year is rendered.