mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-24 03:04:21 +01:00
feat(desktop): sticky diff headers
This commit is contained in:
@@ -44,7 +44,7 @@ import {
|
||||
useDragDropContext,
|
||||
} from "@thisbeyond/solid-dnd"
|
||||
import type { DragEvent, Transformer } from "@thisbeyond/solid-dnd"
|
||||
import type { JSX } from "solid-js"
|
||||
import type { JSX, ParentProps } from "solid-js"
|
||||
import { useSync } from "@/context/sync"
|
||||
import { type AssistantMessage as AssistantMessageType } from "@opencode-ai/sdk"
|
||||
import { Markdown } from "@opencode-ai/ui"
|
||||
@@ -477,7 +477,7 @@ export default function Page() {
|
||||
class="flex flex-col items-start self-stretch gap-8 pb-20"
|
||||
>
|
||||
{/* Title */}
|
||||
<div class="flex flex-col items-start gap-2 self-stretch sticky top-0 bg-background-stronger z-10 pb-1">
|
||||
<div class="flex flex-col items-start gap-2 self-stretch sticky top-0 bg-background-stronger z-20 pb-1">
|
||||
<div class="w-full text-14-medium text-text-strong">
|
||||
<Show
|
||||
when={titled()}
|
||||
@@ -524,7 +524,7 @@ export default function Page() {
|
||||
<For each={message.summary?.diffs ?? []}>
|
||||
{(diff) => (
|
||||
<Accordion.Item value={diff.file}>
|
||||
<Accordion.Header>
|
||||
<StickyAccordionHeader class="top-10 data-expanded:before:-top-10 ">
|
||||
<Accordion.Trigger>
|
||||
<div class="flex items-center justify-between w-full gap-5">
|
||||
<div class="grow flex items-center gap-5 min-w-0">
|
||||
@@ -549,8 +549,8 @@ export default function Page() {
|
||||
</div>
|
||||
</div>
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Header>
|
||||
<Accordion.Content class="max-h-[360px] overflow-y-auto no-scrollbar">
|
||||
</StickyAccordionHeader>
|
||||
<Accordion.Content class="max-h-60 overflow-y-auto no-scrollbar">
|
||||
<Diff
|
||||
before={{
|
||||
name: diff.file!,
|
||||
@@ -682,7 +682,7 @@ export default function Page() {
|
||||
<For each={session.diffs()}>
|
||||
{(diff) => (
|
||||
<Accordion.Item value={diff.file} defaultOpen>
|
||||
<Accordion.Header>
|
||||
<StickyAccordionHeader>
|
||||
<Accordion.Trigger>
|
||||
<div class="flex items-center justify-between w-full gap-5">
|
||||
<div class="grow flex items-center gap-5 min-w-0">
|
||||
@@ -702,7 +702,7 @@ export default function Page() {
|
||||
</div>
|
||||
</div>
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Header>
|
||||
</StickyAccordionHeader>
|
||||
<Accordion.Content>
|
||||
<Diff
|
||||
before={{
|
||||
@@ -725,19 +725,19 @@ export default function Page() {
|
||||
</div>
|
||||
</Tabs.Content>
|
||||
<Show when={local.layout.review.state() === "tab" && session.diffs().length}>
|
||||
<Tabs.Content value="review" class="select-text mt-8">
|
||||
<Tabs.Content value="review" class="select-text flex flex-col h-full overflow-hidden mt-8">
|
||||
<div
|
||||
classList={{
|
||||
"relative px-6 py-2 w-full flex flex-col gap-6 flex-1 min-h-0": true,
|
||||
"relative px-6 py-2 w-full flex flex-col gap-6 flex-1 min-h-0 overflow-hidden": true,
|
||||
}}
|
||||
>
|
||||
<div class="text-14-medium text-text-strong">All changes</div>
|
||||
<div class="h-full pb-40 overflow-y-auto no-scrollbar">
|
||||
<div class="text-14-medium text-text-strong shrink-0">All changes</div>
|
||||
<div class="flex-1 min-h-0 pb-40 overflow-y-auto no-scrollbar">
|
||||
<Accordion class="w-full" multiple>
|
||||
<For each={session.diffs()}>
|
||||
{(diff) => (
|
||||
<Accordion.Item value={diff.file} defaultOpen>
|
||||
<Accordion.Header>
|
||||
<StickyAccordionHeader>
|
||||
<Accordion.Trigger>
|
||||
<div class="flex items-center justify-between w-full gap-5">
|
||||
<div class="grow flex items-center gap-5 min-w-0">
|
||||
@@ -755,7 +755,7 @@ export default function Page() {
|
||||
</div>
|
||||
</div>
|
||||
</Accordion.Trigger>
|
||||
</Accordion.Header>
|
||||
</StickyAccordionHeader>
|
||||
<Accordion.Content>
|
||||
<Diff
|
||||
diffStyle="split"
|
||||
@@ -895,3 +895,18 @@ export default function Page() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function StickyAccordionHeader(props: ParentProps<{ class?: string }>) {
|
||||
return (
|
||||
<Accordion.Header
|
||||
classList={{
|
||||
"sticky top-0 data-expanded:z-10": true,
|
||||
"data-expanded:before:content-[''] data-expanded:before:z-[-10]": true,
|
||||
"data-expanded:before:absolute data-expanded:before:inset-0 data-expanded:before:bg-background-stronger": true,
|
||||
[props.class ?? ""]: !!props.class,
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</Accordion.Header>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,9 +12,6 @@
|
||||
align-items: flex-start;
|
||||
gap: 0px;
|
||||
align-self: stretch;
|
||||
border: 1px solid var(--border-weak-base);
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
overflow: clip;
|
||||
|
||||
[data-slot="accordion-header"] {
|
||||
@@ -36,7 +33,7 @@
|
||||
user-select: none;
|
||||
|
||||
background-color: var(--surface-base);
|
||||
border-bottom: 1px solid var(--border-weak-base);
|
||||
border: 1px solid var(--border-weak-base);
|
||||
overflow: clip;
|
||||
color: var(--text-strong);
|
||||
transition: background-color 0.15s ease;
|
||||
@@ -62,11 +59,19 @@
|
||||
}
|
||||
|
||||
&[data-expanded] {
|
||||
border: 1px solid var(--border-weak-base);
|
||||
border-bottom: 1px solid var(--border-weak-base);
|
||||
margin-top: 8px;
|
||||
margin-bottom: 8px;
|
||||
border-radius: 8px;
|
||||
|
||||
[data-slot="accordion-trigger"] {
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
[data-slot="accordion-content"] {
|
||||
border: 1px solid var(--border-weak-base);
|
||||
border-top: none;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
}
|
||||
|
||||
[data-slot="accordion-item"]:has(+ &) {
|
||||
&[data-closed] {
|
||||
@@ -81,18 +86,23 @@
|
||||
}
|
||||
|
||||
& + [data-slot="accordion-item"] {
|
||||
border-top: 1px solid var(--border-weak-base);
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
margin-top: 8px;
|
||||
|
||||
[data-slot="accordion-trigger"] {
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[data-closed] + &[data-closed] {
|
||||
[data-slot="accordion-trigger"] {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0px;
|
||||
border-top: 1px solid var(--border-weak-base);
|
||||
border-top-left-radius: 8px;
|
||||
border-top-right-radius: 8px;
|
||||
|
||||
&[data-closed] {
|
||||
[data-slot="accordion-trigger"] {
|
||||
@@ -104,8 +114,6 @@
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0px;
|
||||
border-bottom-left-radius: 8px;
|
||||
border-bottom-right-radius: 8px;
|
||||
|
||||
&[data-closed] {
|
||||
[data-slot="accordion-trigger"] {
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
--background-weak: var(--smoke-light-3);
|
||||
--background-strong: var(--smoke-light-1);
|
||||
--background-stronger: #fcfcfc;
|
||||
--surface-base: var(--smoke-light-alpha-2);
|
||||
--surface-base: var(--smoke-light-3);
|
||||
--base: var(--smoke-light-alpha-2);
|
||||
--surface-base-hover: #0500000f;
|
||||
--surface-base-active: var(--smoke-light-alpha-3);
|
||||
@@ -317,7 +317,7 @@
|
||||
--background-weak: #1b1818;
|
||||
--background-strong: #151313;
|
||||
--background-stronger: #191515;
|
||||
--surface-base: var(--smoke-dark-alpha-2);
|
||||
--surface-base: var(--smoke-dark-3);
|
||||
--base: var(--smoke-dark-alpha-2);
|
||||
--surface-base-hover: #e0b7b716;
|
||||
--surface-base-active: var(--smoke-dark-alpha-3);
|
||||
|
||||
Reference in New Issue
Block a user