自动滚动改为折叠进场时预量最终高度;侧栏导航按钮间距加大
原来在 nextTick 量高度,此时折叠动画刚从 0 起步,配置展开量到 0 不滚, 链式代理量到半截滚一半。enter 钩子触发时元素刚插入、还是自然高度, 在把高度压到 0 之前先量,得到的就是折叠结束后的位置,滚动和折叠同时 开跑。触发点也从开关挪进 foldEnter,两个包装函数随之删掉。
This commit is contained in:
+1
-1
@@ -239,7 +239,7 @@ const current = computed(() => NAV.find((n) => n.key === active.value))
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 2px;
|
gap: var(--s-1);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-16
@@ -132,22 +132,19 @@ const open = ref(false)
|
|||||||
const rootEl = ref<HTMLElement | null>(null)
|
const rootEl = ref<HTMLElement | null>(null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 展开配置或拨开链式代理后,详情底部可能长到窗口外,把新出现的内容滚进视野。
|
* 详情底部长出窗口外时,把新内容滚进视野。必须在 foldEnter 把高度压到 0 之前调:
|
||||||
* 只挂在这两个动作上:tab 切换也会变高度,但来回切 tab 时页面跟着跳只会晕。
|
* 那一刻元素刚插入、还是自然高度,量到的 bottom 就是折叠结束后的最终位置,
|
||||||
|
* 滚动因此能和折叠同时开跑、停在正确的地方;动画中途量到的只有半截。
|
||||||
|
* 只由配置展开和链式代理拨开触发(见 foldEnter):tab 切换也变高度,但不滚,
|
||||||
|
* 来回切 tab 时页面跟着跳只会晕。
|
||||||
*/
|
*/
|
||||||
async function revealBottom() {
|
function revealBottom() {
|
||||||
await nextTick()
|
|
||||||
const el = rootEl.value
|
const el = rootEl.value
|
||||||
if (!el) return
|
if (!el) return
|
||||||
const gap = el.getBoundingClientRect().bottom + 16 - window.innerHeight
|
const gap = el.getBoundingClientRect().bottom + 16 - window.innerHeight
|
||||||
if (gap > 0) window.scrollBy({ top: gap, behavior: 'smooth' })
|
if (gap > 0) window.scrollBy({ top: gap, behavior: 'smooth' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleOpen() {
|
|
||||||
open.value = !open.value
|
|
||||||
if (open.value) void revealBottom()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换选中的入站时,内容淡出淡入,容器高度从旧值滑到新值。
|
* 切换选中的入站时,内容淡出淡入,容器高度从旧值滑到新值。
|
||||||
* 高度过渡没法纯 CSS 做:auto 不可插值。所以离开前把当前高度钉住,
|
* 高度过渡没法纯 CSS 做:auto 不可插值。所以离开前把当前高度钉住,
|
||||||
@@ -166,6 +163,8 @@ function lockHeight() {
|
|||||||
*/
|
*/
|
||||||
function foldEnter(element: Element, done: () => void) {
|
function foldEnter(element: Element, done: () => void) {
|
||||||
const el = element as HTMLElement
|
const el = element as HTMLElement
|
||||||
|
// 先量再压:此刻元素是自然高度,revealBottom 量到的就是折叠结束后的位置
|
||||||
|
revealBottom()
|
||||||
el.style.height = '0'
|
el.style.height = '0'
|
||||||
el.style.overflow = 'hidden'
|
el.style.overflow = 'hidden'
|
||||||
void el.offsetHeight
|
void el.offsetHeight
|
||||||
@@ -253,11 +252,6 @@ const chainOn = computed({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
function toggleChain() {
|
|
||||||
chainOn.value = !chainOn.value
|
|
||||||
if (chainOn.value) void revealBottom()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── 草稿预览 ────────────────────────────────────────────
|
// ── 草稿预览 ────────────────────────────────────────────
|
||||||
// 上半部分的显示规则只有一条:草稿和已保存一致时显示现实;不一致时显示「按草稿保存后
|
// 上半部分的显示规则只有一条:草稿和已保存一致时显示现实;不一致时显示「按草稿保存后
|
||||||
// 的样子」。点击的语义看卡片本身:现在就存在的成员任何时候点了都立刻生效,只有保存后
|
// 的样子」。点击的语义看卡片本身:现在就存在的成员任何时候点了都立刻生效,只有保存后
|
||||||
@@ -590,7 +584,7 @@ const complete = computed(
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section v-if="!panel.shared" class="block setup">
|
<section v-if="!panel.shared" class="block setup">
|
||||||
<button type="button" class="toggle" @click="toggleOpen">
|
<button type="button" class="toggle" @click="open = !open">
|
||||||
<span>配置</span>
|
<span>配置</span>
|
||||||
<IconRight :class="['chev', open && 'is-open']" />
|
<IconRight :class="['chev', open && 'is-open']" />
|
||||||
</button>
|
</button>
|
||||||
@@ -627,7 +621,7 @@ const complete = computed(
|
|||||||
role="switch"
|
role="switch"
|
||||||
:aria-checked="chainOn"
|
:aria-checked="chainOn"
|
||||||
:class="['switch', chainOn && 'is-on']"
|
:class="['switch', chainOn && 'is-on']"
|
||||||
@click="toggleChain"
|
@click="chainOn = !chainOn"
|
||||||
>
|
>
|
||||||
<span class="knob"></span>
|
<span class="knob"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user