[bug]: AccordionTrigger throws error with asChild
Describe the bug
If you try to use the asChild prop with AccordionTrigger React throws an error because we try to render a icon and our children, but it can only render 1 (Radix limitation)
Affected component/components
Accordion
How to reproduce
Add asChild prop to an AccordionTrigger
Codesandbox/StackBlitz link
No response
Logs
No response
System Info
None
Before submitting
- [X] I've made research efforts and searched the documentation
- [X] I've searched for existing issues
Heres my fix:
export const AccordionTrigger = React.forwardRef<React.ElementRef<typeof AccordionPrimitive.Trigger>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>>(
({ className, children, ...props }, ref) => {
const content = props.asChild ? (
children
) : (
<>
{children}
<ChevronDown className="size-4 shrink-0 transition-transform duration-200" />
</>
);
return (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn('flex flex-1 text-[16px] tracking-normal items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180', className)}
{...props}
>
{content}
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
}
);
I agree with this
I understand “asChild” in “radix-ui” to be a way to replace the default rendering element with the one you specify.
For example
<AccordionTrigger> is <button> by default, but <AccordionTrigger asChild><div>test</div></AccordionTrigger>
should be <div> by default
Default EX:
<AccordionTrigger>
<div>test</div>
</AccordionTrigger>
asChild EX:
<AccordionTrigger asChild>
<div>test</div>
</AccordionTrigger>
But “accrodion” in “shadcn” contains an icon by default So the “children” in <AccordionPrimitive.Header> renders two elements, returning an error
shadcn Default EX:
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
<div>test</div>
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
shadcn asChild EX:
<AccordionPrimitive.Header className="flex">
<div
ref={ref}
className={cn(
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
test
</div>
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Header>
Two React elements are being rendered in “<AccordionPrimitive.Header>” as shown in the code example above
However, “radix-ui” receives a child component as “children” in <AccordionPrimitive.Header>, which violates the React rule “children can only receive one child component”
@shadcn
I have this issue too.
It's critical for SEO apps.
currently there's no way to set Head aschild
I have to do this:
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => {
const content = props.asChild ? (
<AccordionPrimitive.Header className="flex" asChild>
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 text-[16px] tracking-normal items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
<div className="flex items-center gap-2">
{children}
<ChevronDown className="size-4 shrink-0 transition-transform duration-200" />
</div>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
) : (
(
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
ref={ref}
className={cn(
"flex flex-1 text-[16px] tracking-normal items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...props}
>
{children}
<ChevronDown className="size-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
)
);
What about this bug?