The foot of a family's site: the FamilyBar's links, in the same order, in a quiet row that wraps, with the site being shown marked the same way, and the site's own extras (children) after them. The family's links are a labelled <nav> of plain links, whole in the server HTML.
On this site
This site's own pages use FamilyFooter too. Open one with X-ray pointing it out: The Nautilus's story · The home page
Install
Once per app, with Tailwind CSS v4 and an @/* path alias (Ouro HX is built on Base UI, so --base base; skip -t in an existing app):
npx shadcn@latest init --base base --preset nova --yes --no-monoreponpx shadcn@latest add ourostack/ouro-ui/ouro-base#v1.3.10Then the component. From v0.8.0 it installs only the helpers it imports and never touches your stylesheet (Installing):
npx shadcn@latest add ourostack/ouro-ui/family-footer#v1.3.10Or, with the @ouro namespace set up:
npx shadcn@latest add @ouro/ouro-base @ouro/family-footerIts tests, stories and Playwright spec are optional. They need Vitest 4.1.11 or later, and from v0.8.0 never change a version your app has (Testing):
npx shadcn@latest add ourostack/ouro-ui/family-footer#v1.3.10 ourostack/ouro-ui/family-footer-tests#v1.3.10import { FamilyFooter } from "@/components/ouro/family-bar/family-footer";Paths use shadcn's default @/ alias; the CLI rewrites them to yours.
Example
<FamilyFooter links={sites} current="docs">
<Link href="/privacy" tone="secondary">Privacy</Link>
<Link href="/terms" tone="secondary">Terms</Link>
</FamilyFooter>Use instead when
- Use
FamilyBarinstead for the strip above the site's header, andNavbarfor a site's own pages.
Props
Type: FamilyFooterProps.
children- Type:
ReactNode - The site's own extras, after the family's links: its Privacy and Terms links, a line about who makes it. They fill the rest of the row, or a row of their own, and sit at its end (at its start on a phone) until you spread them:
me-autoon the first. className- Type:
string - Layout only: margins, grid placement (
mt-auto). Appearance classes warn in development. current- Type:
string - The
idof the site being shown, marked as in theFamilyBar:aria-current="true", the text colour and a primary underline. label- Type:
string - Default:
"All sites" - Names the footer's navigation for screen readers, apart from the bar's. It is not shown.
links(required)- Type:
readonly FamilyLink[] - The family's sites, in order: the list the site's
FamilyBartakes. ref- Type:
Ref<HTMLDivElement> - Reaches the rendered element.
Don't use
These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.
currentPath: Not a prop. FamilyFooter marks a site by its id, not by a path:<FamilyFooter current="docs">.items: Not a prop. FamilyFooter takeslinks:<FamilyFooter links={[{ id: "docs", label: "Docs", href: "/" }]} />.
className is for layout only
Pass margins, width and grid placement (mt-4, w-full, col-span-2).
Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (hover:, sm:) and any ! are removed, it starts with bg-, text-, border-, rounded-, shadow-, font-, ring-, from-, via-, to-, fill- or stroke-, or is border, rounded, shadow or ring, or has a dark: variant. Text wrapping, overflow and table layout classes (text-wrap, text-ellipsis, border-collapse) are layout and do not warn.
Alignment classes (text-center) warn too: set alignment on a parent element.
Types
FamilyLink
One site of a family, in a FamilyBar and a FamilyFooter.
interface FamilyLink {
/** Names the site for `current`: "docs". It is not shown. */
id: string;
/** The site's name, the link's text: "Docs". */
label: string;
/** Where the link goes: the site's home page, "https://docs.example.com/". */
href: string;
}