Skip to content

Conversation

@kotAPI
Copy link
Collaborator

@kotAPI kotAPI commented Jul 31, 2025

Summary by CodeRabbit

  • New Features

    • Buttons now include a default type attribute for improved behavior and accessibility.
  • Refactor

    • Updated multiple components to use a unified button primitive, ensuring consistent button rendering and styling across the interface. No changes to component props or public APIs.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 31, 2025

Walkthrough

This change replaces the usage of a generic Primitive.button component with a more specific ButtonPrimitive component across multiple UI and core primitive components. The ButtonPrimitive is also updated to accept a type prop with a default of 'button'. No other logic, props, or exports are altered.

Changes

Cohort / File(s) Change Summary
UI Accordion, Switch, Tooltip Triggers
src/components/ui/Accordion/fragments/AccordionTrigger.tsx, src/components/ui/Switch/fragments/SwitchRoot.tsx, src/components/ui/Tooltip/fragments/TooltipTrigger.tsx
Updated to use ButtonPrimitive instead of Primitive.button for trigger/button elements.
Core Checkbox, Collapsible, Menu, RadioGroup, Toggle, RovingFocus Primitives
src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx, src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx, src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx, src/core/primitives/RadioGroup/fragments/RadioGroupPrimitiveItem.tsx, src/core/primitives/Toggle/index.tsx, src/core/utils/RovingFocusGroup/fragments/RovingFocusItem.tsx
Changed to render button elements using ButtonPrimitive instead of Primitive.button.
Button Primitive Implementation
src/core/primitives/Button/index.tsx
Added a type prop with a default of 'button' to ButtonPrimitive and passed it to the underlying button element.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant ButtonPrimitive
  participant PrimitiveButton

  Caller->>ButtonPrimitive: Render with props (optionally type)
  ButtonPrimitive->>PrimitiveButton: Render <Primitive.button type={type} ...>
  PrimitiveButton-->>ButtonPrimitive: Button element rendered
  ButtonPrimitive-->>Caller: Button rendered in UI component
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested labels

automerge

Poem

A button’s journey, hop by hop,
From primitive roots, it takes a new stop.
With type in tow and purpose clear,
Each trigger and toggle brings UI cheer.
A rabbit’s leap, a tidy sweep—
Code’s refactored, reviews are cheap! 🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0270af6 and 15f1222.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • src/components/ui/Accordion/fragments/AccordionTrigger.tsx (3 hunks)
  • src/components/ui/Switch/fragments/SwitchRoot.tsx (2 hunks)
  • src/components/ui/Tooltip/fragments/TooltipTrigger.tsx (2 hunks)
  • src/core/primitives/Button/index.tsx (2 hunks)
  • src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx (2 hunks)
  • src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx (3 hunks)
  • src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx (3 hunks)
  • src/core/primitives/RadioGroup/fragments/RadioGroupPrimitiveItem.tsx (3 hunks)
  • src/core/primitives/Toggle/index.tsx (2 hunks)
  • src/core/utils/RovingFocusGroup/fragments/RovingFocusItem.tsx (3 hunks)
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: kotAPI
PR: rad-ui/ui#576
File: src/core/primitives/Toggle/index.tsx:15-22
Timestamp: 2024-11-24T06:43:42.194Z
Learning: In the `TogglePrimitive` component (`src/core/primitives/Toggle/index.tsx`), when the component becomes controlled, it's acceptable to not sync the internal `isPressed` state with the external `pressed` prop.
Learnt from: krau5
PR: rad-ui/ui#609
File: src/components/ui/Text/Text.tsx:19-22
Timestamp: 2024-12-06T14:30:05.834Z
Learning: When the keys and values for the `as` prop are the same, we should define the type directly using string literals (e.g., `'div' | 'span' | 'p' | 'label'`) and eliminate extra mappings like `tagMap` to simplify the code.
Learnt from: GoldGroove06
PR: rad-ui/ui#1215
File: src/core/primitives/CheckboxGroup/fragments/CheckboxGroupPrimitiveTrigger.tsx:25-27
Timestamp: 2025-07-18T16:43:26.175Z
Learning: In the CheckboxGroupPrimitiveTrigger component (`src/core/primitives/CheckboxGroup/fragments/CheckboxGroupPrimitiveTrigger.tsx`), the component uses two separate useEffect hooks with different purposes: the first useEffect (lines 25-27) with empty dependency array `[]` is meant to set the initial state only once on mount by syncing with the group's checked values, while the second useEffect (lines 28-34) handles ongoing state updates by propagating local `isChecked` changes back to the group's `checkedValues`. This pattern prevents infinite loops while maintaining proper synchronization.
📚 Learning: in the `toggleprimitive` component (`src/core/primitives/toggle/index.tsx`), when the component beco...
Learnt from: kotAPI
PR: rad-ui/ui#576
File: src/core/primitives/Toggle/index.tsx:15-22
Timestamp: 2024-11-24T06:43:42.194Z
Learning: In the `TogglePrimitive` component (`src/core/primitives/Toggle/index.tsx`), when the component becomes controlled, it's acceptable to not sync the internal `isPressed` state with the external `pressed` prop.

