Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Util classname 3 #632

Merged
merged 2 commits into from
Dec 11, 2024
Merged

Conversation

GoldGroove06
Copy link
Contributor

@GoldGroove06 GoldGroove06 commented Dec 11, 2024

This solves the issue #613 by using clsx to handle passing the className. It ensures no blank space or undefined className is passed. The files have been manually checked after the script did the migration.

Summary by CodeRabbit

  • New Features

    • Enhanced class name management across various components using the clsx utility for improved conditional styling.
  • Bug Fixes

    • No specific bug fixes were noted in this release.
  • Documentation

    • Updated method signatures and import statements to reflect the use of clsx in class name handling.
  • Chores

    • Streamlined class name handling in multiple components without altering their core functionality.

Copy link
Contributor

coderabbitai bot commented Dec 11, 2024

Walkthrough

The changes in this pull request involve the integration of the clsx utility across multiple UI components to enhance class name management. Specifically, several components have been updated to replace string interpolation with clsx for constructing class names. This modification applies to components such as Separator, Skeleton, Strong, Switch, various table components, and others, while maintaining their existing functionality and interfaces.

Changes

File Path Change Summary
src/components/ui/Separator/Separator.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Skeleton/Skeleton.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Strong/Strong.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Switch/Switch.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Table/fragments/TableBody.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Table/fragments/TableCell.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Table/fragments/TableColumnCellHeader.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Table/fragments/TableHead.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Table/fragments/TableRoot.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Table/fragments/TableRow.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Tabs/fragments/TabContent.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Tabs/fragments/TabList.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Tabs/fragments/TabRoot.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Tabs/fragments/TabTrigger.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Text/Text.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/TextArea/TextArea.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/TextArea/fragments/TextAreaRoot.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Toggle/Toggle.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/ToggleGroup/fragments/ToggleGroupRoot.tsx Added clsx import; updated class name handling to use clsx.
src/components/ui/Tree/fragments/TreeItem.tsx Added clsx import; updated class name handling to use clsx.

Possibly related PRs

Suggested labels

automerge

Suggested reviewers

  • kotAPI

Poem

In the garden of UI, we hop and play,
With clsx in hand, we brighten the way.
Class names now dance, so tidy and neat,
A sprinkle of magic makes our code sweet!
So let’s celebrate changes, both big and small,
For the joy of clean code brings happiness to all! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Experiment)
  • @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.

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

🧹 Outside diff range and nitpick comments (12)
src/components/ui/TextArea/fragments/TextAreaRoot.tsx (1)

Line range hint 7-11: Add JSDoc comments to document props

The component has good type safety, but would benefit from documentation explaining the difference between customRootClass and className:

 export type TextAreaProps = {
+  /** The content to be rendered inside the TextArea */
   children: React.ReactNode;
+  /** Custom class to override the default root class from customClassSwitcher */
   customRootClass?: string;
+  /** Additional classes to be applied alongside the root class */
   className?: string;
 }
src/components/ui/TextArea/TextArea.tsx (1)

14-14: Simplify unnecessary clsx usage.

Using clsx for a single className value is redundant. Since there's no conditional logic or multiple classes being combined, you can pass the className directly.

-    return <TextAreaRoot customRootClass={customRootClass} className={clsx(className)}>
+    return <TextAreaRoot customRootClass={customRootClass} className={className}>
src/components/ui/Tabs/fragments/TabList.tsx (1)

20-22: Simplify clsx usage by removing template literal.

The template literal within clsx is unnecessary as clsx can handle string concatenation directly.

-    return <div role="tablist" aria-orientation='horizontal' aria-label="todo" className={clsx(`${rootClass}-list`, className)}>
+    return <div role="tablist" aria-orientation='horizontal' aria-label="todo" className={clsx(rootClass + '-list', className)}>
src/components/ui/Text/Text.tsx (1)

7-9: Consider addressing TODO comments.

There are TODO comments about adding 'as' prop support, but the component already seems to implement this functionality. These comments should either be removed or clarified if there's additional functionality needed.

Would you like me to help implement any missing functionality or create an issue to track these TODOs?

src/components/ui/Table/fragments/TableRoot.tsx (3)

14-14: Simplify the clsx usage for wrapper className

The current implementation can be simplified by removing the template literal within clsx.

