feat: Add Avatar and AvatarGroup components#88
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughIntroduces a new Avatar component system with grouping and overflow support, adds light-mode shadow design tokens, implements custom icon components including a Shipfox logo, extends standard icon mappings with imageAdd, and updates export barrels across the component library. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (2 passed)
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.
Pull Request Overview
This PR adds a new Avatar component along with an AvatarGroup component to the React UI library. It includes support for various content types (letters, logo, logoPlaceholder, image, upload) with customizable sizes and radius options. Additionally, it adds a new custom ShipfoxLogoIcon and the imageAdd icon to support the avatar functionality, and introduces shadow CSS variables for button styling.
- Adds
AvatarandAvatarGroupcomponents with multiple size and radius variants - Introduces
ShipfoxLogoIconcustom icon component - Adds
imageAddicon (RiImageAddFill) to the icon map - Adds shadow CSS variables for button styling
Reviewed Changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| libs/react/ui/src/components/index.ts | Exports the new avatar components |
| libs/react/ui/src/components/icon/icon.tsx | Adds RiImageAddFill icon to the icon map |
| libs/react/ui/src/components/icon/custom/shipfox-logo.tsx | Implements custom ShipfoxLogoIcon component |
| libs/react/ui/src/components/icon/custom/index.ts | Exports the ShipfoxLogoIcon |
| libs/react/ui/src/components/avatar/index.ts | Exports avatar and avatar-group components |
| libs/react/ui/src/components/avatar/avatar.tsx | Main Avatar component implementation with multiple content types |
| libs/react/ui/src/components/avatar/avatar.stories.tsx | Storybook stories demonstrating Avatar and AvatarGroup usage |
| libs/react/ui/src/components/avatar/avatar-group.tsx | AvatarGroup component for displaying multiple avatars with overflow handling |
| libs/react/ui/index.css | Adds shadow CSS variables for button styling |
| .gitignore | Adds .cursorrules to the ignore list |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
libs/react/ui/src/components/icon/custom/shipfox-logo.tsx (1)
4-6: Consider alignment with Remixicon's styling patterns.The custom
colorprop diverges from Remixicon's standard approach, where icons usecurrentColorand are styled via CSS. While the custom prop provides explicit control, it may be less intuitive for users familiar with styling other icons in the system via CSS properties.If you prefer consistency with Remixicon patterns, you could use
currentColorinstead:-type ShipfoxLogoProps = ComponentProps<RemixiconComponentType> & { - color?: string; -}; +type ShipfoxLogoProps = ComponentProps<RemixiconComponentType>;Then in the component:
-export function ShipfoxLogoIcon({color = '#FF4B00', ...props}: ShipfoxLogoProps) { +export function ShipfoxLogoIcon(props: ShipfoxLogoProps) { return ( <svg ... > <title>Shipfox Logo</title> <path fillRule="evenodd" clipRule="evenodd" d="..." - fill={color} + fill="currentColor" /> </svg> ); }Users could then set the color via CSS:
<ShipfoxLogoIcon style={{color: '#FF4B00'}} />orclassName.libs/react/ui/src/components/avatar/avatar.tsx (2)
56-61: Consider handling empty fallback more explicitly.The
getInitialfunction returns 'L' as a default when no valid character is found. While functional, this arbitrary default could be confusing in contexts where an empty fallback is intentional.Consider making the default more explicit or configurable:
-const getInitial = (fallbackText?: string): string => { - if (fallbackText) { - return fallbackText.trim()[0]?.toUpperCase() ?? 'L'; - } - return 'L'; -}; +const getInitial = (fallbackText?: string, defaultInitial = 'L'): string => { + const trimmed = fallbackText?.trim(); + return trimmed?.[0]?.toUpperCase() ?? defaultInitial; +};
164-170: Consider making logo color configurable.The Shipfox logo color is hardcoded to
#FF4B00. While this may be intentional for brand consistency, making it configurable would improve component flexibility.Add an optional
logoColorprop:export type AvatarProps = ComponentProps<typeof AvatarPrimitive.Root> & VariantProps<typeof avatarVariants> & { content?: AvatarContent; src?: string; alt?: string; fallback?: string; lightTheme?: boolean; animateOnHover?: boolean; + logoColor?: string; };Then use it in the logo rendering:
if (content === 'logo') { return ( <AvatarFallback className={cn(innerClassName, 'p-[15%]')}> - <ShipfoxLogoIcon color="#FF4B00" className="h-full w-full p-2" /> + <ShipfoxLogoIcon color={logoColor ?? "#FF4B00"} className="h-full w-full p-2" /> </AvatarFallback> ); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
.gitignore(1 hunks)libs/react/ui/index.css(1 hunks)libs/react/ui/src/components/avatar/avatar-group.tsx(1 hunks)libs/react/ui/src/components/avatar/avatar.stories.tsx(1 hunks)libs/react/ui/src/components/avatar/avatar.tsx(1 hunks)libs/react/ui/src/components/avatar/index.ts(1 hunks)libs/react/ui/src/components/icon/custom/index.ts(1 hunks)libs/react/ui/src/components/icon/custom/shipfox-logo.tsx(1 hunks)libs/react/ui/src/components/icon/icon.tsx(2 hunks)libs/react/ui/src/components/index.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*
⚙️ CodeRabbit configuration file
We handle errors at the edge of our applications in most cases. Do not recommend to add error handling around every single function. We prefer them to bubble up and be handled at upper layers.
Files:
libs/react/ui/src/components/avatar/index.tslibs/react/ui/src/components/icon/custom/shipfox-logo.tsxlibs/react/ui/src/components/avatar/avatar.tsxlibs/react/ui/src/components/icon/custom/index.tslibs/react/ui/src/components/index.tslibs/react/ui/src/components/avatar/avatar.stories.tsxlibs/react/ui/index.csslibs/react/ui/src/components/avatar/avatar-group.tsxlibs/react/ui/src/components/icon/icon.tsx
🧬 Code graph analysis (3)
libs/react/ui/src/components/avatar/avatar.tsx (2)
libs/react/ui/src/components/icon/custom/shipfox-logo.tsx (1)
ShipfoxLogoIcon(8-27)libs/react/ui/src/components/icon/icon.tsx (1)
Icon(47-50)
libs/react/ui/src/components/avatar/avatar.stories.tsx (2)
libs/react/ui/src/components/avatar/avatar.tsx (1)
Avatar(108-234)libs/react/ui/src/components/avatar/avatar-group.tsx (2)
AvatarGroup(56-108)AvatarGroupItem(47-47)
libs/react/ui/src/components/avatar/avatar-group.tsx (1)
libs/react/ui/src/components/avatar/avatar.tsx (2)
AvatarProps(98-106)Avatar(108-234)
⏰ 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: Agent
🔇 Additional comments (11)
.gitignore (1)
142-144: Clean addition of tool-specific ignore rule.The addition of
.cursorrulesto the ignore list is appropriate for local Cursor IDE configuration, following the standard practice of not committing development tool-specific settings. The formatting and organization are consistent with the rest of the file.libs/react/ui/index.css (1)
293-323: Light-mode shadow tokens properly implemented with consistent dark-mode pairing.The new shadow design tokens follow the established pattern with appropriate color adjustments for light mode (using
--color-alpha-white-*variants for focus rings) compared to dark mode. All tokens are properly re-exposed in the@theme inlineblock for Tailwind CSS integration.libs/react/ui/src/components/icon/custom/shipfox-logo.tsx (1)
18-18: Good accessibility practice with the title element.Including a descriptive title improves screen reader support.
libs/react/ui/src/components/icon/custom/index.ts (1)
9-9: Export correctly integrated.The new export follows the existing barrel export pattern and is properly placed alphabetically.
libs/react/ui/src/components/icon/icon.tsx (1)
5-5: Icon integration looks good.The
imageAddicon is correctly imported and mapped following the established pattern. The type system will automatically include it in theIconNameunion.Also applies to: 37-37
libs/react/ui/src/components/index.ts (1)
2-2: LGTM! Clean barrel export.The avatar export is correctly added and maintains alphabetical order.
libs/react/ui/src/components/avatar/avatar.tsx (2)
224-224: Verify the aggressive hover animation translation.The hover animation translates the avatar up by 32px (
-translate-y-8), which is quite significant and could feel jarring, especially for smaller avatar sizes.Consider testing this animation across all size variants to ensure it provides good UX. You might want to make the translation distance proportional to the avatar size:
const translateMap: Record<NonNullable<typeof size>, string> = { '3xs': 'hover:-translate-y-2', '2xs': 'hover:-translate-y-2', 'xs': 'hover:-translate-y-3', 'sm': 'hover:-translate-y-4', 'md': 'hover:-translate-y-6', 'lg': 'hover:-translate-y-8', 'xl': 'hover:-translate-y-10', '2xl': 'hover:-translate-y-16', '3xl': 'hover:-translate-y-20', };
198-216: LGTM! Clean icon size mapping.The upload content implementation with size-based icon scaling is well-structured and handles all size variants appropriately.
libs/react/ui/src/components/avatar/index.ts (1)
1-2: LGTM! Standard barrel exports.The avatar package exports are correctly structured.
libs/react/ui/src/components/avatar/avatar-group.tsx (1)
64-67: LGTM! Overflow logic is well-implemented.The overflow calculation and badge rendering correctly handle the
maxVisibleprop with appropriate z-index stacking.Also applies to: 94-105
libs/react/ui/src/components/avatar/avatar.stories.tsx (1)
93-259: LGTM! Comprehensive story coverage.The AvatarGroup stories provide excellent coverage of all major features including sizing, overflow handling, mixed content types, and animation behaviors.
Summary by CodeRabbit
New Features
Documentation