Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/tools/SandboxEditor/SandboxEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ColorSelect = ({ color, colorName, changeAccentColor }: ColorSelectProps)
style={{ width: dimensions, height: dimensions, backgroundColor: color.light['900'] }}></div>;
};

type SandboxProps = {className?: string} & PropsWithChildren
type SandboxProps = {className?: string | ''} & PropsWithChildren

const SandboxEditor = ({ children, className } : SandboxProps) => {
const [isDarkMode, setIsDarkMode] = useState(false);
Expand Down
25 changes: 12 additions & 13 deletions src/components/ui/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import React from 'react';

import AvatarRoot from './shards/AvatarRoot';
import AvatarImage from './shards/AvatarImage';
import AvatarFallback from './shards/AvatarFallback';
import AvatarPrimitive from '~/core/primitives/Avatar';

const COMPONENT_NAME = 'Avatar';

export type AvatarProps = {
children?: React.ReactNode,

customRootClass?: string,
fallback?: string,
className?: string,
Expand All @@ -16,24 +14,25 @@ export type AvatarProps = {
props?: Record<string, any>[]
}

const Avatar = ({ children, customRootClass, fallback, className, src, alt, ...props }: AvatarProps) => {
const Avatar = ({ customRootClass = '', fallback, className, src, alt, ...props }: AvatarProps) => {
return (
<AvatarRoot customRootClass={customRootClass}>
<AvatarImage
<AvatarPrimitive.Root src={src} customRootClass={customRootClass}>
<AvatarPrimitive.Image
src={src}
alt={alt}
className={className}
customRootClass={customRootClass}
{...props}
/>
<AvatarFallback customRootClass={customRootClass} fallback={fallback}/>
</AvatarRoot>
<AvatarPrimitive.Fallback>
{fallback}
</AvatarPrimitive.Fallback>
</AvatarPrimitive.Root>
);
};

Avatar.displayName = COMPONENT_NAME;
Avatar.Root = AvatarRoot;
Avatar.Image = AvatarImage;
Avatar.Fallback = AvatarFallback;
Avatar.Root = AvatarPrimitive.Root;
Avatar.Image = AvatarPrimitive.Image;
Avatar.Fallback = AvatarPrimitive.Fallback;

export default Avatar;
18 changes: 0 additions & 18 deletions src/components/ui/Avatar/shards/AvatarFallback.tsx

This file was deleted.

37 changes: 0 additions & 37 deletions src/components/ui/Avatar/shards/AvatarImage.tsx

This file was deleted.

18 changes: 0 additions & 18 deletions src/components/ui/Avatar/shards/AvatarRoot.tsx

This file was deleted.

27 changes: 27 additions & 0 deletions src/components/ui/AvatarGroup/AvatarGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

import AvatarGroupRoot from './shards/AvatarGroupRoot';

const COMPONENT_NAME = 'AvatarGroup';

// contexts

// export type AvatarProps = {
// children?: React.ReactNode,
// customRootClass?: string,
// fallback?: string,
// className?: string,
// src?: string,
// alt?: string,
// props?: Record<string, any>[]
// }

Comment on lines +9 to +18
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

Define and implement proper TypeScript interfaces.

The component lacks proper type definitions which are crucial for type safety and developer experience.

  1. Uncomment and modify the AvatarProps interface
  2. Add a new interface for the AvatarGroup component:
export interface AvatarProps {
    children?: React.ReactNode;
    customRootClass?: string;
    fallback?: string;
    className?: string;
    src?: string;
    alt?: string;
    props?: Record<string, unknown>; // More specific than any
}

export interface AvatarGroupProps {
    avatars: AvatarProps[];
    size?: 'sm' | 'md' | 'lg';
    customRootClass?: string;
    className?: string;
}

const AvatarGroup = ({ avatars = [], size, customRootClass = '', className }) => {
return <AvatarGroupRoot>

</AvatarGroupRoot>;
};
Comment on lines +19 to +23
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

Implement avatar rendering logic and type the component.

The component is currently a shell without implementation. It needs proper typing and rendering logic.

Here's a suggested implementation:

-const AvatarGroup = ({ avatars = [], size, customRootClass = '', className }) => {
+const AvatarGroup: FC<AvatarGroupProps> = ({
+  avatars = [],
+  size = 'md',
+  customRootClass = '',
+  className = ''
+}) => {
+  const avatarElements = avatars.map((avatar, index) => (
+    <Avatar
+      key={index}
+      size={size}
+      {...avatar}
+    />
+  ));
+
   return (
-    <AvatarGroupRoot>
-
+    <AvatarGroupRoot
+      className={`avatar-group ${customRootClass} ${className}`.trim()}
+    >
+      {avatarElements}
     </AvatarGroupRoot>
   );
 };

Committable suggestion was skipped due to low confidence.


AvatarGroup.displayName = COMPONENT_NAME;

export default AvatarGroup;
Comment on lines +25 to +27
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Component requires test coverage and documentation

The component lacks:

  • Test files for component testing
  • Story files for component documentation and examples
  • Documentation in markdown files

Please add:

  • Unit tests to verify component behavior and props
  • Storybook stories to showcase different use cases
  • Component documentation in relevant markdown files
🔗 Analysis chain

Verify component documentation and testing.

The component needs proper documentation and testing coverage.

Let's check for related test and story files:

Would you like me to help generate:

  1. Story files for component documentation
  2. Test files for component testing

Let me try another search pattern to verify the component's documentation and testing coverage.


Let me try one more search without the file type restriction:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for test and story files
echo "Checking for test and story files..."
fd -e test.tsx -e stories.tsx "AvatarGroup" src/

Length of output: 131


Script:

#!/bin/bash
# Search for AvatarGroup related files with different extensions
echo "Searching for AvatarGroup related files..."
fd "AvatarGroup" src/

# Search for potential test references
echo -e "\nSearching for AvatarGroup in test files..."
rg "AvatarGroup" -t tsx --glob "*test*"

# Search for potential story references
echo -e "\nSearching for AvatarGroup in story files..."
rg "AvatarGroup" -t tsx --glob "*stories*"

Length of output: 655


Script:

#!/bin/bash
# Search for test and story files without type restriction
echo "Searching in test files..."
rg "AvatarGroup" --glob "*test*"

echo -e "\nSearching in story files..."
rg "AvatarGroup" --glob "*stories*"

# Also check if there's any documentation in README or docs
echo -e "\nSearching in documentation..."
rg "AvatarGroup" --glob "*.md"

Length of output: 308

5 changes: 5 additions & 0 deletions src/components/ui/AvatarGroup/contexts/AvatarGroupContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createContext } from 'react';

const AvatarGroupContext = createContext({});

export default AvatarGroupContext;
17 changes: 17 additions & 0 deletions src/components/ui/AvatarGroup/shards/AvatarGroupRoot.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';

import AvatarGroupContext from './contexts/AvatarGroupContext';

const AvatarGroupRoot = () => {
return (
<div>
<AvatarGroupContext.Provider value={{}}>
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

Initialize context with proper default values

The context provider is initialized with an empty object, which could lead to runtime errors if consumers try to access undefined properties.

Define and use proper context value:

- <AvatarGroupContext.Provider value={{}}>
+ <AvatarGroupContext.Provider 
+   value={{
+     // Add required context properties here
+     avatarCount: 0,
+     maxDisplayed: 5,
+     // ... other necessary values
+   }}
+ >

Committable suggestion was skipped due to low confidence.

<AvatarGroupRoot >
</AvatarGroupRoot>
</AvatarGroupContext.Provider>

</div>
);
};
Comment on lines +5 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

Potential Infinite Recursion in Component Definition

The AvatarGroupRoot component is recursively calling itself within its render method (lines 11-12). This will lead to infinite recursion and crash the application. If the intention was to nest components, consider using a different component or adjusting the structure to prevent recursion.

Suggested change to prevent recursion:

-                <AvatarGroupRoot >
-                </AvatarGroupRoot>
+                {/* Nested components should go here */}
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 AvatarGroupRoot = () => {
return (
<div>
<AvatarGroupContext.Provider value={{}}>
<AvatarGroupRoot >
</AvatarGroupRoot>
</AvatarGroupContext.Provider>
</div>
);
};
const AvatarGroupRoot = () => {
return (
<div>
<AvatarGroupContext.Provider value={{}}>
{/* Nested components should go here */}
</AvatarGroupContext.Provider>
</div>
);
};


export default AvatarGroupRoot;
47 changes: 24 additions & 23 deletions src/components/ui/RadioGroup/RadioGroup.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,38 @@ import SandboxEditor from '~/components/tools/SandboxEditor/SandboxEditor';
import { useState } from 'react';

const RadioButton = (args) => {
const options = [
{id: 'html', value: 'html', label:'HTML'},
{id: 'css', value: 'css', label:'CSS'},
{id: 'javascript', value: 'javascript', label:'JavaScript'},]
const options = [
{ id: 'html', value: 'html', label: 'HTML' },
{ id: 'css', value: 'css', label: 'CSS' },
{ id: 'javascript', value: 'javascript', label: 'JavaScript' }];

const [language, setLanguage] = useState({})
const [language, setLanguage] = useState({});

const handleChange = (e) => {
setLanguage(e.target.value)
}
return (
setLanguage(e.target.value);
};
return (
<SandboxEditor>
{options.map((option) => (
<RadioGroup className='radioItems'{...args}
key={option.id}
id={option.id}
name='language'
value={option.value}
checked={language === option.value}
onChange={handleChange} >
<span id={option.id} >{option.label}</span>
</RadioGroup>
))}
{options.map((option) => (
<RadioGroup
className='radioItems'{...args}
key={option.id}
id={option.id}
name='language'
value={option.value}
checked={language === option.value}
onChange={handleChange} >
<span id={option.id} >{option.label}</span>
</RadioGroup>
))}
</SandboxEditor>
)
}
);
};

export default {
title: 'UI/Input/RadioGroup',
component: RadioGroup,
render: (args) => <RadioButton {...args}/>
render: (args) => <RadioButton {...args}/>
};

export const All = {};
export const All = {};
36 changes: 18 additions & 18 deletions src/components/ui/RadioGroup/RadioGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import React, { DetailedHTMLProps, InputHTMLAttributes, PropsWithChildren} from 'react';
import { customClassSwitcher} from "~/core";
import React, { DetailedHTMLProps, InputHTMLAttributes, PropsWithChildren } from 'react';
import { customClassSwitcher } from '~/core';
import RadioPrimitive from '~/core/primitives/Radio';
const COMPONENT_NAME = 'RadioGroup';

export type RadioGroupProps = {

children?: React.ReactNode;
className: string;
customRootClass: string;
customRootClass: string;
} & DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement> & PropsWithChildren

const RadioGroup =({children,type='radio', className='',customRootClass='', ...props}:RadioGroupProps) => {
const rootClass= customClassSwitcher(customRootClass,COMPONENT_NAME)
const RadioGroup = ({ children, type = 'radio', className = '', customRootClass = '', ...props }:RadioGroupProps) => {
const rootClass = customClassSwitcher(customRootClass, COMPONENT_NAME);

return (
<div className={`${rootClass} ${className}`} role='radiogroup'>
<RadioPrimitive
type={type}
{...props}>
<div className={`${rootClass} ${className}`} role='radiogroup'>
<RadioPrimitive
type={type}
{...props}>

{children}
</RadioPrimitive>
</div>
);
};

{children}
</RadioPrimitive>
</div>
)
}

