mirror of
https://gitea.toothfairyai.com/ToothFairyAI/tf_code.git
synced 2026-04-07 09:18:41 +00:00
fix(app): scroll jitter/loop
This commit is contained in:
19
packages/ui/src/components/scroll-view.test.ts
Normal file
19
packages/ui/src/components/scroll-view.test.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, test } from "bun:test"
|
||||
import { scrollKey } from "./scroll-view"
|
||||
|
||||
describe("scrollKey", () => {
|
||||
test("maps plain navigation keys", () => {
|
||||
expect(scrollKey({ key: "PageDown", altKey: false, ctrlKey: false, metaKey: false, shiftKey: false })).toBe(
|
||||
"page-down",
|
||||
)
|
||||
expect(scrollKey({ key: "ArrowUp", altKey: false, ctrlKey: false, metaKey: false, shiftKey: false })).toBe("up")
|
||||
})
|
||||
|
||||
test("ignores modified keybinds", () => {
|
||||
expect(
|
||||
scrollKey({ key: "ArrowDown", altKey: false, ctrlKey: false, metaKey: true, shiftKey: false }),
|
||||
).toBeUndefined()
|
||||
expect(scrollKey({ key: "PageUp", altKey: false, ctrlKey: true, metaKey: false, shiftKey: false })).toBeUndefined()
|
||||
expect(scrollKey({ key: "End", altKey: false, ctrlKey: false, metaKey: false, shiftKey: true })).toBeUndefined()
|
||||
})
|
||||
})
|
||||
@@ -6,6 +6,25 @@ export interface ScrollViewProps extends ComponentProps<"div"> {
|
||||
orientation?: "vertical" | "horizontal" // currently only vertical is fully implemented for thumb
|
||||
}
|
||||
|
||||
export const scrollKey = (event: Pick<KeyboardEvent, "key" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey">) => {
|
||||
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return
|
||||
|
||||
switch (event.key) {
|
||||
case "PageDown":
|
||||
return "page-down"
|
||||
case "PageUp":
|
||||
return "page-up"
|
||||
case "Home":
|
||||
return "home"
|
||||
case "End":
|
||||
return "end"
|
||||
case "ArrowUp":
|
||||
return "up"
|
||||
case "ArrowDown":
|
||||
return "down"
|
||||
}
|
||||
}
|
||||
|
||||
export function ScrollView(props: ScrollViewProps) {
|
||||
const i18n = useI18n()
|
||||
const merged = mergeProps({ orientation: "vertical" }, props)
|
||||
@@ -133,31 +152,34 @@ export function ScrollView(props: ScrollViewProps) {
|
||||
return
|
||||
}
|
||||
|
||||
const next = scrollKey(e)
|
||||
if (!next) return
|
||||
|
||||
const scrollAmount = viewportRef.clientHeight * 0.8
|
||||
const lineAmount = 40
|
||||
|
||||
switch (e.key) {
|
||||
case "PageDown":
|
||||
switch (next) {
|
||||
case "page-down":
|
||||
e.preventDefault()
|
||||
viewportRef.scrollBy({ top: scrollAmount, behavior: "smooth" })
|
||||
break
|
||||
case "PageUp":
|
||||
case "page-up":
|
||||
e.preventDefault()
|
||||
viewportRef.scrollBy({ top: -scrollAmount, behavior: "smooth" })
|
||||
break
|
||||
case "Home":
|
||||
case "home":
|
||||
e.preventDefault()
|
||||
viewportRef.scrollTo({ top: 0, behavior: "smooth" })
|
||||
break
|
||||
case "End":
|
||||
case "end":
|
||||
e.preventDefault()
|
||||
viewportRef.scrollTo({ top: viewportRef.scrollHeight, behavior: "smooth" })
|
||||
break
|
||||
case "ArrowUp":
|
||||
case "up":
|
||||
e.preventDefault()
|
||||
viewportRef.scrollBy({ top: -lineAmount, behavior: "smooth" })
|
||||
break
|
||||
case "ArrowDown":
|
||||
case "down":
|
||||
e.preventDefault()
|
||||
viewportRef.scrollBy({ top: lineAmount, behavior: "smooth" })
|
||||
break
|
||||
|
||||
Reference in New Issue
Block a user