Skip to content

Conversation

@AndyMik90
Copy link
Owner

@AndyMik90 AndyMik90 commented Jan 20, 2026

Add a minimalistic account profile indicator to the sidebar that shows the active Claude Code integration account. When the user hovers over this indicator, a popup should display detailed rate limit information including session usage, weekly usage (all models), and weekly usage (Sonnet only). This feature integrates with the existing usage monitoring system and requires extending it to support the additional Sonnet-only usage metric.

Summary by CodeRabbit

  • New Features
    • Adds an account profile indicator in the sidebar showing usage metrics with a status dot and popover
    • Shows session, weekly (all models), and optional Sonnet-specific weekly usage with colored progress bars
    • Displays resets time and last-updated timestamps for each metric
    • Handles loading, error, and no-data states with real-time updates
    • Localization added for English and French

✏️ Tip: You can customize this high-level summary in your review settings.

AndyMik90 and others added 6 commits January 19, 2026 23:09
…nal sonnetWeeklyPercent and sonnetWeeklyResetTime fields
…or ClaudeUsageSnapshot

- Create usage-store.ts following patterns from rate-limit-store.ts and claude-profile-store.ts
- Add UsageState interface with usage, isLoading, and error state
- Implement setUsage, setLoading, setError, and clearUsage actions
- Add loadUsageData() async function for initial data load via IPC
- Add subscribeToUsageUpdates() function for real-time updates

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Created new AccountProfileIndicator component for sidebar with:
- Minimalistic trigger button showing profile name and status indicator
- Color-coded status dot based on usage thresholds (green/yellow/orange/red)
- Detailed popup with session, weekly, and Sonnet usage progress bars
- Integration with Zustand usage store for real-time updates
- Proper loading, error, and no-data states
- i18n translation keys for all user-facing text
- Follows patterns from ClaudeCodeStatusBadge and UsageIndicator

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds a new AccountProfileIndicator UI component and supporting Zustand store for Claude usage snapshots, integrates it into the sidebar, adds a reusable UsageProgressBar and usage-color utilities, extends the usage type for Sonnet fields, and adds English and French localization keys.

Changes

Cohort / File(s) Summary
UI — New component
apps/frontend/src/renderer/components/AccountProfileIndicator.tsx
New exported React component that renders a status-trigger with a popover showing session, weekly, and optional Sonnet usage sections; handles loading/error/no-data states, formats timestamps, truncates long names, and subscribes to usage updates.
UI — Minor update
apps/frontend/src/renderer/components/Sidebar.tsx
Imported and rendered AccountProfileIndicator in the sidebar bottom area next to ClaudeCodeStatusBadge.
State — Usage store
apps/frontend/src/renderer/stores/usage-store.ts
New Zustand store useUsageStore plus loadUsageData() and subscribeToUsageUpdates() that fetch and subscribe to usage snapshots via window.electronAPI (IPC), with loading/error handling and concurrency guard.
UI — Progress bar & exports
apps/frontend/src/renderer/components/ui/usage-progress-bar.tsx, apps/frontend/src/renderer/components/ui/index.ts
New UsageProgressBar component and re-exported from UI barrel.
Logic — Usage colors
apps/frontend/src/renderer/lib/usage-colors.ts
Centralized usage thresholds and helpers: USAGE_THRESHOLDS, getUsageBgColor, getUsageTextColor, getUsageBadgeClasses, isUsageCritical, isUsageWarning.
Types
apps/frontend/src/shared/types/agent.ts
Extended ClaudeUsageSnapshot with optional sonnetWeeklyPercent?: number and sonnetWeeklyResetTime?: string.
Localization
apps/frontend/src/shared/i18n/locales/en/navigation.json, apps/frontend/src/shared/i18n/locales/fr/navigation.json
Added accountProfile keys (title, loading, error, noData, viewUsage, noProfile, sessionUsage, weeklyUsage, sonnetUsage, resetsAt, lastUpdated, activeAccount, usageStatusAriaLabel).
Refactor / UsageIndicator
apps/frontend/src/renderer/components/UsageIndicator.tsx
Reworked to use i18n, centralized color helpers and UsageProgressBar, and replace hardcoded thresholds with isUsageWarning/isUsageCritical.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI as AccountProfileIndicator
    participant Store as Usage Store (Zustand)
    participant IPC as Renderer IPC
    participant Main as Main Process

    User->>UI: Mount component / open popover
    activate UI
    UI->>Store: loadUsageData()
    activate Store
    Store->>Store: setLoading(true)
    Store->>IPC: requestUsageUpdate()
    IPC->>Main: forward request
    Main-->>IPC: return ClaudeUsageSnapshot
    IPC-->>Store: deliver snapshot
    Store->>Store: setUsage(snapshot), setLoading(false)
    deactivate Store
    UI->>Store: subscribeToUsageUpdates()
    Store->>IPC: register onUsageUpdated listener
    IPC->>Main: (listener registered)
    Main->>IPC: emit usage update
    IPC-->>Store: onUsageUpdated(newSnapshot)
    Store->>Store: setUsage(newSnapshot)
    Store->>UI: triggers re-render with updated usage
    deactivate UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Suggested labels