-    return <div className={clsx(`${rootClass}-wrapper`, className)} {...props} >
+    return <div className={clsx(rootClass + '-wrapper', className)} {...props} >

15-15: Consider addressing the TODO comment

The comment indicates a need to break down the wrapper into its own component, which could improve modularity.

Would you like me to help create a separate wrapper component or create an issue to track this task?


Line range hint 7-7: Consider adding proper TypeScript types

The component uses any type which defeats TypeScript's type checking benefits. Consider defining proper interface for the props.

interface TableRootProps extends React.HTMLAttributes<HTMLDivElement> {
    customRootClass?: string;
    children: React.ReactNode;
}
src/components/ui/Tabs/fragments/TabContent.tsx (1)

Line range hint 22-28: Consider using tab.value as key instead of index

Using array indices as keys can lead to issues with component identity during array modifications.

-            return <div key={index}>{tab.content}</div>;
+            return <div key={tab.value}>{tab.content}</div>;
src/components/ui/Switch/Switch.tsx (1)

30-30: LGTM! Simple clsx implementation

The clsx usage is appropriate here, though currently only handling a single class. Consider utilizing the color prop in the className if it's meant for styling.

-            <input type='checkbox' className={clsx(rootClass)} {...props} checked= {isChecked}/>
+            <input type='checkbox' className={clsx(rootClass, color && `${rootClass}--${color}`)} {...props} checked={isChecked}/>
src/components/ui/Toggle/Toggle.tsx (1)

Line range hint 9-17: Consider consolidating className props

The component accepts both customRootClass and className props which serve similar purposes. Consider consolidating these to reduce API complexity.

Consider updating the props interface:

export type ToggleProps = {
    defaultPressed?: boolean;
    pressed: boolean;
-   customRootClass? : string;
    disabled? : boolean;
    children? : React.ReactNode;
    className? : string;
    onChange : (isPressed:boolean) => void;
};
src/components/ui/ToggleGroup/fragments/ToggleGroupRoot.tsx (1)

Line range hint 7-7: Add proper TypeScript types for props

Using any type reduces type safety and IDE support. Consider defining a proper interface for the component props.

Add a proper type definition:

interface ToggleGroupRootProps {
  type?: 'multiple' | 'single';
  className?: string;
  loop?: boolean;
  customRootClass?: string;
  componentName: string;
  value: string | string[] | null;
  children: React.ReactNode;
}
src/components/ui/Tabs/fragments/TabTrigger.tsx (1)

52-52: Simplify the className implementation

While the clsx implementation is a good improvement, we can further optimize it by removing the template literal for the active class.

-className={clsx(`${rootClass}-trigger`, `${isActive ? 'active' : ''}`, className)}
+className={clsx(`${rootClass}-trigger`, isActive && 'active', className)}

This change:

  1. Removes unnecessary template literal
  2. Uses boolean shorthand which automatically handles the empty string case
  3. Maintains the same functionality with cleaner code
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7a389a2 and 5bc3860.

📒 Files selected for processing (20)
  • src/components/ui/Separator/Separator.tsx (2 hunks)
  • src/components/ui/Skeleton/Skeleton.tsx (1 hunks)
  • src/components/ui/Strong/Strong.tsx (2 hunks)
  • src/components/ui/Switch/Switch.tsx (2 hunks)
  • src/components/ui/Table/fragments/TableBody.tsx (1 hunks)
  • src/components/ui/Table/fragments/TableCell.tsx (1 hunks)
  • src/components/ui/Table/fragments/TableColumnCellHeader.tsx (1 hunks)
  • src/components/ui/Table/fragments/TableHead.tsx (1 hunks)
  • src/components/ui/Table/fragments/TableRoot.tsx (2 hunks)
  • src/components/ui/Table/fragments/TableRow.tsx (1 hunks)
  • src/components/ui/Tabs/fragments/TabContent.tsx (2 hunks)
  • src/components/ui/Tabs/fragments/TabList.tsx (2 hunks)
  • src/components/ui/Tabs/fragments/TabRoot.tsx (2 hunks)
  • src/components/ui/Tabs/fragments/TabTrigger.tsx (2 hunks)
  • src/components/ui/Text/Text.tsx (2 hunks)
  • src/components/ui/TextArea/TextArea.tsx (2 hunks)
  • src/components/ui/TextArea/fragments/TextAreaRoot.tsx (2 hunks)
  • src/components/ui/Toggle/Toggle.tsx (2 hunks)
  • src/components/ui/ToggleGroup/fragments/ToggleGroupRoot.tsx (2 hunks)
  • src/components/ui/Tree/fragments/TreeItem.tsx (2 hunks)
