Loading...
Avatar Components (src/components/ui/avatar.tsx)
Converted 3 components: Avatar, AvatarImage, AvatarFallback
Ref now passed as optional prop: ref?: React.Ref<React.ElementRef<typeof AvatarPrimitive.Root>>
All Radix UI primitive integrations maintained
Checkbox Component (src/components/ui/checkbox.tsx)
Single component conversion with CheckboxPrimitive.Root integration
Preserved all accessibility features and visual states
Command Components (src/components/ui/command.tsx)
Converted 7 components: Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandSeparator, CommandItem
Largest refactor - maintained cmdk integration and dialog functionality
Radio Group Components (src/components/ui/radio-group.tsx)
Converted 2 components: RadioGroup, RadioGroupItem
Preserved indicator logic and Lucide icon integration
Separator Component (src/components/ui/separator.tsx)
Single component with default parameter preservation (orientation, decorative)
Maintained horizontal/vertical orientation logic
Switch Component (src/components/ui/switch.tsx)
Converted Switch with SwitchPrimitives.Thumb integration
All data-state attributes and animations preserved
React 19 Deprecation Warnings (15 warnings eliminated)
Removed all React.forwardRef usage across UI components
Converted to React 19's ref-as-prop pattern (refs passed as regular props)
Zero runtime overhead - purely signature changes
All components maintain identical functionality and behavior
Full TypeScript type safety preserved with proper ref typing
TL;DR: Migrated 6 shadcn/ui components (15 total component instances) from deprecated React.forwardRef pattern to React 19's ref-as-prop pattern, eliminating all forwardRef deprecation warnings while maintaining full type safety and functionality.
Comprehensive migration of shadcn/ui components to React 19 standards, removing all uses of the deprecated React.forwardRef API in favor of the new ref-as-prop pattern. This modernizes the component library while preserving 100% backward compatibility and type safety.
React.forwardRef usage across UI componentsAvatar Components (src/components/ui/avatar.tsx)
ref?: React.Ref<React.ElementRef<typeof AvatarPrimitive.Root>>Checkbox Component (src/components/ui/checkbox.tsx)
Command Components (src/components/ui/command.tsx)
Radio Group Components (src/components/ui/radio-group.tsx)
Separator Component (src/components/ui/separator.tsx)
Switch Component (src/components/ui/switch.tsx)
Before (Deprecated React.forwardRef):
const Component = React.forwardRef<
React.ElementRef<typeof Primitive>,
React.ComponentPropsWithoutRef<typeof Primitive>
>(({ className, ...props }, ref) => (
<Primitive ref={ref} className={cn(/* ... */)} {...props} />
));
Component.displayName = Primitive.displayName;
After (React 19 Ref-as-Prop):
const Component = ({
className,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof Primitive> & {
ref?: React.Ref<React.ElementRef<typeof Primitive>>;
}) => (
<Primitive ref={ref} className={cn(/* ... */)} {...props} />
);
Component.displayName = Primitive.displayName;
Type Safety Pattern:
React.ComponentPropsWithoutRef<typeof Primitive> for all props& { ref?: React.Ref<...> } for optional refReact.ElementRef<typeof Primitive> for exact ref typingFiles Modified (6 files, 15 component instances):
src/components/ui/avatar.tsx - 3 components (Avatar, AvatarImage, AvatarFallback)src/components/ui/checkbox.tsx - 1 component (Checkbox)src/components/ui/command.tsx - 7 components (Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandSeparator, CommandItem)src/components/ui/radio-group.tsx - 2 components (RadioGroup, RadioGroupItem)src/components/ui/separator.tsx - 1 component (Separator)src/components/ui/switch.tsx - 1 component (Switch)Import Optimization:
import * as React to import type * as Reactnpm run lint - 580 files checked)npm run type-check)When creating new shadcn/ui components, use the React 19 ref-as-prop pattern:
const MyComponent = ({
className,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof Primitive> & {
ref?: React.Ref<React.ElementRef<typeof Primitive>>;
}) => (
<Primitive ref={ref} className={cn(/* ... */)} {...props} />
);
Do not use React.forwardRef - it's deprecated in React 19.
Run npm run lint and npm run type-check before committing to ensure compliance.