export default RadioGroup;
export default RadioGroup;
11 changes: 5 additions & 6 deletions src/components/ui/Switch/stories/Switch.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ const CheckBox = (args) => {
setIsChecked(state);
};
return <SandboxEditor className="space-x-1">
{variants.map((variant,index) => (
<Switch defaultChecked={args} key={index} variant={variant} onChange={handleChange} {...args} />
))}

</SandboxEditor>;

{variants.map((variant, index) => (
<Switch defaultChecked={args} key={index} variant={variant} onChange={handleChange} {...args} />
))}

</SandboxEditor>;
};

export const All = {};
13 changes: 13 additions & 0 deletions src/core/primitives/Avatar/contexts/AvatarPrimitiveContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createContext } from 'react';

interface AvatarPrimitiveContextType {
rootClass: string;
fallBackRootClass: string;
isImageLoaded: boolean;
hasError: boolean;
handleLoadImage: () => void;
handleErrorImage: () => void;
src?: string;
}
Comment on lines +3 to +11
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

Enhance type definitions for better maintainability.

A few suggestions to improve the interface:

  1. Consider using a discriminated union for better state management:
type AvatarPrimitiveContextType = {
  rootClass: string;
  fallBackRootClass: string;
} & (
  | { status: 'loading'; src: string }
  | { status: 'loaded'; src: string }
  | { status: 'error'; src: string }
  | { status: 'idle'; src?: never }
);
  1. Consider adding constraints for class names (e.g., non-empty strings)