✅ Files skipped from review due to trivial changes (3)
  • src/components/ui/Table/fragments/TableRow.tsx
  • src/components/ui/Table/fragments/TableBody.tsx
  • src/components/ui/Table/fragments/TableCell.tsx
🔇 Additional comments (13)
src/components/ui/Table/fragments/TableHead.tsx (1)

5-5: LGTM: Correct usage of clsx

The implementation correctly uses clsx for className management, which aligns with the PR objectives of preventing blank spaces/undefined values.

src/components/ui/Table/fragments/TableColumnCellHeader.tsx (1)

4-7: 🛠️ Refactor suggestion

Similar type safety improvements needed as in TableHead

This component has the same type safety concerns. Consider adding proper TypeScript types:

-const TableColumnCellHeader = ({ children, className = 'cell-header', ...props }:any) => {
+type TableColumnCellHeaderProps = React.ComponentPropsWithoutRef<'th'> & {
+  children: React.ReactNode;
+  className?: string;
+};
+
+const TableColumnCellHeader = ({ 
+  children, 
+  className = 'th-cell-header', 
+  ...props 
+}: TableColumnCellHeaderProps) => {
src/components/ui/TextArea/fragments/TextAreaRoot.tsx (1)

15-15: LGTM: Excellent implementation of clsx

The implementation correctly uses clsx with both the root class and additional className, which perfectly aligns with the PR objectives. The use of customClassSwitcher adds an extra layer of class name management.

src/components/ui/Skeleton/Skeleton.tsx (1)

12-14: LGTM! Correct implementation of clsx.

The change from string interpolation to clsx is appropriate and aligns with the PR objectives.

src/components/ui/Strong/Strong.tsx (1)

15-15: LGTM! Well-structured implementation.

The component is properly typed and the clsx implementation is correct. This is a good example of how the className management should be handled.

src/components/ui/Tabs/fragments/TabList.tsx (1)

3-3: LGTM! Correct implementation of clsx.

The integration of clsx for className management is properly implemented, maintaining the component's functionality while improving className handling.

Also applies to: 20-22

src/components/ui/Separator/Separator.tsx (1)

3-3: LGTM! Well-structured implementation of clsx.

The clsx integration effectively combines the root class, orientation class, and custom className prop. The implementation maintains component functionality while improving className management.

Also applies to: 17-17

src/components/ui/Text/Text.tsx (1)

4-4: LGTM! Clean implementation of clsx.

The clsx integration is well implemented, properly combining the root className with custom className props while maintaining component functionality.

Also applies to: 28-28

src/components/ui/Tabs/fragments/TabContent.tsx (1)

21-21: LGTM! Clean clsx implementation

The clsx usage here is clean and straightforward, properly combining the rootClass and className props.

src/components/ui/Tabs/fragments/TabRoot.tsx (1)

4-4: LGTM! Proper implementation of clsx

The changes correctly implement the clsx library for className composition, maintaining all existing functionality.

Also applies to: 41-41

src/components/ui/ToggleGroup/fragments/ToggleGroupRoot.tsx (1)

2-2: LGTM! Proper implementation of clsx

The changes correctly implement the clsx library for className composition.

Also applies to: 41-41

src/components/ui/Tabs/fragments/TabTrigger.tsx (1)

3-3: LGTM: Clean import of clsx utility

The addition of the clsx import aligns with the PR objective of improving className management.

src/components/ui/Tree/fragments/TreeItem.tsx (1)

4-4: LGTM: Clean import of clsx utility

The addition of the clsx import aligns with the PR objective of improving className management.

@@ -1,7 +1,8 @@
import React from 'react';
import { clsx } from 'clsx';

const TableHead = ({ children, className = 'header', ...props }:any) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add proper TypeScript types instead of using any

Using any type defeats TypeScript's type checking benefits. Consider defining proper types:

-const TableHead = ({ children, className = 'header', ...props }:any) => {
+type TableHeadProps = React.ComponentPropsWithoutRef<'thead'> & {
+  children: React.ReactNode;
+  className?: string;
+};
+
+const TableHead = ({ children, className = 'thead-header', ...props }: TableHeadProps) => {
📝 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
const TableHead = ({ children, className = 'header', ...props }:any) => {
type TableHeadProps = React.ComponentPropsWithoutRef<'thead'> & {
children: React.ReactNode;
className?: string;
};
const TableHead = ({ children, className = 'thead-header', ...props }: TableHeadProps) => {

@@ -1,15 +1,15 @@
'use client';
import React from 'react';
import { customClassSwitcher } from '~/core';

import { clsx } from 'clsx';
const COMPONENT_NAME = 'Skeleton';

const Skeleton = ({ loading = true, className = '', customRootClass = '', children, ...props }:any) => {
// If loading is false, return the children
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace 'any' type with proper component props interface.

Using 'any' type reduces type safety. Consider defining a proper interface for the component props.

-const Skeleton = ({ loading = true, className = '', customRootClass = '', children, ...props }:any) => {
+interface SkeletonProps extends React.ComponentProps<'span'> {
+  loading?: boolean;
+  className?: string;
+  customRootClass?: string;
+  children?: React.ReactNode;
+}
+
+const Skeleton = ({ loading = true, className = '', customRootClass = '', children, ...props }: SkeletonProps) => {

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 15 to 17
<TextAreaInput placeholder="enter text">
{children}
</TextAreaInput>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Make placeholder configurable.

The hardcoded placeholder "enter text" limits the component's reusability. Consider making it a prop.

-        <TextAreaInput placeholder="enter text">
+        <TextAreaInput placeholder={props.placeholder ?? "enter text"}>

And update the TextAreaProps interface:

 export type TextAreaProps = {
     children: React.ReactNode;
     customRootClass?: string;
     className?: string;
+    placeholder?: string;
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +30 to 32
<input type='checkbox' className={clsx(rootClass)} {...props} checked= {isChecked}/>
<button type="button" onClick={handleChecked} role="switch"></button>
</>
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider improving accessibility

The current implementation using separate checkbox and button elements might cause accessibility issues. Consider using ARIA attributes and combining the elements.

-            <input type='checkbox' className={clsx(rootClass)} {...props} checked= {isChecked}/>
-            <button type="button" onClick={handleChecked} role="switch"></button>
+            <button
+                type="button"
+                role="switch"
+                aria-checked={isChecked}
+                className={clsx(rootClass, color && `${rootClass}--${color}`)}
+                onClick={handleChecked}
+                {...props}
+            >
+                <span className="sr-only">Toggle switch</span>
+            </button>
📝 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
<input type='checkbox' className={clsx(rootClass)} {...props} checked= {isChecked}/>
<button type="button" onClick={handleChecked} role="switch"></button>
</>
<button
type="button"
role="switch"
aria-checked={isChecked}
className={clsx(rootClass, color && `${rootClass}--${color}`)}
onClick={handleChecked}
{...props}
>
<span className="sr-only">Toggle switch</span>
</button>

@@ -43,7 +43,7 @@ const Toggle: React.FC<ToggleProps> = ({
return (

<TogglePrimitive
className={`${rootClass}`}
className={clsx(rootClass)}
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

Include the className prop in clsx call

The className prop is being passed but not utilized in the component's class composition.

Update the className composition:

-className={clsx(rootClass)}
+className={clsx(rootClass, className)}
📝 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
className={clsx(rootClass)}
className={clsx(rootClass, className)}

@@ -60,7 +61,7 @@ const TreeItem = ({ children, item, level = 0, className = '', ...props }: TreeI
return <>

<ButtonPrimitive
className={className}
className={clsx(className)}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Unnecessary use of clsx

The current implementation clsx(className) doesn't provide any benefits over directly using className since:

  1. No conditional classes are being combined
  2. No template literals are being handled
-className={clsx(className)}
+className={className}

Additionally, consider moving inline styles to className-based styling for better maintainability:

-style={{ display: 'block', alignItems: 'center', gap: '0.5rem' }}
+className={clsx(className, 'tree-item-button')}
-style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}
+className="tree-item-content"

This would require adding corresponding CSS classes but would improve maintainability and consistency.

Committable suggestion skipped: line range outside the PR's diff.

@kotAPI kotAPI added the automerge A tag that tells kodiak bot to automerge PRs for us when tests and approval conditions are met label Dec 11, 2024
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.

2 participants