fix: 顶部遮罩合并为横跨左右的一条

- 移除内容区 content-veil,只保留一条 fixed 遮罩
- 遮罩宽度从侧栏左边缘到内容区右边缘,左右同一水平高度
- 保留渐变与 blur(14px),验证 left=50 width=1340 top=148
This commit is contained in:
2026-10-31 16:28:14 +08:00
parent 50aea29ea6
commit 7a61acfa02
4 changed files with 20 additions and 10 deletions
+1 -1
View File
@@ -167,7 +167,7 @@ GET /api/backup SQLite 快照附件 需登录
- 当前 `PRAGMA user_version = 22`;`schema::migrate` 逐级升级:0 建全量、15→16→17→18→19→20→21→22、更高版本拒绝启动。
- 格式在 `entry.format`(apps / posters / articles),同组可混合;`node` 的旧 `view_mode` 仅保留兼容,不再决定渲染。
- `settings.sidebar.show_profile / show_service` 控制侧栏两张卡片显隐(默认 true)。
- 首页滚动:`#page-scroll`(Layout 的 body)是唯一滚动容器,搜索框固定在其上方;左右两栏顶部对齐,左侧到底后通过 `translateY` 吸底,右侧继续滚动;滚动条隐藏;侧栏顶部有独立 fixed 模糊遮罩(`backdrop-filter`),卡片半透明。
- 首页滚动:`#page-scroll`(Layout 的 body)是唯一滚动容器,搜索框固定在其上方;左右两栏顶部对齐,左侧到底后通过 `translateY` 吸底,右侧继续滚动;滚动条隐藏;顶部是一条横跨侧栏到内容区的固定模糊遮罩,卡片半透明。
- 本地服务是运行时卡片,但 `card` 表里有一行 `local-service` 只用于排序;内容来自 `/api/projects`,后端禁止删除/改名/配置分组。
- `node` 是统一分组树(根节点 `kind='section'`,子节点 `kind='group'` 可多层);`enabled` 控制启停;`icon` 可为空。
- 主要表:`node`、`entry`、`entry_tag`、`section_block`、`admin`、`session`、`setting`、`audit`。
+6
View File
@@ -147,6 +147,12 @@ DELETE /api/items/:id
## 11. 实施记录
### P22(2026-10-31,遮罩合并为整条)
- 去掉内容区自带的 `.content-veil`,只保留一条固定遮罩;
- 遮罩宽度从侧栏左边缘一直覆盖到内容区右边缘(实测 left=50、width=1340),左右同一水平高度(top=148),不再像两个块拼接;
- 渐变、模糊参数不变,滚动后整体淡入。
### P21(2026-10-31,侧栏虚化遮罩与透明度)
- 侧栏顶部增加独立 fixed 遮罩层:位置跟随侧栏左右/宽度,固定在滚动区顶部(y=148),滚动后淡入;
+7 -3
View File
@@ -1318,11 +1318,11 @@ a.entry-href:hover {
position: relative;
}
/* 侧栏进入滚动后,顶部做半透明虚化遮罩,避免内容被硬切 */
.sidebar-fade {
/* 侧栏到内容区共用一条滚动虚化遮罩,同一水平高度 */
.scroll-fade {
position: fixed;
z-index: 20;
height: 56px;
height: 64px;
pointer-events: none;
opacity: 0;
background: linear-gradient(
@@ -1335,6 +1335,10 @@ a.entry-href:hover {
transition: opacity var(--su-duration-fast) var(--su-ease-in-out);
}
.scroll-fade.is-visible {
opacity: 1;
}
.sidebar-fade.is-visible {
opacity: 1;
}
+6 -6
View File
@@ -223,17 +223,18 @@ export default function AppNext() {
// 独立渐隐层:固定在滚动区顶部,不随侧栏 transform 移动
const fade = document.createElement('div')
fade.className = 'sidebar-fade'
fade.className = 'scroll-fade'
fade.setAttribute('aria-hidden', 'true')
document.body.appendChild(fade)
const updateFade = () => {
if (!(sider instanceof HTMLElement)) return
const rect = sider.getBoundingClientRect()
fade.style.left = `${rect.left}px`
fade.style.width = `${rect.width}px`
const siderRect = sider.getBoundingClientRect()
const contentRect = content.getBoundingClientRect()
fade.style.left = `${siderRect.left}px`
fade.style.width = `${Math.max(0, contentRect.right - siderRect.left)}px`
fade.style.top = `${body.getBoundingClientRect().top}px`
fade.classList.toggle('is-visible', body.scrollTop > 4 && rect.width > 0)
fade.classList.toggle('is-visible', body.scrollTop > 4 && siderRect.width > 0)
}
const updateSticky = () => {
@@ -672,7 +673,6 @@ export default function AppNext() {
}
>
<div className="content">
<div className={`content-veil${scrolled ? ' is-visible' : ''}`} aria-hidden="true" />
<SearchBar value={keyword} onChange={setKeyword} inputRef={searchRef} />
<h1 className="sr-only">Stash 本地应用工作区</h1>