chore: refine codex usage modal layout - #4386
Conversation
WalkthroughThis PR enhances the CodexUsageModal component by introducing responsive mobile-aware modal sizing, refactoring rate-limit window rendering into a reusable component structure, and extending support for displaying additional rate limits with their respective usage windows and status indicators. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (4)
web/src/components/table/channels/modals/CodexUsageModal.jsx (4)
344-358: Rawmetered_featurelabel is not translated.Line 350 renders the literal string
metered_featureas a UI label, while every other user-facing string in this file goes throughtt('中文'). If this is intended as a fixed technical/API field name it's fine to leave; if it's meant to be a user-facing caption, it should follow the project i18n convention.As per coding guidelines, "Use
useTranslation()hook and callt('中文key')in components" with Chinese source strings as translation keys.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/table/channels/modals/CodexUsageModal.jsx` around lines 344 - 358, The literal label "metered_feature" in the CodexUsageModal JSX should be translated; update the component to use the i18n hook (useTranslation) and replace the raw string with a t(...) call (e.g., t('计量特性') or your chosen Chinese key) where the span currently renders "metered_feature", ensuring you import/use useTranslation at the top of CodexUsageModal.jsx and call t inside the component so the featureText caption follows the project's i18n convention.
483-531: Status tag is now rendered twice for the base group.The outer account card already renders
statusTagat Line 422, and the baseRateLimitGroupSectionrenders it again at Line 342 via thestatusTagprop. For the additional-rate-limit items this makes sense (each has its own status), but for the "基础额度" section it duplicates information that the user just saw directly above. Consider either omitting thestatusTagprop for the base section, or dropping the status tag from the outer account card so the per-section tags become the single source of truth.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/table/channels/modals/CodexUsageModal.jsx` around lines 483 - 531, The base "基础额度" section is rendering the same status twice: once in the outer account card via statusTag and again by passing statusTag into the base RateLimitGroupSection; remove the duplication by deleting the statusTag prop from the base RateLimitGroupSection (the one with title={tt('基础额度')} and rateLimitSource={data}) so the outer account card remains the single source of truth; do not change the additionalRateLimits mapping (which should still pass resolveUsageStatusTag(tt, item?.rate_limit) into RateLimitGroupSection).
144-173: Responsive layout is computed once at modal open.
getCodexUsageModalLayout()is invoked only atopenCodexUsageModaltime (Line 649) and its result is frozen into theModal.infoprops. If the user rotates their device or resizes the viewport across the 768px threshold while the modal is open, the modal will not re-switch between the mobile and desktop layouts. For a responsive polish PR this is worth addressing — e.g., render the modal content through a small wrapper that subscribes to the existinguseIsMobilehook and updates the modal instance, or switch toModal.destroyAll()+ re-open on breakpoint change.Not a blocker given modals are typically short-lived, but flagging since the whole intent here is responsiveness.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/table/channels/modals/CodexUsageModal.jsx` around lines 144 - 173, The modal layout returned by getCodexUsageModalLayout is computed once in openCodexUsageModal and frozen into Modal.info, so it doesn't respond to viewport changes; fix by making the open flow subscribe to the existing useIsMobile (or a resize/breakpoint listener) and update the open modal when the breakpoint crosses 768px — either call Modal.destroyAll() and re-open with the new getCodexUsageModalLayout output or call the Modal instance update method when available; locate references to getCodexUsageModalLayout, openCodexUsageModal, Modal.info, and the useIsMobile hook to implement the subscription and the re-open/update logic.
321-369:RateLimitGroupSectionprop contract is implicit — worth a brief comment.
rateLimitSourceis passed two shapes from the caller: the top-leveldata(for the base group, wheredata.rate_limitanddata.plan_typeare read byresolveRateLimitWindows) and eachadditional_rate_limits[]item (whereplan_typeis absent, so the free-plan branch at Line 87 is silently skipped). The behavior is correct, but the coupling between the two call sites andresolveRateLimitWindows' internal field access is non-obvious. A one-line JSDoc on this component describing the expected shape ofrateLimitSourcewould reduce the chance of a future caller passing e.g.rateLimitSource={data.rate_limit}and breaking the lookup.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/table/channels/modals/CodexUsageModal.jsx` around lines 321 - 369, Add a one-line JSDoc above the RateLimitGroupSection component clarifying the expected shape of the rateLimitSource prop: it can be the full top-level data object (with optional rate_limit and plan_type fields used by resolveRateLimitWindows) or an individual additional_rate_limits[] item (which may omit plan_type), and note that resolveRateLimitWindows reads data.rate_limit and data.plan_type; this will make the implicit contract between the callers and resolveRateLimitWindows explicit and prevent future incorrect calls like rateLimitSource={data.rate_limit}.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@web/src/components/table/channels/modals/CodexUsageModal.jsx`:
- Around line 344-358: The literal label "metered_feature" in the
CodexUsageModal JSX should be translated; update the component to use the i18n
hook (useTranslation) and replace the raw string with a t(...) call (e.g.,
t('计量特性') or your chosen Chinese key) where the span currently renders
"metered_feature", ensuring you import/use useTranslation at the top of
CodexUsageModal.jsx and call t inside the component so the featureText caption
follows the project's i18n convention.
- Around line 483-531: The base "基础额度" section is rendering the same status
twice: once in the outer account card via statusTag and again by passing
statusTag into the base RateLimitGroupSection; remove the duplication by
deleting the statusTag prop from the base RateLimitGroupSection (the one with
title={tt('基础额度')} and rateLimitSource={data}) so the outer account card remains
the single source of truth; do not change the additionalRateLimits mapping
(which should still pass resolveUsageStatusTag(tt, item?.rate_limit) into
RateLimitGroupSection).
- Around line 144-173: The modal layout returned by getCodexUsageModalLayout is
computed once in openCodexUsageModal and frozen into Modal.info, so it doesn't
respond to viewport changes; fix by making the open flow subscribe to the
existing useIsMobile (or a resize/breakpoint listener) and update the open modal
when the breakpoint crosses 768px — either call Modal.destroyAll() and re-open
with the new getCodexUsageModalLayout output or call the Modal instance update
method when available; locate references to getCodexUsageModalLayout,
openCodexUsageModal, Modal.info, and the useIsMobile hook to implement the
subscription and the re-open/update logic.
- Around line 321-369: Add a one-line JSDoc above the RateLimitGroupSection
component clarifying the expected shape of the rateLimitSource prop: it can be
the full top-level data object (with optional rate_limit and plan_type fields
used by resolveRateLimitWindows) or an individual additional_rate_limits[] item
(which may omit plan_type), and note that resolveRateLimitWindows reads
data.rate_limit and data.plan_type; this will make the implicit contract between
the callers and resolveRateLimitWindows explicit and prevent future incorrect
calls like rateLimitSource={data.rate_limit}.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2c33e295-137d-490f-9763-361b7aef738d
📒 Files selected for processing (1)
web/src/components/table/channels/modals/CodexUsageModal.jsx
* chore: refine codex usage modal layout * fix: polish codex usage modal responsiveness
* chore: refine codex usage modal layout * fix: polish codex usage modal responsiveness
* chore: refine codex usage modal layout * fix: polish codex usage modal responsiveness
Important
📝 变更描述 / Description
优化额度窗口展示,新增 GPT-5.3-Codex-Spark 单独计费的模型展示
🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
(请在此粘贴截图、关键日志或测试报告,以证明变更生效)
Summary by CodeRabbit