ui: address PR comments and rename 'usage-limit' to 'quota'

This commit is contained in:
Keith Guerin
2026-02-28 23:55:24 -08:00
parent ea965bc149
commit 94272f3f24
7 changed files with 47 additions and 55 deletions

View File

@@ -19,7 +19,7 @@ describe('deriveItemsFromLegacySettings', () => {
'git-branch',
'sandbox-status',
'model-name',
'usage-limit',
'quota',
]);
});
@@ -39,14 +39,14 @@ describe('deriveItemsFromLegacySettings', () => {
expect(items).not.toContain('sandbox-status');
});
it('removes model-name, context-remaining, and usage-limit when hideModelInfo is true', () => {
it('removes model-name, context-remaining, and quota when hideModelInfo is true', () => {
const settings = createMockSettings({
ui: { footer: { hideModelInfo: true, hideContextPercentage: true } },
}).merged;
const items = deriveItemsFromLegacySettings(settings);
expect(items).not.toContain('model-name');
expect(items).not.toContain('context-remaining');
expect(items).not.toContain('usage-limit');
expect(items).not.toContain('quota');
});
it('includes context-remaining when hideContextPercentage is false', () => {

View File

@@ -33,7 +33,7 @@ export const ALL_ITEMS = [
description: 'Percentage of context window remaining',
},
{
id: 'usage-limit',
id: 'quota',
header: '/stats',
description: 'Remaining usage on daily limit (not shown when unavailable)',
},
@@ -67,7 +67,7 @@ export const DEFAULT_ORDER = [
'sandbox-status',
'model-name',
'context-remaining',
'usage-limit',
'quota',
'memory-usage',
'session-id',
'code-changes',
@@ -82,7 +82,7 @@ export function deriveItemsFromLegacySettings(
'git-branch',
'sandbox-status',
'model-name',
'usage-limit',
'quota',
];
const items = [...defaults];
@@ -96,7 +96,7 @@ export function deriveItemsFromLegacySettings(
if (settings.ui.footer.hideModelInfo) {
remove(items, 'model-name');
remove(items, 'context-remaining');
remove(items, 'usage-limit');
remove(items, 'quota');
}
if (
!settings.ui.footer.hideContextPercentage &&

View File

@@ -17,10 +17,7 @@ import { ConsoleSummaryDisplay } from './ConsoleSummaryDisplay.js';
import process from 'node:process';
import { MemoryUsageDisplay } from './MemoryUsageDisplay.js';
import { ContextUsageDisplay } from './ContextUsageDisplay.js';
import {
QUOTA_THRESHOLD_HIGH,
QUOTA_THRESHOLD_MEDIUM,
} from '../utils/displayUtils.js';
import { QuotaDisplay } from './QuotaDisplay.js';
import { DebugProfiler } from './DebugProfiler.js';
import { useUIState } from '../contexts/UIStateContext.js';
import { useConfig } from '../contexts/ConfigContext.js';
@@ -312,24 +309,22 @@ export const Footer: React.FC = () => {
);
break;
}
case 'usage-limit': {
case 'quota': {
if (quotaStats?.remaining !== undefined && quotaStats.limit) {
const percentage = (quotaStats.remaining / quotaStats.limit) * 100;
let color = itemColor;
if (percentage < QUOTA_THRESHOLD_MEDIUM) {
color = theme.status.error;
} else if (percentage < QUOTA_THRESHOLD_HIGH) {
color = theme.status.warning;
}
const text =
quotaStats.remaining === 0
? 'limit reached'
: `daily ${percentage.toFixed(0)}%`;
addCol(
id,
header,
() => <Text color={color}>{text}</Text>,
text.length,
() => (
<QuotaDisplay
remaining={quotaStats.remaining}
limit={quotaStats.limit}
resetTime={quotaStats.resetTime}
terse={true}
forceShow={true}
lowercase={true}
/>
),
10, // "daily 100%" is 10 chars, but terse is "100%" (4 chars)
);
}
break;
@@ -375,18 +370,16 @@ export const Footer: React.FC = () => {
for (const m of Object.values(uiState.sessionStats.metrics.models))
total += m.tokens.total;
if (total > 0) {
const formatted =
new Intl.NumberFormat('en-US', {
notation: 'compact',
maximumFractionDigits: 1,
})
.format(total)
.toLowerCase() + ' tokens';
const formatter = new Intl.NumberFormat('en-US', {
notation: 'compact',
maximumFractionDigits: 1,
});
const formatted = formatter.format(total).toLowerCase();
addCol(
id,
header,
() => <Text color={itemColor}>{formatted}</Text>,
formatted.length,
() => <Text color={itemColor}>{formatted} tokens</Text>,
formatted.length + 7,
);
}
break;

View File

@@ -285,9 +285,7 @@ export const FooterConfigDialog: React.FC<FooterConfigDialogProps> = ({
'context-remaining': (
<Text color={getColor('context-remaining', itemColor)}>85% left</Text>
),
'usage-limit': (
<Text color={getColor('usage-limit', itemColor)}>daily 97%</Text>
),
quota: <Text color={getColor('quota', itemColor)}>97%</Text>,
'memory-usage': (
<Text color={getColor('memory-usage', itemColor)}>260 MB</Text>
),

View File

@@ -18,6 +18,8 @@ interface QuotaDisplayProps {
limit: number | undefined;
resetTime?: string;
terse?: boolean;
forceShow?: boolean;
lowercase?: boolean;
}
export const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
@@ -25,6 +27,8 @@ export const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
limit,
resetTime,
terse = false,
forceShow = false,
lowercase = false,
}) => {
if (remaining === undefined || limit === undefined || limit === 0) {
return null;
@@ -32,7 +36,7 @@ export const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
const percentage = (remaining / limit) * 100;
if (percentage > QUOTA_THRESHOLD_HIGH) {
if (!forceShow && percentage > QUOTA_THRESHOLD_HIGH) {
return null;
}
@@ -45,20 +49,17 @@ export const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
!terse && resetTime ? `, ${formatResetTime(resetTime)}` : '';
if (remaining === 0) {
return (
<Text color={color}>
{terse
? 'Limit reached'
: `/stats Limit reached${resetInfo}${!terse && '. /auth to continue.'}`}
</Text>
);
let text = terse
? 'Limit reached'
: `/stats Limit reached${resetInfo}${!terse && '. /auth to continue.'}`;
if (lowercase) text = text.toLowerCase();
return <Text color={color}>{text}</Text>;
}
return (
<Text color={color}>
{terse
? `${percentage.toFixed(0)}%`
: `/stats ${percentage.toFixed(0)}% usage remaining${resetInfo}`}
</Text>
);
let text = terse
? `${percentage.toFixed(0)}%`
: `/stats ${percentage.toFixed(0)}% usage remaining${resetInfo}`;
if (lowercase) text = text.toLowerCase();
return <Text color={color}>{text}</Text>;
};

View File

@@ -8,7 +8,7 @@ exports[`<Footer /> > displays "Limit reached" message when remaining is 0 1`] =
exports[`<Footer /> > displays the usage indicator when usage is low 1`] = `
" workspace (/directory) sandbox /model /stats
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro daily 15%
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro 15%
"
`;
@@ -40,6 +40,6 @@ exports[`<Footer /> > footer configuration filtering (golden snapshots) > render
exports[`<Footer /> > hides the usage indicator when usage is not near limit 1`] = `
" workspace (/directory) sandbox /model /stats
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro daily 85%
~/project/foo/bar/and/some/more/directories/to/make/it/long no sandbox gemini-pro 85%
"
`;

View File

@@ -26,7 +26,7 @@ exports[`<FooterConfigDialog /> > renders correctly with default settings 1`] =
│ ┌────────────────────────────────────────────────────────────────────────────────────────────┐ │
│ │ Preview: │ │
│ │ workspace (/directory) branch sandbox /model /stats │ │
│ │ ~/project/path main docker gemini-2.5-pro daily 97% │ │
│ │ ~/project/path main docker gemini-2.5-pro 97% │ │
│ └────────────────────────────────────────────────────────────────────────────────────────────┘ │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