Applied to files:

  • src/components/ui/Tooltip/fragments/TooltipTrigger.tsx
  • src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx
  • src/core/primitives/Toggle/index.tsx
  • src/components/ui/Switch/fragments/SwitchRoot.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx
  • src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx
  • src/core/primitives/Button/index.tsx
  • src/core/primitives/RadioGroup/fragments/RadioGroupPrimitiveItem.tsx
  • src/components/ui/Accordion/fragments/AccordionTrigger.tsx
  • src/core/utils/RovingFocusGroup/fragments/RovingFocusItem.tsx
📚 Learning: ensure to verify existing aria attributes in components before suggesting additions during code revi...
Learnt from: decipher-cs
PR: rad-ui/ui#417
File: src/components/ui/Dropdown/Dropdown.stories.tsx:43-50
Timestamp: 2024-12-12T08:34:33.079Z
Learning: Ensure to verify existing ARIA attributes in components before suggesting additions during code reviews, especially in the `Dropdown.Trigger` component in `src/components/ui/Dropdown/Dropdown.stories.tsx`.

Applied to files:

  • src/components/ui/Tooltip/fragments/TooltipTrigger.tsx
  • src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx
  • src/core/primitives/Toggle/index.tsx
  • src/components/ui/Switch/fragments/SwitchRoot.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx
  • src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx
  • src/core/primitives/Button/index.tsx
  • src/components/ui/Accordion/fragments/AccordionTrigger.tsx
  • src/core/utils/RovingFocusGroup/fragments/RovingFocusItem.tsx
