fix(ui): split message header into two rows

Move assistant meta below speaker label and bump speaker label size.
This commit is contained in:
Shantur Rathore
2026-02-11 16:02:24 +00:00
parent fd5941fb36
commit 3382736f05
2 changed files with 84 additions and 61 deletions

View File

@@ -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]">

View File

@@ -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"] {