Skip to content

Commit

Permalink
fix(chat): Adjust scroll bar positioning (#1861)
Browse files Browse the repository at this point in the history
  • Loading branch information
gadenbuie authored Feb 24, 2025
1 parent ac375b3 commit bc07d2c
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 23 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/verify-js-built.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
run: |
if [[ `git status --porcelain` ]]; then
git diff
echo "Uncommitted changes found. Please commit any changes that result from 'npm run build'."
echo "Uncommitted changes found. Please commit any changes that result from 'npm ci && npm run build'."
exit 1
else
echo "No uncommitted changes found."
Expand Down
22 changes: 14 additions & 8 deletions js/chat/chat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ shiny-chat-container {
--shiny-chat-user-message-bg: RGBA(var(--bs-primary-rgb, 0, 123, 194), 0.06);
--_chat-container-padding: 0.25rem;

display: flex;
flex-direction: column;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr auto;
margin: 0 auto;
gap: 1rem;
overflow: auto;
gap: 0;
padding: var(--_chat-container-padding);
padding-bottom: 0; // Bottom padding is on input element

Expand Down Expand Up @@ -54,6 +54,13 @@ shiny-chat-messages {
display: flex;
flex-direction: column;
gap: 2rem;
overflow: auto;
margin-bottom: 1rem;

// Make space for the scroll bar
--_scroll-margin: 1rem;
padding-right: var(--_scroll-margin);
margin-right: calc(-1 * var(--_scroll-margin));
}

shiny-chat-message {
Expand Down Expand Up @@ -96,13 +103,12 @@ shiny-chat-message {
}

shiny-chat-input {
--_input-padding-top: 1rem;
--_input-padding-top: 0;
--_input-padding-bottom: var(--_chat-container-padding, 0.25rem);

margin-top: auto;
margin-top: calc(-1 * var(--_input-padding-top));
position: sticky;
bottom: 0;
background: linear-gradient(to bottom, transparent, var(--bs-body-bg, white) calc(var(--_input-padding-top) - var(--_input-padding-bottom)));
bottom: calc(-1 * var(--_input-padding-bottom));
padding-block: var(--_input-padding-top) var(--_input-padding-bottom);

textarea {
Expand Down
33 changes: 33 additions & 0 deletions js/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ class ChatInput extends LightElement {
}

class ChatContainer extends LightElement {
inputSentinelObserver?: IntersectionObserver;

private get input(): ChatInput {
return this.querySelector(CHAT_INPUT_TAG) as ChatInput;
Expand All @@ -280,6 +281,35 @@ class ChatContainer extends LightElement {
return html``;
}

connectedCallback(): void {
super.connectedCallback();

// We use a sentinel element that we place just above the shiny-chat-input. When it
// moves off-screen we know that the text area input is now floating, add shadow.
let sentinel = this.querySelector<HTMLElement>("div");
if (!sentinel) {
sentinel = createElement("div", {
style: "width: 100%; height: 0;",
}) as HTMLElement;
this.input.insertAdjacentElement("afterend", sentinel);
}

this.inputSentinelObserver = new IntersectionObserver(
(entries) => {
const inputTextarea = this.input.querySelector("textarea");
if (!inputTextarea) return;
const addShadow = entries[0]?.intersectionRatio === 0;
inputTextarea.classList.toggle("shadow", addShadow);
},
{
threshold: [0, 1],
rootMargin: "0px",
}
);

this.inputSentinelObserver.observe(sentinel);
}

firstUpdated(): void {
// Don't attach event listeners until child elements are rendered
if (!this.messages) return;
Expand All @@ -306,6 +336,9 @@ class ChatContainer extends LightElement {
disconnectedCallback(): void {
super.disconnectedCallback();

this.inputSentinelObserver?.disconnect();
this.inputSentinelObserver = undefined;

this.removeEventListener("shiny-chat-input-sent", this.#onInputSent);
this.removeEventListener("shiny-chat-append-message", this.#onAppend);
this.removeEventListener(
Expand Down
2 changes: 1 addition & 1 deletion shiny/www/py-shiny/chat/chat.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions shiny/www/py-shiny/chat/chat.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bc07d2c

Please sign in to comment.