📚 Learning: in the checkboxgroupprimitivetrigger component (`src/core/primitives/checkboxgroup/fragments/checkbo...
Learnt from: GoldGroove06
PR: rad-ui/ui#1215
File: src/core/primitives/CheckboxGroup/fragments/CheckboxGroupPrimitiveTrigger.tsx:25-27
Timestamp: 2025-07-18T16:43:26.175Z
Learning: In the CheckboxGroupPrimitiveTrigger component (`src/core/primitives/CheckboxGroup/fragments/CheckboxGroupPrimitiveTrigger.tsx`), the component uses two separate useEffect hooks with different purposes: the first useEffect (lines 25-27) with empty dependency array `[]` is meant to set the initial state only once on mount by syncing with the group's checked values, while the second useEffect (lines 28-34) handles ongoing state updates by propagating local `isChecked` changes back to the group's `checkedValues`. This pattern prevents infinite loops while maintaining proper synchronization.

Applied to files:

  • src/components/ui/Tooltip/fragments/TooltipTrigger.tsx
  • src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx
  • src/core/primitives/Toggle/index.tsx
  • src/components/ui/Switch/fragments/SwitchRoot.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx
  • src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx
  • src/core/primitives/Button/index.tsx
  • src/core/primitives/RadioGroup/fragments/RadioGroupPrimitiveItem.tsx
  • src/components/ui/Accordion/fragments/AccordionTrigger.tsx
  • src/core/utils/RovingFocusGroup/fragments/RovingFocusItem.tsx
📚 Learning: the `dropdown.trigger` component is customizable and needs to be used with `dropdown.root`....
Learnt from: decipher-cs
PR: rad-ui/ui#417
File: src/components/ui/Dropdown/Dropdown.tsx:0-0
Timestamp: 2024-12-12T08:22:59.375Z
Learning: The `Dropdown.Trigger` component is customizable and needs to be used with `Dropdown.Root`.

Applied to files:

  • src/components/ui/Tooltip/fragments/TooltipTrigger.tsx
  • src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx
  • src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx
  • src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx
  • src/components/ui/Accordion/fragments/AccordionTrigger.tsx
📚 Learning: the accordion component in rad-ui/ui supports both controlled and uncontrolled modes through props l...
Learnt from: kotAPI
PR: rad-ui/ui#1031
File: src/components/ui/Accordion/fragments/AccordionRoot.tsx:41-44
Timestamp: 2025-04-07T04:38:34.864Z
Learning: The Accordion component in rad-ui/ui supports both controlled and uncontrolled modes through props like `value`, `defaultValue`, and `onValueChange`. When implementing controlled components, remember to: 1) Initialize state from defaultValue, 2) Update internal state when value changes (controlled mode), 3) Call onValueChange callback, and 4) Prevent internal state updates when in controlled mode.

Applied to files:

  • src/components/ui/Accordion/fragments/AccordionTrigger.tsx
⏰ 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). (1)
  • GitHub Check: build
🔇 Additional comments (20)
src/core/primitives/Button/index.tsx (2)

20-20: LGTM! Good addition of explicit type prop.

Adding the type prop with a default value of 'button' is a solid improvement that ensures explicit button type specification and prevents unintended form submission behavior.


45-45: LGTM! Type prop correctly passed to underlying element.

The type prop is properly forwarded to the underlying Primitive.button element, ensuring the button type attribute is set correctly.

src/components/ui/Tooltip/fragments/TooltipTrigger.tsx (2)

4-4: LGTM! Import updated consistently with refactor.

The import change from generic Primitive to specific ButtonPrimitive aligns with the systematic refactor across the codebase.


23-25: LGTM! Component usage updated correctly.

The JSX has been properly updated to use ButtonPrimitive while preserving all existing props and the asChild pattern. The component will now benefit from the enhanced button primitive with explicit type specification.

src/core/utils/RovingFocusGroup/fragments/RovingFocusItem.tsx (2)

3-3: LGTM! Import updated for systematic refactor.

The import change from generic Primitive to specific ButtonPrimitive is consistent with the codebase-wide refactor.


249-266: LGTM! Complex component functionality preserved.

The update to ButtonPrimitive correctly maintains all existing functionality including keyboard navigation, ARIA attributes, focus management, and the asChild pattern. The component will now benefit from the enhanced button primitive with explicit type specification.

src/components/ui/Accordion/fragments/AccordionTrigger.tsx (2)

9-9: LGTM! Import updated consistently.

The import change to ButtonPrimitive aligns with the systematic refactor across the codebase.


46-55: LGTM! Component updated correctly.

The update to ButtonPrimitive preserves all existing functionality including className, ref, ARIA attributes, and click handler logic. The component maintains proper integration with CollapsiblePrimitive.Trigger and accessibility features.

src/core/primitives/Menu/fragments/MenuPrimitiveTrigger.tsx (2)

4-4: LGTM! Import updated with appropriate relative path.

The import change to ButtonPrimitive uses the correct relative path for a primitive importing another primitive and aligns with the systematic refactor.


19-31: LGTM! Component functionality preserved.

The update to ButtonPrimitive correctly maintains all existing functionality including complex tabIndex logic for nested menus, floating UI integration with refs and props, and the asChild pattern.

src/core/primitives/Toggle/index.tsx (2)

3-3: LGTM: Import updated consistently

The import change from Primitive to ButtonPrimitive aligns with the standardization effort across the codebase.


57-65: LGTM: JSX usage updated correctly

The component now uses ButtonPrimitive instead of Primitive.button, maintaining all existing props, event handlers, and accessibility attributes. The change is consistent with the broader refactor.

src/components/ui/Switch/fragments/SwitchRoot.tsx (2)

4-4: LGTM: Import standardization

The import change to ButtonPrimitive is consistent with the codebase-wide refactor.


29-29: LGTM: ButtonPrimitive usage maintained correctly

The JSX conversion preserves all functionality including the onClick handler, className, data-state attribute, and composed attributes.

src/core/primitives/RadioGroup/fragments/RadioGroupPrimitiveItem.tsx (2)

5-5: LGTM: Import alignment with refactor

The import change to ButtonPrimitive follows the consistent pattern across the codebase.


27-44: LGTM: Radio functionality preserved

The conversion to ButtonPrimitive maintains all critical radio group functionality including role="radio", accessibility attributes, and event handlers. The explicit type="button" will work well with the new ButtonPrimitive component.

src/core/primitives/Checkbox/fragments/CheckboxPrimitiveTrigger.tsx (2)

4-4: LGTM: Consistent import update

The import change aligns with the ButtonPrimitive standardization effort.


14-14: LGTM: Checkbox functionality preserved

The conversion to ButtonPrimitive maintains all essential checkbox attributes including role="checkbox", aria-checked, and the toggle functionality through the onClick handler.

src/core/primitives/Collapsible/fragments/CollapsiblePrimitiveTrigger.tsx (2)

2-2: LGTM: Import standardization

The import change to ButtonPrimitive is consistent with the codebase refactor.


36-47: LGTM: Collapsible functionality maintained

The conversion to ButtonPrimitive preserves all essential collapsible trigger functionality including ARIA attributes (aria-controls, aria-expanded), data attributes, forward ref support, and event handling.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kotapi/replace-button-primitive-wrapper

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@GoldGroove06 GoldGroove06 added the automerge A tag that tells kodiak bot to automerge PRs for us when tests and approval conditions are met label Aug 1, 2025
@kodiakhq kodiakhq bot merged commit b069d83 into main Aug 1, 2025
7 checks passed
@kodiakhq kodiakhq bot deleted the kotapi/replace-button-primitive-wrapper branch August 1, 2025 04:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

automerge A tag that tells kodiak bot to automerge PRs for us when tests and approval conditions are met

Projects

None yet

Development

Successfully merging this pull request may close these issues.

All the buttons that are used inside components should have type="button"

3 participants