Page components
This page lists the components every admin and account page is made of, with their props and slots. It is for app developers and module authors who build those pages. Set up the module first: Overview.
The components add structure and spacing only. Colours and radius come from Nuxt UI. When to use which one is explained in the UX patterns; this page does not repeat those rules.
How they are registered
The components are auto-imported by name, with no prefix. None is a global component, so each page only loads the ones it uses.
resolveComponent('PageHeading') with a literal name. Nuxt resolves it at build
time. Do not register the component with global: true: a global component is bundled into the app entry and
slows the first render of every page.Every built-in string is a prop, and its default is translated. See
the patterns strings.
Page frame
The heading, tabs and toolbar at the top of a page. The admin area's shell is on App shell.
| Component | Props | Slots | Use |
|---|---|---|---|
PageHeading | title?, description?, breadcrumb?: string | BreadcrumbItem[] | title, badge, description, default (meta row), actions | The title block of an app page. |
PageTabs | items: (NavigationMenuItem & { value? })[], v-model? | none | Tabs under a heading, for sections the page owns. |
PageSectionSwitcher | items: NavigationMenuItem[], label? | none | A button that opens a menu of every section, for narrow screens. The account area uses it. |
PageToolbar | none | default (search and filters), right | The row of search and filter controls above a table. |
breadcrumb. A string is a plain label above the title. An array renders breadcrumbs, such as
[{ label: 'Users', to: '/admin/users' }, { label: 'Ada' }].
PageTabs modes. When the items have to, each tab is a route (link mode). With v-model, the tab whose value
matches is active (state mode). On narrow screens the strip scrolls sideways and hides icons.
PageSectionSwitcher label. label names the button for screen readers. The current section is appended to it.
Cards
The framed blocks a page is made of.
| Component | Props | Slots | Use |
|---|---|---|---|
SectionCard | title?, description?, icon?, loading?, flush? | header, actions, default, footer | A framed block of a page. flush removes the body padding. |
TableCard | title?, description?, loading?, refreshing? | default (the UTable), header, actions, footer | The frame a table sits in. footer holds TablePagination. |
StatCard | label, value?, hint?, icon?, to?, loading?, empty? | default (replaces value) | A number with a label. to links the card to the list it counts. |
ListCard | title, description?, loading?, isEmpty?, empty?, to?, toLabel? | default (<li> rows), actions | A short divided list with a "View all" link. |
DescriptionList | items: { key?, label, value? }[], empty?, loading?, align? | one slot per key | Label and value rows. A missing value shows "Not set". |
TableCard loading. loading shows skeleton rows. refreshing keeps the rows on screen and dims them while new
ones load. When to pass which is on Pages.
No table wrapper. Write <TableCard><UTable :ui="tableUi()" /></TableCard> yourself. A wrapper component would
lose the slot types of UTable.
Table rows
The cells and controls inside a list.
| Component | Props | Slots | Use |
|---|---|---|---|
TableIdentity | title, description?, avatar?: AvatarProps | badges | The first cell of a row: a name, a muted second line and an optional avatar. |
StatusBadge | status, label?, colors?: Record<string, StatusColor>, size?, icon? | none | A status as a subtle badge, coloured by statusColor. |
RowMenu | items: DropdownMenuItem[] | DropdownMenuItem[][], subject?, variant?: 'ghost' | 'outline', size?, label? | none | The ⋯ menu of a row or heading. |
TablePagination | total, v-model:page, v-model:page-size, pageSizes? | default ({ range }, replaces the range text) | The footer of a paginated list: "21–40 of 132", rows per page and pages. |
StatusBadge. colors recolours single statuses, such as { archived: 'warning' }. label defaults to the
status, so pass a translated one. Without a status or label it renders nothing. The colours are listed under
statusColor.
RowMenu. A click on the menu does not reach the row. Its accessible name is "Actions for {subject}", or label.
Use variant="outline" in a heading.
TablePagination. pageSizes defaults to [20, 50, 100]. The pages hide while everything fits on one page. A
new page size goes back to page 1.
Forms and dialogs
The pieces of create, edit and confirm flows. How they fit together is on Forms and actions.
| Component | Props | Slots | Use |
|---|---|---|---|
FormRow | every UFormField prop (a ui is merged) | every UFormField slot | One horizontal row of an inline settings form: label and hint left, control right. |
FormSlideover | title, description?, formId, submitLabel, cancelLabel?, loading?, disabled? | default (the form), footer({ cancel }) | A slideover for create and edit forms. Emits close. |
ConfirmDialog | title?, description?, confirmText?, cancelText?, destructive?, dismissible? | none | The modal behind useConfirmDialog. Emits close(boolean). |
FormRow. The label column takes a third of the row, at most 16rem. Rows stack below the sm breakpoint. Each
row holds one control, which gets the row's id. Sizing rules are on Pages.
FormSlideover footer. By default it shows Cancel and a submit button wired to form="<formId>". The footer slot
replaces both. It receives cancel, which closes the slideover with false.
ConfirmDialog. Open it through useConfirmDialog rather than
directly.
Empty states and the page root
UI has no empty-state component and no page wrapper:
- An empty state is Nuxt UI's
UEmpty, withvariant="naked"inside a card. - A page root is
<div class="flex flex-col gap-4">.
A complete detail page built from these components is on Pages.
Next steps
- Pages – combine these components into a list or a detail page.
- Forms and actions – build the create, edit and delete flows.
- Composables and helpers – look up
useConfirmDialogandtableUi.