ui
ui copied to clipboard
How to use a different icon in accordion and make it rotate.
I need help how to customize the accordion component icon.
You can change the Accordion
icon by changing the icon component in the accordion.tsx
file:
const AccordionTrigger = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
>(({ className, children, ...props }, ref) => (
<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}
>
{children}
- <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
+ <NewIcon className="h-4 w-4 shrink-0 transition-transform duration-200" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
Set NewIcon
to whatever icon component you like.
if my icon is custom.meaning it is svg file,How can i achieve the same behavior or i need to make it a component first?
You can either use the <img>
tag or copy & paste the svg code directly in the accordion file and apply the same classes to the element.
I'm used to create components for icons but those are just personal preferences.
`interface Props { size?: number; color?: string; className?: string; }
const Arrow = ({ size = 42, color = '#013047', className }: Props) => {
return (
<svg
width={size}
height={size}
viewBox="0 0 42 42"
fill="none"
stroke={color}
xmlns="http://www.w3.org/2000/svg"
className={className}
>
export default Arrow;
`
Seems good to me.
Guys is there any way of changing icons when the Item gets clicked? Like open folder icon vs close folder icon?
So I got it with a bit of a react state:
`` const AccordionTrigger = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Trigger>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>>(({ className, children, ...props }, ref) => {
const [isOpen, setIsOpen] = React.useState(false);
const handleToggle = () => {
setIsOpen((prevIsOpen) => !prevIsOpen);
};
return (
<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",
className
)}
{...props}
onClick={handleToggle}
>
{children}
{
isOpen
? <FolderOpen className="h-4 w-4 shrink-0 transition-transform duration-200" />
: <FolderClosed className="h-4 w-4 shrink-0 transition-transform duration-200" />
}
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
)
}); ``
@toty88 I have been trying to do the same with useState
, but there are a bunch of messy edge cases.
I have been experimenting with using the data attributes, with no luck:
<>
<MinusIcon className="h-4 w-4 shrink-0 transition-transform duration-200 data-[state=open]:hidden" />
<PlusIcon className="h-4 w-4 shrink-0 transition-transform duration-200 data-[state=closed]:hidden" />
</>
@toty88 you can add the group
tailwind class to the parent AccordionPrimitive.Trigger
element, detailed here:
https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
My solution:
<MinusIcon className="h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=open]:hidden" />
<PlusIcon className="h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=closed]:hidden" />
For more info, see the answers on #1133
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.