export const AvatarPrimitiveContext = createContext<AvatarPrimitiveContextType>({} as AvatarPrimitiveContextType);
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

Improve type safety of context initialization.

The current implementation uses type assertion with an empty object, which could lead to runtime errors if context is accessed before provider is set up.

Consider this safer implementation:

-export const AvatarPrimitiveContext = createContext<AvatarPrimitiveContextType>({} as AvatarPrimitiveContextType);
+export const AvatarPrimitiveContext = createContext<AvatarPrimitiveContextType | null>(null);
+
+export function useAvatarPrimitiveContext(): AvatarPrimitiveContextType {
+  const context = useContext(AvatarPrimitiveContext);
+  if (context === null) {
+    throw new Error('useAvatarPrimitiveContext must be used within an AvatarPrimitiveProvider');
+  }
+  return context;
+}

This approach:

  1. Makes the context nullable by default
  2. Provides a custom hook with runtime checks
  3. Improves error messages for debugging

Committable suggestion was skipped due to low confidence.

19 changes: 19 additions & 0 deletions src/core/primitives/Avatar/fragments/AvatarPrimitiveFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useContext } from 'react';
import { AvatarPrimitiveContext } from '../contexts/AvatarPrimitiveContext';

export interface AvatarPrimitiveFallbackProps {
children: React.ReactNode;
className?: string | '';
}

