Skip to content

Instantly share code, notes, and snippets.

@mrtcmn
Created October 31, 2025 06:28
Show Gist options
  • Select an option

  • Save mrtcmn/18a17a6d1f9f15e36f9750d4b7dcdbc1 to your computer and use it in GitHub Desktop.

Select an option

Save mrtcmn/18a17a6d1f9f15e36f9750d4b7dcdbc1 to your computer and use it in GitHub Desktop.
accordion.tsx shadcn with opening effect
"use client";
import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { motion } from "motion/react";
import type * as React from "react";
import { cn } from "@/lib/utils";
const Accordion = AccordionPrimitive.Root;
const AccordionItem = ({
className,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item> & {
ref?: React.RefObject<React.ElementRef<
typeof AccordionPrimitive.Item
> | null>;
}) => (
<AccordionPrimitive.Item
className={cn("border-b last:border-b-0", "cursor-pointer", className)}
ref={ref}
{...props}
/>
);
AccordionItem.displayName = "AccordionItem";
const AccordionTrigger = ({
className,
children,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> & {
ref?: React.RefObject<React.ElementRef<
typeof AccordionPrimitive.Trigger
> | null>;
}) => (
<AccordionPrimitive.Header className="flex">
<AccordionPrimitive.Trigger
className={cn(
"flex flex-1 items-center justify-start gap-1.5 py-2 font-medium text-sm transition-all",
"px-2 [&a[data-state=open]>svg]:rotate-180",
"[&>svg]:h-4 [&>svg]:w-4",
"rounded-md data-[state=closed]:hover:bg-accent/50",
"cursor-pointer",
className
)}
ref={ref}
{...props}
>
{children}
<p className="grow" />
<svg
fill="none"
height="14"
viewBox="0 0 14 14"
width="14"
xmlns="http://www.w3.org/2000/svg"
>
<title>Toggle accordion</title>
<path
d="M8 2V14M2 8H14"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>
);
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
const AccordionContent = ({
className,
children,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content> & {
ref?: React.RefObject<React.ElementRef<
typeof AccordionPrimitive.Content
> | null>;
}) => (
<AccordionPrimitive.Content
className={cn(
"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down",
"overflow-hidden text-sm",
className
)}
ref={ref}
{...props}
>
<motion.div
animate={{
filter: "blur(0px)",
opacity: 1,
transform: "translateY(0px)",
scale: 1,
}}
className="px-2 pb-3"
initial={{
filter: "blur(20px)",
opacity: 0,
transform: "translateY(100px)",
scale: 0.7,
}}
transition={{ duration: 0.2 }}
>
{children}
</motion.div>
</AccordionPrimitive.Content>
);
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment