Skip to content

Fixed React development mode warnings in admin-x-design-system#25650

Open
kevinansfield wants to merge 1 commit intomainfrom
cleanup-react-dev-errors
Open

Fixed React development mode warnings in admin-x-design-system#25650
kevinansfield wants to merge 1 commit intomainfrom
cleanup-react-dev-errors

Conversation

@kevinansfield
Copy link
Member

no issue

Some aspects of admin-x-design-system and its usage within admin-x-settings caused a lot of errors to be output in the console in development mode making it difficult to find real problems.

  • Added missing key props to list items in TabView, ButtonGroup, CheckboxGroup, and TiersList to fix "unique key" warnings
  • Added asChild to Tooltip's TooltipPrimitive.Trigger to fix nested button warning when Button components are wrapped in Tooltip
  • Destructured unused separator prop in NewsletterItemContainer to prevent it being passed to DragIndicator causing errors

no issue

Some aspects of `admin-x-design-system` and its usage within `admin-x-settings` caused a lot of errors to be output in the console in development mode making it difficult to find real problems.

- Added missing `key` props to list items in `TabView`, `ButtonGroup`, `CheckboxGroup`, and `TiersList` to fix "unique key" warnings
- Added `asChild` to `Tooltip`'s `TooltipPrimitive.Trigger` to fix nested button warning when Button components are wrapped in Tooltip
- Destructured unused `separator` prop in NewsletterItemContainer to prevent it being passed to `DragIndicator` causing errors
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 8, 2025

Walkthrough

This pull request improves React rendering stability and component structure across design system and settings components. Key-related changes are made to list-rendered elements in button-group, checkbox-group, tab-view, and tiers-list to ensure deterministic React keys with fallback synthesis. The button-group introduces centralized key management through a buttonKey variable that unifies key usage. The tooltip component adopts the Radix asChild pattern for trigger handling. The newsletter-list adds a new separator prop to an internal component with void casting to prevent unused prop errors.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

  • button-group.tsx: Requires careful verification of the buttonKey fallback logic and how it affects both React key assignment and activeKey comparisons. The centralized key management and additional border-transparent styling path warrant attention.
  • tooltip.tsx: Verify the asChild prop implementation on Radix Trigger and confirm onClick prevention behavior is preserved under this new pattern.
  • checkbox-group.tsx and tab-view.tsx: Confirm fallback key generation is deterministic and matches intended behavior.
  • newsletter-list.tsx: Verify the void casting approach prevents runtime errors and is the intended solution for the unused prop.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective: fixing React development mode warnings in admin-x-design-system through key props and component prop handling.
Description check ✅ Passed The description clearly explains the purpose and provides specific details about the changes made to address React development mode warnings.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cleanup-react-dev-errors

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.

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: 0

🧹 Nitpick comments (4)
apps/admin-x-design-system/src/global/tab-view.tsx (1)

92-103: Tab keys are now stable; consider avoiding the extra wrapper element

Using tab.id as the key in both the tab list and TabsPrimitive.Content is correct and should eliminate the key warnings while keeping state aligned with the Radix value.

You likely don’t need the extra <div> around TabButton purely for the key, though. If layout allows, you could instead key the button itself (or use a keyed React.Fragment) to avoid an extra DOM node:

{tabs.map(tab => (
    <TabButton
        key={tab.id}
        border={buttonBorder}
        counter={tab.counter}
        icon={tab.icon}
        id={tab.id}
        title={tab.title}
        onClick={handleTabChange}
    />
))}

This is a minor, optional cleanup; behavior-wise the current change is fine.

Please verify that no CSS relies specifically on that wrapper <div> (e.g., targeting children count or direct descendants) before inlining the key as above.

Also applies to: 163-169

apps/admin-x-settings/src/components/settings/email/newsletters/newsletters-list.tsx (1)

14-24: Separator handling in NewsletterItemContainer is safe and clear

Destructuring separator and then void‑ing it before spreading ...props into DragIndicator neatly prevents the prop from leaking into the drag handle while still allowing it on the container type.

If your lint setup supports the conventional “unused underscore” pattern, an alternative is:

const NewsletterItemContainer: React.FC<Partial<SortableItemContainerProps>> = ({
    separator: _separator,
    ...props
}) => { /* ... */ }

but what you have is perfectly valid.

apps/admin-x-design-system/src/global/form/checkbox-group.tsx (1)

23-25: Deterministic key fallback is good; be mindful if the list is reorderable

Using key ?? \checkbox-${index}`` will remove key warnings when callers don’t provide a key and is a reasonable fallback for mostly static checkbox lists.

If you ever expect checkboxes to be dynamically reordered/inserted/removed, it’s worth encouraging callers to pass a stable semantic key (e.g., an id) instead of relying on the index, to avoid unnecessary remounts and state loss inside individual Checkbox instances.

It may be worth scanning current CheckboxGroup call sites to confirm they’re using stable keys (or static arrays) and won’t rely on stateful checkboxes that could be impacted by index‑based keys.

apps/admin-x-design-system/src/global/button-group.tsx (1)

42-65: Centralized buttonKey handling is good; just be cautious with index-based identity

Using {key, ...props} plus const buttonKey = key ?? \button-${index}`` nicely fixes React key warnings and unifies the key used for:

  • the React list key (key={buttonKey} on Tooltip / Button), and
  • the active state check (buttonKey === activeKey).

