mirror of
https://gitee.com/zhangsken/opencode.git
synced 2026-10-16 02:24:10 +08:00
fix(app): fade home project list edges on scroll
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { createMemo, For, type JSX, onCleanup, Show, splitProps } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { createResizeObserver } from "@solid-primitives/resize-observer"
|
||||
import { Popover } from "@kobalte/core/popover"
|
||||
import { DragDropProvider, PointerSensor } from "@dnd-kit/solid"
|
||||
import { isSortable, useSortable } from "@dnd-kit/solid/sortable"
|
||||
@@ -151,10 +152,20 @@ export function HomeProjectsView(props: HomeProjectsViewProps) {
|
||||
}
|
||||
|
||||
function HomeProjectsPanel(props: HomeProjectsViewProps) {
|
||||
const [contextMenu, setContextMenu] = createStore({ open: undefined as string | undefined })
|
||||
let observer: MutationObserver | undefined
|
||||
let frame = 0
|
||||
const [state, setState] = createStore({ contextMenu: undefined as string | undefined })
|
||||
const updateFades = (element: HTMLDivElement) => {
|
||||
element.toggleAttribute("data-fade-top", element.scrollTop > 0)
|
||||
element.toggleAttribute("data-fade-bottom", element.scrollTop + element.clientHeight < element.scrollHeight - 1)
|
||||
}
|
||||
onCleanup(() => {
|
||||
observer?.disconnect()
|
||||
cancelAnimationFrame(frame)
|
||||
})
|
||||
const contextMenuProps = {
|
||||
contextMenuOpen: (id: string) => contextMenu.open === id,
|
||||
onSetContextMenuOpen: (id: string, open: boolean) => setContextMenu("open", open ? id : undefined),
|
||||
contextMenuOpen: (id: string) => state.contextMenu === id,
|
||||
onSetContextMenuOpen: (id: string, open: boolean) => setState("contextMenu", open ? id : undefined),
|
||||
}
|
||||
return (
|
||||
<aside
|
||||
@@ -191,7 +202,17 @@ function HomeProjectsPanel(props: HomeProjectsViewProps) {
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
<ScrollView data-slot="home-projects-scroll" class="min-h-0 min-w-0 shrink">
|
||||
<ScrollView
|
||||
data-slot="home-projects-scroll"
|
||||
class="min-h-0 min-w-0 shrink"
|
||||
viewportRef={(element) => {
|
||||
createResizeObserver(element, () => updateFades(element))
|
||||
observer = new MutationObserver(() => updateFades(element))
|
||||
observer.observe(element, { childList: true, subtree: true })
|
||||
frame = requestAnimationFrame(() => updateFades(element))
|
||||
}}
|
||||
onScroll={(event) => updateFades(event.currentTarget)}
|
||||
>
|
||||
<Show when={props.dropdown && props.servers.length === 1}>
|
||||
<HomeProjectNavButton
|
||||
type="button"
|
||||
|
||||
+19
-32
@@ -445,8 +445,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"] {
|
||||
timeline-scope: --home-projects-scroll;
|
||||
[data-slot="home-projects-scroll"] > .scroll-view__viewport[data-fade-top] {
|
||||
-webkit-mask-image: linear-gradient(to bottom, transparent, black 16px);
|
||||
mask-image: linear-gradient(to bottom, transparent, black 16px);
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"] > .scroll-view__viewport[data-fade-bottom] {
|
||||
-webkit-mask-image: linear-gradient(to bottom, black calc(100% - 16px), transparent);
|
||||
mask-image: linear-gradient(to bottom, black calc(100% - 16px), transparent);
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"] > .scroll-view__viewport[data-fade-top][data-fade-bottom] {
|
||||
-webkit-mask-image: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
black 16px,
|
||||
black calc(100% - 16px),
|
||||
transparent
|
||||
);
|
||||
mask-image: linear-gradient(to bottom, transparent, black 16px, black calc(100% - 16px), transparent);
|
||||
}
|
||||
|
||||
[data-slot="model-selector-scroll"] {
|
||||
@@ -457,8 +474,6 @@
|
||||
timeline-scope: --manage-models-scroll;
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"]::before,
|
||||
[data-slot="home-projects-scroll"]::after,
|
||||
[data-slot="model-selector-scroll"]::before,
|
||||
[data-slot="model-selector-scroll"]::after,
|
||||
[data-slot="manage-models-scroll"]::before {
|
||||
@@ -472,11 +487,6 @@
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"]::before {
|
||||
top: 0;
|
||||
background: linear-gradient(to bottom, var(--v2-background-bg-base), transparent);
|
||||
}
|
||||
|
||||
[data-slot="model-selector-scroll"]::before {
|
||||
top: 0;
|
||||
height: 12px;
|
||||
@@ -506,11 +516,6 @@
|
||||
background: linear-gradient(to bottom, var(--v2-background-bg-base), transparent);
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"]::after {
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, var(--v2-background-bg-base), transparent);
|
||||
}
|
||||
|
||||
[data-slot="model-selector-scroll"]::after {
|
||||
bottom: 0;
|
||||
height: 12px;
|
||||
@@ -535,24 +540,6 @@
|
||||
);
|
||||
}
|
||||
|
||||
@supports (animation-timeline: --home-projects-scroll) and (timeline-scope: --home-projects-scroll) {
|
||||
[data-slot="home-projects-scroll"] .scroll-view__viewport {
|
||||
scroll-timeline: --home-projects-scroll y;
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"]::before {
|
||||
animation: home-projects-fade-top linear both;
|
||||
animation-timeline: --home-projects-scroll;
|
||||
animation-range: 0 0.1px;
|
||||
}
|
||||
|
||||
[data-slot="home-projects-scroll"]::after {
|
||||
animation: home-projects-fade-bottom linear both;
|
||||
animation-timeline: --home-projects-scroll;
|
||||
animation-range: calc(100% - 1.1px) calc(100% - 1px);
|
||||
}
|
||||
}
|
||||
|
||||
@supports (animation-timeline: --model-selector-scroll) and (timeline-scope: --model-selector-scroll) {
|
||||
[data-slot="model-selector-scroll"] .scroll-view__viewport {
|
||||
scroll-timeline: --model-selector-scroll y;
|
||||
|
||||
Reference in New Issue
Block a user