fix: /菜单手动滚动后高亮条切换为鼠标hover模式

This commit is contained in:
JOJO 2026-06-12 01:17:51 +08:00
parent 095e0631c1
commit 50e49d60ec

View File

@ -50,6 +50,7 @@
<div
ref="skillSlashList"
class="skill-slash-menu"
@scroll="onSlashScroll"
>
<button
v-for="(item, index) in activeSlashMenuItems"
@ -57,7 +58,7 @@
type="button"
class="skill-slash-item"
:class="{
'skill-slash-item--active': index === skillSlashActiveIndex,
'skill-slash-item--active': index === skillSlashActiveIndex && !slashManualScrolled,
'skill-slash-item--disabled': item.disabled
}"
role="option"
@ -566,9 +567,12 @@ const slashMenuMode = ref<SlashMenuMode>('root');
const slashMenuParentIndex = ref(0);
const slashMenuTransitioning = ref(false);
const slashHighlightTop = ref(4);
/** 手动滚动后切到鼠标 hover 模式,隐藏 JS 高亮条 */
const slashManualScrolled = ref(false);
let slashAnimId: number | null = null;
const slashHighlightStyle = computed(() => {
if (slashManualScrolled.value) return { display: 'none' };
const isFirst = skillSlashActiveIndex.value === 0 && skillSlashList.value?.scrollTop === 0;
return {
top: `${slashHighlightTop.value}px`,
@ -580,7 +584,8 @@ const slashHighlightStyle = computed(() => {
});
const animateSlash = (element: HTMLElement, targetScroll: number) => {
if (slashAnimId !== null) {
const interrupted = slashAnimId !== null;
if (interrupted) {
cancelAnimationFrame(slashAnimId);
}
const startScroll = element.scrollTop;
@ -588,7 +593,7 @@ const animateSlash = (element: HTMLElement, targetScroll: number) => {
const distScroll = targetScroll - startScroll;
const targetHighlight = 4 + skillSlashActiveIndex.value * 31 - targetScroll;
const distHighlight = targetHighlight - startHighlight;
const duration = 180;
const duration = interrupted ? 60 : 180;
const startTime = performance.now();
const step = (now: number) => {
@ -605,6 +610,13 @@ const animateSlash = (element: HTMLElement, targetScroll: number) => {
};
slashAnimId = requestAnimationFrame(step);
};
/** 手动滚动时切到鼠标 hover 模式,不再跟踪键盘选中 */
const onSlashScroll = () => {
if (slashAnimId !== null) return;
slashManualScrolled.value = true;
};
let composerResizeObserver: ResizeObserver | null = null;
let syncingEditorFromProps = false;
@ -733,6 +745,7 @@ const closeSlashMenu = () => {
slashMenuMode.value = 'root';
slashMenuParentIndex.value = 0;
slashHighlightTop.value = 4;
slashManualScrolled.value = false;
};
const deleteSlashToken = () => {
@ -1218,6 +1231,7 @@ const handleSlashMenuKeydown = (event: KeyboardEvent): boolean => {
if (skillSlashOpen.value) {
if (event.key === 'ArrowDown') {
event.preventDefault();
slashManualScrolled.value = false;
const count = activeSlashMenuItems.value.length;
if (count > 0) {
skillSlashActiveIndex.value = (skillSlashActiveIndex.value + 1) % count;
@ -1227,6 +1241,7 @@ const handleSlashMenuKeydown = (event: KeyboardEvent): boolean => {
}
if (event.key === 'ArrowUp') {
event.preventDefault();
slashManualScrolled.value = false;
const count = activeSlashMenuItems.value.length;
if (count > 0) {
skillSlashActiveIndex.value = (skillSlashActiveIndex.value - 1 + count) % count;