AppShell
A header + sidebar + main + aside + footer CSS Grid layout — a recommended starting point for full-app scaffolding.
Basic usage
AppShell fixes the most common layout regions: a sticky header, a left sidebar, an optional right aside, the main area, and a footer. Each region is a named slot / prop — leaving it empty omits the region.
The sidebar width is controlled via sidebarWidth (number, px); sidebarCollapsed=true shrinks the sidebar to zero width while keeping its DOM, which is convenient for responsive toggling.
<script setup lang="ts">
import { ref } from 'vue';
import { CfAppShell, CfButton } from '@chufix-design/vue';
const collapsed = ref(false);
</script>
<template>
<div style="height: 360px; border: 1px solid var(--line-1); border-radius: 8px; overflow: hidden;">
<CfAppShell :sidebar-collapsed="collapsed" :sidebar-width="180">
<template #header>
<div style="display:flex; align-items:center; gap: 12px; width: 100%;">
<CfButton size="sm" variant="tertiary" @click="collapsed = !collapsed">
{{ collapsed ? '展开侧栏' : '收起侧栏' }}
</CfButton>
<strong style="margin-right:auto;">My App</strong>
<span style="font-size: 12px; color: var(--fg-3);">[email protected]</span>
</div>
</template>
<template #sidebar>
<nav style="padding: 12px;">
<div style="font-size: 11px; color: var(--fg-3); padding: 0 8px 6px;">导航</div>
<a href="#" style="display:block; padding: 6px 8px; border-radius: 4px; background: var(--accent-soft); color: var(--accent-1); font-size: 13px;">概览</a>
<a href="#" style="display:block; padding: 6px 8px; border-radius: 4px; color: var(--fg-2); font-size: 13px;">分析</a>
<a href="#" style="display:block; padding: 6px 8px; border-radius: 4px; color: var(--fg-2); font-size: 13px;">订单</a>
<a href="#" style="display:block; padding: 6px 8px; border-radius: 4px; color: var(--fg-2); font-size: 13px;">用户</a>
<a href="#" style="display:block; padding: 6px 8px; border-radius: 4px; color: var(--fg-2); font-size: 13px;">设置</a>
</nav>
</template>
<template #footer>
© ChuFix · v0.0.1
</template>
<div style="padding: 24px;">
<h2 style="margin: 0 0 6px; font-size: 18px;">主区域</h2>
<p style="margin: 0; color: var(--fg-2);">点击左上角按钮可以收起 / 展开侧栏。</p>
</div>
</CfAppShell>
</div>
</template>
import { useState } from 'react';
import { CfAppShell, CfButton } from '@chufix-design/react';
export default function Demo() {
const [collapsed, setCollapsed] = useState(false);
return (
<CfAppShell
sidebarCollapsed={collapsed}
sidebarWidth={180}
header={
<>
<CfButton size="sm" variant="tertiary" onClick={() => setCollapsed((v) => !v)}>
{collapsed ? 'Expand sidebar' : 'Collapse sidebar'}
</CfButton>
<strong>My App</strong>
</>
}
sidebar={<nav>Navigation list</nav>}
footer={<>© ChuFix</>}
>
<div>Main content</div>
</CfAppShell>
);
} Layout regions
┌──────────────────────────────────────────┐
│ header (sticky) │
├────────┬──────────────────┬──────────────┤
│ │ │ │
│ side- │ main │ aside │
│ bar │ │ (right col) │
│ │ │ │
├────────┴──────────────────┴──────────────┤
│ footer │
└──────────────────────────────────────────┘
headerdefaults toposition: sticky; top: 0and stays pinned while the main area scrollssidebar/aside/maineach have their ownoverflow-y: autoand scroll independently; all useoverscroll-behavior: containto prevent scroll chaining- The whole shell uses
display: grid, with regions defined bygrid-template-areas
With a right aside
The aside slot enables the rightmost column — useful for detail panels, outlines, or tip rails. asideWidth controls its width.
<script setup lang="ts">
import { CfAppShell } from '@chufix-design/vue';
</script>
<template>
<CfAppShell :sidebar-width="160" :aside-width="200">
<template #header><strong>顶栏</strong></template>
<template #sidebar><nav>左侧导航</nav></template>
<template #aside>
<div style="padding: 8px;">右侧 aside — 详情 / 大纲 / 提示</div>
</template>
<template #footer>底栏</template>
<div style="padding: 12px;">主内容区,左右两侧栏 + 顶底栏的完整脚手架。</div>
</CfAppShell>
</template>
<CfAppShell
sidebarWidth={160}
asideWidth={200}
header={<>Header</>}
sidebar={<>Left navigation</>}
aside={<>Right aside</>}
footer={<>Footer</>}
>
<div>Main content</div>
</CfAppShell> Three density variants
variant controls the overall font size / spacing tier — default / condensed (compact admin) / spacious (landing pages or large screens).
<script setup lang="ts">
import { CfAppShell } from '@chufix-design/vue';
</script>
<template>
<div class="demo-stack">
<div>
<div style="font-size: 12px; color: var(--fg-3); margin-bottom: 4px;">variant = condensed</div>
<CfAppShell variant="condensed" :sidebar-width="140">
<template #header>condensed 顶栏</template>
<template #sidebar>侧栏</template>
<div style="padding: 8px;">紧凑型 — 整体字号小一档</div>
</CfAppShell>
</div>
<div>
<div style="font-size: 12px; color: var(--fg-3); margin-bottom: 4px;">variant = spacious</div>
<CfAppShell variant="spacious" :sidebar-width="160">
<template #header>spacious 顶栏</template>
<template #sidebar>侧栏</template>
<div style="padding: 12px;">宽松型 — 字号 / 内距大一档</div>
</CfAppShell>
</div>
</div>
</template>
<CfAppShell variant="condensed">…</CfAppShell>
<CfAppShell variant="spacious">…</CfAppShell> API
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'condensed' | 'spacious' | 'default' | Overall font size tier |
sidebarWidth | number | 240 | Sidebar width (px) |
headerHeight | number | auto | Fixed header height (px); auto-fits content when omitted |
bordered | boolean | true | Whether the sidebar shows a right border |
sidebarCollapsed | boolean | false | Whether to collapse the sidebar (visual width 0) |
Vue slots: header / sidebar / aside / footer / default (main).
React accepts the same names as ReactNode props; main content goes through children.
反馈与讨论
AppShell · Discussion