# Layout 布局

经典的顶部 + 侧栏 + 内容 + 底部页面骨架，配合语义化子组件使用。

## 基础用法

<DemoBlock title="侧栏 + 头部 + 内容 + 底部">
  <oas-layout style="height: 300px; width: 100%">
    <oas-header slot="header">头部区域</oas-header>
    <oas-sider slot="sider">侧边栏</oas-sider>
    <oas-content slot="content">
      <oas-space direction="vertical" style="width: 100%">
        <p>主要内容区，可放置任意内容。</p>
        <oas-tag type="primary">flex 1</oas-tag>
      </oas-space>
    </oas-content>
    <oas-footer slot="footer">底部信息</oas-footer>
  </oas-layout>
</DemoBlock>

## 无侧栏

<DemoBlock title="头部 + 内容 + 底部">
  <oas-layout style="height: 260px; width: 100%">
    <oas-header slot="header">头部区域</oas-header>
    <oas-content slot="content">仅含头部与底部的内容布局。</oas-content>
    <oas-footer slot="footer">底部信息</oas-footer>
  </oas-layout>
</DemoBlock>

## 侧栏位置切换

<DemoBlock title="side：left / right / top">
  <oas-space direction="vertical" style="width: 100%">
    <oas-space size="small">
      <oas-button size="small" onclick="document.getElementById('layout-side').setAttribute('side','left')">左侧</oas-button>
      <oas-button size="small" onclick="document.getElementById('layout-side').setAttribute('side','right')">右侧</oas-button>
      <oas-button size="small" onclick="document.getElementById('layout-side').setAttribute('side','top')">顶部</oas-button>
    </oas-space>
    <oas-layout id="layout-side" style="height: 220px; width: 100%">
      <div slot="sider" style="background: var(--oas-color-bg-hover); padding: 12px; min-width: 140px">菜单</div>
      <oas-content slot="content">内容区：菜单位置可在 左 / 右 / 顶 之间切换（顶部建议复用 oas-menubar / oas-navigation-menu）。</oas-content>
    </oas-layout>
  </oas-space>
</DemoBlock>

`side` 属性（`left` 默认 / `right` / `top`）控制侧栏槽内容落位：默认左列、`right` 右列、`top` 顶部横向铺满——顶部菜单可复用现有水平导航（oas-menubar / oas-navigation-menu / oas-toolbar），布局只负责排出位置。

## 可折叠侧栏

<DemoBlock title="折叠侧栏 collapsed">
  <oas-space direction="vertical" style="width: 100%">
    <oas-button size="small" onclick="document.querySelector('#layout-sider').toggleAttribute('collapsed')">切换侧栏折叠</oas-button>
    <oas-layout style="height: 260px; width: 100%">
      <oas-header slot="header">头部区域</oas-header>
      <oas-sider id="layout-sider" slot="sider">侧边栏</oas-sider>
      <oas-content slot="content">点击上方按钮折叠 / 展开侧栏。</oas-content>
      <oas-footer slot="footer">底部信息</oas-footer>
    </oas-layout>
  </oas-space>
</DemoBlock>

**职责边界**：sider 的折叠触发器（折叠按钮、菜单折叠操作）归 `oas-sidebar` 负责——`oas-sidebar` 自带 `collapsible` 折叠能力并派发折叠事件，`oas-sider` 监听后同步自身 `collapsed` 窄条；`oas-layout` 只负责骨架排布（槽位、主轴方向、视口锁定），**不重复实现折叠触发逻辑**。

## 侧栏宽度（width）

`oas-sider` 的 `width` 属性显式指定轨道宽度（纯数字按 px，支持长度/百分比），缺省走 `--oas-sider-width` token（默认 200px）；折叠时仍按窄条契约（`--oas-sider-collapsed-width`，默认 64px）收窄——显式宽度与折叠契约互斥共存，解除折叠后恢复显式宽度。

<DemoBlock title="width 显式轨道宽度">
  <oas-space direction="vertical" style="width: 100%">
    <oas-layout style="height: 160px; width: 100%">
      <oas-sider slot="sider" width="280">width=280 侧栏</oas-sider>
      <oas-content slot="content">内容区：轨道宽度由 width 属性显式指定为 280px（缺省为 --oas-sider-width 的 200px）。</oas-content>
    </oas-layout>
    <oas-layout style="height: 160px; width: 100%">
      <oas-sider slot="sider" width="280" collapsed>折叠中</oas-sider>
      <oas-content slot="content">折叠时窄条契约优先（--oas-sider-collapsed-width，64px），width 让位；解除折叠恢复 280px。</oas-content>
    </oas-layout>
  </oas-space>
</DemoBlock>

## 视口锁定布局

`viewport`：admin 后台模式——布局锁定视口高，**顶栏/底栏固定，侧栏与内容各自独立滚动**（页面整体不出滚动条）。默认不带此属性时是整页滚动模型（内容多高页面多高）。

高度默认 `100dvh`（移动端地址栏友好，不支持时级联回退 `100vh`），可用 `--oas-layout-height` 改为 `100%` / `calc(...)` 等（下面 demo 为便于展示锁定为 320px）。

