|
2 | 2 | import ConfigurableScrollableContainer from '$components/ConfigurableScrollableContainer.svelte';
|
3 | 3 | import { Button } from '@gitbutler/ui';
|
4 | 4 | import { focusable } from '@gitbutler/ui/focus/focusable';
|
| 5 | + import { fade } from 'svelte/transition'; |
5 | 6 | import type { Snippet } from 'svelte';
|
6 | 7 |
|
7 | 8 | type Props = {
|
|
17 | 18 | $props();
|
18 | 19 |
|
19 | 20 | let scrollableContainer: ConfigurableScrollableContainer;
|
| 21 | + let scrollDistanceFromBottom = $state(0); |
20 | 22 |
|
21 | 23 | // Export method to scroll to bottom
|
22 | 24 | export function scrollToBottom() {
|
23 |
| - if (scrollableContainer?.scrollToBottom) { |
24 |
| - scrollableContainer.scrollToBottom(); |
25 |
| - } |
| 25 | + scrollableContainer?.scrollToBottom(); |
| 26 | + } |
| 27 | +
|
| 28 | + // Calculate distance from bottom when scrolling |
| 29 | + function handleScroll(event: Event) { |
| 30 | + const { scrollTop, scrollHeight, clientHeight } = event.target as HTMLElement; |
| 31 | + scrollDistanceFromBottom = scrollHeight - scrollTop - clientHeight; |
26 | 32 | }
|
| 33 | +
|
| 34 | + // Show button only when user has scrolled more than 1000px from bottom |
| 35 | + const showScrollButton = $derived(scrollDistanceFromBottom > 600); |
27 | 36 | </script>
|
28 | 37 |
|
29 | 38 | <div class="chat" use:focusable={{ vertical: true }}>
|
|
43 | 52 | </div>
|
44 | 53 |
|
45 | 54 | <div class="chat-container">
|
46 |
| - <ConfigurableScrollableContainer bind:this={scrollableContainer} childrenWrapHeight="100%"> |
| 55 | + <ConfigurableScrollableContainer |
| 56 | + bind:this={scrollableContainer} |
| 57 | + childrenWrapHeight="100%" |
| 58 | + onscroll={handleScroll} |
| 59 | + > |
47 | 60 | <div class="chat-messages">
|
48 | 61 | {@render messages()}
|
49 | 62 | </div>
|
50 | 63 | </ConfigurableScrollableContainer>
|
51 | 64 |
|
52 |
| - <div class="chat-scroll-to-bottom"> |
53 |
| - <Button |
54 |
| - kind="outline" |
55 |
| - icon="arrow-down" |
56 |
| - tooltip="Scroll to bottom" |
57 |
| - onclick={scrollToBottom} |
58 |
| - /> |
59 |
| - </div> |
| 65 | + {#if showScrollButton} |
| 66 | + <div class="chat-scroll-to-bottom" transition:fade={{ duration: 150 }}> |
| 67 | + <Button |
| 68 | + kind="outline" |
| 69 | + icon="arrow-down" |
| 70 | + tooltip="Scroll to bottom" |
| 71 | + onclick={scrollToBottom} |
| 72 | + /> |
| 73 | + </div> |
| 74 | + {/if} |
60 | 75 | </div>
|
61 | 76 |
|
62 | 77 | <div class="chat-footer" use:focusable>
|
|
119 | 134 | transform var(--transition-medium);
|
120 | 135 |
|
121 | 136 | &:hover {
|
122 |
| - transform: translateY(-2px); |
| 137 | + transform: scale(1.05) translateY(-2px); |
123 | 138 | box-shadow: var(--fx-shadow-s);
|
124 | 139 | }
|
125 | 140 | }
|
|
0 commit comments