Components

Layout

Structure pages with header and pane content containers.

UiFooter closes a page. UiHeaderContent renders a page header (title, subtitle, optional back button and actions). UiHeroContent is its page-opening counterpart, with a display-sized title and CTA slot. UiSubheadingContent labels a section inside a page. UiPaneContent is a content container with a row/column layout.

Add a page header

<template>
  <UiHeaderContent
    title="Projects"
    subtitle="Manage your team's work"
    back-button
    @back="goBack"
  >
    <template #actions>
      <UiButton variant="filled" color="primary" text="New" />
    </template>
  </UiHeaderContent>
</template>

Wrap content in a pane

<template>
  <UiPaneContent is-full-height aria-label="Project list">
    <!-- content -->
  </UiPaneContent>
</template>

UiHeaderContent props

PropTypeDefaultDescription
asstring'h1'Heading element for the title. Section headers inside a page should step down from the page's own h1.
headingIdstringgenerated with useId()ID for the heading, for external aria-labelledby references.
headlinestring | null—Small eyebrow label above the title, rendered with caption text-primary.
titlestring | null—Header title.
subtitlestring | null—Header subtitle.
size'sm' | 'md' | 'lg' | 'xl' | '2xl''sm'Title size: sm is --cffy-fs-xl, then --cffy-fs-2xl … --cffy-fs-5xl. Each step also takes the line height the type scale pairs with it.
hideActionsWhenNarrowbooleanfalseDrop the actions from the layout once the header's container is 700px or narrower, instead of wrapping them below the title.
backButtonbooleanfalseShow a back button.
backButtonLabelstring'Go back'Back button tooltip.
viewTransitionNamestring | null—Shared name pairing this header with the matching one on another page for a view transition.
containerClassstring | string[] | Record<string, boolean>—Extra classes.

Emits: back (back button). Slots: #actions — filling it is what renders the actions area; there is no flag to set.

Header CSS variables

UiHeaderContent (.header-container) reads these. The 2xl to 5xl title sizes keep their own size and line height.

VariableDefaultControls
--cffy-header-margin-block-end--cffy-space-16Space below the header
--cffy-header-gap--cffy-space-16Space between the title and the actions
--cffy-header-title-font-size / --cffy-header-title-line-height--cffy-fs-xl / --cffy-fs-xl--line-heightTitle
--cffy-header-description-font-size / --cffy-header-description-color--cffy-fs-xs / --cffy-muted-a10Description
--cffy-header-description-max-width50chDescription line length

Open a page with a hero

size uses the same sm–xl vocabulary as UiHeaderContent, mapped onto the display scale, and align moves the whole block, text and actions together.

<template>
  <UiHeroContent
    headline="Open source"
    title="Build vibrant interfaces"
    subtitle="70+ headless components for Vue 3 and Nuxt."
    size="lg"
    align="center"
  >
    <template #actions>
      <UiButton variant="filled" color="primary" text="Get started" />
      <UiButton variant="outline" text="Documentation" />
    </template>
  </UiHeroContent>
</template>

UiHeroContent props

PropTypeDefaultDescription
headingIdstringgenerated with useId()ID for the title; the <section> references it with aria-labelledby.
headlinestring | null—Small eyebrow label above the title.
titlestring | null—Main title, rendered with the display class.
subtitlestring | null—Supporting description.
size'sm' | 'md' | 'lg' | 'xl''xl'Title size on the display scale: sm is display-4, xl is display-1.
align'start' | 'center' | 'end''start'Alignment of the whole hero.
viewTransitionNamestring | null—Shared name pairing this hero with the matching element on another page for a view transition.
customClassstring | string[] | Record<string, boolean>—Extra classes.

Slots: #actions for the call-to-action buttons.

Hero CSS variables

UiHeroContent (.hero-content) reads these.

VariableDefaultControls
--cffy-hero-gap--cffy-space-8Space between the title, description and other text
--cffy-hero-margin-block-end--cffy-space-32Space below the hero
--cffy-hero-max-width60chTitle and description line length
--cffy-hero-description-font-size / --cffy-hero-description-line-height--cffy-fs-lg / --cffy-fs-lg--line-heightDescription text
--cffy-hero-description-color--cffy-muted-a10Description color
--cffy-hero-actions-offset / --cffy-hero-actions-gap--cffy-space-24 / --cffy-space-12Space above the actions, and between them

Morph a title across pages

viewTransitionName is the name both pages share, so the browser can pair the two titles. Nothing is emitted when the prop is omitted.

<template>
  <!-- list page -->
  <UiHeaderContent title="Atlas" view-transition-name="project-atlas" />

  <!-- detail page -->
  <UiHeaderContent title="Atlas" view-transition-name="project-atlas" back-button />
</template>

The description derives <name>-description, so one prop covers both lines.

A view-transition-name has to be unique within a document — two elements sharing one make the browser skip the transition entirely. Give each header its own name, and only name the ones that actually morph.

In Nuxt, the transition itself is enabled with experimental.viewTransition in nuxt.config.ts. If the app also sets pageTransition or layoutTransition, the Nuxt docs suggest a global middleware that turns those off where document.startViewTransition exists, so the two do not animate the same navigation.

Label a section