<DemoBlock title="视口锁定（viewport）+ 内嵌侧栏">
  <oas-layout id="layout-viewport" viewport style="--oas-layout-height: 320px; width: 100%">
    <oas-header slot="header">顶栏固定（不随内容滚动）</oas-header>
    <oas-sider slot="sider">
      <oas-sidebar id="layout-viewport-sidebar" collapsible items='[
        {"label":"仪表盘","value":"1","icon":"star"},
        {"label":"订单管理","value":"2","icon":"edit"},
        {"label":"商品管理","value":"3","icon":"heart"},
        {"label":"用户管理","value":"4","icon":"user"},
        {"label":"营销中心","value":"5","icon":"mail"},
        {"label":"财务结算","value":"6","icon":"lock"},
        {"label":"数据报表","value":"7","icon":"calendar"},
        {"label":"物流配置","value":"8","icon":"upload"},
        {"label":"消息通知","value":"9","icon":"info"},
        {"label":"权限管理","value":"10","icon":"filter"},
        {"label":"日志审计","value":"11","icon":"clock"},
        {"label":"系统设置","value":"12","icon":"gear"}
      ]'></oas-sidebar>
    </oas-sider>
    <oas-content slot="content">
      <div id="layout-viewport-content" style="padding: var(--oas-space-4)">
        <p>内容区独立滚动——向下滚动长内容，注意左侧侧栏与顶部顶栏保持不动。</p>
        <p>段落 1：视口锁定模式下，侧栏与内容各自在本区内滚动。</p>
        <p>段落 2：页面（body）不产生滚动条。</p>
        <p>段落 3：内嵌侧栏自动填满轨道宽度（sider 管宽、sidebar 跟随）。</p>
        <p>段落 4：滚动到这里时，顶栏仍然可见。</p>
        <p>段落 5：继续向下……</p>
        <p>段落 6：内容再长也只滚内容区。</p>
        <p>段落 7：侧栏菜单超出视口时，在侧栏内独立滚动。</p>
        <p>段落 8：适合后台管理系统的主框架布局。</p>
        <p>段落 9：顶栏固定 + 双区独立滚动的经典组合。</p>
        <p>段落 10：到 demo 底部了。</p>
      </div>
    </oas-content>
    <oas-footer slot="footer">底部固定</oas-footer>
  </oas-layout>
</DemoBlock>

> 内嵌宽度契约：`oas-sider` 管轨道宽度（`--oas-sider-width`，默认 200px，折叠 64px），内嵌的 `oas-sidebar` 自动填满轨道（不再用自身默认 220px，轨道 padding 同时卸除）；`oas-sidebar` 独立使用时仍走 `--oas-sidebar-width`（默认 220px）。两个变量职责：**sider 管轨道、sidebar 管独立**，改任一侧都不会错位。

**对照说明**：固定头部 / 固定侧栏（fixed 定位）是经典后台布局场景——`viewport` 视口锁定模式即为此而设：顶栏/底栏天然固定、侧栏与内容各自独立滚动，等价覆盖该类需求而无需手动套 fixed 定位，语义更现代。

## API

| 组件          | 说明                                                                   |
| ------------- | ---------------------------------------------------------------------- |
| `oas-layout`  | 布局容器（含侧栏时自动横向排布）                                       |
| `oas-header`  | 顶栏，渲染为 `<header>`                                                |
| `oas-sider`   | 侧栏，`collapsed` 属性折叠为窄条，渲染为 `<aside aria-label="侧边栏">` |
| `oas-content` | 内容区，渲染为 `<main>`                                                |
| `oas-footer`  | 底部，渲染为 `<footer>`                                                |

子组件需带对应 `slot` 属性（`header` / `sider` / `content` / `footer`）。

### oas-layout

#### 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `side` | 侧栏位置：`left`（默认）/ `right` / `top`；非法值回落 `left`；`top` 时侧栏槽占满整行宽（可复用水平导航组件） | `string` | `left` |
| `viewport` | 视口锁定模式：布局锁定视口高（默认 100dvh，不支持级联回退 100vh；`--oas-layout-height` 可改 100%/calc()），顶栏/底栏固定，侧栏与内容各自独立滚动；默认为整页滚动模型 | `boolean` | — |

#### 插槽

| 名称 | 说明 |
| --- | --- |
| `content` | 主内容区 |
| `footer` | 底部区 |
| `header` | 顶部区 |
| `sider` | 侧边区 |

#### CSS 变量

| CSS 变量 | 默认值 |
| --- | --- |
| `--oas-layout-height` | `100dvh` |

### oas-header

#### 插槽

| 名称 | 说明 |
| --- | --- |
| 默认 | 顶部内容 |

### oas-sider

#### 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| `collapsed` | 折叠为窄条（存在即折叠） | `boolean` | — |
| `width` | 轨道宽度显式覆盖（纯数字按 px；折叠时窄条契约优先，缺省走 --oas-sider-width） | `string` | — |

#### 插槽

| 名称 | 说明 |
| --- | --- |
| 默认 | 侧边内容 |

#### CSS 变量

| CSS 变量 | 默认值 |
| --- | --- |
| `--oas-sider-collapsed-width` | `64px` |
| `--oas-sider-width` | `200px` |

### oas-content

#### 插槽

| 名称 | 说明 |
| --- | --- |
| 默认 | 内容区 |

### oas-footer

#### 插槽

| 名称 | 说明 |
| --- | --- |
| 默认 | 底部内容 |
