ui
ui copied to clipboard
How to change the default chevron icon in Accordion to +/- ?
How to change the default chevron icon in Accordion to +/- ?
ChevronDownIcon is hardcoded in the @/component/ui/accordion but you can easily replace it with PlusIcon & MinusIcon.
P.S. you need to change the animation (accordion-down) in the AccordionContent because it rotate the chevron
Hi @Huydnph076901606 you can do like this:
'use client';
import * as React from 'react';
import * as AccordionPrimitive from '@radix-ui/react-accordion';
import { ChevronDown, Plus, Minus } from 'lucide-react';
import { cn } from '@/lib/utils';
const Accordion = AccordionPrimitive.Root;
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item ref={ref} className={cn('border-b', className)} {...props} />
));
AccordionItem.displayName = 'AccordionItem';
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 group',
className
)}
{...props}
>
{children}
<Plus className="h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=open]:hidden" />
<Minus className="h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=closed]:hidden" />
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
));
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className={cn(
'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
className
)}
{...props}
>
<div className="pb-4 pt-0">{children}</div>
</AccordionPrimitive.Content>
));
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
The Plus and Minus icon will be hidden based on the current state of the accordion.
@dan5py Thanks a lot, this is exactly what i wanted
@dan5py thanks a lot, didn't realise group was the solution, i was trying to rotate the vertical line of a + icon to make it -.
for ref:
<div className="relative">
<div className="absolute h-[1px] w-[9px] bg-white" />
<div className="absolute h-[1px] w-[9px] bg-white transition-transform duration-200 group-data-[state=closed]:rotate-90 group-data-[state=open]:rotate-0" />
</div>
how to remove the ChevronDown icon in @/component/ui/accordion
As answered in #777 you can change the <ChevronDown /> component in the accordion.tsx file and insert whatever icon you like or just remove it.
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" /> // <-- Old Icon
+ // Add any icon here
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
Hi @Huydnph076901606 you can do like this:
'use client'; import * as React from 'react'; import * as AccordionPrimitive from '@radix-ui/react-accordion'; import { ChevronDown, Plus, Minus } from 'lucide-react'; import { cn } from '@/lib/utils'; const Accordion = AccordionPrimitive.Root; const AccordionItem = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Item>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> >(({ className, ...props }, ref) => ( <AccordionPrimitive.Item ref={ref} className={cn('border-b', className)} {...props} /> )); AccordionItem.displayName = 'AccordionItem'; 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 group', className )} {...props} > {children} <Plus className="h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=open]:hidden" /> <Minus className="h-4 w-4 shrink-0 transition-transform duration-200 group-data-[state=closed]:hidden" /> </AccordionPrimitive.Trigger> </AccordionPrimitive.Header> )); AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName; const AccordionContent = React.forwardRef< React.ElementRef<typeof AccordionPrimitive.Content>, React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> >(({ className, children, ...props }, ref) => ( <AccordionPrimitive.Content ref={ref} className={cn( 'overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down', className )} {...props} > <div className="pb-4 pt-0">{children}</div> </AccordionPrimitive.Content> )); AccordionContent.displayName = AccordionPrimitive.Content.displayName; export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };The
PlusandMinusicon will be hidden based on the current state of the accordion.
Thanks brother!
You can use only CSS instead of icons, so you can still use rotate animation instead of hidden.
"use client"
import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion"
// import { ChevronDown } from "lucide-react"
import { cn } from "@/lib/utils"
const Accordion = AccordionPrimitive.Root
const AccordionItem = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
>(({ className, ...props }, ref) => (
<AccordionPrimitive.Item
ref={ref}
className={cn("border-b", className)}
{...props}
/>
))
AccordionItem.displayName = "AccordionItem"
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 [&[data-state=open]>span]:rotate-180 group",
className
)}
{...props}
>
{children}
<span className="relative h-3 w-3 shrink-0 transition-transform duration-200 custom-plus-minus group-data-[state=open]:after:opacity-0"></span>
{/* <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" /> */}
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
))
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
const AccordionContent = React.forwardRef<
React.ElementRef<typeof AccordionPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<AccordionPrimitive.Content
ref={ref}
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
{...props}
>
<div className={cn("pb-4 pt-0", className)}>{children}</div>
</AccordionPrimitive.Content>
))
AccordionContent.displayName = AccordionPrimitive.Content.displayName
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
CSS
.custom-plus-minus:before,
.custom-plus-minus:after {
content: "";
display: block;
position: absolute;
top: 50%;
left: 0;
background-color: hsl(var(--foreground));
width: 100%;
height: 1px;
}
.custom-plus-minus:before {
transform: translatey(-50%);
}
.custom-plus-minus:after {
transform: translatey(-50%) rotate(90deg);
}
Thank you very much @dan5py ❤️
thanks man @jeanzuck @dan5py