Beautiful and modern React UI library with comprehensive components, theming, and accessibility support.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
NextUI provides a comprehensive set of utility functions, custom hooks, and helper types that extend functionality and enable advanced customization patterns for building sophisticated user interfaces.
A versatile hook for managing open/closed state in overlay components, modals, popovers, and other interactive elements.
interface UseDisclosureProps {
/** Whether overlay is open */
isOpen?: boolean;
/** Default open state for uncontrolled mode */
defaultOpen?: boolean;
/** Close event handler */
onClose?: () => void;
/** Open change event handler */
onOpenChange?: (isOpen: boolean) => void;
/** Unique identifier for the disclosure */
id?: string;
}
interface UseDisclosureReturn {
/** Current open state */
isOpen: boolean;
/** Function to open the overlay */
onOpen: () => void;
/** Function to close the overlay */
onClose: () => void;
/** Function to toggle overlay state */
onOpenChange: (isOpen: boolean) => void;
/** Function to toggle between open and closed */
onToggle: () => void;
/** Whether the state is controlled externally */
isControlled: boolean;
/** Props for trigger button */
getButtonProps: (props?: any) => any;
/** Props for disclosure content */
getDisclosureProps: (props?: any) => any;
}
/**
* Hook for managing disclosure state (open/closed) for overlays
* @param props Configuration options
* @returns Disclosure state and handlers
*/
function useDisclosure(props?: UseDisclosureProps): UseDisclosureReturn;Usage Examples:
import { useDisclosure, Modal, ModalContent, Button } from "@nextui-org/react";
function DisclosureExample() {
// Basic usage
const { isOpen, onOpen, onOpenChange } = useDisclosure();
// Controlled usage
const [modalOpen, setModalOpen] = useState(false);
const modal = useDisclosure({
isOpen: modalOpen,
onOpenChange: setModalOpen,
});
// With default state
const drawer = useDisclosure({ defaultOpen: true });
return (
<div className="space-y-4">
{/* Basic modal */}
<Button onPress={onOpen}>Open Modal</Button>
<Modal isOpen={isOpen} onOpenChange={onOpenChange}>
<ModalContent>
<p>Modal content</p>
</ModalContent>
</Modal>
{/* Controlled modal */}
<Button onPress={modal.onOpen}>Controlled Modal</Button>
<Modal isOpen={modal.isOpen} onOpenChange={modal.onOpenChange}>
<ModalContent>
<p>Controlled modal content</p>
</ModalContent>
</Modal>
{/* Multiple disclosures */}
<Button onPress={drawer.onToggle}>
{drawer.isOpen ? "Close" : "Open"} Drawer
</Button>
</div>
);
}Advanced hook for implementing drag functionality with constraints and gestures.
interface UseDraggableProps {
/** Whether dragging is disabled */
isDisabled?: boolean;
/** Target element reference */
targetRef?: React.RefObject<HTMLElement>;
/** Body element reference for constraints */
bodyRef?: React.RefObject<HTMLElement>;
/** Drag constraint boundaries */
dragConstraints?: {
top?: number;
left?: number;
right?: number;
bottom?: number;
} | React.RefObject<Element>;
/** Elastic drag behavior */
dragElastic?: boolean | number;
/** Drag momentum configuration */
dragMomentum?: boolean;
/** Drag transition spring configuration */
dragTransition?: {
bounceStiffness?: number;
bounceDamping?: number;
};
}
interface UseDraggableReturn {
/** Motion props for the draggable element */
dragProps: {
drag?: boolean | "x" | "y";
dragConstraints?: any;
dragElastic?: boolean | number;
dragMomentum?: boolean;
dragTransition?: any;
dragControls?: any;
onDragStart?: (event: any, info: any) => void;
onDrag?: (event: any, info: any) => void;
onDragEnd?: (event: any, info: any) => void;
};
/** Drag controls for programmatic control */
dragControls: any;
}
/**
* Hook for implementing draggable functionality with Framer Motion
* @param props Drag configuration options
* @returns Drag props and controls
*/
function useDraggable(props: UseDraggableProps): UseDraggableReturn;Usage Example:
import { useDraggable, Card, CardBody } from "@nextui-org/react";
import { motion } from "framer-motion";
function DraggableExample() {
const constraintsRef = useRef<HTMLDivElement>(null);
const { dragProps } = useDraggable({
dragConstraints: constraintsRef,
dragElastic: 0.1,
});
return (
<div
ref={constraintsRef}
className="w-96 h-96 bg-default-100 rounded-lg relative"
>
<motion.div {...dragProps} className="absolute">
<Card className="w-32 h-32 cursor-grab active:cursor-grabbing">
<CardBody className="flex items-center justify-center">
<p className="text-sm">Drag me!</p>
</CardBody>
</Card>
</motion.div>
</div>
);
}Hook for implementing Material Design ripple effects on interactive elements.
interface UseRippleProps {
/** Ripple color theme */
color?: "current" | "white" | "default" | "primary" | "secondary" | "success" | "warning" | "danger";
/** Whether ripple is disabled */
isDisabled?: boolean;
/** Disable ripple for specific interactions */
disableRipple?: boolean;
/** Custom ripple duration in milliseconds */
duration?: number;
}
interface UseRippleReturn {
/** Ripple component to render */
ripples: React.ReactNode;
/** Function to trigger ripple effect */
onClick: (event: React.MouseEvent) => void;
/** Clear all active ripples */
clear: () => void;
}
/**
* Hook for Material Design ripple effects
* @param props Ripple configuration
* @returns Ripple state and handlers
*/
function useRipple(props?: UseRippleProps): UseRippleReturn;Usage Example:
import { useRipple, Card, CardBody } from "@nextui-org/react";
function RippleExample() {
const { ripples, onClick } = useRipple({
color: "primary",
});
return (
<Card
isPressable
className="w-64 h-32 relative overflow-hidden"
onPress={onClick}
>
<CardBody className="flex items-center justify-center">
<p>Click for ripple effect</p>
{ripples}
</CardBody>
</Card>
);
}Hook for implementing scroll shadows that indicate scrollable content overflow.
interface UseScrollShadowProps {
/** Scroll container reference */
ref?: React.RefObject<HTMLElement>;
/** Shadow visibility configuration */
visibility?: "auto" | "top" | "bottom" | "left" | "right" | "both" | "none";
/** Scroll orientation for shadow calculation */
orientation?: "vertical" | "horizontal";
/** Whether shadows are enabled */
isEnabled?: boolean;
/** Shadow size in pixels */
size?: number;
/** Offset threshold before showing shadows */
offset?: number;
/** Update interval for scroll position checking */
updateInterval?: number;
}
interface UseScrollShadowReturn {
/** Scroll container ref to attach */
scrollRef: React.RefObject<HTMLElement>;
/** Whether top shadow should be visible */
isTopShadowVisible: boolean;
/** Whether bottom shadow should be visible */
isBottomShadowVisible: boolean;
/** Whether left shadow should be visible */
isLeftShadowVisible: boolean;
/** Whether right shadow should be visible */
isRightShadowVisible: boolean;
/** Current scroll position */
scrollPosition: { top: number; left: number };
/** Scroll container dimensions */
dimensions: {
scrollWidth: number;
scrollHeight: number;
clientWidth: number;
clientHeight: number;
};
}
/**
* Hook for scroll shadow functionality
* @param props Scroll shadow configuration
* @returns Scroll shadow state and refs
*/
function useScrollShadow(props?: UseScrollShadowProps): UseScrollShadowReturn;Usage Example:
import { useScrollShadow, Card, CardBody } from "@nextui-org/react";
function ScrollShadowExample() {
const {
scrollRef,
isTopShadowVisible,
isBottomShadowVisible
} = useScrollShadow({
orientation: "vertical",
size: 8,
});
const items = Array.from({ length: 50 }, (_, i) => `Item ${i + 1}`);
return (
<Card className="w-64 h-96 relative">
<CardBody className="p-0">
{/* Top shadow */}
{isTopShadowVisible && (
<div className="absolute top-0 left-0 right-0 h-8 bg-gradient-to-b from-background to-transparent z-10 pointer-events-none" />
)}
{/* Scrollable content */}
<div
ref={scrollRef}
className="h-full overflow-y-auto p-4 space-y-2"
>
{items.map((item) => (
<div key={item} className="p-2 bg-default-100 rounded">
{item}
</div>
))}
</div>
{/* Bottom shadow */}
{isBottomShadowVisible && (
<div className="absolute bottom-0 left-0 right-0 h-8 bg-gradient-to-t from-background to-transparent z-10 pointer-events-none" />
)}
</CardBody>
</Card>
);
}Hook for accessing NextUI provider configuration throughout the component tree.
interface ProviderContextProps {
/** Current theme */
theme?: "light" | "dark";
/** Available themes */
themes?: ConfigThemes;
/** Default theme key */
defaultTheme?: string;
/** Whether animations are disabled globally */
disableAnimation?: boolean;
/** Whether ripple effects are disabled globally */
disableRipple?: boolean;
/** Validation behavior mode */
validationBehavior?: "aria" | "native";
/** Current locale */
locale?: string;
/** Navigation function for client-side routing */
navigate?: (path: string) => void;
/** Whether portal container is created */
createPortalContainer?: boolean;
}
/**
* Hook to access NextUI provider context
* @returns Provider context props or undefined if outside provider
*/
function useProviderContext(): ProviderContextProps | undefined;Usage Example:
import { useProviderContext, Button, Card, CardBody } from "@nextui-org/react";
function ThemeAwareComponent() {
const context = useProviderContext();
const handleThemeToggle = () => {
// Access theme configuration
const currentTheme = context?.theme;
console.log("Current theme:", currentTheme);
};
return (
<Card>
<CardBody>
<p>Current theme: {context?.theme || "No theme"}</p>
<p>Animations: {context?.disableAnimation ? "Disabled" : "Enabled"}</p>
<p>Locale: {context?.locale || "Default"}</p>
<Button
onPress={handleThemeToggle}
color="primary"
>
Check Theme
</Button>
</CardBody>
</Card>
);
}Enhanced forwardRef function that works seamlessly with NextUI's component system.
/**
* Enhanced forwardRef function for NextUI components
* @param render Render function that receives props and ref
* @returns Forwarded ref component
*/
function forwardRef<T, P = {}>(
render: (props: P, ref: React.Ref<T>) => React.ReactElement | null
): (props: P & React.RefAttributes<T>) => React.ReactElement | null;Usage Example:
import { forwardRef, Button } from "@nextui-org/react";
interface CustomButtonProps {
variant?: "primary" | "secondary";
children: React.ReactNode;
}
const CustomButton = forwardRef<HTMLButtonElement, CustomButtonProps>(
({ variant = "primary", children, ...props }, ref) => {
return (
<Button
ref={ref}
color={variant}
{...props}
>
{children}
</Button>
);
}
);
// Usage
function App() {
const buttonRef = useRef<HTMLButtonElement>(null);
return (
<CustomButton
ref={buttonRef}
variant="secondary"
onPress={() => buttonRef.current?.focus()}
>
Custom Button
</CustomButton>
);
}Utility functions for working with CSS classes and styling.
/**
* Class name utility (alias for clsx/cn)
* @param inputs Class name inputs (strings, objects, arrays)
* @returns Merged class name string
*/
function cn(...inputs: ClassValue[]): string;
type ClassValue =
| string
| number
| boolean
| undefined
| null
| ClassValue[]
| Record<string, any>;
/**
* Merge classes utility for combining class strings
* @param classes Class name strings to merge
* @returns Combined class string
*/
function mergeClasses(...classes: string[]): string;Usage Examples:
import { cn, Card, CardBody } from "@nextui-org/react";
function ClassUtilityExample() {
const [isActive, setIsActive] = useState(false);
const [variant, setVariant] = useState<"primary" | "secondary">("primary");
// Using cn for conditional classes
const cardClasses = cn(
"transition-all duration-200",
{
"scale-105 shadow-lg": isActive,
"bg-primary": variant === "primary",
"bg-secondary": variant === "secondary",
}
);
// Using cn with arrays
const buttonClasses = cn([
"px-4 py-2 rounded",
isActive && "bg-primary text-white",
!isActive && "bg-gray-200 text-gray-700"
]);
return (
<div className="space-y-4">
<Card
className={cardClasses}
isPressable
onPress={() => setIsActive(!isActive)}
>
<CardBody>
<p>Click to toggle active state</p>
<p>Current variant: {variant}</p>
</CardBody>
</Card>
<button
className={buttonClasses}
onClick={() => setIsActive(!isActive)}
>
Toggle Active
</button>
</div>
);
}Utilities for working with iterables and collections.
/**
* Convert value to iterator
* @param value Iterable or function that returns iterable
* @returns Iterator instance
*/
function toIterator<T>(value: Iterable<T> | (() => Iterable<T>)): Iterator<T>;
/**
* Check if element is a NextUI component
* @param element React element to check
* @returns Whether element is NextUI component
*/
function isNextUIEl(element: React.ReactElement): boolean;Usage Example:
import { toIterator, isNextUIEl, Button, Card } from "@nextui-org/react";
function IteratorExample() {
// Convert array to iterator
const items = ["apple", "banana", "cherry"];
const iterator = toIterator(items);
// Convert generator function to iterator
function* numberGenerator() {
for (let i = 0; i < 5; i++) {
yield i;
}
}
const numberIterator = toIterator(numberGenerator);
// Check if elements are NextUI components
const checkComponents = () => {
const button = <Button>Test</Button>;
const div = <div>Test</div>;
const card = <Card>Test</Card>;
console.log("Button is NextUI:", isNextUIEl(button)); // true
console.log("Div is NextUI:", isNextUIEl(div)); // false
console.log("Card is NextUI:", isNextUIEl(card)); // true
};
return (
<div className="space-y-4">
<Button onPress={checkComponents}>
Check Components
</Button>
<div>
<p>Iterator example:</p>
<ul>
{Array.from(iterator).map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
</div>
</div>
);
}Utilities for component variant and prop management.
/**
* Map props to variants and common props
* @param props Component props
* @param variantKeys Keys that should be treated as variants
* @param removeVariantProps Whether to remove variant props from main props
* @returns Tuple of [remainingProps, variantProps]
*/
function mapPropsVariants<T, K extends keyof T>(
props: T,
variantKeys: K[],
removeVariantProps?: boolean
): [Omit<T, K>, Pick<T, K>];
/**
* Map props to variants and common props with additional common keys
* @param props Component props
* @param variantKeys Keys that should be treated as variants
* @param commonKeys Keys that should be treated as common props
* @param removeVariantProps Whether to remove variant props from main props
* @returns Tuple of [remainingProps, variantProps, commonProps]
*/
function mapPropsVariantsWithCommon<T, K extends keyof T, C extends keyof T>(
props: T,
variantKeys: K[],
commonKeys: C[],
removeVariantProps?: boolean
): [Omit<T, K | C>, Pick<T, K>, Pick<T, C>];Utilities for extending and customizing NextUI components.
/**
* Extend component variants with custom styling
* @param component Component function created with tv()
* @param variants Additional variant configurations
* @param defaultVariants Default variant selections
* @returns Extended component function
*/
function extendVariants<T extends (...args: any[]) => any>(
component: T,
variants: ExtendVariantProps<T>,
defaultVariants?: Record<string, any>
): T;
interface ExtendVariantProps<T> {
/** Additional variants to add */
variants?: Record<string, Record<string, any>>;
/** Default variant values */
defaultVariants?: Record<string, any>;
/** Compound variants for complex styling */
compoundVariants?: Array<{
/** Variant conditions */
[key: string]: any;
/** Classes to apply when conditions match */
class?: string | string[];
}>;
}Usage Example:
import { extendVariants, Button } from "@nextui-org/react";
// Extend Button with custom variants
const CustomButton = extendVariants(Button, {
variants: {
color: {
olive: "bg-[#84cc16] text-[#000] data-[hover=true]:bg-[#65a30d]",
orange: "bg-[#ff8c00] text-[#fff] data-[hover=true]:bg-[#ff7700]",
violet: "bg-[#8b5cf6] text-[#fff] data-[hover=true]:bg-[#7c3aed]",
},
isDisabled: {
true: "bg-[#eaeaea] text-[#000] opacity-50 cursor-not-allowed",
},
size: {
xs: "px-2 py-1 text-xs",
xl: "px-8 py-4 text-xl",
},
},
defaultVariants: {
color: "olive",
size: "md",
},
compoundVariants: [
{
color: "olive",
size: "xl",
class: "uppercase font-bold",
},
],
});
function ExtendVariantsExample() {
return (
<div className="flex gap-4 items-center">
<CustomButton color="olive" size="sm">
Olive Button
</CustomButton>
<CustomButton color="orange" size="md">
Orange Button
</CustomButton>
<CustomButton color="violet" size="xl">
Violet XL Button
</CustomButton>
</div>
);
}// Common utility types
type Size = "sm" | "md" | "lg";
type Color = "default" | "primary" | "secondary" | "success" | "warning" | "danger";
type Radius = "none" | "sm" | "md" | "lg" | "full";
type Variant = "solid" | "bordered" | "light" | "flat" | "faded" | "shadow";
// Component polymorphism types
type As<Props = any> = React.ElementType<Props>;
type PropsOf<T extends As> = React.ComponentPropsWithoutRef<T> & {
as?: T;
};
type OmitCommonProps<T, K extends keyof any = never> = Omit<T, "id" | "children" | K>;
type RightJoinProps<
SourceProps extends object = {},
OverrideProps extends object = {}
> = OmitCommonProps<SourceProps, keyof OverrideProps> & OverrideProps;
type MergeWithAs<
ComponentProps extends object,
AsProps extends object,
AdditionalProps extends object = {},
AsComponent extends As = As
> = RightJoinProps<ComponentProps, AdditionalProps> &
RightJoinProps<AsProps, AdditionalProps> & {
as?: AsComponent;
};
// Prop getter types
type PropGetter<P = Record<string, unknown>, R = Record<string, unknown>> = (
props?: P,
forwardedRef?: React.Ref<any>
) => R;
// Slot-based styling types
type SlotsToClasses<S extends string> = {
[K in S]?: string;
};
type SlotProps<T> = T extends Record<infer S, any> ? S : never;
// Theme and variant types
interface ConfigThemes {
light?: ConfigTheme;
dark?: ConfigTheme;
[key: string]: ConfigTheme | undefined;
}
interface ConfigTheme {
colors?: Record<string, any>;
layout?: LayoutTheme;
}
interface LayoutTheme {
spacingUnit?: number;
disableAnimation?: boolean;
radius?: BaseThemeUnit;
borderWidth?: BaseThemeUnit;
}
interface BaseThemeUnit {
small?: string;
medium?: string;
large?: string;
}
// Selection types
type Selection = "all" | Set<React.Key>;
type SelectionMode = "none" | "single" | "multiple";
type SelectionBehavior = "toggle" | "replace";
interface SharedSelection {
selectedKeys?: Selection;
defaultSelectedKeys?: Selection;
selectionMode?: SelectionMode;
selectionBehavior?: SelectionBehavior;
disallowEmptySelection?: boolean;
onSelectionChange?: (keys: Selection) => void;
}
// Validation types
type ValidationBehavior = "aria" | "native";
type ValidationError = string | string[];
interface ValidationResult {
isInvalid: boolean;
validationErrors: string[];
validationDetails: ValidationDetails;
}
interface ValidationDetails {
[key: string]: any;
}
// Motion and animation types
interface MotionProps {
initial?: any;
animate?: any;
exit?: any;
transition?: any;
variants?: any;
whileHover?: any;
whileTap?: any;
whileFocus?: any;
whileInView?: any;
}
// Placement types for overlays
type PlacementAxis = "top" | "bottom" | "left" | "right";
type PlacementAlign = "start" | "end";
type Placement = PlacementAxis | `${PlacementAxis}-${PlacementAlign}`;
// Date/Time utility types
type DateValue = CalendarDate | CalendarDateTime | ZonedDateTime;
type TimeValue = Time;
interface RangeValue<T> {
start: T;
end: T;
}
// Hook return type patterns
interface UseComponentReturn<TElement = HTMLElement> {
Component: React.ElementType;
domRef: React.RefObject<TElement>;
slots: Record<string, string>;
classNames: Record<string, string>;
[key: string]: any;
}
// Event handler types
type PressHandler = () => void;
type ValueChangeHandler<T> = (value: T) => void;
type SelectionChangeHandler = (keys: Selection) => void;
type OpenChangeHandler = (isOpen: boolean) => void;Combining multiple NextUI hooks for complex functionality.
import {
useDisclosure, useScrollShadow, useRipple,
Card, CardHeader, CardBody, Button, Modal, ModalContent
} from "@nextui-org/react";
function useEnhancedCard() {
const modal = useDisclosure();
const { ripples, onClick } = useRipple({ color: "primary" });
const {
scrollRef,
isTopShadowVisible,
isBottomShadowVisible
} = useScrollShadow();
const cardProps = {
isPressable: true,
onClick: (e: React.MouseEvent) => {
onClick(e);
modal.onOpen();
},
className: "relative overflow-hidden",
};
return {
modal,
scrollRef,
isTopShadowVisible,
isBottomShadowVisible,
ripples,
cardProps,
};
}
function EnhancedCardExample() {
const {
modal,
scrollRef,
isTopShadowVisible,
isBottomShadowVisible,
ripples,
cardProps,
} = useEnhancedCard();
const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`);
return (
<>
<Card {...cardProps}>
<CardHeader>
<h3>Enhanced Interactive Card</h3>
</CardHeader>
<CardBody className="relative">
{isTopShadowVisible && (
<div className="absolute top-0 left-0 right-0 h-4 bg-gradient-to-b from-background to-transparent z-10" />
)}
<div
ref={scrollRef}
className="max-h-32 overflow-y-auto space-y-2"
>
{items.map((item) => (
<div key={item} className="p-2 bg-default-100 rounded">
{item}
</div>
))}
</div>
{isBottomShadowVisible && (
<div className="absolute bottom-0 left-0 right-0 h-4 bg-gradient-to-t from-background to-transparent z-10" />
)}
{ripples}
</CardBody>
</Card>
<Modal isOpen={modal.isOpen} onOpenChange={modal.onOpenChange}>
<ModalContent>
<div className="p-6">
<h2 className="text-xl font-bold mb-4">Card Details</h2>
<p>This modal was opened by clicking the card above!</p>
<Button
color="primary"
onPress={modal.onClose}
className="mt-4"
>
Close
</Button>
</div>
</ModalContent>
</Modal>
</>
);
}Creating sophisticated component extensions using NextUI utilities.
import {
extendVariants, forwardRef, cn,
Button, Card, Badge
} from "@nextui-org/react";
// Extended button with notification capabilities
const NotificationButton = extendVariants(Button, {
variants: {
notification: {
true: "relative",
false: "",
},
notificationColor: {
primary: "",
danger: "",
warning: "",
success: "",
},
},
defaultVariants: {
notification: false,
notificationColor: "primary",
},
});
// Enhanced card with advanced features
interface EnhancedCardProps {
children: React.ReactNode;
isInteractive?: boolean;
showRipple?: boolean;
notification?: {
count: number;
color?: "primary" | "danger" | "warning" | "success";
};
className?: string;
}
const EnhancedCard = forwardRef<HTMLDivElement, EnhancedCardProps>(
({
children,
isInteractive = false,
showRipple = false,
notification,
className,
...props
}, ref) => {
const { ripples, onClick } = useRipple({
color: "primary",
isDisabled: !showRipple,
});
return (
<Card
ref={ref}
isPressable={isInteractive}
className={cn(
"relative transition-transform",
isInteractive && "hover:scale-105",
showRipple && "overflow-hidden",
className
)}
onPress={showRipple ? onClick : undefined}
{...props}
>
{children}
{showRipple && ripples}
{notification && (
<Badge
content={notification.count}
color={notification.color}
className="absolute -top-2 -right-2"
/>
)}
</Card>
);
}
);
function AdvancedComponentExample() {
return (
<div className="space-y-6">
{/* Enhanced notification button */}
<NotificationButton
notification={true}
notificationColor="danger"
color="primary"
>
Messages
<Badge
content={5}
color="danger"
className="absolute -top-2 -right-2"
/>
</NotificationButton>
{/* Enhanced interactive card */}
<EnhancedCard
isInteractive
showRipple
notification={{ count: 3, color: "warning" }}
className="w-64 h-32"
>
<div className="p-4">
<h3 className="font-bold">Interactive Card</h3>
<p className="text-sm text-default-500">
Click for ripple effect
</p>
</div>
</EnhancedCard>
</div>
);
}Advanced resizable panel component built with Framer Motion for creating flexible layout systems.
interface ResizablePanelProps {
/** Panel content */
children: React.ReactNode;
/** Initial panel size */
defaultSize?: number;
/** Minimum panel size */
minSize?: number;
/** Maximum panel size */
maxSize?: number;
/** Resize direction */
direction?: "horizontal" | "vertical";
/** Whether resizing is disabled */
isDisabled?: boolean;
/** Panel identifier */
id?: string;
/** Custom CSS class */
className?: string;
/** Size change handler */
onSizeChange?: (size: number) => void;
/** Resize start handler */
onResizeStart?: () => void;
/** Resize end handler */
onResizeEnd?: (size: number) => void;
}
function ResizablePanel(props: ResizablePanelProps): JSX.Element;
/**
* Hook for managing resizable panel groups
*/
function useResizablePanelGroup(): {
registerPanel: (id: string, config: ResizablePanelConfig) => void;
unregisterPanel: (id: string) => void;
getPanel: (id: string) => ResizablePanelState | undefined;
resizePanel: (id: string, size: number) => void;
};
interface ResizablePanelConfig {
defaultSize: number;
minSize?: number;
maxSize?: number;
direction: "horizontal" | "vertical";
}
interface ResizablePanelState {
id: string;
size: number;
minSize: number;
maxSize: number;
isResizing: boolean;
}ResizablePanel Usage Example:
import { ResizablePanel, Card, CardBody } from "@nextui-org/react";
function ResizablePanelExample() {
const [leftSize, setLeftSize] = useState(300);
const [rightSize, setRightSize] = useState(400);
return (
<div className="flex h-96 border border-divider rounded-lg overflow-hidden">
{/* Left panel */}
<ResizablePanel
defaultSize={leftSize}
minSize={200}
maxSize={500}
direction="horizontal"
onSizeChange={setLeftSize}
className="border-r border-divider"
>
<Card className="h-full shadow-none">
<CardBody>
<h3 className="font-semibold mb-2">Left Panel</h3>
<p className="text-sm text-default-500">
This panel can be resized horizontally.
Current width: {leftSize}px
</p>
<div className="mt-4 space-y-2">
<div className="h-2 bg-primary rounded" />
<div className="h-2 bg-secondary rounded" />
<div className="h-2 bg-success rounded" />
</div>
</CardBody>
</Card>
</ResizablePanel>
{/* Center panel */}
<div className="flex-1 border-r border-divider">
<Card className="h-full shadow-none">
<CardBody>
<h3 className="font-semibold mb-2">Fixed Center</h3>
<p className="text-sm text-default-500">
This panel takes remaining space between the resizable panels.
</p>
</CardBody>
</Card>
</div>
{/* Right panel */}
<ResizablePanel
defaultSize={rightSize}
minSize={250}
maxSize={600}
direction="horizontal"
onSizeChange={setRightSize}
>
<Card className="h-full shadow-none">
<CardBody>
<h3 className="font-semibold mb-2">Right Panel</h3>
<p className="text-sm text-default-500">
Another resizable panel.
Current width: {rightSize}px
</p>
<div className="mt-4">
<div className="grid grid-cols-2 gap-2">
<div className="h-8 bg-warning rounded" />
<div className="h-8 bg-danger rounded" />
<div className="h-8 bg-default rounded" />
<div className="h-8 bg-foreground rounded" />
</div>
</div>
</CardBody>
</Card>
</ResizablePanel>
</div>
);
}// Framer Motion utilities
export { ResizablePanel } from "@nextui-org/framer-utils";
// React Aria utilities
export { VisuallyHidden } from "@react-aria/visually-hidden";
// Date utilities
export type { CalendarDate, CalendarDateTime, ZonedDateTime, Time } from "@internationalized/date";
export {
today,
now,
getLocalTimeZone,
isWeekend,
startOfWeek,
endOfWeek,
parseDate,
parseDateTime,
parseZonedDateTime,
parseTime
} from "@internationalized/date";