Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

* Added a new `ui.MarkdownStream()` component for performantly streaming in chunks of markdown/html strings into the UI. This component is primarily useful for text-based generative AI where responses are received incrementally. (#1782)

* The `ui.Chat()` component now supports input suggestion links. This feature is useful for providing users with clickable suggestions that can be used to quickly input text into the chat. This can be done in 2
different ways (see #1845 for more details):
* By adding a `.chat-input-suggestion` CSS class to an HTML element (e.g., `<span class="chat-input-suggestion">A suggestion</span>`)
* Add a `data-input-suggestion` attribute to an HTML element, and set the value to the input suggestion text (e.g., `<span data-input-suggestion="Suggestion value">Suggestion link</span>`)

* Added a new `.add_sass_layer_file()` method to `ui.Theme` that supports reading a Sass file with layer boundary comments, e.g. `/*-- scss:defaults --*/`. This format [is supported by Quarto](https://quarto.org/docs/output-formats/html-themes-more.html#bootstrap-bootswatch-layering) and makes it easier to store Sass rules and declarations that need to be woven into Shiny's Sass Bootstrap files. (#1790)

* The `ui.Chat()` component's `.on_user_submit()` decorator method now passes the user input to the decorated function. This makes it a bit more obvious how to access the user input inside the decorated function. See the new templates (mentioned below) for examples. (#1801)
Expand Down
7 changes: 7 additions & 0 deletions js/chat/chat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ shiny-chat-container {
p:last-child {
margin-bottom: 0;
}

.chat-input-suggestion, [data-input-suggestion] {
text-decoration: underline;
text-decoration-style: dotted;
text-decoration-color: var(--bs-link-color, #007bc2);
cursor: pointer;
}
}

shiny-chat-messages {
Expand Down
20 changes: 20 additions & 0 deletions js/chat/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ class ChatContainer extends LightElement {
"shiny-chat-remove-loading-message",
this.#onRemoveLoadingMessage
);
this.addEventListener("click", this.#onInputSuggestionClick);
}

disconnectedCallback(): void {
Expand All @@ -247,6 +248,7 @@ class ChatContainer extends LightElement {
"shiny-chat-remove-loading-message",
this.#onRemoveLoadingMessage
);
this.removeEventListener("click", this.#onInputSuggestionClick);
}

// When user submits input, append it to the chat, and add a loading message
Expand Down Expand Up @@ -332,6 +334,24 @@ class ChatContainer extends LightElement {
}
}

#onInputSuggestionClick(e: Event): void {
const target = e.target;
if (!(target instanceof HTMLElement)) return;

const isSuggestion =
target.classList.contains("chat-input-suggestion") ||
target.dataset.inputSuggestion !== undefined;

if (!isSuggestion) return;

e.preventDefault();

const suggestion = target.dataset.inputSuggestion || target.textContent;
if (suggestion) {
this.input.setInputValue(suggestion);
}
}

#onRemoveLoadingMessage(): void {
this.#removeLoadingMessage();
this.#finalizeMessage();
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
Loading