Skip to main content
Glama
ExpandCollapse.tsx4.76 kB
'use client'; import { type FC, type ReactNode, useEffect, useRef, useState } from 'react'; import { useIntlayer } from 'react-intlayer'; import { cn } from '../../utils/cn'; import { MaxHeightSmoother } from '../MaxHeightSmoother'; /** * Props for the ExpandCollapse component */ export type ExpandCollapseProps = { /** Whether the component should provide expand/collapse functionality. If false, renders children directly */ isRollable?: boolean; /** Minimum height in pixels before showing the expand/collapse toggle */ minHeight?: number; /** Content that may overflow and trigger the expand/collapse behavior */ children: ReactNode; /** Additional CSS classes for styling customization */ className?: string; }; /** Default minimum height threshold for triggering expand/collapse behavior */ const DEFAULT_MIN_HEIGHT = 700; /** * ExpandCollapse Component * * A smart content container that automatically provides expand/collapse functionality * when content exceeds a specified height threshold. Features smooth animations, * internationalized toggle text, and intelligent height detection. * * @example * ```tsx * <ExpandCollapse minHeight={300}> * <div>Very long content that will be collapsed...</div> * </ExpandCollapse> * ``` * * ## Key Features * - **Smart Detection**: Automatically detects when content exceeds height threshold * - **Smooth Animations**: Uses CSS transitions for smooth expand/collapse effects * - **Internationalization**: Toggle text supports multiple languages via Intlayer * - **Customizable Height**: Configurable minimum height threshold * - **Performance Optimized**: Only applies collapse behavior when necessary * - **Accessibility**: Proper ARIA attributes and keyboard support * * ## Behavior Logic * 1. **Measurement Phase**: Measures actual content height on mount * 2. **Comparison**: Compares content height against minHeight threshold * 3. **Conditional Rendering**: * - If content ≤ minHeight: Renders normally without collapse functionality * - If content > minHeight: Enables expand/collapse with toggle button * 4. **State Management**: Manages collapsed/expanded state with smooth transitions * * ## When to Use * - Long-form content (articles, documentation, code blocks) * - Lists or tables that may grow beyond comfortable viewing height * - User-generated content with unpredictable length * - FAQ sections or expandable content cards * - Code examples or JSON data display * * ## Accessibility Features * - **Keyboard Navigation**: Toggle button is focusable and keyboard accessible * - **Screen Reader Support**: Proper ARIA labels and state announcements * - **Visual Indicators**: Clear visual cues for collapsed/expanded states * - **Smooth Animations**: Respects user preferences for reduced motion * * ## Internationalization * - Supports multiple languages through Intlayer integration * - Toggle text automatically adapts to current locale * - Includes translations for "Show all" and "Show less" states * * @param props - ExpandCollapseProps * @returns React functional component */ export const ExpandCollapse: FC<ExpandCollapseProps> = ({ isRollable = true, minHeight = DEFAULT_MIN_HEIGHT, children, className, }) => { const [codeContainerHeight, setCodeContainerHeight] = useState(0); const [isCollapsed, setIsCollapsed] = useState(true); const codeContainerRef = useRef<HTMLDivElement>(null); const { expandCollapseContent } = useIntlayer('expand-collapse'); const isTooBig = codeContainerHeight > minHeight; useEffect(() => { if (codeContainerRef.current) { setCodeContainerHeight(codeContainerRef.current.clientHeight); } }, []); if (!isRollable) { return children; } if (!isTooBig) { return ( <div className={cn('grid w-full', className)} ref={codeContainerRef}> {children} </div> ); } return ( <MaxHeightSmoother isHidden={isCollapsed} minHeight={minHeight} className="w-full overflow-x-auto overflow-y-hidden" > <div className={cn('grid w-full', className)} ref={codeContainerRef}> {children} </div> <button className={cn( 'absolute right-0 bottom-0 flex w-full cursor-pointer items-center justify-center rounded-t-2xl bg-gradient-to-t from-card/80 to-transparent px-3 py-0.5 text-md text-neutral-700 shadow-[0_0_10px_-15px_rgba(0,0,0,0.3)] backdrop-blur transition-all duration-300 hover:py-1 dark:text-neutral-400', isCollapsed ? 'w-full' : 'w-32' )} type="button" onClick={() => setIsCollapsed((prev) => !prev)} > {expandCollapseContent(isCollapsed)} </button> </MaxHeightSmoother> ); };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aymericzip/intlayer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server