mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-30 11:00:11 +08:00
Revert chatbot styling (#8758)
* fix * fix * add changeset * add changeset * tests * Fix button panel (#8762) --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Freddy Boulton <alfonsoboulton@gmail.com>
This commit is contained in:
parent
078663a3a4
commit
26cdd0ffe0
6
.changeset/nine-ways-sink.md
Normal file
6
.changeset/nine-ways-sink.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"@gradio/chatbot": patch
|
||||
"gradio": patch
|
||||
---
|
||||
|
||||
fix:Revert chatbot styling
|
@ -1 +1 @@
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_with_tools"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from gradio import ChatMessage\n", "import time\n", "\n", "def generate_response(history):\n", " history.append(ChatMessage(role=\"user\", content=\"What is the weather in San Francisco right now?\"))\n", " yield history\n", " time.sleep(0.25)\n", " history.append(ChatMessage(role=\"assistant\",\n", " content=\"In order to find the current weather in San Francisco, I will need to use my weather tool.\")\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(ChatMessage(role=\"assistant\",\n", " content=\"API Error when connecting to weather service.\",\n", " metadata={\"title\": \"\ud83d\udca5 Error using tool 'Weather'\"})\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(ChatMessage(role=\"assistant\",\n", " content=\"I will try again\",\n", " ))\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(ChatMessage(role=\"assistant\",\n", " content=\"Weather 72 degrees Fahrenheit with 20% chance of rain.\",\n", " metadata={\"title\": \"\ud83d\udee0\ufe0f Used tool 'Weather'\"}\n", " ))\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(ChatMessage(role=\"assistant\",\n", " content=\"Now that the API succeeded I can complete my task.\",\n", " ))\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(ChatMessage(role=\"assistant\",\n", " content=\"It's a sunny day in San Francisco with a current temperature of 72 degrees Fahrenheit and a 20% chance of rain. Enjoy the weather!\",\n", " ))\n", " yield history\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(type=\"messages\")\n", " button = gr.Button(\"Get San Francisco Weather\")\n", " button.click(generate_response, chatbot, chatbot)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
||||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: chatbot_with_tools"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "from gradio import ChatMessage\n", "import time\n", "\n", "\n", "def generate_response(history):\n", " history.append(\n", " ChatMessage(\n", " role=\"user\", content=\"What is the weather in San Francisco right now?\"\n", " )\n", " )\n", " yield history\n", " time.sleep(0.25)\n", " history.append(\n", " ChatMessage(\n", " role=\"assistant\",\n", " content=\"In order to find the current weather in San Francisco, I will need to use my weather tool.\",\n", " )\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(\n", " ChatMessage(\n", " role=\"assistant\",\n", " content=\"API Error when connecting to weather service.\",\n", " metadata={\"title\": \"\ud83d\udca5 Error using tool 'Weather'\"},\n", " )\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(\n", " ChatMessage(\n", " role=\"assistant\",\n", " content=\"I will try again\",\n", " )\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(\n", " ChatMessage(\n", " role=\"assistant\",\n", " content=\"Weather 72 degrees Fahrenheit with 20% chance of rain.\",\n", " metadata={\"title\": \"\ud83d\udee0\ufe0f Used tool 'Weather'\"},\n", " )\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(\n", " ChatMessage(\n", " role=\"assistant\",\n", " content=\"Now that the API succeeded I can complete my task.\",\n", " )\n", " )\n", " yield history\n", " time.sleep(0.25)\n", "\n", " history.append(\n", " ChatMessage(\n", " role=\"assistant\",\n", " content=\"It's a sunny day in San Francisco with a current temperature of 72 degrees Fahrenheit and a 20% chance of rain. Enjoy the weather!\",\n", " )\n", " )\n", " yield history\n", "\n", "\n", "def like(evt: gr.LikeData):\n", " print(\"User liked the response\")\n", " print(evt.index, evt.liked, evt.value)\n", "\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot(type=\"messages\", height=500, show_copy_button=True)\n", " button = gr.Button(\"Get San Francisco Weather\")\n", " button.click(generate_response, chatbot, chatbot)\n", " chatbot.like(like)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
|
@ -2,52 +2,81 @@ import gradio as gr
|
||||
from gradio import ChatMessage
|
||||
import time
|
||||
|
||||
|
||||
def generate_response(history):
|
||||
history.append(ChatMessage(role="user", content="What is the weather in San Francisco right now?"))
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="user", content="What is the weather in San Francisco right now?"
|
||||
)
|
||||
)
|
||||
yield history
|
||||
time.sleep(0.25)
|
||||
history.append(ChatMessage(role="assistant",
|
||||
content="In order to find the current weather in San Francisco, I will need to use my weather tool.")
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
content="In order to find the current weather in San Francisco, I will need to use my weather tool.",
|
||||
)
|
||||
)
|
||||
yield history
|
||||
time.sleep(0.25)
|
||||
|
||||
history.append(ChatMessage(role="assistant",
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
content="API Error when connecting to weather service.",
|
||||
metadata={"title": "💥 Error using tool 'Weather'"})
|
||||
metadata={"title": "💥 Error using tool 'Weather'"},
|
||||
)
|
||||
)
|
||||
yield history
|
||||
time.sleep(0.25)
|
||||
|
||||
history.append(ChatMessage(role="assistant",
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
content="I will try again",
|
||||
))
|
||||
)
|
||||
)
|
||||
yield history
|
||||
time.sleep(0.25)
|
||||
|
||||
history.append(ChatMessage(role="assistant",
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
content="Weather 72 degrees Fahrenheit with 20% chance of rain.",
|
||||
metadata={"title": "🛠️ Used tool 'Weather'"}
|
||||
))
|
||||
metadata={"title": "🛠️ Used tool 'Weather'"},
|
||||
)
|
||||
)
|
||||
yield history
|
||||
time.sleep(0.25)
|
||||
|
||||
history.append(ChatMessage(role="assistant",
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
content="Now that the API succeeded I can complete my task.",
|
||||
))
|
||||
)
|
||||
)
|
||||
yield history
|
||||
time.sleep(0.25)
|
||||
|
||||
history.append(ChatMessage(role="assistant",
|
||||
history.append(
|
||||
ChatMessage(
|
||||
role="assistant",
|
||||
content="It's a sunny day in San Francisco with a current temperature of 72 degrees Fahrenheit and a 20% chance of rain. Enjoy the weather!",
|
||||
))
|
||||
)
|
||||
)
|
||||
yield history
|
||||
|
||||
|
||||
def like(evt: gr.LikeData):
|
||||
print("User liked the response")
|
||||
print(evt.index, evt.liked, evt.value)
|
||||
|
||||
|
||||
with gr.Blocks() as demo:
|
||||
chatbot = gr.Chatbot(type="messages")
|
||||
chatbot = gr.Chatbot(type="messages", height=500, show_copy_button=True)
|
||||
button = gr.Button("Get San Francisco Weather")
|
||||
button.click(generate_response, chatbot, chatbot)
|
||||
chatbot.like(like)
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo.launch()
|
||||
|
@ -58,9 +58,11 @@ def set_cancel_events(
|
||||
|
||||
root_block.set_event_trigger(
|
||||
triggers,
|
||||
fn=lambda: [Timer(active=False) for _ in timers_to_cancel]
|
||||
fn=lambda: (
|
||||
[Timer(active=False) for _ in timers_to_cancel]
|
||||
if len(timers_to_cancel) > 1
|
||||
else Timer(active=False),
|
||||
else Timer(active=False)
|
||||
),
|
||||
inputs=None,
|
||||
outputs=timers_to_cancel,
|
||||
show_api=False,
|
||||
|
@ -239,7 +239,7 @@ for (const msg_format of ["tuples", "messages"]) {
|
||||
await page.getByTestId("textbox").fill("hello");
|
||||
await page.keyboard.press("Enter");
|
||||
await page.getByLabel("like", { exact: true }).click();
|
||||
await page.getByLabel("dislike").click();
|
||||
await page.getByLabel("dislike", { exact: true }).click();
|
||||
|
||||
expect(await page.getByLabel("clicked dislike").count()).toEqual(1);
|
||||
expect(await page.getByLabel("clicked like").count()).toEqual(0);
|
||||
|
@ -124,6 +124,7 @@
|
||||
upload={gradio.client.upload}
|
||||
_fetch={gradio.client.fetch}
|
||||
load_component={gradio.load_component}
|
||||
msg_format={type}
|
||||
/>
|
||||
</div>
|
||||
</Block>
|
||||
|
@ -4,19 +4,43 @@
|
||||
import type { FileData } from "@gradio/client";
|
||||
import DownloadIcon from "./Download.svelte";
|
||||
import { DownloadLink } from "@gradio/wasm/svelte";
|
||||
import type { NormalisedMessage, TextMessage } from "../types";
|
||||
import { is_component_message } from "./utils";
|
||||
|
||||
export let likeable: boolean;
|
||||
export let show_copy_button: boolean;
|
||||
export let show: boolean;
|
||||
export let message: Record<string, any>;
|
||||
export let message: NormalisedMessage | NormalisedMessage[];
|
||||
export let position: "right" | "left";
|
||||
export let avatar: FileData | null;
|
||||
|
||||
export let handle_action: (selected: string | null) => void;
|
||||
export let layout: "bubble" | "panel";
|
||||
$: show_copy = show_copy_button && message && message?.type === "text";
|
||||
|
||||
function is_all_text(
|
||||
message: NormalisedMessage[] | NormalisedMessage
|
||||
): message is TextMessage[] | TextMessage {
|
||||
return (
|
||||
(Array.isArray(message) &&
|
||||
message.every((m) => typeof m.content === "string")) ||
|
||||
(!Array.isArray(message) && typeof message.content === "string")
|
||||
);
|
||||
}
|
||||
|
||||
function all_text(message: TextMessage[] | TextMessage): string {
|
||||
if (Array.isArray(message)) {
|
||||
return message.map((m) => m.content).join("\n");
|
||||
}
|
||||
return message.content;
|
||||
}
|
||||
|
||||
$: message_text = is_all_text(message) ? all_text(message) : "";
|
||||
|
||||
$: show_copy = show_copy_button && message && is_all_text(message);
|
||||
$: show_download =
|
||||
show_copy_button && (message?.value?.video?.url || message?.value?.url);
|
||||
!Array.isArray(message) &&
|
||||
is_component_message(message) &&
|
||||
message.content.value.url;
|
||||
</script>
|
||||
|
||||
{#if show}
|
||||
@ -25,21 +49,19 @@
|
||||
null && 'with-avatar'}"
|
||||
>
|
||||
{#if show_copy}
|
||||
<Copy value={message.value} />
|
||||
<Copy value={message_text} />
|
||||
{/if}
|
||||
{#if show_download}
|
||||
{#if show_download && !Array.isArray(message) && is_component_message(message)}
|
||||
<DownloadLink
|
||||
href={message?.value?.video?.url || message?.value?.url}
|
||||
download={message?.value?.video?.orig_name ||
|
||||
message.value.orig_name ||
|
||||
"image"}
|
||||
href={message?.content?.value.url}
|
||||
download={message.content.value.orig_name || "image"}
|
||||
>
|
||||
<span class="icon-wrap">
|
||||
<DownloadIcon />
|
||||
</span>
|
||||
</DownloadLink>
|
||||
{/if}
|
||||
{#if likeable && position === "left"}
|
||||
{#if likeable}
|
||||
<LikeDislike {handle_action} padded={show_copy || show_download} />
|
||||
{/if}
|
||||
</div>
|
||||
@ -54,36 +76,34 @@
|
||||
.icon-wrap:hover {
|
||||
color: var(--body-text-color);
|
||||
}
|
||||
.message-buttons-right,
|
||||
.message-buttons-left {
|
||||
|
||||
.message-buttons {
|
||||
border-radius: var(--radius-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
bottom: 0;
|
||||
|
||||
height: var(--size-7);
|
||||
align-self: self-end;
|
||||
/* position: absolute; */
|
||||
bottom: -15px;
|
||||
margin: 2px;
|
||||
margin: 0px calc(var(--spacing-xl) * 3);
|
||||
padding-left: 5px;
|
||||
z-index: 1;
|
||||
padding-bottom: var(--spacing-xl);
|
||||
padding: var(--spacing-md) 2px;
|
||||
padding: var(--spacing-md) var(--spacing-md);
|
||||
border: 1px solid var(--border-color-primary);
|
||||
background: var(--border-color-secondary);
|
||||
gap: var(--spacing-md);
|
||||
}
|
||||
.message-buttons-left {
|
||||
align-self: start;
|
||||
left: 0px;
|
||||
}
|
||||
.message-buttons-right {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.panel.message-buttons-left,
|
||||
.panel.message-buttons-right {
|
||||
margin: 10px 0 2px 0;
|
||||
}
|
||||
|
||||
.message-buttons {
|
||||
/* .message-buttons {
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
top: unset;
|
||||
@ -92,9 +112,13 @@
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: 0px;
|
||||
}
|
||||
} */
|
||||
|
||||
.message-buttons :global(> *) {
|
||||
margin-right: 7px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.with-avatar {
|
||||
margin-left: calc(var(--spacing-xl) * 4 + 31px);
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { format_chat_for_sharing } from "./utils";
|
||||
import { format_chat_for_sharing, is_component_message } from "./utils";
|
||||
import type { NormalisedMessage } from "../types";
|
||||
import { Gradio, copy } from "@gradio/utils";
|
||||
|
||||
@ -92,6 +92,8 @@
|
||||
export let layout: "bubble" | "panel" = "bubble";
|
||||
export let placeholder: string | null = null;
|
||||
export let upload: Client["upload"];
|
||||
export let msg_format: "tuples" | "messages" = "tuples";
|
||||
|
||||
let target = document.querySelector("div.gradio-container");
|
||||
|
||||
let div: HTMLDivElement;
|
||||
@ -172,6 +174,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: groupedMessages = value && group_messages(value);
|
||||
|
||||
function handle_select(i: number, message: NormalisedMessage): void {
|
||||
dispatch("select", {
|
||||
index: message.index,
|
||||
@ -184,11 +188,27 @@
|
||||
message: NormalisedMessage,
|
||||
selected: string | null
|
||||
): void {
|
||||
if (msg_format === "tuples") {
|
||||
dispatch("like", {
|
||||
index: message.index,
|
||||
value: message.content,
|
||||
liked: selected === "like"
|
||||
});
|
||||
} else {
|
||||
if (!groupedMessages) return;
|
||||
|
||||
const message_group = groupedMessages[i];
|
||||
const [first, last] = [
|
||||
message_group[0],
|
||||
message_group[message_group.length - 1]
|
||||
];
|
||||
|
||||
dispatch("like", {
|
||||
index: [first.index, last.index] as [number, number],
|
||||
value: message_group.map((m) => m.content),
|
||||
liked: selected === "like"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function get_message_label_data(message: NormalisedMessage): string {
|
||||
@ -209,12 +229,6 @@
|
||||
return `a component of type ${message.content.component ?? "unknown"}`;
|
||||
}
|
||||
|
||||
function is_component_message(
|
||||
message: NormalisedMessage
|
||||
): message is ComponentMessage {
|
||||
return message.type === "component";
|
||||
}
|
||||
|
||||
function group_messages(
|
||||
messages: NormalisedMessage[]
|
||||
): NormalisedMessage[][] {
|
||||
@ -223,6 +237,10 @@
|
||||
let currentRole: MessageRole | null = null;
|
||||
|
||||
for (const message of messages) {
|
||||
if (msg_format === "tuples") {
|
||||
currentRole = null;
|
||||
}
|
||||
|
||||
if (!(message.role === "assistant" || message.role === "user")) {
|
||||
continue;
|
||||
}
|
||||
@ -266,8 +284,7 @@
|
||||
aria-live="polite"
|
||||
>
|
||||
<div class="message-wrap" use:copy>
|
||||
{#if value !== null && value.length > 0}
|
||||
{@const groupedMessages = group_messages(value)}
|
||||
{#if value !== null && value.length > 0 && groupedMessages !== null}
|
||||
{#each groupedMessages as messages, i}
|
||||
{@const role = messages[0].role === "user" ? "user" : "bot"}
|
||||
{@const avatar_img = avatar_images[role === "user" ? 0 : 1]}
|
||||
@ -297,7 +314,10 @@
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="flex-wrap">
|
||||
<div
|
||||
class="flex-wrap {role} "
|
||||
class:component-wrap={messages[0].type === "component"}
|
||||
>
|
||||
{#each messages as message, thought_index}
|
||||
{@const msg_type = messages[0].type}
|
||||
<div
|
||||
@ -385,20 +405,20 @@
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<LikeButtons
|
||||
show={role === "bot" && (likeable || show_copy_button)}
|
||||
handle_action={(selected) => handle_like(i, message, selected)}
|
||||
show={likeable || show_copy_button}
|
||||
handle_action={(selected) => handle_like(i, messages[0], selected)}
|
||||
{likeable}
|
||||
{show_copy_button}
|
||||
{message}
|
||||
message={msg_format === "tuples" ? messages[0] : messages}
|
||||
position={role === "user" ? "right" : "left"}
|
||||
avatar={avatar_img}
|
||||
{layout}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
{#if pending_message}
|
||||
<Pending {layout} />
|
||||
{/if}
|
||||
@ -430,7 +450,6 @@
|
||||
.bubble-wrap {
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
|
||||
height: 100%;
|
||||
padding-top: var(--spacing-xxl);
|
||||
}
|
||||
@ -475,16 +494,7 @@
|
||||
|
||||
.message-bubble-border {
|
||||
border-width: 1px;
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
|
||||
.bubble .user {
|
||||
border-width: 1px;
|
||||
border-radius: var(--radius-xl);
|
||||
align-self: flex-start;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
box-shadow: var(--shadow-drop-lg);
|
||||
border-radius: var(--radius-md);
|
||||
}
|
||||
|
||||
.user {
|
||||
@ -502,11 +512,30 @@
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.bubble .user {
|
||||
.flex-wrap.user {
|
||||
border-width: 1px;
|
||||
border-radius: var(--radius-md);
|
||||
align-self: flex-start;
|
||||
border-bottom-right-radius: 0;
|
||||
box-shadow: var(--shadow-drop);
|
||||
align-self: flex-start;
|
||||
text-align: right;
|
||||
padding: var(--spacing-sm) var(--spacing-xl);
|
||||
border-color: var(--border-color-accent-subdued);
|
||||
background-color: var(--color-accent-soft);
|
||||
}
|
||||
|
||||
:not(.component-wrap).flex-wrap.bot {
|
||||
border-width: 1px;
|
||||
border-radius: var(--radius-lg);
|
||||
align-self: flex-start;
|
||||
border-bottom-left-radius: 0;
|
||||
box-shadow: var(--shadow-drop);
|
||||
align-self: flex-start;
|
||||
text-align: right;
|
||||
padding: var(--spacing-sm) var(--spacing-xl);
|
||||
border-color: var(--border-color-primary);
|
||||
background-color: var(--background-fill-secondary);
|
||||
}
|
||||
|
||||
.panel .user :global(*) {
|
||||
@ -518,11 +547,6 @@
|
||||
border-color: var(--border-color-primary);
|
||||
}
|
||||
|
||||
.bubble .user {
|
||||
border-color: var(--border-color-accent-subdued);
|
||||
background-color: var(--color-accent-soft);
|
||||
}
|
||||
|
||||
.message-row {
|
||||
display: flex;
|
||||
/* flex-direction: column; */
|
||||
@ -534,6 +558,7 @@
|
||||
}
|
||||
.message-row.bubble {
|
||||
margin: calc(var(--spacing-xl) * 3);
|
||||
margin-bottom: var(--spacing-xl);
|
||||
}
|
||||
|
||||
.with_avatar.message-row.panel {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
export let handle_action: (selected: string | null) => void;
|
||||
export let padded = false;
|
||||
export let position: "right" | "left" = "left";
|
||||
|
||||
let selected: "like" | "dislike" | null = null;
|
||||
</script>
|
||||
@ -18,15 +19,13 @@
|
||||
aria-label={selected === "dislike" ? "clicked dislike" : "dislike"}
|
||||
class:padded
|
||||
class:selected={selected === "dislike"}
|
||||
class="dislike-button"
|
||||
class="dislike-button {position}"
|
||||
>
|
||||
<span>
|
||||
{#if selected === "dislike"}
|
||||
<ThumbDownActive />
|
||||
{:else}
|
||||
<ThumbDownDefault />
|
||||
{/if}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@ -39,13 +38,11 @@
|
||||
aria-label={selected === "like" ? "clicked like" : "like"}
|
||||
class:selected={selected === "like"}
|
||||
>
|
||||
<span>
|
||||
{#if selected === "like"}
|
||||
<ThumbUpActive />
|
||||
{:else}
|
||||
<ThumbUpDefault />
|
||||
{/if}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<style>
|
||||
@ -55,11 +52,6 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 7px !important;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
@ -72,8 +64,4 @@
|
||||
.selected:hover {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.like-button {
|
||||
transform: translateY(0px);
|
||||
}
|
||||
</style>
|
||||
|
@ -30,18 +30,24 @@
|
||||
cursor: pointer;
|
||||
max-width: max-content;
|
||||
background: var(--color-accent-soft);
|
||||
border: 1px solid var(--border-color-accent-subdued);
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
padding: 3px 6px;
|
||||
color: var(--body-text-color);
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 8px;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.content :global(*) {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
|
@ -156,3 +156,9 @@ export function normalise_tuples(
|
||||
});
|
||||
return msg.filter((message) => message != null) as NormalisedMessage[];
|
||||
}
|
||||
|
||||
export function is_component_message(
|
||||
message: NormalisedMessage
|
||||
): message is ComponentMessage {
|
||||
return message.type === "component";
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export interface Message {
|
||||
role: MessageRole;
|
||||
metadata: Metadata;
|
||||
content: string | FileData | ComponentData;
|
||||
index: [number, number] | number;
|
||||
index: number | [number, number];
|
||||
}
|
||||
|
||||
export interface TextMessage extends Message {
|
||||
|
Loading…
Reference in New Issue
Block a user