feat(ui): move context usage pills to right drawer header

This commit is contained in:
Shantur Rathore
2026-02-06 10:34:44 +00:00
parent e2ff758003
commit 6f73adaef6
2 changed files with 41 additions and 53 deletions

View File

@@ -923,7 +923,6 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
<Show when={activeSessionForInstance()}> <Show when={activeSessionForInstance()}>
{(activeSession) => ( {(activeSession) => (
<> <>
<ContextUsagePanel instanceId={props.instance.id} sessionId={activeSession().id} />
<div class="session-sidebar-controls px-4 py-4 border-t border-base flex flex-col gap-3"> <div class="session-sidebar-controls px-4 py-4 border-t border-base flex flex-col gap-3">
<AgentSelector <AgentSelector
instanceId={props.instance.id} instanceId={props.instance.id}
@@ -1091,35 +1090,46 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
return ( return (
<div class="flex flex-col h-full" ref={setRightDrawerContentEl}> <div class="flex flex-col h-full" ref={setRightDrawerContentEl}>
<div class="relative flex items-center px-4 py-2 border-b border-base text-primary"> <div class="border-b border-base text-primary">
<div class="flex items-center gap-2"> <div class="relative flex items-center px-4 py-2">
<Show when={rightDrawerState() === "floating-open"}> <div class="flex items-center gap-2">
<IconButton <Show when={rightDrawerState() === "floating-open"}>
size="small" <IconButton
color="inherit" size="small"
aria-label={t("instanceShell.rightDrawer.toggle.close")} color="inherit"
title={t("instanceShell.rightDrawer.toggle.close")} aria-label={t("instanceShell.rightDrawer.toggle.close")}
onClick={closeRightDrawer} title={t("instanceShell.rightDrawer.toggle.close")}
> onClick={closeRightDrawer}
<MenuOpenIcon fontSize="small" sx={{ transform: "scaleX(-1)" }} /> >
</IconButton> <MenuOpenIcon fontSize="small" sx={{ transform: "scaleX(-1)" }} />
</Show> </IconButton>
<Show when={!isPhoneLayout()}> </Show>
<IconButton <Show when={!isPhoneLayout()}>
size="small" <IconButton
color="inherit" size="small"
aria-label={rightPinned() ? t("instanceShell.rightDrawer.unpin") : t("instanceShell.rightDrawer.pin")} color="inherit"
onClick={() => (rightPinned() ? unpinRightDrawer() : pinRightDrawer())} aria-label={rightPinned() ? t("instanceShell.rightDrawer.unpin") : t("instanceShell.rightDrawer.pin")}
> onClick={() => (rightPinned() ? unpinRightDrawer() : pinRightDrawer())}
{rightPinned() ? <PushPinIcon fontSize="small" /> : <PushPinOutlinedIcon fontSize="small" />} >
</IconButton> {rightPinned() ? <PushPinIcon fontSize="small" /> : <PushPinOutlinedIcon fontSize="small" />}
</Show> </IconButton>
</div> </Show>
<div class="pointer-events-none absolute inset-0 flex items-center justify-center"> </div>
<Typography variant="subtitle2" class="uppercase tracking-wide text-xs font-semibold text-primary"> <div class="pointer-events-none absolute inset-0 flex items-center justify-center">
{t("instanceShell.rightPanel.title")} <span class="session-sidebar-title text-sm font-semibold uppercase text-primary">
</Typography> {t("instanceShell.rightPanel.title")}
</span>
</div>
</div> </div>
<Show when={activeSessionForInstance()}>
{(activeSession) => (
<ContextUsagePanel
instanceId={props.instance.id}
sessionId={activeSession().id}
class="border-t border-base"
/>
)}
</Show>
</div> </div>
<div class="flex-1 overflow-y-auto"> <div class="flex-1 overflow-y-auto">
<Accordion.Root <Accordion.Root

View File

@@ -6,11 +6,11 @@ import { useI18n } from "../../lib/i18n"
interface ContextUsagePanelProps { interface ContextUsagePanelProps {
instanceId: string instanceId: string
sessionId: string sessionId: string
class?: string
} }
const chipClass = "inline-flex items-center gap-1 rounded-full border border-base px-2 py-0.5 text-xs text-primary" const chipClass = "inline-flex items-center gap-1 rounded-full border border-base px-2 py-0.5 text-xs text-primary"
const chipLabelClass = "uppercase text-[10px] tracking-wide text-muted" const chipLabelClass = "uppercase text-[10px] tracking-wide text-muted"
const headingClass = "text-xs font-semibold text-muted uppercase tracking-wide"
const ContextUsagePanel: Component<ContextUsagePanelProps> = (props) => { const ContextUsagePanel: Component<ContextUsagePanelProps> = (props) => {
const { t } = useI18n() const { t } = useI18n()
@@ -31,26 +31,16 @@ const ContextUsagePanel: Component<ContextUsagePanelProps> = (props) => {
const inputTokens = createMemo(() => info().inputTokens ?? 0) const inputTokens = createMemo(() => info().inputTokens ?? 0)
const outputTokens = createMemo(() => info().outputTokens ?? 0) const outputTokens = createMemo(() => info().outputTokens ?? 0)
const actualUsageTokens = createMemo(() => info().actualUsageTokens ?? 0)
const availableTokens = createMemo(() => info().contextAvailableTokens)
const outputLimit = createMemo(() => info().modelOutputLimit ?? 0)
const costValue = createMemo(() => { const costValue = createMemo(() => {
const value = info().isSubscriptionModel ? 0 : info().cost const value = info().isSubscriptionModel ? 0 : info().cost
return value > 0 ? value : 0 return value > 0 ? value : 0
}) })
const formatTokenValue = (value: number | null | undefined) => {
if (value === null || value === undefined) return t("contextUsagePanel.unavailable")
return formatTokenTotal(value)
}
const costDisplay = createMemo(() => `$${costValue().toFixed(2)}`) const costDisplay = createMemo(() => `$${costValue().toFixed(2)}`)
return ( return (
<div class="session-context-panel border-r border-base border-b px-3 py-3 space-y-3"> <div class={`session-context-panel px-4 py-2 ${props.class ?? ""}`}>
<div class="flex flex-wrap items-center gap-2 text-xs text-primary"> <div class="flex flex-wrap items-center gap-2 text-xs text-primary">
<div class={headingClass}>{t("contextUsagePanel.headings.tokens")}</div>
<div class={chipClass}> <div class={chipClass}>
<span class={chipLabelClass}>{t("contextUsagePanel.labels.input")}</span> <span class={chipLabelClass}>{t("contextUsagePanel.labels.input")}</span>
<span class="font-semibold text-primary">{formatTokenTotal(inputTokens())}</span> <span class="font-semibold text-primary">{formatTokenTotal(inputTokens())}</span>
@@ -64,18 +54,6 @@ const ContextUsagePanel: Component<ContextUsagePanelProps> = (props) => {
<span class="font-semibold text-primary">{costDisplay()}</span> <span class="font-semibold text-primary">{costDisplay()}</span>
</div> </div>
</div> </div>
<div class="flex flex-wrap items-center gap-2 text-xs text-primary">
<div class={headingClass}>{t("contextUsagePanel.headings.context")}</div>
<div class={chipClass}>
<span class={chipLabelClass}>{t("contextUsagePanel.labels.used")}</span>
<span class="font-semibold text-primary">{formatTokenTotal(actualUsageTokens())}</span>
</div>
<div class={chipClass}>
<span class={chipLabelClass}>{t("contextUsagePanel.labels.available")}</span>
<span class="font-semibold text-primary">{formatTokenValue(availableTokens())}</span>
</div>
</div>
</div> </div>
) )
} }