Simplify message header markup
This commit is contained in:
@@ -21,12 +21,15 @@ interface MessageItemProps {
|
|||||||
export default function MessageItem(props: MessageItemProps) {
|
export default function MessageItem(props: MessageItemProps) {
|
||||||
|
|
||||||
const isUser = () => props.record.role === "user"
|
const isUser = () => props.record.role === "user"
|
||||||
|
const createdTimestamp = () => props.messageInfo?.time?.created ?? props.record.createdAt
|
||||||
|
|
||||||
const timestamp = () => {
|
const timestamp = () => {
|
||||||
const createdTime = props.messageInfo?.time?.created ?? props.record.createdAt
|
const date = new Date(createdTimestamp())
|
||||||
const date = new Date(createdTime)
|
|
||||||
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const timestampIso = () => new Date(createdTimestamp()).toISOString()
|
||||||
|
|
||||||
type FilePart = Extract<ClientPart, { type: "file" }> & {
|
type FilePart = Extract<ClientPart, { type: "file" }> & {
|
||||||
url?: string
|
url?: string
|
||||||
mime?: string
|
mime?: string
|
||||||
@@ -149,6 +152,8 @@ interface MessageItemProps {
|
|||||||
? "message-item-base bg-[var(--message-user-bg)] border-l-4 border-[var(--message-user-border)]"
|
? "message-item-base bg-[var(--message-user-bg)] border-l-4 border-[var(--message-user-border)]"
|
||||||
: "message-item-base assistant-message bg-[var(--message-assistant-bg)] border-l-4 border-[var(--message-assistant-border)]"
|
: "message-item-base assistant-message bg-[var(--message-assistant-bg)] border-l-4 border-[var(--message-assistant-border)]"
|
||||||
|
|
||||||
|
const speakerLabel = () => (isUser() ? "You" : "Assistant")
|
||||||
|
|
||||||
const agentIdentifier = () => {
|
const agentIdentifier = () => {
|
||||||
if (isUser()) return ""
|
if (isUser()) return ""
|
||||||
const info = props.messageInfo
|
const info = props.messageInfo
|
||||||
@@ -166,29 +171,31 @@ interface MessageItemProps {
|
|||||||
return modelID
|
return modelID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const agentMeta = () => {
|
||||||
|
if (isUser() || !props.showAgentMeta) return ""
|
||||||
|
const segments: string[] = []
|
||||||
|
const agent = agentIdentifier()
|
||||||
|
const model = modelIdentifier()
|
||||||
|
if (agent) {
|
||||||
|
segments.push(`Agent: ${agent}`)
|
||||||
|
}
|
||||||
|
if (model) {
|
||||||
|
segments.push(`Model: ${model}`)
|
||||||
|
}
|
||||||
|
return segments.join(" • ")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div class={containerClass()}>
|
||||||
<div class={containerClass()}>
|
<header class={`message-item-header ${isUser() ? "pb-0.5" : "pb-0"}`}>
|
||||||
<div class={`flex justify-between items-center gap-2.5 ${isUser() ? "pb-0.5" : "pb-0"}`}>
|
<div class="message-speaker">
|
||||||
<div class="flex flex-col">
|
<span class="message-speaker-label" data-role={isUser() ? "user" : "assistant"}>
|
||||||
<Show when={isUser()}>
|
{speakerLabel()}
|
||||||
<span class="font-semibold text-xs text-[var(--message-user-border)]">You</span>
|
</span>
|
||||||
</Show>
|
<Show when={agentMeta()}>{(meta) => <span class="message-agent-meta">{meta()}</span>}</Show>
|
||||||
<Show when={!isUser()}>
|
</div>
|
||||||
<div class="flex flex-wrap items-center gap-2 text-xs text-[var(--message-assistant-border)]">
|
<div class="message-item-actions">
|
||||||
<span class="font-semibold">Assistant</span>
|
|
||||||
<Show when={props.showAgentMeta && (agentIdentifier() || modelIdentifier())}>
|
|
||||||
<span class="message-step-meta-inline">
|
|
||||||
<Show when={agentIdentifier()}>{(value) => <span class="font-medium text-[var(--message-assistant-border)]">Agent: {value()}</span>}</Show>
|
|
||||||
<Show when={modelIdentifier()}>{(value) => <span class="font-medium text-[var(--message-assistant-border)]">Model: {value()}</span>}</Show>
|
|
||||||
</span>
|
|
||||||
</Show>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
|
|
||||||
<Show when={isUser() && props.onRevert}>
|
<Show when={isUser() && props.onRevert}>
|
||||||
<button
|
<button
|
||||||
class="bg-transparent border border-[var(--border-base)] text-[var(--text-muted)] cursor-pointer px-3 py-0.5 rounded text-xs font-semibold leading-none transition-all duration-200 flex items-center justify-center h-6 hover:bg-[var(--surface-hover)] hover:border-[var(--accent-primary)] hover:text-[var(--accent-primary)] active:scale-95"
|
class="bg-transparent border border-[var(--border-base)] text-[var(--text-muted)] cursor-pointer px-3 py-0.5 rounded text-xs font-semibold leading-none transition-all duration-200 flex items-center justify-center h-6 hover:bg-[var(--surface-hover)] hover:border-[var(--accent-primary)] hover:text-[var(--accent-primary)] active:scale-95"
|
||||||
@@ -209,12 +216,13 @@ interface MessageItemProps {
|
|||||||
Fork
|
Fork
|
||||||
</button>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
<span class="text-[11px] text-[var(--text-muted)]">{timestamp()}</span>
|
<time class="message-timestamp" dateTime={timestampIso()}>{timestamp()}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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]">
|
||||||
|
|
||||||
|
|
||||||
<Show when={props.isQueued && isUser()}>
|
<Show when={props.isQueued && isUser()}>
|
||||||
<div class="message-queued-badge">QUEUED</div>
|
<div class="message-queued-badge">QUEUED</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|||||||
@@ -3,6 +3,38 @@
|
|||||||
@apply flex flex-col gap-2 p-3 w-full;
|
@apply flex flex-col gap-2 p-3 w-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-item-header {
|
||||||
|
@apply flex justify-between items-start gap-2.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-speaker {
|
||||||
|
@apply flex flex-col gap-0.5 text-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-speaker-label {
|
||||||
|
font-weight: var(--font-weight-semibold);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-speaker-label[data-role="user"] {
|
||||||
|
color: var(--message-user-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-speaker-label[data-role="assistant"] {
|
||||||
|
color: var(--message-assistant-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-agent-meta {
|
||||||
|
@apply text-xs text-[var(--message-assistant-border)];
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-item-actions {
|
||||||
|
@apply flex items-center gap-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-timestamp {
|
||||||
|
@apply text-[11px] text-[var(--text-muted)];
|
||||||
|
}
|
||||||
|
|
||||||
.assistant-message {
|
.assistant-message {
|
||||||
/* gap: 0.25rem; */
|
/* gap: 0.25rem; */
|
||||||
padding: 0.6rem 0.65rem;
|
padding: 0.6rem 0.65rem;
|
||||||
|
|||||||
Reference in New Issue
Block a user