fix(ui): split message header into two rows
Move assistant meta below speaker label and bump speaker label size.
This commit is contained in:
@@ -268,74 +268,84 @@ export default function MessageItem(props: MessageItemProps) {
|
|||||||
return (
|
return (
|
||||||
<div class={containerClass()}>
|
<div class={containerClass()}>
|
||||||
<header class={`message-item-header ${isUser() ? "pb-0.5" : "pb-0"}`}>
|
<header class={`message-item-header ${isUser() ? "pb-0.5" : "pb-0"}`}>
|
||||||
<div class="message-speaker">
|
<div class="message-item-header-row message-item-header-row--top">
|
||||||
<span class="message-speaker-label" data-role={isUser() ? "user" : "assistant"}>
|
<div class="message-speaker">
|
||||||
{speakerLabel()}
|
<span class="message-speaker-label" data-role={isUser() ? "user" : "assistant"}>
|
||||||
</span>
|
{speakerLabel()}
|
||||||
<Show when={agentMeta()}>{(meta) => <span class="message-agent-meta">{meta()}</span>}</Show>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-item-actions">
|
|
||||||
<Show when={isUser()}>
|
|
||||||
<div class="message-action-group">
|
|
||||||
<Show when={props.onRevert}>
|
|
||||||
<button
|
|
||||||
class="message-action-button"
|
|
||||||
onClick={handleRevert}
|
|
||||||
title={t("messageItem.actions.revert")}
|
|
||||||
aria-label={t("messageItem.actions.revert")}
|
|
||||||
>
|
|
||||||
<Undo class="w-3.5 h-3.5" aria-hidden="true" />
|
|
||||||
</button>
|
|
||||||
</Show>
|
|
||||||
<Show when={props.onFork}>
|
|
||||||
<button
|
|
||||||
class="message-action-button"
|
|
||||||
onClick={() => props.onFork?.(props.record.id)}
|
|
||||||
title={t("messageItem.actions.fork")}
|
|
||||||
aria-label={t("messageItem.actions.fork")}
|
|
||||||
>
|
|
||||||
<Split class="w-3.5 h-3.5" aria-hidden="true" />
|
|
||||||
</button>
|
|
||||||
</Show>
|
|
||||||
<button
|
|
||||||
class="message-action-button"
|
|
||||||
onClick={handleCopy}
|
|
||||||
title={copyLabel()}
|
|
||||||
aria-label={copyLabel()}
|
|
||||||
>
|
|
||||||
<Copy class="w-3.5 h-3.5" aria-hidden="true" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
<Show when={!isUser()}>
|
|
||||||
<div class="message-action-group">
|
|
||||||
<button
|
|
||||||
class="message-action-button"
|
|
||||||
onClick={handleCopy}
|
|
||||||
title={copyLabel()}
|
|
||||||
aria-label={copyLabel()}
|
|
||||||
>
|
|
||||||
<Copy class="w-3.5 h-3.5" aria-hidden="true" />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<Show when={deletableTextPartId()}>
|
<div class="message-item-actions">
|
||||||
{(partId) => (
|
<Show when={isUser()}>
|
||||||
|
<div class="message-action-group">
|
||||||
|
<Show when={props.onRevert}>
|
||||||
<button
|
<button
|
||||||
class="message-action-button"
|
class="message-action-button"
|
||||||
onClick={() => void handleDeletePart(partId())}
|
onClick={handleRevert}
|
||||||
disabled={isDeletingPart(partId())}
|
title={t("messageItem.actions.revert")}
|
||||||
title={isDeletingPart(partId()) ? t("messagePart.actions.deleting") : t("messagePart.actions.delete")}
|
aria-label={t("messageItem.actions.revert")}
|
||||||
aria-label={isDeletingPart(partId()) ? t("messagePart.actions.deleting") : t("messagePart.actions.delete")}
|
|
||||||
>
|
>
|
||||||
<Trash2 class="w-3.5 h-3.5" aria-hidden="true" />
|
<Undo class="w-3.5 h-3.5" aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
</Show>
|
||||||
</Show>
|
<Show when={props.onFork}>
|
||||||
</div>
|
<button
|
||||||
</Show>
|
class="message-action-button"
|
||||||
<time class="message-timestamp" dateTime={timestampIso()}>{timestamp()}</time>
|
onClick={() => props.onFork?.(props.record.id)}
|
||||||
|
title={t("messageItem.actions.fork")}
|
||||||
|
aria-label={t("messageItem.actions.fork")}
|
||||||
|
>
|
||||||
|
<Split class="w-3.5 h-3.5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</Show>
|
||||||
|
<button
|
||||||
|
class="message-action-button"
|
||||||
|
onClick={handleCopy}
|
||||||
|
title={copyLabel()}
|
||||||
|
aria-label={copyLabel()}
|
||||||
|
>
|
||||||
|
<Copy class="w-3.5 h-3.5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
<Show when={!isUser()}>
|
||||||
|
<div class="message-action-group">
|
||||||
|
<button
|
||||||
|
class="message-action-button"
|
||||||
|
onClick={handleCopy}
|
||||||
|
title={copyLabel()}
|
||||||
|
aria-label={copyLabel()}
|
||||||
|
>
|
||||||
|
<Copy class="w-3.5 h-3.5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<Show when={deletableTextPartId()}>
|
||||||
|
{(partId) => (
|
||||||
|
<button
|
||||||
|
class="message-action-button"
|
||||||
|
onClick={() => void handleDeletePart(partId())}
|
||||||
|
disabled={isDeletingPart(partId())}
|
||||||
|
title={isDeletingPart(partId()) ? t("messagePart.actions.deleting") : t("messagePart.actions.delete")}
|
||||||
|
aria-label={isDeletingPart(partId()) ? t("messagePart.actions.deleting") : t("messagePart.actions.delete")}
|
||||||
|
>
|
||||||
|
<Trash2 class="w-3.5 h-3.5" aria-hidden="true" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
<time class="message-timestamp" dateTime={timestampIso()}>{timestamp()}</time>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Show when={agentMeta()}>
|
||||||
|
{(meta) => (
|
||||||
|
<div class="message-item-header-row message-item-header-row--bottom">
|
||||||
|
<span class="message-agent-meta">{meta()}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Show>
|
||||||
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="pt-1 whitespace-pre-wrap break-words leading-[1.1]">
|
<div class="pt-1 whitespace-pre-wrap break-words leading-[1.1]">
|
||||||
|
|||||||
@@ -4,15 +4,28 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.message-item-header {
|
.message-item-header {
|
||||||
|
@apply flex flex-col gap-0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item-header-row {
|
||||||
|
@apply w-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item-header-row--top {
|
||||||
@apply flex justify-between items-start gap-2.5;
|
@apply flex justify-between items-start gap-2.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-item-header-row--bottom {
|
||||||
|
@apply flex items-start;
|
||||||
|
}
|
||||||
|
|
||||||
.message-speaker {
|
.message-speaker {
|
||||||
@apply flex flex-col gap-0.5 text-xs;
|
@apply flex flex-col gap-0.5 text-xs;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-speaker-label {
|
.message-speaker-label {
|
||||||
font-weight: var(--font-weight-semibold);
|
font-weight: var(--font-weight-semibold);
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-speaker-label[data-role="user"] {
|
.message-speaker-label[data-role="user"] {
|
||||||
|
|||||||
Reference in New Issue
Block a user