Common layout patterns and page structures
Tags: pattern layout structure
This guide covers common layout patterns for building applications with the theme library.
Application Shells
Dashboard Application
<!-- +layout.svelte -->
<script>
import { DashboardLayout } from '@classic-homes/theme-svelte';
const navigation = [
{
id: 'main',
items: [
{ id: 'dashboard', name: 'Dashboard', href: '/', icon: 'home' },
{ id: 'projects', name: 'Projects', href: '/projects', icon: 'folder' },
{ id: 'analytics', name: 'Analytics', href: '/analytics', icon: 'chart' },
],
},
{
id: 'settings',
title: 'Settings',
items: [
{ id: 'profile', name: 'Profile', href: '/settings/profile' },
{ id: 'team', name: 'Team', href: '/settings/team' },
],
},
];
const user = {
name: 'John Doe',
email: 'john@example.com',
initials: 'JD',
};
</script>
<DashboardLayout {navigation} {user}>
<slot />
</DashboardLayout>Marketing Site
<!-- +layout.svelte -->
<script>
import { PublicLayout } from '@classic-homes/theme-svelte';
const navigation = [
{ id: 'features', name: 'Features', href: '/features' },
{ id: 'pricing', name: 'Pricing', href: '/pricing' },
{ id: 'docs', name: 'Docs', href: '/docs' },
{ id: 'blog', name: 'Blog', href: '/blog' },
];
const footerLinks = [
{
id: 'product',
title: 'Product',
items: [
{ id: 'features', name: 'Features', href: '/features' },
{ id: 'pricing', name: 'Pricing', href: '/pricing' },
],
},
{
id: 'company',
title: 'Company',
items: [
{ id: 'about', name: 'About', href: '/about' },
{ id: 'blog', name: 'Blog', href: '/blog' },
],
},
];
</script>
<PublicLayout {navigation} {footerLinks}>
<slot />
</PublicLayout>Page Patterns
Dashboard Page
<script>
import { PageHeader, Section, Card, DataTable } from '@classic-homes/theme-svelte';
</script>
<div class="space-y-6">
<PageHeader title="Dashboard" subtitle="Welcome back, John">
{#snippet actions()}
<Button>New Project</Button>
{/snippet}
</PageHeader>
<!-- Stats Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<Card>
<Card.Header>
<Card.Title>Total Revenue</Card.Title>
</Card.Header>
<Card.Content>
<p class="text-3xl font-bold">$45,231</p>
<p class="text-sm text-muted-foreground">+20% from last month</p>
</Card.Content>
</Card>
<!-- More stat cards -->
</div>
<!-- Content Sections -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<Section title="Recent Activity">
<DataTable data={activities} columns={activityColumns} />
</Section>
<Section title="Quick Actions">
<!-- Action buttons -->
</Section>
</div>
</div>Settings Page
<script>
import { Tabs, TabPanel, Section } from '@classic-homes/theme-svelte';
const tabs = [
{ id: 'profile', label: 'Profile' },
{ id: 'security', label: 'Security' },
{ id: 'notifications', label: 'Notifications' },
];
</script>
<div class="max-w-4xl">
<PageHeader title="Settings" subtitle="Manage your account settings" />
<Tabs {tabs} class="mt-6">
<TabPanel id="profile">
<Section title="Personal Information">
<!-- Profile form -->
</Section>
</TabPanel>
<TabPanel id="security">
<Section title="Password">
<!-- Password form -->
</Section>
<Section title="Two-Factor Authentication" class="mt-6">
<!-- 2FA settings -->
</Section>
</TabPanel>
<TabPanel id="notifications">
<Section title="Email Notifications">
<!-- Notification toggles -->
</Section>
</TabPanel>
</Tabs>
</div>List/Detail Pattern
<!-- List page -->
<div class="space-y-4">
<PageHeader title="Projects">
{#snippet actions()}
<Button href="/projects/new">New Project</Button>
{/snippet}
</PageHeader>
<Card>
<DataTable
data={projects}
columns={projectColumns}
onRowClick={(project) => goto(`/projects/${project.id}`)}
/>
</Card>
</div>
<!-- Detail page -->
<div class="space-y-6">
<PageHeader title={project.name} subtitle={`Created ${formatDate(project.createdAt)}`}>
{#snippet actions()}
<Button variant="outline" href="/projects">Back</Button>
<Button href={`/projects/${project.id}/edit`}>Edit</Button>
{/snippet}
</PageHeader>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div class="lg:col-span-2 space-y-6">
<Section title="Details">
<!-- Project details -->
</Section>
</div>
<div>
<Section title="Activity">
<!-- Activity timeline -->
</Section>
</div>
</div>
</div>Content Layouts
Two Column with Sidebar
<div class="grid grid-cols-1 lg:grid-cols-[1fr,300px] gap-6">
<main>
<!-- Main content -->
</main>
<aside>
<!-- Sidebar content -->
</aside>
</div>Three Column
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>Column 1</div>
<div>Column 2</div>
<div>Column 3</div>
</div>Masonry-style Grid
<div class="columns-1 md:columns-2 lg:columns-3 gap-4 space-y-4">
{#each items as item}
<Card class="break-inside-avoid">
<!-- Card content -->
</Card>
{/each}
</div>Responsive Patterns
Stack to Grid
<div class="flex flex-col md:flex-row gap-4">
<div class="md:w-1/3">Sidebar</div>
<div class="md:w-2/3">Content</div>
</div>Hide on Mobile
<div class="hidden md:block">
<!-- Desktop only content -->
</div>
<div class="md:hidden">
<!-- Mobile only content -->
</div>Responsive Navigation
<nav class="flex items-center justify-between">
<Logo />
<!-- Desktop nav -->
<div class="hidden md:flex gap-4">
{#each navItems as item}
<a href={item.href}>{item.name}</a>
{/each}
</div>
<!-- Mobile menu button -->
<Button class="md:hidden" variant="ghost" onclick={toggleMenu}>Menu</Button>
</nav>Empty States
<div class="flex flex-col items-center justify-center py-12">
<svg class="h-16 w-16 text-muted-foreground/50 mb-4">
<!-- Empty state icon -->
</svg>
<h3 class="text-lg font-semibold mb-2">No projects yet</h3>
<p class="text-muted-foreground mb-4">Create your first project to get started.</p>
<Button href="/projects/new">Create Project</Button>
</div>Loading States
{#if loading}
<div class="space-y-4">
<Skeleton class="h-8 w-48" />
<div class="grid grid-cols-3 gap-4">
<Skeleton class="h-32" />
<Skeleton class="h-32" />
<Skeleton class="h-32" />
</div>
</div>
{:else}
<!-- Content -->
{/if}Best Practices
- Use layout components: DashboardLayout, PublicLayout, FormPageLayout
- Consistent spacing: Use
space-y-*andgap-*utilities - Responsive first: Design for mobile, enhance for desktop
- Logical grouping: Use Section and Card to organize content
- Clear hierarchy: Use PageHeader for page titles