Prompt engineering is the practice of creating clear and effective instructions so an AI model understands exactly what you want. Common techniques include:
- Few-shot: Providing examples to guide the model.
- Chain-of-thought: Asking the model to reason step by step.
- System prompts: Defining the assistant’s role and behavior.
- Temperature: Adjusting creativity vs. precision.
You are an expert assistant specialized in...1import {2 Collapsible,3 CollapsibleContent,4 CollapsibleTrigger,5} from '@/components/ui/collapsible';67export function CollapsibleDemo() {8 return (9 <div className="space-y-3">10 <Collapsible variant="bordered" defaultOpen>11 <CollapsibleTrigger>12 <span className="text-lg font-semibold">Prompt Engineering</span>13 </CollapsibleTrigger>14 <CollapsibleContent>15 <div className="space-y-3 pt-3">16 <p className="text-muted-foreground text-sm">17 Prompt engineering is the practice of creating clear and effective instructions so an18 AI model understands exactly what you want. Common techniques include:19 </p>20 <ul className="text-muted-foreground list-disc space-y-1 pl-5 text-sm">21 <li>22 <strong>Few-shot:</strong> Providing examples to guide the model.23 </li>24 <li>25 <strong>Chain-of-thought:</strong> Asking the model to reason step by step.26 </li>27 <li>28 <strong>System prompts:</strong> Defining the assistant’s role and behavior.29 </li>30 <li>31 <strong>Temperature:</strong> Adjusting creativity vs. precision.32 </li>33 </ul>34 <div className="pt-2">35 <code className="bg-secondary rounded px-2 py-1 text-xs">36 You are an expert assistant specialized in...37 </code>38 </div>39 </div>40 </CollapsibleContent>41 </Collapsible>42 <Collapsible variant="bordered">43 <CollapsibleTrigger>44 <span className="text-lg font-semibold">RAG (Retrieval-Augmented Generation)</span>45 </CollapsibleTrigger>46 <CollapsibleContent>47 <div className="space-y-3 pt-3">48 <p className="text-muted-foreground text-sm">49 RAG combines a language model with an external knowledge base. The AI retrieves50 information from your documents and then generates an answer based on those sources.51 </p>52 <ul className="text-muted-foreground list-disc space-y-1 pl-5 text-sm">53 <li>Reduces hallucinations by grounding answers in real data.</li>54 <li>Allows up-to-date information without retraining models.</li>55 <li>Perfect for documentation, support assistants, and intelligent search.</li>56 </ul>57 </div>58 </CollapsibleContent>59 </Collapsible>60 <Collapsible variant="bordered">61 <CollapsibleTrigger>62 <span className="text-lg font-semibold">AI SDKs & Model Providers</span>63 </CollapsibleTrigger>64 <CollapsibleContent>65 <div className="space-y-3 pt-3">66 <p className="text-muted-foreground text-sm">67 AI SDKs make it easy to connect your application with large language models. They68 simplify authentication, requests, streaming, and model selection.69 </p>70 <ul className="text-muted-foreground list-disc space-y-1 pl-5 text-sm">71 <li>72 <strong>Groq:</strong> Extremely fast inference, ideal for real-time apps.73 </li>74 <li>75 <strong>OpenAI:</strong> Access to GPT models, embeddings, and multimodal features.76 </li>77 <li>78 <strong>Anthropic:</strong> Known for Claude models with strong reasoning and79 safety.80 </li>81 <li>82 <strong>Vercel AI SDK:</strong> A friendly layer for building chat and AI features83 in React and Next.js.84 </li>85 </ul>86 <p className="text-muted-foreground pt-2 text-xs">87 *Quick note:* These SDKs help developers focus on the product experience instead of88 handling low-level API details.89 </p>90 </div>91 </CollapsibleContent>92 </Collapsible>93 </div>94 );95}
Installation
Copy and paste the following code into your project.
'use client';import { cva } from 'class-variance-authority';import { ChevronDown } from 'lucide-react';import { AnimatePresence, HTMLMotionProps, motion } from 'motion/react';import * as React from 'react';import { cn } from '../../../lib/cn';const collapsibleVariants = cva('', {variants: {variant: {default: '',bordered: 'rounded-lg border border-border',card: 'rounded-lg border border-border bg-card shadow-sm',},},defaultVariants: {variant: 'default',},});const collapsibleTriggerVariants = cva(['flex w-full items-center justify-between','transition-all duration-200','focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2','disabled:pointer-events-none disabled:opacity-50',].join(' '),{variants: {variant: {default: 'hover:opacity-80',bordered: 'p-4',card: 'p-4',},},defaultVariants: {variant: 'default',},},);const collapsibleContentVariants = cva('overflow-hidden', {variants: {variant: {default: '',bordered: 'px-4 pb-4',card: 'px-4 pb-4',},},defaultVariants: {variant: 'default',},});interface CollapsibleContextValue {isOpen: boolean;setIsOpen: (open: boolean) => void;disabled?: boolean;variant?: 'default' | 'bordered' | 'card';}interface CollapsibleProps extends React.HTMLAttributes<HTMLDivElement> {defaultOpen?: boolean;open?: boolean;onOpenChange?: (open: boolean) => void;disabled?: boolean;variant?: 'default' | 'bordered' | 'card';}interface CollapsibleTriggerProps extends Omit<HTMLMotionProps<'button'>, 'children'> {showChevron?: boolean;chevronIcon?: React.ReactNode;chevronPosition?: 'left' | 'right';asChild?: boolean;children?: React.ReactNode;}interface CollapsibleContentProps extends Omit<HTMLMotionProps<'div'>, 'children'> {forceMount?: boolean;children?: React.ReactNode;}const CollapsibleContext = React.createContext<CollapsibleContextValue | null>(null);const useCollapsibleContext = (): CollapsibleContextValue => {const context = React.useContext(CollapsibleContext);if (!context) {throw new Error('Collapsible components must be used within Collapsible');}return context;};const Collapsible = React.forwardRef<HTMLDivElement, CollapsibleProps>(({className,defaultOpen = false,open: controlledOpen,onOpenChange,disabled = false,variant = 'default',children,...props},ref,) => {const [internalOpen, setInternalOpen] = React.useState(defaultOpen);const isControlled = controlledOpen !== undefined;const isOpen = isControlled ? controlledOpen : internalOpen;const setIsOpen = React.useCallback((open: boolean) => {if (disabled) return;if (!isControlled) {setInternalOpen(open);}onOpenChange?.(open);},[disabled, isControlled, onOpenChange],);const contextValue = React.useMemo<CollapsibleContextValue>(() => ({ isOpen, setIsOpen, disabled, variant }),[isOpen, setIsOpen, disabled, variant],);return (<CollapsibleContext.Provider value={contextValue}><divref={ref}data-state={isOpen ? 'open' : 'closed'}data-disabled={disabled ? '' : undefined}className={cn(collapsibleVariants({ variant }), className)}{...props}>{children}</div></CollapsibleContext.Provider>);},);Collapsible.displayName = 'Collapsible';const CollapsibleTrigger = React.forwardRef<HTMLButtonElement, CollapsibleTriggerProps>(({className,showChevron = true,chevronIcon,chevronPosition = 'right',asChild = false,children,onClick,...props},ref,) => {const { isOpen, setIsOpen, disabled, variant } = useCollapsibleContext();const handleClick = React.useCallback((e: React.MouseEvent<HTMLButtonElement>) => {if (!disabled) {setIsOpen(!isOpen);onClick?.(e);}},[disabled, isOpen, setIsOpen, onClick],);const chevron = chevronIcon ?? <ChevronDown className="h-4 w-4 shrink-0" />;const iconTransition = { type: 'spring', stiffness: 300, damping: 20 } as const;if (asChild && React.isValidElement(children)) {return React.cloneElement(children, {onClick: handleClick,'data-state': isOpen ? 'open' : 'closed','aria-expanded': isOpen,disabled,} as React.HTMLAttributes<HTMLElement>);}return (<motion.buttonref={ref}type="button"onClick={handleClick}disabled={disabled}data-state={isOpen ? 'open' : 'closed'}aria-expanded={isOpen}whileHover={{ scale: 1.005, backgroundColor: 'rgba(0,0,0,0.02)' }}whileTap={{ scale: 0.99 }}className={cn(collapsibleTriggerVariants({ variant }), className)}{...props}>{showChevron && chevronPosition === 'left' && (<motion.spanaria-hidden="true"animate={{ rotate: isOpen ? 90 : 0 }}transition={iconTransition}className="mr-2">{chevron}</motion.span>)}<span className="flex-1 text-left">{children}</span>{showChevron && chevronPosition === 'right' && (<motion.spanaria-hidden="true"animate={{ rotate: isOpen ? 180 : 0 }}transition={iconTransition}className="ml-2">{chevron}</motion.span>)}</motion.button>);},);CollapsibleTrigger.displayName = 'CollapsibleTrigger';const CollapsibleContent = React.forwardRef<HTMLDivElement, CollapsibleContentProps>(({ className, forceMount = false, children, ...props }, ref) => {const { isOpen, variant } = useCollapsibleContext();return (<AnimatePresence initial={false} mode="sync">{(isOpen || forceMount) && (<motion.divref={ref}initial={{ height: 0, opacity: 0, filter: 'blur(10px)' }}animate={{height: 'auto',opacity: 1,filter: 'blur(0px)',transition: {height: { duration: 0.3, ease: [0.04, 0.62, 0.23, 0.98] },opacity: { duration: 0.25, delay: 0.05 },filter: { duration: 0.3 },},}}exit={{height: 0,opacity: 0,filter: 'blur(10px)',transition: {height: { duration: 0.25, ease: [0.04, 0.62, 0.23, 0.98] },opacity: { duration: 0.15 }, // Desaparece rápido para no estorbarfilter: { duration: 0.2 },},}}className={cn(collapsibleContentVariants({ variant }), className)}{...props}><motion.divinitial={{ y: -8, scale: 0.98 }}animate={{y: 0,scale: 1,transition: { duration: 0.3, ease: 'easeOut' },}}exit={{y: -8,scale: 0.98,transition: { duration: 0.2 },}}>{children}</motion.div></motion.div>)}</AnimatePresence>);},);CollapsibleContent.displayName = 'CollapsibleContent';export {Collapsible,CollapsibleContent,collapsibleContentVariants,CollapsibleTrigger,collapsibleTriggerVariants,collapsibleVariants,};export type { CollapsibleContentProps, CollapsibleProps, CollapsibleTriggerProps };
Make sure to update the import paths to match your project structure.
Usage
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
<Collapsible><CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger><CollapsibleContent>Yes. Free to use for personal and commercial projects.</CollapsibleContent></Collapsible>
Variants
Bordered
Collapsible with border and rounded corners.
A bordered collapsible adds a visual container around the content with a border and rounded corners, making it stand out from the surrounding content.
1import {2 Collapsible,3 CollapsibleContent,4 CollapsibleTrigger,5} from '@/components/ui/collapsible';67export function CollapsibleBorderedDemo() {8 return (9 <div className="w-full max-w-md space-y-4">10 <Collapsible variant="bordered" defaultOpen>11 <CollapsibleTrigger>What is a bordered collapsible?</CollapsibleTrigger>12 <CollapsibleContent>13 <p>14 A bordered collapsible adds a visual container around the content with a border and15 rounded corners, making it stand out from the surrounding content.16 </p>17 </CollapsibleContent>18 </Collapsible>1920 <Collapsible variant="bordered">21 <CollapsibleTrigger>When should I use it?</CollapsibleTrigger>22 <CollapsibleContent>23 <p>24 Use bordered collapsibles when you want to group related content visually or when you25 need clear separation between different collapsible sections.26 </p>27 </CollapsibleContent>28 </Collapsible>29 </div>30 );31}
Card
Collapsible with card styling including border, background, and shadow.
The card variant provides the most visual prominence with a background color, border, and subtle shadow. It's perfect for important content that needs to stand out.
1import {2 Collapsible,3 CollapsibleContent,4 CollapsibleTrigger,5} from '@/components/ui/collapsible';67export function CollapsibleCardDemo() {8 return (9 <div className="w-full max-w-md space-y-4">10 <Collapsible variant="card" defaultOpen>11 <CollapsibleTrigger>What makes the card variant special?</CollapsibleTrigger>12 <CollapsibleContent>13 <p>14 The card variant provides the most visual prominence with a background color, border,15 and subtle shadow. It's perfect for important content that needs to stand out.16 </p>17 </CollapsibleContent>18 </Collapsible>1920 <Collapsible variant="card">21 <CollapsibleTrigger>Best practices</CollapsibleTrigger>22 <CollapsibleContent>23 <p>24 Use card variant sparingly for emphasis. Too many card-styled elements can make your25 interface feel cluttered. Reserve it for primary information or key features.26 </p>27 </CollapsibleContent>28 </Collapsible>29 </div>30 );31}
Disabled
Collapsible in disabled state.
This collapsible started open but is now disabled. The content is visible but cannot be collapsed.
1import {2 Collapsible,3 CollapsibleContent,4 CollapsibleTrigger,5} from '@/components/ui/collapsible';67export function CollapsibleDisabledDemo() {8 return (9 <div className="w-full max-w-md space-y-4">10 <Collapsible variant="bordered" disabled>11 <CollapsibleTrigger>Disabled Collapsible (Closed)</CollapsibleTrigger>12 <CollapsibleContent>13 <p>This content cannot be revealed because the collapsible is disabled.</p>14 </CollapsibleContent>15 </Collapsible>1617 <Collapsible variant="bordered" disabled defaultOpen>18 <CollapsibleTrigger>Disabled Collapsible (Open)</CollapsibleTrigger>19 <CollapsibleContent>20 <p>21 This collapsible started open but is now disabled. The content is visible but cannot be22 collapsed.23 </p>24 </CollapsibleContent>25 </Collapsible>26 </div>27 );28}
No Chevron
Collapsible without indicator icon.
1import {2 Collapsible,3 CollapsibleContent,4 CollapsibleTrigger,5} from '@/components/ui/collapsible';67export function CollapsibleNoChevronDemo() {8 return (9 <div className="w-full max-w-md space-y-4">10 <Collapsible variant="bordered">11 <CollapsibleTrigger showChevron={false}>Click me (No Chevron)</CollapsibleTrigger>12 <CollapsibleContent>13 <p>14 This collapsible doesn't show a chevron icon. Useful when you want a cleaner look or15 when the expandable nature is obvious from context.16 </p>17 </CollapsibleContent>18 </Collapsible>1920 <Collapsible variant="card">21 <CollapsibleTrigger showChevron={false} className="font-semibold">22 Another Example23 </CollapsibleTrigger>24 <CollapsibleContent>25 <p>26 Without the chevron, the trigger can look like a simple heading or button, making it27 more subtle in your design.28 </p>29 </CollapsibleContent>30 </Collapsible>31 </div>32 );33}
Custom Icon
Use a custom icon instead of the default chevron.
1import { Minus, Plus } from 'lucide-react';2import {3 Collapsible,4 CollapsibleContent,5 CollapsibleTrigger,6} from '@/components/ui/collapsible';78export function CollapsibleCustomIconDemo() {9 return (10 <div className="w-full max-w-md space-y-4">11 <Collapsible variant="bordered">12 <CollapsibleTrigger chevronIcon={<Plus className="h-4 w-4" />}>13 Custom Plus Icon14 </CollapsibleTrigger>15 <CollapsibleContent>16 <p>17 This collapsible uses a plus icon instead of the default chevron. The icon rotates when18 opened, creating a nice visual transition.19 </p>20 </CollapsibleContent>21 </Collapsible>2223 <Collapsible variant="card">24 <CollapsibleTrigger chevronIcon={<Minus className="h-4 w-4" />}>25 Custom Minus Icon26 </CollapsibleTrigger>27 <CollapsibleContent>28 <p>29 You can use any icon you want! This example uses a minus icon to indicate collapsible30 content.31 </p>32 </CollapsibleContent>33 </Collapsible>34 </div>35 );36}
API Reference
Collapsible
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | false | Initial open state (uncontrolled mode). |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Callback fired when the open state changes. |
disabled | boolean | false | Disables interaction. |
variant | 'default' | 'bordered' | 'card' | 'default' | Visual style of the collapsible container. |
className | string | — | Additional classes. |
children | React.ReactNode | — | Content inside the collapsible. |
CollapsibleTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
showChevron | boolean | true | Shows the chevron icon. |
chevronIcon | React.ReactNode | — | Custom icon for the chevron. |
chevronPosition | 'left' | 'right' | 'right' | Position of the chevron icon. |
asChild | boolean | false | Allows passing a custom child element as the trigger. |
children | React.ReactNode | — | Trigger label or content. |
onClick | (event: React.MouseEvent) => void | — | Click handler (merged with open/close logic). |
className | string | — | Additional classes. |
CollapsibleContent
| Prop | Type | Default | Description |
|---|---|---|---|
forceMount | boolean | false | Renders content even when closed (useful for SSR). |
children | React.ReactNode | — | Content to be revealed/collapsed. |
className | string | — | Additional classes. |