From 93bb5cbb28e17c8bfbf1824caabf0a6498ae8fdd Mon Sep 17 00:00:00 2001 From: CNWei Date: Sun, 1 Nov 2026 15:15:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20Layout=20=E6=96=B0=E5=A2=9E=20toolb?= =?UTF-8?q?ar=20=E6=8F=92=E6=A7=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 页头与页身之间的一条真实占位带(搜索 / 筛选 / 操作),宽度跟随容器, contained 时与侧栏 + 内容同宽,height=screen 下不参与内容区滚动。 用它替代「搜索框 fixed + contentOffset 让位」的写法。 - Layout.tsx / Layout.module.css:新增 toolbar prop 与样式 - 展示页 #layout 增加「页头下的工具条」示例 - COMPONENTS.md 补契约、与 contentOffset 的分工说明、changelog --- docs/COMPONENTS.md | 3 +++ site/app.css | 13 ++++++++++ site/sections/PageLayout.tsx | 43 +++++++++++++++++++++++++++++++- src/components/Layout.module.css | 7 ++++++ src/components/Layout.tsx | 8 ++++++ 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/docs/COMPONENTS.md b/docs/COMPONENTS.md index 091e106..9584265 100644 --- a/docs/COMPONENTS.md +++ b/docs/COMPONENTS.md @@ -500,6 +500,7 @@ | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `header` | `ReactNode` | — | 页头,默认吸顶(半透明 + 模糊) | + | `toolbar` | `ReactNode` | — | 页头与页身之间的工具条(搜索 / 筛选 / 操作带),宽度随容器,不参与内容区滚动 | | `sider` | `ReactNode` | — | 左侧栏,固定宽度 | | `aside` | `ReactNode` | — | 右侧栏,固定宽度(目录 / 聚合 / 广告位) | | `footer` | `ReactNode` | — | 页脚 | @@ -522,6 +523,7 @@ | `contentId` | `string` | — | 内容区 id(供 ScrollTop 等按 id 滚动) | - **规则**:Layout 不写业务内容,也不带背景装饰(需要渐变/光晕时由页面自己放绝对定位层);响应式在组件内处理——≤1200px 右栏堆到内容下方、≤1100px 侧栏堆到内容上方,**内容都不隐藏**。 +- **`toolbar` 与 `contentOffset` 的分工**:`toolbar` 是**真实占位**的一层,搜索框照常参与文档流,侧栏与内容的顶边天然对齐(推荐);`contentOffset` 只用于「浮在页面上、不能占位」的场景(悬浮条、绝对定位的返回按钮),不要把两者叠加使用。 - **常用配方**:顶栏+内容(首页)、左栏+内容(管理页)、内容+右栏(文章)、三栏(工作台)、窄内容(设置/阅读),展示页用 `Segmented` 切换。 - **展示页**:`#layout` @@ -700,3 +702,4 @@ | 2026-10-29 | 新增 `Textarea`(`rows` / `resize` / `invalid`),与 `Input` 共用边框与焦点样式。兼容性:纯新增 | | 2026-10-29 | 新增 `PasswordInput`(`icon` / `size` / `toggle`):锁图标 + 显隐切换 + `aria-pressed`,事件语义与 `Input` 一致。兼容性:纯新增 | | 2026-10-30 | **修复**:`PasswordInput` 的眼睛按钮移入输入框内部(`Input` 新增 `suffix` 插槽);`Input` 隐藏 Edge 原生 `::-ms-reveal` / `::-ms-clear`,避免与自带显隐按钮叠成两个眼睛。兼容性:`Input` 新增可选 prop,无破坏性;`PasswordInput` API 不变、仅外观变化 | +| 2026-10-31 | `Layout` 新增 `toolbar` 插槽:页头与页身之间的一条真实占位带(搜索 / 筛选 / 操作),宽度跟随容器(`contained` 时与侧栏 + 内容同宽),在 `height="screen"` 下不参与内部滚动。用它替代「搜索框 fixed + `contentOffset` 让位」的写法,页面不再需要用 JS 改 DOM 尺寸。兼容性:纯新增可选 prop,`contentOffset` 行为不变 | diff --git a/site/app.css b/site/app.css index 6079521..afaa587 100644 --- a/site/app.css +++ b/site/app.css @@ -562,6 +562,19 @@ code { gap: var(--su-space-1); } +/* 工具条:页头与页身之间的一条搜索带(toolbar 插槽) */ +.layout-toolbar { + display: flex; + align-items: center; + justify-content: center; + padding: var(--su-space-3) var(--su-space-5); + border-bottom: 1px solid var(--su-border); +} + +.layout-toolbar > * { + width: min(360px, 100%); +} + .layout-side { display: flex; flex-direction: column; diff --git a/site/sections/PageLayout.tsx b/site/sections/PageLayout.tsx index 3fd3fe9..8437341 100644 --- a/site/sections/PageLayout.tsx +++ b/site/sections/PageLayout.tsx @@ -1,5 +1,5 @@ import { useState } from 'react' -import { Card, Grid, Layout, Segmented, Space, Tag, Text, Title } from '../../src' +import { Card, Grid, Input, Layout, Segmented, Space, Tag, Text, Title } from '../../src' import { Demo } from '../components/Demo' import { PropsTable } from '../components/PropsTable' import { Section } from '../components/Section' @@ -214,9 +214,50 @@ export function PageLayout() { + } + toolbar={} + sider={