For buttons that do specify a key, behavior is preserved and more robust.

A couple of small considerations:

  • For buttons without an explicit key, their identity is now effectively “button-${index}”. That’s fine for static arrays, but if a caller ever wants to make such a button active via activeKey, they’d have to know that synthesized value—and any reordering would change it.
  • If there’s any chance the buttons array becomes dynamic, it may be worth nudging consumers towards always providing a stable semantic key (e.g., id) and treating the index fallback as a last resort only.

The added border-transparent for inactive buttons is also a nice touch to keep border behavior explicit.

Consider auditing ButtonGroup call sites that use activeKey to ensure they always pair it with an explicit key on the corresponding button config, avoiding reliance on the synthesized button-${index} form.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f7be8e and 5107ea6.

📒 Files selected for processing (6)
  • apps/admin-x-design-system/src/global/button-group.tsx (2 hunks)
  • apps/admin-x-design-system/src/global/form/checkbox-group.tsx (1 hunks)
  • apps/admin-x-design-system/src/global/tab-view.tsx (2 hunks)
  • apps/admin-x-design-system/src/global/tooltip.tsx (1 hunks)
  • apps/admin-x-settings/src/components/settings/email/newsletters/newsletters-list.tsx (1 hunks)
  • apps/admin-x-settings/src/components/settings/membership/tiers/tiers-list.tsx (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: danielraffel
Repo: TryGhost/Ghost PR: 25366
File: apps/admin/src/layout/app-sidebar/NavHeader.tsx:13-23
Timestamp: 2025-11-06T05:35:41.162Z
Learning: In apps/admin/src/layout/app-sidebar/NavHeader.tsx, the React component dispatches a synthetic KeyboardEvent to trigger the Ember keymaster.js search modal shortcut. This approach is known to have cross-browser reliability issues but was deferred for architectural refactoring in a separate PR. The recommended fix is to expose a global function or custom DOM event from the Ember app instead of relying on synthetic keyboard events with keymaster.js.
📚 Learning: 2025-11-06T05:35:41.162Z
Learnt from: danielraffel
Repo: TryGhost/Ghost PR: 25366
File: apps/admin/src/layout/app-sidebar/NavHeader.tsx:13-23
Timestamp: 2025-11-06T05:35:41.162Z
Learning: In apps/admin/src/layout/app-sidebar/NavHeader.tsx, the React component dispatches a synthetic KeyboardEvent to trigger the Ember keymaster.js search modal shortcut. This approach is known to have cross-browser reliability issues but was deferred for architectural refactoring in a separate PR. The recommended fix is to expose a global function or custom DOM event from the Ember app instead of relying on synthetic keyboard events with keymaster.js.

Applied to files:

  • apps/admin-x-design-system/src/global/tab-view.tsx
📚 Learning: 2025-11-26T11:05:59.314Z
Learnt from: CR
Repo: TryGhost/Ghost PR: 0
File: apps/shade/AGENTS.md:0-0
Timestamp: 2025-11-26T11:05:59.314Z
Learning: Applies to apps/shade/src/components/**/*.{ts,tsx} : Use CVA (Class Variance Authority) for component variants when useful instead of heavy prop configuration

Applied to files:

  • apps/admin-x-design-system/src/global/tab-view.tsx
🧬 Code graph analysis (1)
apps/admin-x-design-system/src/global/button-group.tsx (1)
apps/shade/src/components/ui/tooltip.tsx (1)
  • Tooltip (33-33)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Unit tests (Node 22.18.0)
  • GitHub Check: Admin-X Settings tests
  • GitHub Check: Lint
  • GitHub Check: Build & Push
🔇 Additional comments (2)
apps/admin-x-settings/src/components/settings/membership/tiers/tiers-list.tsx (1)

72-74: Stable key on TierCard looks good

Using tier.id as the React key is a solid choice here and will clean up the dev warnings, assuming id is always defined and unique within the list.

Please just double‑check that Tier[] can’t contain duplicate/undefined id values for this view.

apps/admin-x-design-system/src/global/tooltip.tsx (1)

26-32: asChild usage correctly avoids nested interactive elements

Switching the Radix TooltipPrimitive.Trigger to asChild while keeping onClick={event => event.preventDefault()} is a solid way to avoid nested <button> warnings when wrapping Button components, without changing existing click behavior.

One implication is that Tooltip now effectively requires a single valid React element as its child (no strings or multiple siblings), which matches typical usages like Tooltip><Button /></Tooltip>.

Please confirm your Radix version fully supports asChild on TooltipPrimitive.Trigger and that all Tooltip usages pass exactly one React element child.

@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

Ember E2E Tests Failed

To view the Playwright test report locally, run:

REPORT_DIR=$(mktemp -d) && gh run download 20030850384 -n playwright-report-ember -D "$REPORT_DIR" && npx playwright show-report "$REPORT_DIR"

1 similar comment
@github-actions
Copy link
Contributor

github-actions bot commented Dec 9, 2025

Ember E2E Tests Failed

To view the Playwright test report locally, run:

REPORT_DIR=$(mktemp -d) && gh run download 20030850384 -n playwright-report-ember -D "$REPORT_DIR" && npx playwright show-report "$REPORT_DIR"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants