# All files / src/transition Collapse.tsx

100% Statements 84/84
100% Branches 2/2
100% Functions 1/1
100% Lines 84/84

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    851x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    47x
    47x
    47x
    47x
    47x
    47x
    47x
    47x
    47x
    47x
    47x
    47x
     "use client";
    import { cnb } from "cnbuilder";
    import { Children, cloneElement, type ReactElement } from "react";
    import {
      useCollapseTransition,
      type CollapseElementProps,
      type CollapseTransitionHookOptions,
    } from "./useCollapseTransition.js";

    /**
     * @typeParam E - An HTMLElement type used for the ref required for the
     * transition.
     *
     * @remarks
     * \@since 2.0.0
     * \@since 4.0.0 Updated for the new CSS Transition API.
     */
    export interface CollapseProps<E extends HTMLElement>
      extends Omit<CollapseTransitionHookOptions<E>, "transitionIn"> {
      /**
       * The child element that should have a `ref` and the `style`/`className`
       * props cloned into using the `cloneElement` API. If the child is a custom
       * component, you **must** use `React.forwardRef` and pass the `ref` and the
       * other props for the transition to work correctly.
       */
      children: ReactElement<CollapseElementProps<E>>;

      /**
       * Boolean if the element should be collapsed.
       *
       * @see {@link CollapseTransitionHookOptions.transitionIn}
       */
      collapsed: boolean;
    }

    /**
     * **Client Component**
     *
     * This is a component implementation of the {@link useCollapseTransition} hook
     * that implements the `temporary` behavior. Since this component uses the
     * `React.cloneElement` to inject the `ref` and `className` into the `children`,
     * it is recommended to use the hook instead.
     *
     * @example
     * Simple Example
     * ```tsx
     * function Example(): ReactElement {
     *   const [collapsed, setCollapsed] = useState(true);
     *
     *   return (
     *     <>
     *       <Button onClick={() => setCollapsed(!collapsed)}>
     *         Toggle
     *       </Button>
     *       <Collapse collapsed={collapsed}>
     *         <div>
     *           Some content that should only be visible while not collapsed.
     *         </div>
     *       </Collapse>
     *     </>
     *   );
     * }
     * ```
     *
     * @see {@link useCollapseTransition} for additional examples
     * @typeParam E - An HTMLElement type used for the ref required for the
     * transition.
     * @remarks
     * \@since 2.0.0
     * \@since 4.0.0 Updated for the new CSS Transition API.
     */
    export function Collapse<E extends HTMLElement>(
      props: CollapseProps<E>
    ): ReactElement {
      const { children, collapsed, className, ...options } = props;
      const child = Children.only(children);
      const { elementProps, rendered } = useCollapseTransition({
        ...options,
        className: cnb(child.props.className, className),
        transitionIn: !collapsed,
      });

      return <>{rendered && cloneElement(children, elementProps)}</>;
    }