const AvatarPrimitiveFallback = ({ children, className = '' }: AvatarPrimitiveFallbackProps) => {
const { hasError, fallBackRootClass } = useContext(AvatarPrimitiveContext);

if (!hasError) {
return null;
}

return <span className={`${fallBackRootClass} ${className}`}>{children}</span>;
};

export default AvatarPrimitiveFallback;
37 changes: 37 additions & 0 deletions src/core/primitives/Avatar/fragments/AvatarPrimitiveImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { useContext } from 'react';

import { AvatarPrimitiveContext } from '../contexts/AvatarPrimitiveContext';

export interface AvatarRootImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
src?: string;
alt?: string;
className?: string | '';
status?: 'loading' | 'loaded' | 'error';
}
Comment on lines +5 to +10
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

Remove unused status prop from interface.

The status prop is defined in the interface but not used in the component implementation. Either remove it or implement the status handling logic.

 export interface AvatarRootImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
     src?: string;
     alt?: string;
     className?: string | '';
-    status?: 'loading' | 'loaded' | 'error';
 }
📝 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
export interface AvatarRootImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
src?: string;
alt?: string;
className?: string | '';
status?: 'loading' | 'loaded' | 'error';
}
export interface AvatarRootImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
src?: string;
alt?: string;
className?: string | '';
}


const AvatarPrimitiveImage = ({
src,
alt = 'Avatar',
className = '',
...props
}: AvatarRootImageProps) => {
const { handleErrorImage, handleLoadImage, hasError } = useContext(AvatarPrimitiveContext);

// If there's no src or there's an error, render nothing
if (!src || hasError) {
return null;
}
Comment on lines +20 to +23
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 adding explicit error state handling.

While returning null is a valid approach, consider implementing an error boundary or providing feedback about why the image isn't rendered for better debugging and user experience.

     // If there's no src or there's an error, render nothing
     if (!src || hasError) {
+        if (process.env.NODE_ENV !== 'production') {
+            console.warn(
+                `AvatarPrimitiveImage: Image not rendered due to ${!src ? 'missing src' : 'error state'}`
+            );
+        }
         return null;
     }
📝 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
// If there's no src or there's an error, render nothing
if (!src || hasError) {
return null;
}
// If there's no src or there's an error, render nothing
if (!src || hasError) {
if (process.env.NODE_ENV !== 'production') {
console.warn(
`AvatarPrimitiveImage: Image not rendered due to ${!src ? 'missing src' : 'error state'}`
);
}
return null;
}


return (
<img
src={src}
alt={alt}
onError={handleErrorImage}
onLoad={handleLoadImage}
className={className}
{...props}
/>
);
Comment on lines +25 to +34
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 loading optimization and ensure props safety.

Consider adding loading optimization attributes and ensure important props aren't accidentally overridden.

     return (
         <img
             src={src}
             alt={alt}
             onError={handleErrorImage}
             onLoad={handleLoadImage}
             className={className}
+            loading="lazy"
+            decoding="async"
-            {...props}
+            {...props}
+            // Ensure these props can't be overridden
+            onError={handleErrorImage}
+            onLoad={handleLoadImage}
         />
     );

Committable suggestion was skipped due to low confidence.

};

export default AvatarPrimitiveImage;
Loading
Loading