diff --git a/Components/AssistantMessage.svelte b/Components/AssistantMessage.svelte
index 2a281f2..09a0081 100644
--- a/Components/AssistantMessage.svelte
+++ b/Components/AssistantMessage.svelte
@@ -29,6 +29,24 @@
}
return tally;
}
+
+ let isScrolledToBottom = true;
+
+ function updateScrollFade(element: HTMLElement) {
+ const { scrollTop, scrollHeight, clientHeight } = element;
+ isScrolledToBottom = scrollHeight - scrollTop - clientHeight < 1;
+ }
+
+ function artifactsListScrollAction(element: HTMLElement) {
+ updateScrollFade(element);
+ const handleScroll = () => updateScrollFade(element);
+ element.addEventListener("scroll", handleScroll);
+ return {
+ destroy() {
+ element.removeEventListener("scroll", handleScroll);
+ }
+ };
+ }
@@ -50,18 +68,24 @@
{/if}
{/each}
-
- {#each message.artifacts as artifact}
-
-
+
+
+ {#each message.artifacts as artifact}
-
{basename(artifact.filePath)}
-
{artifactActionToCopy(artifact.action)}
-
- {/each}
+ class="artifact-card"
+ aria-label="{artifact.filePath}"
+ >
+
+
+
{basename(artifact.filePath)}
+
{artifactActionToCopy(artifact.action)}
+
+ {/each}
+
+
{/if}
@@ -169,9 +193,14 @@
margin-left: var(--size-4-1);
}
- .artifacts-list-container {
+ .artifacts-list-wrapper {
grid-row: 2;
grid-column: 1 / 3;
+ position: relative;
+ width: 100%;
+ }
+
+ .artifacts-list-container {
display: flex;
flex-direction: column;
overflow: scroll;
@@ -184,6 +213,22 @@
display: none;
}
+ .artifacts-list-fade {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ height: var(--size-4-8);
+ background-image: linear-gradient(to bottom, transparent, var(--background-secondary));
+ pointer-events: none;
+ opacity: 1;
+ transition: opacity 0.2s ease-out;
+ }
+
+ .artifacts-list-fade.hidden {
+ opacity: 0;
+ }
+
.artifact-card {
display: grid;
grid-template-rows: auto;
@@ -195,6 +240,7 @@
background-color: var(--background-secondary-alt);
border-radius: var(--size-4-2);
padding: 0 var(--size-4-1) 0 var(--size-4-2);
+ cursor: pointer;
}
.artifact-ellipse {
@@ -207,16 +253,25 @@
align-self: center;
}
+ .artifact-card:hover .artifact-ellipse {
+ width: 12px;
+ height: 12px;
+ box-shadow: 0px 0px 4px 1px currentColor;
+ }
+
.artifact-ellipse-create {
background: var(--color-green);
+ color: var(--color-green);
}
.artifact-ellipse-modify {
background: var(--color-blue);
+ color: var(--color-blue);
}
.artifact-ellipse-delete {
background: var(--color-red);
+ color: var(--color-red);
}
.artifact-icon {
diff --git a/Components/ChatPlanArea.svelte b/Components/ChatPlanArea.svelte
index e7616bc..79916ad 100644
--- a/Components/ChatPlanArea.svelte
+++ b/Components/ChatPlanArea.svelte
@@ -19,6 +19,8 @@
let stepElements: (HTMLDivElement | null)[] = [];
let isTransitioning = false;
let resizeObserver: ResizeObserver | null = null;
+ let isScrolledToTop = true;
+ let isScrolledToBottom = true;
$: steps = $executionPlanState.plan?.executionSteps;
$: activeStepIndex = $executionPlanState.currentStepIndex;
@@ -65,6 +67,8 @@
const stepsToShow = Math.min(3, steps.length);
collapsedHeight = (stepsToShow * stepHeight) + (Math.max(0, stepsToShow - 1) * separatorHeight);
+
+ updateScrollFade();
}
onDestroy(() => {
@@ -73,6 +77,15 @@
}
});
+ function updateScrollFade() {
+ if (!wrapperDiv) {
+ return;
+ }
+ const { scrollTop, scrollHeight, clientHeight } = wrapperDiv;
+ isScrolledToTop = scrollTop < 1;
+ isScrolledToBottom = scrollHeight - scrollTop - clientHeight < 1;
+ }
+
async function scrollToActiveStep() {
if (!wrapperDiv || !$executionPlanState.plan || activeStepIndex === -1) {
return;
@@ -124,7 +137,7 @@
aria-label={expanded ? "Collapse planned steps" : "Expand planned steps"}
role="button"
tabindex=0>
-
+
{#each steps as step, index }
@@ -153,8 +166,8 @@
{#if steps.length > 2}
-
-
+
+
{/if}