fix(web): prevent list cell text and badge overflow - #5510
Conversation
- add default truncation with hover details for text cells in shared and static data tables to prevent content from spilling into adjacent columns. - adjust API key group, model, and IP restriction columns to fix badge overlap and left alignment drift. - reuse a shared truncated cell component and add width constraints for composite badge cells.
- make table text and badge cells shrink within constrained columns so long values truncate instead of bleeding into adjacent cells. - add a shared BadgeCell wrapper to keep badge alignment consistent across API keys and other list pages. - update affected list views to use constrained wrappers for group, provider, pricing, OAuth, and API info values.
WalkthroughIntroduces two new shared data-table cell components — ChangesBadgeCell & TruncatedCell: new cell components + data-table truncation wiring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 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.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/default/src/features/subscriptions/components/subscriptions-columns.tsx (1)
139-152:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winLocalize payment channel badge labels
Line 141, Line 147, and Line 151 use hardcoded user-facing text (
Stripe,Creem,Waffo Pancake) instead oft(...), so these labels won’t be translated.Suggested fix
{plan.stripe_price_id && ( <StatusBadge - label='Stripe' + label={t('Stripe')} variant='neutral' copyable={false} /> )} {plan.creem_product_id && ( - <StatusBadge label='Creem' variant='neutral' copyable={false} /> + <StatusBadge + label={t('Creem')} + variant='neutral' + copyable={false} + /> )} {plan.waffo_pancake_product_id && ( <StatusBadge - label='Waffo Pancake' + label={t('Waffo Pancake')} variant='neutral' copyable={false} /> )}As per coding guidelines, "All user-facing text content must support i18n using the
t()function fromuseTranslation()in React components".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@web/default/src/features/subscriptions/components/subscriptions-columns.tsx` around lines 139 - 152, Replace the hardcoded user-facing text labels in the StatusBadge components with internationalized strings using the t() function. For the three StatusBadge components in subscriptions-columns.tsx with label props containing 'Stripe', 'Creem', and 'Waffo Pancake', wrap each label string with the t() function to ensure proper translation support. Make sure you are using the t function from the useTranslation() hook that should already be available in this React component.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/default/src/components/data-table/core/truncated-cell.tsx`:
- Around line 87-90: The getTextContent function currently handles strings,
numbers, and arrays but returns an empty string for React elements, causing
tooltips to be skipped for components like span or other React elements. Extend
the function to check if the node is a React element (using React.isValidElement
or similar check), and if so, recursively extract text from its children
property or children prop to preserve the text content from nested React
elements rather than silently dropping it with an empty return.
In `@web/default/src/components/status-badge.tsx`:
- Around line 158-160: The hardcoded English string "Click to copy: " in the
title variable assignment bypasses i18n and violates localization guidelines.
Extract the "Click to copy: " text and wrap it with the t() function from
useTranslation() to properly localize this user-facing message. Ensure the
component is using the useTranslation hook and replace the hardcoded string with
a translation key that includes both the instructional text and the dynamic
content (copyText or label).
In `@web/default/src/features/system-settings/content/api-info-section.tsx`:
- Around line 148-156: The handleToggleEnabled function updates the UI state and
shows a success message even when the API mutation resolves with success: false.
Capture the response from updateOption.mutateAsync and verify that the response
contains success: true before proceeding to call setIsEnabledDraft(checked) and
toast.success(). If success is false, handle that case appropriately (such as
showing an error message or reverting the draft state).
---
Outside diff comments:
In `@web/default/src/features/subscriptions/components/subscriptions-columns.tsx`:
- Around line 139-152: Replace the hardcoded user-facing text labels in the
StatusBadge components with internationalized strings using the t() function.
For the three StatusBadge components in subscriptions-columns.tsx with label
props containing 'Stripe', 'Creem', and 'Waffo Pancake', wrap each label string
with the t() function to ensure proper translation support. Make sure you are
using the t function from the useTranslation() hook that should already be
available in this React component.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f3b8c0ae-66b4-4996-a250-b42cc9c9e8cf
📒 Files selected for processing (20)
web/default/src/components/data-table/core/badge-cell.tsxweb/default/src/components/data-table/core/badge-list-cell.tsxweb/default/src/components/data-table/core/data-table-row.tsxweb/default/src/components/data-table/core/truncated-cell.tsxweb/default/src/components/data-table/index.tsweb/default/src/components/data-table/static/static-data-table.tsxweb/default/src/components/group-badge.tsxweb/default/src/components/status-badge.tsxweb/default/src/components/truncated-text.tsxweb/default/src/features/keys/components/api-keys-cells.tsxweb/default/src/features/keys/components/api-keys-columns.tsxweb/default/src/features/models/components/deployments-columns.tsxweb/default/src/features/models/components/models-columns.tsxweb/default/src/features/pricing/components/pricing-columns.tsxweb/default/src/features/redemption-codes/components/redemptions-columns.tsxweb/default/src/features/subscriptions/components/subscriptions-columns.tsxweb/default/src/features/system-settings/auth/custom-oauth/components/provider-table.tsxweb/default/src/features/system-settings/content/api-info-section.tsxweb/default/src/features/system-settings/models/upstream-ratio-sync-columns.tsxweb/default/src/features/users/components/users-columns.tsx
| function getTextContent(node: React.ReactNode): string { | ||
| if (typeof node === 'string' || typeof node === 'number') return String(node) | ||
| if (Array.isArray(node)) return node.map(getTextContent).join('') | ||
| return '' |
There was a problem hiding this comment.
Handle React element children in text extraction.
On Line 87, getTextContent skips valid React elements, so <TruncatedCell><span>foo</span></TruncatedCell> won’t derive tooltip text and silently drops the tooltip fallback path.
Suggested fix
function getTextContent(node: React.ReactNode): string {
if (typeof node === 'string' || typeof node === 'number') return String(node)
if (Array.isArray(node)) return node.map(getTextContent).join('')
+ if (React.isValidElement(node)) return getTextContent(node.props.children)
return ''
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/default/src/components/data-table/core/truncated-cell.tsx` around lines
87 - 90, The getTextContent function currently handles strings, numbers, and
arrays but returns an empty string for React elements, causing tooltips to be
skipped for components like span or other React elements. Extend the function to
check if the node is a React element (using React.isValidElement or similar
check), and if so, recursively extract text from its children property or
children prop to preserve the text content from nested React elements rather
than silently dropping it with an empty return.
| const title = copyable | ||
| ? `Click to copy: ${copyText || label || ''}` | ||
| : label || undefined |
There was a problem hiding this comment.
Localize the new title text.
On Line 159, "Click to copy: ..." is hardcoded English and bypasses i18n.
Suggested fix
import * as React from 'react'
+import { t } from 'i18next'
...
const title = copyable
- ? `Click to copy: ${copyText || label || ''}`
+ ? t('Click to copy: {{value}}', { value: copyText || label || '' })
: label || undefinedAs per coding guidelines, “All user-facing text content must support i18n using the t() function from useTranslation() in React components.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/default/src/components/status-badge.tsx` around lines 158 - 160, The
hardcoded English string "Click to copy: " in the title variable assignment
bypasses i18n and violates localization guidelines. Extract the "Click to copy:
" text and wrap it with the t() function from useTranslation() to properly
localize this user-facing message. Ensure the component is using the
useTranslation hook and replace the hardcoded string with a translation key that
includes both the instructional text and the dynamic content (copyText or
label).
Source: Coding guidelines
| const handleToggleEnabled = async (checked: boolean) => { | ||
| try { | ||
| await updateOption.mutateAsync({ | ||
| key: 'console_setting.api_info_enabled', | ||
| value: checked, | ||
| }) | ||
| setIsEnabled(checked) | ||
| setIsEnabledDraft(checked) | ||
| toast.success(t('Setting saved')) | ||
| } catch { |
There was a problem hiding this comment.
Gate enabled-state update on mutation result success
Line 154 and Line 155 run even when mutateAsync resolves with success: false, which can desync UI state and show a false success message.
Suggested fix
const handleToggleEnabled = async (checked: boolean) => {
try {
- await updateOption.mutateAsync({
+ const result = await updateOption.mutateAsync({
key: 'console_setting.api_info_enabled',
value: checked,
})
- setIsEnabledDraft(checked)
- toast.success(t('Setting saved'))
+ if (!result.success) return
+ setIsEnabledDraft(checked)
+ // Optional: remove local success toast if useUpdateOption already toasts on success
} catch {
toast.error(t('Failed to update setting'))
}
}📝 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.
| const handleToggleEnabled = async (checked: boolean) => { | |
| try { | |
| await updateOption.mutateAsync({ | |
| key: 'console_setting.api_info_enabled', | |
| value: checked, | |
| }) | |
| setIsEnabled(checked) | |
| setIsEnabledDraft(checked) | |
| toast.success(t('Setting saved')) | |
| } catch { | |
| const handleToggleEnabled = async (checked: boolean) => { | |
| try { | |
| const result = await updateOption.mutateAsync({ | |
| key: 'console_setting.api_info_enabled', | |
| value: checked, | |
| }) | |
| if (!result.success) return | |
| setIsEnabledDraft(checked) | |
| toast.success(t('Setting saved')) | |
| } catch { | |
| toast.error(t('Failed to update setting')) | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@web/default/src/features/system-settings/content/api-info-section.tsx` around
lines 148 - 156, The handleToggleEnabled function updates the UI state and shows
a success message even when the API mutation resolves with success: false.
Capture the response from updateOption.mutateAsync and verify that the response
contains success: true before proceeding to call setIsEnabledDraft(checked) and
toast.success(). If success is false, handle that case appropriately (such as
showing an error message or reverting the draft state).
Upstream changes (50+ commits, v1.0.0-rc.11): - data-table perf: row selection memo, column pinning, badge display - Fixes: channel test dialog (QuantumNous#5517), CC Switch model selector (QuantumNous#5515), API key form options (QuantumNous#5512), cell overflow (QuantumNous#5510), kimi k2.6 temp (QuantumNous#5390), Anthropic-compatible GLM chunked encoding (QuantumNous#5307), streaming image relay (QuantumNous#4608) - Feat: audit auth method tracking (QuantumNous#5462), channel affinity clear toggle (QuantumNous#5306), relay idle timeout config (QuantumNous#5309), 6-decimal pricing precision (QuantumNous#5332) - Classic frontend: Rsbuild support, Semi React 19 adapter - Shared dialog wrapper, JSON code editor, debounce channel search Conflict resolved: web/bun.lock (accepted upstream, will regenerate) Co-Authored-By: Claude <noreply@anthropic.com>
* fix(ui): prevent table cell text overflow - add default truncation with hover details for text cells in shared and static data tables to prevent content from spilling into adjacent columns. - adjust API key group, model, and IP restriction columns to fix badge overlap and left alignment drift. - reuse a shared truncated cell component and add width constraints for composite badge cells. * fix(table): prevent badge content from overflowing columns - make table text and badge cells shrink within constrained columns so long values truncate instead of bleeding into adjacent cells. - add a shared BadgeCell wrapper to keep badge alignment consistent across API keys and other list pages. - update affected list views to use constrained wrappers for group, provider, pricing, OAuth, and API info values.
* fix(ui): prevent table cell text overflow - add default truncation with hover details for text cells in shared and static data tables to prevent content from spilling into adjacent columns. - adjust API key group, model, and IP restriction columns to fix badge overlap and left alignment drift. - reuse a shared truncated cell component and add width constraints for composite badge cells. * fix(table): prevent badge content from overflowing columns - make table text and badge cells shrink within constrained columns so long values truncate instead of bleeding into adjacent cells. - add a shared BadgeCell wrapper to keep badge alignment consistent across API keys and other list pages. - update affected list views to use constrained wrappers for group, provider, pricing, OAuth, and API info values.
* fix(ui): prevent table cell text overflow - add default truncation with hover details for text cells in shared and static data tables to prevent content from spilling into adjacent columns. - adjust API key group, model, and IP restriction columns to fix badge overlap and left alignment drift. - reuse a shared truncated cell component and add width constraints for composite badge cells. * fix(table): prevent badge content from overflowing columns - make table text and badge cells shrink within constrained columns so long values truncate instead of bleeding into adjacent cells. - add a shared BadgeCell wrapper to keep badge alignment consistent across API keys and other list pages. - update affected list views to use constrained wrappers for group, provider, pricing, OAuth, and API info values.
Important
📝 变更描述 / Description
问题描述
/keys页面的分组、模型、IP 限制等徽标内容也存在与列头左侧对齐不一致的问题。修复方式
min-w-0、overflow 裁剪和左侧对齐。测试说明
bunx eslint检查相关变更文件。git diff --check。bun run typecheck。bun run build。🚀 变更类型 / Type of change
🔗 关联任务 / Related Issue
✅ 提交前检查项 / Checklist
Bug fix,我已提交或关联对应 Issue,且不会将设计取舍、预期不一致或理解偏差直接归类为 bug。📸 运行证明 / Proof of Work
bunx eslint ...git diff --checkbun run typecheckbun run buildSummary by CodeRabbit
New Features
Improvements