Page Header System
Page Header System The Page Header System allows you to register custom page headers that appear at the top of each page, providing context and navigation information to users. Table of Contents Overview Basic Usage Header Variants Gradient Options Leading icon Stats Display Adva
Page Header System
The Page Header System allows you to register custom page headers that appear at the top of each page, providing context and navigation information to users.
Table of Contents
- Overview
- Basic Usage
- Header Variants
- Gradient Options
- Leading icon
- Stats Display
- Advanced Features
- Real-World Examples
- Best Practices
- API Reference
Overview
Page headers provide:
- Title and Description: Clear page context for users
- Leading icon: Optional icon beside the title (or resolved from the sidebar menu for the current route)
- Stats Display: Show key metrics at a glance
- Visual Variants: Different layouts for different use cases
- Accent strip: When gradient is not none, a subtle horizontal tint runs behind the header row (not a full-page background)
- Auto-Cleanup: Headers automatically cleared on route change
Basic Usage
Simple Page Header
<script setup>
const { registerPageHeader } = usePageHeaderRegistry();
registerPageHeader({
title: "Dashboard",
description: "Welcome to your dashboard",
variant: "minimal",
gradient: "cyan"
});
</script>
Page Header with Description
<script setup>
const { registerPageHeader } = usePageHeaderRegistry();
registerPageHeader({
title: "User Management",
description: "Manage user accounts, roles, and permissions",
variant: "default",
gradient: "blue"
});
</script>
Header Variants
Default Variant
Standard layout with title, description, and optional stats.
registerPageHeader({
title: "Collections",
description: "Manage your data collections",
variant: "default",
gradient: "purple"
});
Minimal Variant
Compact layout focusing on title only.
registerPageHeader({
title: "Dashboard",
variant: "minimal",
gradient: "cyan"
});
Stats Focus Variant
Emphasizes statistics display.
registerPageHeader({
title: "Analytics",
description: "View your analytics data",
variant: "stats-focus",
gradient: "blue",
stats: [
{ label: "Total Users", value: 1250 },
{ label: "Active Sessions", value: 42 }
]
});
Gradient Options
gradient controls two things: (1) a light horizontal strip behind the header row, and (2) colors for the leading icon tile when an icon is shown.
- purple / blue / cyan: Tinted strip + matching icon shell
- none: No strip; icon shell uses neutral surface styling
// Accent strip + icon shell (purple family)
registerPageHeader({
title: "Settings",
gradient: "purple"
});
// No accent strip (neutral icon tile if icon is shown)
registerPageHeader({
title: "Simple Page",
gradient: "none"
});
Leading icon
leadingIcon: Iconify / Nuxt UI icon name (e.g.i-lucide-layout-dashboard). Shown in a rounded tile next to the title.hideLeadingIcon: true: Never show the icon tile (even if the menu has an icon for this path).- Default: If you omit
leadingIconand do not hide it, the app tries to use the menu icon registered for the current route (useMenuRegistry/findMenuIconForPath).
Stats Display
Basic Stats
const { registerPageHeader } = usePageHeaderRegistry();
registerPageHeader({
title: "User Manager",
stats: [
{ label: "Total Users", value: 1250 },
{ label: "Active", value: 892 },
{ label: "Pending", value: 45 }
]
});
Reactive stats
Update the header whenever the underlying numbers change (same pattern as dynamic titles):
<script setup>
const totalCount = ref(0);
const activeCount = ref(0);
const { registerPageHeader } = usePageHeaderRegistry();
watch([totalCount, activeCount], () => {
registerPageHeader({
title: "Dashboard",
stats: [
{ label: "Total", value: totalCount.value },
{ label: "Active", value: activeCount.value },
],
});
}, { immediate: true });
onMounted(async () => {
const data = await fetchStats();
totalCount.value = data.total;
activeCount.value = data.active;
});
</script>
Advanced Features
Conditional Page Headers
<script setup>
const route = useRoute();
const { registerPageHeader } = usePageHeaderRegistry();
// Only show header on specific route
if (route.name === 'dashboard') {
registerPageHeader({
title: "Dashboard",
variant: "minimal"
});
}
</script>
Dynamic titles and stats
registerPageHeader stores a plain snapshot of the config (not reactive refs inside the object). When the title or stats depend on async data, use watch (or watchEffect) and call registerPageHeader again when values change.
<script setup>
const route = useRoute();
const tableName = computed(() => String(route.params.table ?? ""));
const recordCount = ref(0);
const { registerPageHeader } = usePageHeaderRegistry();
watch([tableName, recordCount], ([name, count]) => {
if (!name) return;
registerPageHeader({
title: `${name} data`,
description: "Browse and manage records",
gradient: "purple",
stats: [
{ label: "Total", value: count },
],
});
}, { immediate: true });
</script>
Checking Header Status
<script setup>
const { hasPageHeader, pageHeader } = usePageHeaderRegistry();
// Check if header is registered
if (hasPageHeader.value) {
console.log('Current header:', pageHeader.value);
}
</script>
Real-World Examples
1. Data Table Page
<template>
<div class="p-6">
<!-- Data table content -->
</div>
</template>
<script setup>
const route = useRoute();
const tableName = computed(() => String(route.params.table ?? ""));
const { data: records } = useApi(() => `/${tableName.value}`);
const { registerPageHeader } = usePageHeaderRegistry();
watch(
[tableName, records],
() => {
const name = tableName.value;
if (!name) return;
registerPageHeader({
title: `${name} data`,
description: `Browse and manage ${name} records`,
variant: "default",
gradient: "blue",
stats: [
{ label: "Total Records", value: records.value?.meta?.totalCount ?? 0 },
{ label: "Showing", value: records.value?.data?.length ?? 0 },
],
});
},
{ immediate: true, deep: true },
);
</script>
2. Settings Page
<template>
<div class="settings-page">
<h2>General Settings</h2>
<!-- Settings form -->
</div>
</template>
<script setup>
const { registerPageHeader } = usePageHeaderRegistry();
registerPageHeader({
title: "Settings",
description: "Configure application settings and preferences",
variant: "minimal",
gradient: "purple"
});
</script>
3. Analytics Dashboard
<template>
<div class="analytics-dashboard">
<!-- Charts and analytics -->
</div>
</template>
<script setup>
const totalUsers = ref(0);
const activeUsers = ref(0);
const revenue = ref(0);
const { registerPageHeader } = usePageHeaderRegistry();
watch([totalUsers, activeUsers, revenue], () => {
registerPageHeader({
title: "Analytics",
description: "Real-time analytics and insights",
variant: "stats-focus",
gradient: "cyan",
stats: [
{ label: "Total Users", value: totalUsers.value.toLocaleString() },
{ label: "Active Now", value: activeUsers.value },
{ label: "Revenue", value: `$${revenue.value.toLocaleString()}` },
],
});
}, { immediate: true });
// Fetch analytics data
onMounted(async () => {
const { data } = await useApi('/analytics');
totalUsers.value = data.value.totalUsers;
activeUsers.value = data.value.activeUsers;
revenue.value = data.value.revenue;
});
</script>
Best Practices
1. Use Appropriate Variants
// Dashboard/landing pages
{ variant: "minimal" }
// Data listing pages
{ variant: "default", stats: [...] }
// Analytics pages
{ variant: "stats-focus", stats: [...] }
2. Match Gradient to Content
// Data/collections
{ gradient: "blue" }
// Settings/configuration
{ gradient: "purple" }
// Dashboard/overview
{ gradient: "cyan" }
3. Keep Descriptions Concise
// Good
{ description: "Manage user accounts and permissions" }
// Too long
{ description: "This page allows you to manage all user accounts in the system including creating new users, editing existing users, and configuring their permissions..." }
4. Use Reactive Stats
// Good - reactive
const stats = computed(() => [
{ label: "Total", value: count.value }
]);
// Avoid - static
const stats = [
{ label: "Total", value: 100 }
];
5. Clear Headers When Not Needed
const { clearPageHeader } = usePageHeaderRegistry();
// Clear when navigating away
onUnmounted(() => {
clearPageHeader();
});
API Reference
PageHeaderConfig Interface
interface PageHeaderConfig {
title: string; // Page title (required)
description?: string; // Page description
stats?: PageHeaderStat[]; // Statistics to display
variant?: "default" | "minimal" | "stats-focus"; // Layout variant
gradient?: "purple" | "blue" | "cyan" | "none"; // Header strip + leading icon tint
leadingIcon?: string; // Icon name; if omitted, menu icon for route may be used
hideLeadingIcon?: boolean; // If true, no leading icon tile
}
PageHeaderStat Interface
interface PageHeaderStat {
label: string; // Stat label
value: string | number; // Stat value
}
usePageHeaderRegistry()
const {
// Read-only current header config
pageHeader: Readonly<Ref<PageHeaderConfig | null>>,
// Check if header is registered
hasPageHeader: ComputedRef<boolean>,
// Register page header
registerPageHeader: (config: PageHeaderConfig) => void,
// Clear page header
clearPageHeader: () => void
} = usePageHeaderRegistry();
Summary
The Page Header System provides:
Consistent page headers across the application
Multiple layout variants for different page types
Accent strip + optional leading icon (menu-driven or explicit)
Stats display for key metrics
Auto-cleanup on route changes
Update via watch when title or stats change
Related Documentation: - Header Actions - Adding actions to headers - Form System - Dynamic form generation