codeburn/app/renderer/components/ListRow.tsx
iamtoruk f8b2894b4e feat(app): Sessions provider quick-filter + Spend project inline expand
- Sessions: All + per-provider logo buttons (detected, cost > 0) that
  drive the same app-level provider state as the top-bar dropdown, so
  the two controls can never disagree; aria-pressed group semantics
- Spend By project: rows expand inline (single-open, aria-expanded,
  chevron rotation) to the project's sessions: date, top model, calls,
  currency-aware cost; date-only strings parsed at local noon so days
  never roll across time zones

194/194, typecheck + build green.
2026-07-16 02:49:17 -07:00

58 lines
1.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { CSSProperties, KeyboardEvent, ReactNode } from 'react'
export { seriesColorForModel } from '../lib/modelSeries'
/**
* A `.li` list row: optional rank `.no`, optional model series `.mdot`, a
* title + sub line `.lx`, an optional right-aligned `.val`. When `onClick` is
* provided the row becomes a keyboard-operable button and shows the trailing
* chevron; without it the row is inert and the chevron is omitted (honest).
* Pass `expanded` on an interactive row to reflect its open/closed state
* (`aria-expanded`, which also rotates the chevron).
*/
export function ListRow({
no,
dotColor,
title,
sub,
value,
valueClass,
onClick,
expanded,
}: {
no?: ReactNode
dotColor?: string
title: ReactNode
sub?: ReactNode
value?: ReactNode
valueClass?: string
onClick?: () => void
expanded?: boolean
}) {
const dot: CSSProperties | undefined = dotColor ? { background: dotColor } : undefined
const interactive = onClick !== undefined
const onKeyDown = interactive
? (event: KeyboardEvent<HTMLDivElement>) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault()
onClick()
}
}
: undefined
return (
<div
className={interactive ? 'li li-clickable' : 'li'}
{...(interactive ? { role: 'button', tabIndex: 0, onClick, onKeyDown } : {})}
{...(interactive && expanded !== undefined ? { 'aria-expanded': expanded } : {})}
>
{no !== undefined && <span className="no">{no}</span>}
{dotColor !== undefined && <span className="mdot" style={dot} />}
<div className="lx">
<b>{title}</b>
{sub !== undefined && <span>{sub}</span>}
</div>
{value !== undefined && <span className={valueClass ? `val ${valueClass}` : 'val'}>{value}</span>}
{interactive && <span className="chev"></span>}
</div>
)
}