<template>
  <UiSubheadingContent
    title="Integrations"
    subtitle="Connect the tools your team already uses."
  >
    <template #actions>
      <UiBadge text="3 active" variant="outline" size="sm" />
    </template>
  </UiSubheadingContent>
</template>

UiSubheadingContent props

PropTypeDefaultDescription
asstring'h3'Heading element, so the page keeps a valid heading order.
titlestring | null—Subheading text, rendered with .text-subheading.
subtitlestring | null—Description; picks up the muted styling by being the heading's sibling.
gutter'none' | 'sm' | 'md''md'Space below the block. The title-to-description gap is fixed and does not follow it.
customClassstring | string[] | Record<string, boolean>—Extra classes for the wrapper.

Slots: #actions — a badge or control beside the subheading; the wrapper switches to two columns when it is filled.

Subheading CSS variables

UiSubheadingContent (.subheading-content) reads these.

VariableDefaultControls
--cffy-subheading-gap--cffy-space-16Space between the title and the actions
--cffy-subheading-actions-gap--cffy-space-8Space between actions

UiFooter renders the brand block and an optional bottom bar, UiFooterGroup lays out each set of links (stacked by default, or in a row) and UiFooterItem is the link itself.

<template>
  <UiFooter title="Colorffy UI" subtitle="MIT licensed">
    <UiFooterGroup title="Docs">
      <UiFooterItem text="Installation" :as="NuxtLink" to="/install" />
      <UiFooterItem text="Components" :as="NuxtLink" to="/components" />
    </UiFooterGroup>

    <UiFooterGroup title="Social" direction="row">
      <UiFooterItem text="GitHub" href="https://github.com" icon="&#xe86f;" />
    </UiFooterGroup>

    <template #bottom>
      <p>&copy; 2026 Colorffy</p>
      <UiBadge text="v2.5.1" variant="outline" size="sm" />
    </template>
  </UiFooter>
</template>

A row group with a title keeps its heading on its own line and lays the links out beside each other; without a title the whole group is one row, which suits a legal strip. overline renders the heading small and uppercase.

The footer wraps its own content in a .container, so it lines up with the rest of the page without any extra markup. fluid swaps that for .container-fluid, the same way UiNavbar does it.

UiFooter props

PropTypeDefaultDescription
titlestring | null—Brand title.
subtitlestring | null—Supporting line below the title.
fluidbooleanfalseUse .container-fluid instead of .container.
customClassstring | string[] | Record<string, boolean>—Extra classes.

Slots: #brand replaces the title/subtitle block, the default slot takes the link groups, and #bottom renders a divided bar under them, split left and right.

UiFooterGroup props

PropTypeDefaultDescription
titlestring | null—Heading for the group.
direction'col' | 'row''col'Stacks the links or lays them out in a row. With a title, the heading stays on its own line.
overlinebooleanfalseRenders the title small and uppercase.
customClassstring | string[] | Record<string, boolean>—Extra classes.

UiFooterItem props

PropTypeDefaultDescription
textstring | null—Label text; the default slot overrides it.
iconstring | null—Leading Material Symbols code point.
to / hrefstring | object | null—Link target. Without one the item renders a plain .anchor-link entry.
asstring | object | null—Link component for client-side routing (NuxtLink in Nuxt, RouterLink in Vue).
customClassstring | string[] | Record<string, boolean>—Extra classes.
On its own, a string to or href renders a plain <a href> — the package ships to Vue as well as Nuxt, so it never imports a router link itself. Pass :as="NuxtLink" (or RouterLink) for client-side navigation, the same way UiNavbarLink and UiSidebarLink take it. External href values stay plain anchors even with as set, and get target="_blank" and rel="noopener noreferrer".

Set these on :root or on a wrapper. Row groups (row on UiFooterGroup) keep their wider gap.

:root {
  --cffy-footer-bg-color: var(--cffy-surface-container-low);
  --cffy-footer-link-hover-color: var(--cffy-accent-a10);
}
VariableDefaultControls
--cffy-footer-bg-color / --cffy-footer-color--cffy-surface-body-pane / --cffy-on-backgroundBackground and text
--cffy-footer-muted-color--cffy-muted-a10Subtitle, links and bottom-bar text
--cffy-footer-border-color--cffy-outline-surfaceBottom-bar divider
--cffy-footer-padding-inline / --cffy-footer-padding-block0 / --cffy-space-32 + --cffy-space-8Padding
--cffy-footer-margin-block-startthe block paddingSpace above the footer
--cffy-footer-gap--cffy-space-16Space between groups and items
--cffy-footer-title-font-size / --cffy-footer-title-font-weight--cffy-fs-lg / --cffy-fw-800Brand title
--cffy-footer-link-color / --cffy-footer-link-hover-colorthe muted color / --cffy-primary-a10Links
--cffy-footer-link-font-size--cffy-fs-2xsLink text size
--cffy-footer-icon-color--cffy-on-secondary-containerLink icons

UiPaneContent props

PropTypeDefaultDescription
idstring—DOM id for the <section>.
isFullHeightbooleanfalseExpand to full height.
customClass / containerClassstring | string[] | Record<string, boolean>—Extra classes.
ariaLabel / ariaLabelledby / ariaDescribedbystring—ARIA wiring.

Slots: default — the pane content. Exposed: paneContentRef, the <section> element.

Copyright © 2026