import * as React from "react"; import {Separator} from "@/components/ui/separator"; import {cn} from "@/lib/utilities"; import styles from "./item.module.css"; /** Supported surface variants for {@link Item}. */ export type ItemVariant = "default" | "outline" | "muted"; /** Supported size variants for {@link Item}. */ export type ItemSize = "default" | "sm"; /** Supported media treatments for {@link ItemMedia}. */ export type ItemMediaVariant = "default" | "icon" | "image"; type ItemDataAttributes = Record<`data-${string}`, string | boolean | undefined>; /** * Props for the {@link ItemGroup} component. */ export type ItemGroupProps = React.ComponentPropsWithoutRef<"div">; /** * Props for the {@link ItemSeparator} component. */ export type ItemSeparatorProps = React.ComponentPropsWithoutRef; /** * Props for the {@link Item} component. */ export interface ItemProps extends React.ComponentPropsWithoutRef<"div"> { /** Enables rendering an existing div-compatible child element. @default false */ asChild?: boolean; /** Compactness applied to the item container. @default "default" */ size?: ItemSize; /** Visual surface treatment for the item container. @default "default" */ variant?: ItemVariant; } /** * Props for the {@link ItemMedia} component. */ export interface ItemMediaProps extends React.ComponentPropsWithoutRef<"div"> { /** Visual treatment used for the media slot. @default "default" */ variant?: ItemMediaVariant; } /** * Props for the {@link ItemContent} component. */ export type ItemContentProps = React.ComponentPropsWithoutRef<"div">; /** * Props for the {@link ItemTitle} component. */ export type ItemTitleProps = React.ComponentPropsWithoutRef<"div">; /** * Props for the {@link ItemDescription} component. */ export type ItemDescriptionProps = React.ComponentPropsWithoutRef<"p">; /** * Props for the {@link ItemActions} component. */ export type ItemActionsProps = React.ComponentPropsWithoutRef<"div">; /** * Props for the {@link ItemHeader} component. */ export type ItemHeaderProps = React.ComponentPropsWithoutRef<"div">; /** * Props for the {@link ItemFooter} component. */ export type ItemFooterProps = React.ComponentPropsWithoutRef<"div">; /** * Groups a collection of list-like items with consistent spacing. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * * * ``` * * @see {@link ItemGroupProps} for available props */ const ItemGroup = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Inserts a separator between adjacent items. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a wrapped `Separator` component * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * ``` * * @see {@link ItemSeparatorProps} for available props */ const ItemSeparator = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => ( ), ); /** * Creates a flexible data-display row with optional media and actions. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element by default * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * Content * ``` * * @see {@link ItemProps} for available props */ const Item = React.forwardRef( ( {className, variant = "default", size = "default", asChild = false, children, ...props}: Readonly, ref, ): React.JSX.Element => { const mergedClassName = cn( styles.item, variant === "outline" && styles.outline, variant === "muted" && styles.muted, size === "sm" ? styles.sizeSm : styles.sizeDefault, className, ); if (asChild && React.isValidElement(children)) { const child = children as React.ReactElement< React.ComponentPropsWithoutRef<"div"> & ItemDataAttributes & {ref?: React.Ref} >; // eslint-disable-next-line react-x/no-clone-element -- replaces Radix Slot while preserving asChild prop merging return React.cloneElement(child, { ...props, ref, "data-size": size, "data-slot": "item", "data-variant": variant, className: cn(mergedClassName, child.props.className), }); } return (
{children}
); }, ); /** * Renders the leading media slot for an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * ``` * * @see {@link ItemMediaProps} for available props */ const ItemMedia = React.forwardRef( ({className, variant = "default", ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Wraps the main textual content for an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * Details * ``` * * @see {@link ItemContentProps} for available props */ const ItemContent = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Displays the primary title text for an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * Title * ``` * * @see {@link ItemTitleProps} for available props */ const ItemTitle = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Displays secondary descriptive content for an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `

` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * Support text * ``` * * @see {@link ItemDescriptionProps} for available props */ const ItemDescription = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (

), ); /** * Hosts action controls aligned to the trailing edge of an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `

` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * * * ``` * * @see {@link ItemActionsProps} for available props */ const ItemActions = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Wraps leading title and description content for an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * * Profile * * ``` * * @see {@link ItemHeaderProps} for available props */ const ItemHeader = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (
), ); /** * Wraps trailing metadata or supplementary content for an item. * * @remarks * - Pure CSS component (no Base UI primitive) * - Renders a `
` element * - Styling via CSS Modules with `--ac-*` custom properties * * @example * ```tsx * Updated 2m ago * ``` * * @see {@link ItemFooterProps} for available props */ const ItemFooter = React.forwardRef( ({className, ...props}: Readonly, ref): React.JSX.Element => (
), ); ItemGroup.displayName = "ItemGroup"; ItemSeparator.displayName = "ItemSeparator"; Item.displayName = "Item"; ItemMedia.displayName = "ItemMedia"; ItemContent.displayName = "ItemContent"; ItemTitle.displayName = "ItemTitle"; ItemDescription.displayName = "ItemDescription"; ItemActions.displayName = "ItemActions"; ItemHeader.displayName = "ItemHeader"; ItemFooter.displayName = "ItemFooter"; export {Item, ItemActions, ItemContent, ItemDescription, ItemFooter, ItemGroup, ItemHeader, ItemMedia, ItemSeparator, ItemTitle};