size/M

Suggested reviewers

  • AlexMadera

Poem

🐰 A little indicator hopped to the side,
Showing bars where the usage does hide,
Sonnet and weekly in colors so bright,
Real-time updates keep everything right,
Hooray for the sidebar — hop, nibble, delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 76.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main addition: a sidebar account profile indicator with a rate limit popup, which is the primary feature across all file changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AndyMik90, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a new UI element in the sidebar that provides users with quick access to their Claude Code integration account status and detailed rate limit information. This enhancement aims to improve user awareness of their usage against various limits, including a new Sonnet-specific weekly limit, by presenting this data in an easily accessible and visually intuitive manner.

Highlights

  • New Account Profile Indicator: A new AccountProfileIndicator component has been added to the sidebar, providing a minimalistic display of the active Claude Code integration account.
  • Detailed Rate Limit Popup: Hovering over the account indicator now triggers a popup displaying detailed rate limit information, including session usage, weekly usage across all models, and a newly introduced Sonnet-specific weekly usage.
  • Usage Data Management: A new Zustand store (usage-store.ts) has been implemented to manage the fetching, loading, and state of Claude usage data, including real-time updates.
  • Extended Usage Metrics: The ClaudeUsageSnapshot type has been extended to include sonnetWeeklyPercent and sonnetWeeklyResetTime, enabling tracking of Sonnet-specific rate limits.
  • Internationalization Support: New internationalization strings for the account profile and rate limit details have been added for both English and French.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added area/frontend This is frontend only size/M Medium (100-499 lines) labels Jan 20, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new AccountProfileIndicator component in the sidebar to display Claude account information and rate limit usage. It adds a new Zustand store (usage-store) for managing usage data, extends the ClaudeUsageSnapshot type, and includes new i18n strings. The implementation is solid, with good handling of loading and error states. My review includes suggestions to improve maintainability and robustness, such as refactoring duplicated logic, extracting a large component into a smaller one, using constants for magic numbers, and preventing race conditions in data loading. Overall, this is a great addition that enhances user visibility into their account status.

Comment on lines 18 to 33
function getUsageColor(percent: number): string {
if (percent >= 95) return 'bg-red-500';
if (percent >= 91) return 'bg-orange-500';
if (percent >= 71) return 'bg-yellow-500';
return 'bg-green-500';
}

