codeburn/app/renderer/components/CliErrorPanel.tsx
iamtoruk 015a1a069a polish(app): shared empty states, type ladder, AA contrast, honest affordances, a11y semantics
D1 one shared EmptyNote (7 copies removed); CliErrorPanel on canonical
   tokens; dead code deleted (CapsuleChart, stale SERIES_HEX palette,
   Stat tone API, unused rail/doc-chrome CSS)
D2 type ladder tokens (--fs-*/--fw-*); panel titles unified 13/600/ink;
   high-visibility sizes/weights snapped to rungs
D3 contrast: --mut2 5.00:1 light / 5.74:1 dark (was 2.37/3.11); new
   --accent-text 5.07:1 + persistent underline on text links; last
   prose em-dash removed
D4 'See all' and 'Most expensive sessions' navigate to Sessions; 'add
   alias' jumps to Settings/Aliases; chevrons only on clickable rows;
   inline confirm replaces window.confirm; default-period setting
   honored at boot; Sankey caption no longer promises a click; Optimize
   'improving' trend badges; cursor + Space-key fixes
D5 aria-current on nav, SegTabs as real tablist, aria-pressed toggles,
   ProviderPop rebuilt on Dropdown (one tab stop, arrow keys, focus ring)

191/191, typecheck + build green. Contrast ratios independently
recomputed. Net -93 lines.
2026-07-16 02:27:41 -07:00

59 lines
2.1 KiB
TypeScript

import { Panel } from './Panel'
import type { CliError } from '../lib/types'
export function isPermissionCliError(error: CliError | null): boolean {
return error?.kind === 'nonzero' && /permission|full disk access|eacces/i.test(error.message)
}
export function cliErrorDisplay(error: CliError): { title: string; message: string; tone: 'amber' | 'red' | 'muted' } {
if (error.kind === 'not-found') {
return {
title: 'Locate the codeburn CLI',
message: 'Install it with npm i -g codeburn, then reopen this window.',
tone: 'muted',
}
}
if (isPermissionCliError(error)) {
return {
title: 'Permission denied',
message: 'permission denied; grant Full Disk Access',
tone: 'amber',
}
}
return { title: "Couldn't read data", message: error.message, tone: 'red' }
}
function colorForTone(tone: 'amber' | 'red' | 'muted'): string {
if (tone === 'amber') return 'var(--warn)'
if (tone === 'red') return 'var(--bad)'
return 'var(--mut2)'
}
export function CliErrorText({ error }: { error: CliError }) {
const display = cliErrorDisplay(error)
return <p style={{ color: colorForTone(display.tone), margin: 0, fontSize: 12 }}>{display.message}</p>
}
export function CliErrorPanel({ error, subject = 'usage' }: { error: CliError; subject?: string }) {
const display = cliErrorDisplay(error)
if (error.kind === 'not-found') {
return (
<Panel title={display.title}>
<p style={{ color: 'var(--mut)', margin: '0 0 6px', fontSize: 12.5 }}>
CodeBurn Desktop reads {subject} by running the{' '}
<code style={{ fontFamily: 'var(--mono)', color: 'var(--accent)' }}>codeburn</code> command, but it isn&apos;t
on your PATH yet.
</p>
<p style={{ color: colorForTone(display.tone), margin: 0, fontSize: 11.5 }}>
Install it with <code style={{ fontFamily: 'var(--mono)', color: 'var(--accent)' }}>npm i -g codeburn</code>,
then reopen this window.
</p>
</Panel>
)
}
return (
<Panel title={display.title}>
<CliErrorText error={error} />
</Panel>
)
}