page-layouts
GitHub指导在Tabler项目中选择并配置页面布局,涵盖DefaultLayout等9种布局的适用场景、内容属性及UI控制标志,规范页面结构组件的使用。
Trigger Scenarios
Install
npx skills add tabler/tabler --skill page-layouts -g -y
SKILL.md
Frontmatter
{
"name": "page-layouts",
"description": "Pick and configure the right layout for a Tabler preview page, and change or add a layout in `shared\/layouts\/`. Use whenever a page needs different page chrome — sidebar, navbar variant, boxed\/fluid body, centered card, error or marketing page — whenever a page hand-rolls a page header or wrapper markup, and before adding a new layout file. Covers the layout map, the `DefaultLayout` props, the page-header slot, and the rules for a new layout."
}
Page layouts
Layouts own the page chrome: <head>, assets, body classes, navbar/sidebar, page header, footer. A page supplies content and a handful of props — never its own header block, wrapper divs, or <html> scaffolding.
1. Which layout
| Layout | Use for |
|---|---|
DefaultLayout |
the normal app page — navbar/sidebar, page header, footer (98 of the preview pages) |
SingleLayout |
centered card on an empty page: sign-in, sign-up, error-ish flows (containerSize, hideLogo) |
SettingsLayout |
settings pages — wraps the body in a card with the settings nav (active) |
ProseLayout |
long-form text in a card-lg + .prose body (terms, changelog) |
ErrorLayout |
error pages, content driven by pageError keyed into errors.json |
MarketingLayout |
marketing/landing pages with the marketing navbar and footer |
PayLayout |
minimal checkout chrome: small logo + close button |
RedirectLayout |
bare meta-refresh document (url, base) |
BaseLayout |
only when a page needs no chrome at all (screenshot/playground pages). Everything above wraps it. |
Docs pages do not choose a layout — docs/pages/[...slug].astro renders the collection through DocsLayout, and MDX front matter has no layout: key.
2. DefaultLayout — content props
| Prop | Effect |
|---|---|
title |
<title> and, by default, the page header title |
pageHeader |
header title when it differs from title; pageHeader={false} removes the header |
pretitle |
small line above the title (page-pretitle) |
description |
line under the title and <meta name="description"> |
pageMenu |
menu entry to highlight, e.g. base.badges — must match a key in shared/data/menu.json |
pageLibs |
third-party libs to load, keyed into core/libs.json (['apexcharts']) |
pageHeaderFile |
swaps the title block for a prebuilt header ("profile", "uptime") |
Do not pass pageHeader when it repeats title — the fallback already covers it.
3. DefaultLayout — chrome flags
Every page renders both navigations — the vertical sidebar and the horizontal navbar — and the layout is chosen by data-bs-* attributes on <html>, which the theme settings panel can change at runtime. Props that map to an attribute state the page's own layout; a visitor's stored choice still wins.
| Prop | Result |
|---|---|
navbarPosition |
data-bs-navbar-position — horizontal (default) or vertical |
layout |
data-bs-layout — fluid or boxed |
navbarSticky |
data-bs-navbar="sticky" |
navbarDark |
data-bs-navbar-theme="dark" — the dark palette on whichever navigation shows |
sidebarMode |
data-bs-sidebar — folded or folded-hover |
sidebarEnd, sidebarFoldToggle |
sidebar markup: end side, pin button |
navbarTransparent, navbarCondensed, navbarOverlap |
navbar markup variants |
wrapperFull |
page-wrapper-full, drops the .container-xl around the body |
containerCentered, containerClass |
my-auto / extra classes on the .container-xl |
bodyClass |
free-form body classes; use layout for the container width |
rtl |
dir="rtl" plus the RTL stylesheets |
There is no sidebar, hideTopbar or sidebarUser prop any more: which navigation shows is navbarPosition, not which one is rendered, and the sidebar always carries the user block, like the navbar always carries the user menu.
4. The page-header slot
Anything to the right of the title goes in the page-header-actions slot, as a direct child of the layout:
<DocsLink slot="page-header-actions" path="/ui/components/badge" />
<HeaderActionsButtons slot="page-header-actions" />
Prebuilt groups live in shared/components/layout/ (HeaderActionsButtons, HeaderActionsPrint, HeaderActionsPhotos, HeaderActionsBreadcrumb, …). The header renders the actions column only when the slot has content.
5. Never hand-roll chrome
If a page contains <div class="page-header">, <h2 class="page-title">, page-wrapper, page-body, or its own <head> markup, that is a layout prop that was missed. Add or extend the prop instead of duplicating the markup — the same header exists on 100+ pages and drifts the moment one copy is edited.
6. Adding or changing a layout
- A new layout wraps
BaseLayout(orDefaultLayoutwhen it only reshapes the body, likeSettingsLayoutandProseLayout). It never re-emits<html>, assets, or theme settings. - Every prop gets a doc comment naming the class or front-matter key it maps to — follow the existing style in
DefaultLayout. - Booleans default to off; content props are optional with a sensible fallback.
- Keep
<!-- BEGIN … -->/<!-- END … -->markers around structural blocks: users copy the rendered HTML. - Pass
pageLibsthrough toBaseLayoutso pages using the new layout can still load plugins. - Changing a shared layout touches every page that uses it — prove it with the
html-diffskill.
7. Checklist
- Layout chosen from the table, not
BaseLayoutplus hand-written chrome -
title,description,pageMenuset; nopageHeaderrepeatingtitle - Chrome via named flags,
bodyClassonly forlayout-boxed/layout-fluid - Header extras in the
page-header-actionsslot -
pageLibslisted for every plugin the page initialises - Page opened in the browser (
astro-devskill);html-diffrun if a shared layout changed
Version History
- 340f719 Current 2026-09-22 21:47