/**
* Get the text color class for a usage percentage.
*/
function getUsageTextColor(percent: number): string {
if (percent >= 95) return 'text-red-500';
if (percent >= 91) return 'text-orange-500';
if (percent >= 71) return 'text-yellow-500';
return 'text-green-500';
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The getUsageColor and getUsageTextColor functions contain duplicated logic for determining colors based on usage percentage. This can be refactored by extracting the common logic into a helper function. This will improve maintainability and reduce redundancy, making it easier to update the thresholds and colors in one place.

function getUsageColorName(percent: number): string {
  if (percent >= 95) return 'red-500';
  if (percent >= 91) return 'orange-500';
  if (percent >= 71) return 'yellow-500';
  return 'green-500';
}

/**
 * Get the color class for a usage percentage based on thresholds.
 * Color thresholds: green (0-70), yellow (71-90), orange (91-94), red (95+)
 */
function getUsageColor(percent: number): string {
  return `bg-${getUsageColorName(percent)}`;
}

/**
 * Get the text color class for a usage percentage.
 */
function getUsageTextColor(percent: number): string {
  return `text-${getUsageColorName(percent)}`;
}

* - Detailed popup with session, weekly, and Sonnet usage
* - Color-coded progress bars based on usage thresholds
*/
export function AccountProfileIndicator({ className }: AccountProfileIndicatorProps) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The AccountProfileIndicator component is quite large (over 200 lines) and handles both the trigger logic and the detailed popover content. To improve modularity and readability, consider extracting the content of the PopoverContent into a separate, more focused component (e.g., AccountProfilePopoverContent). This would simplify the AccountProfileIndicator to primarily manage the trigger and popover state.

Comment on lines +108 to +112
const displayName = usage?.profileName
? usage.profileName.length > 20
? `${usage.profileName.substring(0, 17)}...`
: usage.profileName
: t('navigation:accountProfile.noProfile');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The logic for truncating the displayName uses magic numbers (20 and 17). It's a best practice to define these as named constants at the top of the file or component. This improves code readability and makes it easier to understand the purpose of these values and modify them in the future.

  // Truncate profile name if too long
  const MAX_DISPLAY_NAME_LENGTH = 20;
  const TRUNCATED_NAME_LENGTH = 17;
  const displayName = usage?.profileName
    ? usage.profileName.length > MAX_DISPLAY_NAME_LENGTH
      ? `${usage.profileName.substring(0, TRUNCATED_NAME_LENGTH)}...`
      : usage.profileName
    : t('navigation:accountProfile.noProfile');

Comment on lines 52 to 53
const store = useUsageStore.getState();
store.setLoading(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The loadUsageData function could be called multiple times concurrently, leading to redundant network requests and potential race conditions with the isLoading state. To make it more robust, add a guard to prevent new data loading requests if one is already in progress.

Suggested change
const store = useUsageStore.getState();
store.setLoading(true);
const store = useUsageStore.getState();
if (store.isLoading) return;
store.setLoading(true);

@AndyMik90 AndyMik90 self-assigned this Jan 20, 2026
cursor[bot]

This comment was marked as outdated.

Copy link
Owner Author

@AndyMik90 AndyMik90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Auto Claude PR Review

Merge Verdict: 🟠 NEEDS REVISION

🟠 Needs revision - 1 issue(s) require attention.

Branch is out of date with base branch. Update branch first - if no conflicts arise, you can merge. If merge conflicts arise, resolve them and run follow-up review again. 1 issue(s) must be addressed (0 required, 1 recommended). 5 non-blocking suggestion(s) to consider.

Risk Assessment

Factor Level Notes
Complexity Medium Based on lines changed
Security Impact None Based on security findings
Scope Coherence Good Based on structural review

🚨 Blocking Issues (Must Fix)

  • Branch Out of Date: PR branch is behind the base branch and needs to be updated

Findings Summary

  • Medium: 1 issue(s)
  • Low: 5 issue(s)

Generated by Auto Claude PR Review

Findings (6 selected of 6 total)

🟡 [df092b580fb4] [MEDIUM] [Potential] Inconsistent red threshold with existing UsageIndicator (95% vs 99%)

📁 apps/frontend/src/renderer/components/AccountProfileIndicator.tsx:19

AccountProfileIndicator.tsx uses 95% threshold for red color on ALL usage types, but existing UsageIndicator.tsx uses 99% for weekly usage (line 118). This causes visible UI inconsistency where 96% weekly usage shows red in the sidebar but orange in the header indicator. Users will see conflicting color signals for the same data.

Suggested fix:

Align thresholds between both components. Either update AccountProfileIndicator to use 99% for weekly (to match existing), or update UsageIndicator.tsx to use 95% consistently, then extract to a shared utility.

🔵 [19c5bc58da11] [LOW] [Potential] Color threshold logic duplicates existing UsageIndicator.tsx

📁 apps/frontend/src/renderer/components/AccountProfileIndicator.tsx:18

The getUsageColor() and getUsageTextColor() functions (lines 18-33) implement the same threshold logic (95, 91, 71) that already exists inline in UsageIndicator.tsx (lines 49-53, 91-94, 117-121). This duplication makes threshold changes error-prone (as evidenced by finding-1's inconsistency) and increases maintenance burden.

Suggested fix:

Extract color threshold logic to a shared utility like `src/renderer/lib/usage-colors.ts` with functions like `getUsageColorClass(percent, type: 'bg' | 'text')`. Both components should import from this shared location.

🔵 [70cf2c3938e2] [LOW] [Potential] setError does not clear stale usage data

📁 apps/frontend/src/renderer/stores/usage-store.ts:35

The setError action (lines 35-37) only sets the error without clearing the usage state. Meanwhile, setUsage (lines 24-29) properly clears error when setting usage. This asymmetry means when an API call fails after previously succeeding, both error AND stale usage data remain in the store. The UI could show the error message alongside outdated usage percentages.

Suggested fix:

Either have setError also clear usage: `set({ error, usage: null })`, or update AccountProfileIndicator.tsx UI to not display usage when there's an error: change `{usage && !isLoading && (` to `{usage && !isLoading && !error && (`

🔵 [88574f7e491c] [LOW] [Potential] Three nearly identical usage section JSX blocks

📁 apps/frontend/src/renderer/components/AccountProfileIndicator.tsx:198

The Session Usage (lines 198-218), Weekly Usage (lines 221-241), and Sonnet Weekly Usage (lines 244-266) sections are structurally identical, differing only in label translation key, percent value, and reset time. This creates ~60 lines of repetitive JSX that could be consolidated into a reusable UsageSection component.

Suggested fix:

Extract a UsageSection component that takes labelKey, percent, and resetTime props. Use it three times instead of repeating the JSX structure.

🔵 [15725805e477] [LOW] [Potential] UsageProgressBar duplicates pattern from UsageIndicator.tsx

📁 apps/frontend/src/renderer/components/AccountProfileIndicator.tsx:50

The UsageProgressBar component (lines 50-58) implements a progress bar pattern that already exists inline in UsageIndicator.tsx (lines 88-98 and 115-125). Both use identical structure: outer div with 'h-1.5 bg-muted rounded-full overflow-hidden' and inner div with dynamic width and color.

Suggested fix:

Extract UsageProgressBar to a shared UI component in src/renderer/components/ui/ that both AccountProfileIndicator and UsageIndicator can import.

🔵 [513f51e70939] [LOW] [Potential] Race condition in loadUsageData without concurrency guard

📁 apps/frontend/src/renderer/stores/usage-store.ts:51

The loadUsageData function has no guard against concurrent calls. If called multiple times rapidly, responses could arrive out of order causing stale data to overwrite fresh data. Currently only called on component mount (AccountProfileIndicator line 79), limiting practical impact, but the pattern is fragile if called from additional locations in the future.

Suggested fix:

Add a loading guard at the start: `if (store.isLoading) return;` or implement request cancellation with AbortController/request counter to ignore stale responses.

This review was generated by Auto Claude.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/frontend/src/renderer/components/AccountProfileIndicator.tsx`:
- Around line 180-184: The component AccountProfileIndicator renders a raw
user-visible error string; replace the direct {error} usage with an i18n
translation call (e.g., t('navigation.profileError', { error })) inside the
error block so the message is localized, and add the corresponding key
"profileError": "Error: {{error}}" (and French equivalent) to both en/fr
navigation.json files; ensure you import/use the same translation hook used
elsewhere (e.g., useTranslation or t) and keep the surrounding markup
(AlertTriangle, classes, condition) unchanged.
♻️ Duplicate comments (1)
apps/frontend/src/renderer/stores/usage-store.ts (1)

35-43: Clear stale usage when setting an error.
Keeping prior usage while setting error allows stale data to render alongside the error state.

✅ Suggested fix
-  setError: (error: string | null) => {
-    set({ error });
-  },
+  setError: (error: string | null) => {
+    set({ error, usage: null });
+  },

Comment on lines +180 to +187
{error && !isLoading && (
<div className="text-xs p-2 bg-destructive/10 text-destructive rounded-md flex items-center gap-2">
<AlertTriangle className="h-3 w-3 shrink-0" />
<span>{error}</span>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Localize the dynamic error message.
The raw error string is user-visible and bypasses i18n; wrap it in a translation key with interpolation and add the key to both en/fr navigation.json.

✅ Suggested fix
-              <span>{error}</span>
+              <span>{t('navigation:accountProfile.errorWithDetail', { error })}</span>
As per coding guidelines, user-facing text must use i18n keys.
🤖 Prompt for AI Agents
In `@apps/frontend/src/renderer/components/AccountProfileIndicator.tsx` around
lines 180 - 184, The component AccountProfileIndicator renders a raw
user-visible error string; replace the direct {error} usage with an i18n
translation call (e.g., t('navigation.profileError', { error })) inside the
error block so the message is localized, and add the corresponding key
"profileError": "Error: {{error}}" (and French equivalent) to both en/fr
navigation.json files; ensure you import/use the same translation hook used
elsewhere (e.g., useTranslation or t) and keep the surrounding markup
(AlertTriangle, classes, condition) unchanged.

cursor[bot]

This comment was marked as outdated.

AndyMik90 and others added 2 commits January 21, 2026 10:23
…plication

- Fix inconsistent red threshold (95% vs 99%) between UsageIndicator and
  AccountProfileIndicator by creating shared usage-colors.ts utility
- Extract reusable UsageProgressBar component to ui/ folder
- Add UsageSection component to reduce repetitive JSX (~60 lines)
- Fix setError to clear stale usage data preventing outdated display
- Add concurrency guard to loadUsageData preventing race conditions
- Add !error check to usage display condition to hide usage during errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace 6 hardcoded English strings in UsageIndicator.tsx with i18n keys
- Add useTranslation hook for navigation namespace
- Add missing translation keys (activeAccount, usageStatusAriaLabel) to both
  English and French navigation.json
- Export UsageProgressBar from ui/index.ts for consistency

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@AndyMik90 AndyMik90 force-pushed the auto-claude/140-api-error-401-type-error-error-type-authentication branch from 8ae09d7 to dfebe67 Compare January 21, 2026 09:37
@github-actions github-actions bot added size/L Large (500-999 lines) and removed size/M Medium (100-499 lines) labels Jan 21, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/frontend/src/renderer/components/ui/usage-progress-bar.tsx`:
- Around line 13-21: The UsageProgressBar component is missing ARIA attributes;
update the inner and/or outer element in UsageProgressBar to include
role="progressbar" and set aria-valuemin="0", aria-valuemax="100" and
aria-valuenow={Math.min(Math.round(percent), 100)} (or provide aria-valuetext
for a custom label) so screen readers can expose the percent; keep the visual
width logic (style width: `${Math.min(percent,100)}%`) and ensure
getUsageBgColor(percent) remains used for color so accessibility does not change
appearance.
♻️ Duplicate comments (3)
apps/frontend/src/renderer/stores/usage-store.ts (1)

65-69: Handle the case when API returns unsuccessful without an error message.

When result.success is false but result.error is falsy, neither setUsage nor setError is called. The loading state clears, leaving usage as null and displaying "No data available" instead of an appropriate error message.

Proposed fix
     if (result.success && result.data) {
       store.setUsage(result.data);
     } else if (result.error) {
       store.setError(result.error);
+    } else {
+      store.setError('Failed to load usage data');
     }
apps/frontend/src/renderer/components/AccountProfileIndicator.tsx (2)

110-115: Extract magic numbers to named constants.

The truncation logic uses magic numbers (20 and 17). Define these as named constants for improved readability and maintainability.

Proposed refactor
+const MAX_DISPLAY_NAME_LENGTH = 20;
+const TRUNCATED_NAME_SUFFIX_LENGTH = 17;
+
 export function AccountProfileIndicator({ className }: AccountProfileIndicatorProps) {
   // ...
 
   // Truncate profile name if too long
   const displayName = usage?.profileName
-    ? usage.profileName.length > 20
-      ? `${usage.profileName.substring(0, 17)}...`
+    ? usage.profileName.length > MAX_DISPLAY_NAME_LENGTH
+      ? `${usage.profileName.substring(0, TRUNCATED_NAME_SUFFIX_LENGTH)}...`
       : usage.profileName
     : t('navigation:accountProfile.noProfile');

182-188: Localize the dynamic error message.

The raw error string is displayed directly to users, bypassing i18n. Use interpolation to wrap the error message in a translation key. As per coding guidelines, all user-facing text must use i18n translation keys.

Proposed fix
           {/* Error state */}
           {error && !isLoading && (
             <div className="text-xs p-2 bg-destructive/10 text-destructive rounded-md flex items-center gap-2">
               <AlertTriangle className="h-3 w-3 shrink-0" />
-              <span>{error}</span>
+              <span>{t('navigation:accountProfile.errorWithDetail', { error })}</span>
             </div>
           )}

Add the corresponding key to both locale files:

en/navigation.json:

"errorWithDetail": "Error: {{error}}"

fr/navigation.json:

"errorWithDetail": "Erreur: {{error}}"

Comment on lines +13 to +21
export function UsageProgressBar({ percent, className }: UsageProgressBarProps) {
return (
<div className={cn('mt-1.5 h-1.5 bg-muted rounded-full overflow-hidden', className)}>
<div
className={cn('h-full transition-all', getUsageBgColor(percent))}
style={{ width: `${Math.min(percent, 100)}%` }}
/>
</div>
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding ARIA attributes for accessibility.

The progress bar is functional but lacks accessibility attributes. Screen readers won't convey the progress information.

♻️ Suggested improvement for accessibility
 export function UsageProgressBar({ percent, className }: UsageProgressBarProps) {
+  const clampedPercent = Math.min(Math.max(percent, 0), 100);
   return (
-    <div className={cn('mt-1.5 h-1.5 bg-muted rounded-full overflow-hidden', className)}>
+    <div
+      role="progressbar"
+      aria-valuenow={Math.round(clampedPercent)}
+      aria-valuemin={0}
+      aria-valuemax={100}
+      className={cn('mt-1.5 h-1.5 bg-muted rounded-full overflow-hidden', className)}
+    >
       <div
         className={cn('h-full transition-all', getUsageBgColor(percent))}
-        style={{ width: `${Math.min(percent, 100)}%` }}
+        style={{ width: `${clampedPercent}%` }}
       />
     </div>
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function UsageProgressBar({ percent, className }: UsageProgressBarProps) {
return (
<div className={cn('mt-1.5 h-1.5 bg-muted rounded-full overflow-hidden', className)}>
<div
className={cn('h-full transition-all', getUsageBgColor(percent))}
style={{ width: `${Math.min(percent, 100)}%` }}
/>
</div>
);
export function UsageProgressBar({ percent, className }: UsageProgressBarProps) {
const clampedPercent = Math.min(Math.max(percent, 0), 100);
return (
<div
role="progressbar"
aria-valuenow={Math.round(clampedPercent)}
aria-valuemin={0}
aria-valuemax={100}
className={cn('mt-1.5 h-1.5 bg-muted rounded-full overflow-hidden', className)}
>
<div
className={cn('h-full transition-all', getUsageBgColor(percent))}
style={{ width: `${clampedPercent}%` }}
/>
</div>
);
}
🤖 Prompt for AI Agents
In `@apps/frontend/src/renderer/components/ui/usage-progress-bar.tsx` around lines
13 - 21, The UsageProgressBar component is missing ARIA attributes; update the
inner and/or outer element in UsageProgressBar to include role="progressbar" and
set aria-valuemin="0", aria-valuemax="100" and
aria-valuenow={Math.min(Math.round(percent), 100)} (or provide aria-valuetext
for a custom label) so screen readers can expose the percent; keep the visual
width logic (style width: `${Math.min(percent,100)}%`) and ensure
getUsageBgColor(percent) remains used for color so accessibility does not change
appearance.

cursor[bot]

This comment was marked as outdated.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

style={{ width: `${Math.min(usage.weeklyPercent, 100)}%` }}
/>
</div>
<UsageProgressBar percent={usage.weeklyPercent} />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weekly progress bar red threshold changed from 99% to 95%

Medium Severity

The refactoring to use the shared UsageProgressBar component inadvertently changed the weekly usage red threshold from 99% to 95%. The original code intentionally used different thresholds - session at 95% and weekly at 99% - but the new shared component uses a unified 95% threshold. Users will now see the weekly progress bar turn red 4% earlier than before, which changes the existing user experience.

Fix in Cursor Fix in Web

@AndyMik90 AndyMik90 force-pushed the develop branch 2 times, most recently from 67a743f to e83e445 Compare January 21, 2026 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/frontend This is frontend only size/L Large (500-999 lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants