# All files / src/layout LayoutNavToggle.tsx

0% Statements 0/115
0% Branches 0/1
0% Functions 0/1
0% Lines 0/115

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
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116

     import { cnb } from "cnbuilder";
    import { forwardRef } from "react";
    import { Button } from "../button";
    import { useIcon } from "../icon";
    import { DEFAULT_SHEET_TIMEOUT } from "../sheet";
    import { useCSSTransition } from "../transition";
    import { DEFAULT_LAYOUT_NAV_TOGGLE_CLASSNAMES } from "./constants";
    import { useLayoutConfig } from "./LayoutProvider";
    import type { LayoutNavToggleProps } from "./types";
    import { isTemporaryLayout, isToggleableLayout } from "./utils";

    /**
     * This is the default implementation for the navigation toggle button within
     * the `Layout` component and should normally be the first child for the
     * `LayoutAppBar`. In addition, this component will automatically update itself
     * to provide an accessible `aria-label` for screen readers and change to a
     * toggle button for toggleable layouts.
     */
    export const LayoutNavToggle = forwardRef<
      HTMLButtonElement,
      LayoutNavToggleProps
    >(function LayoutNavToggle(props, nodeRef) {
      const {
        "aria-label": propAriaLabel,
        "aria-pressed": propAriaPressed,
        children: propChildren,
        className,
        buttonType = "icon",
        onClick,
        offset: propOffset,
        rendered,
        tabIndex: propTabIndex,
        timeout = DEFAULT_SHEET_TIMEOUT,
        classNames = DEFAULT_LAYOUT_NAV_TOGGLE_CLASSNAMES,
        ...remaining
      } = props;

      const icon = useIcon("menu");
      const { baseId, layout, showNav, hideNav, visible } = useLayoutConfig();
      const isToggleable = isToggleableLayout(layout);
      const isTemporary = isTemporaryLayout(layout);

      let isRendered = rendered;
      if (typeof isRendered === "undefined") {
        isRendered = isTemporary || isToggleable;
      }

      let offset = propOffset;
      if (typeof offset === "undefined") {
        offset = isToggleable && visible;
      }

      const { elementProps } = useCSSTransition<HTMLButtonElement>({
        nodeRef,
        transitionIn: offset,
        temporary: false,
        timeout,
        classNames,
        className: cnb("rmd-layout-nav-toggle", className),
      });

      if (!isRendered) {
        return null;
      }

      let children = propChildren;
      if (buttonType === "icon" && typeof children === "undefined") {
        children = icon;
      }

      let tabIndex = propTabIndex;
      if (typeof tabIndex === "undefined" && visible && isToggleable) {
        // set to -1 so it isn't tab focusable but is still programmatically
        // focusable for temporary navigation drawers to re-focus once closed
        tabIndex = -1;
      }

      let ariaPressed = propAriaPressed;
      if (typeof ariaPressed === "undefined" && isToggleable) {
        ariaPressed = visible;
      }

      let ariaLabel = propAriaLabel;
      if (
        typeof ariaLabel === "undefined" &&
        typeof remaining["aria-labelledby"] === "undefined"
      ) {
        ariaLabel = isToggleable ? "Navigation" : "Show Navigation";
      }

      return (
        <Button
          id={`${baseId}-nav-toggle`}
          {...remaining}
          {...elementProps}
          aria-label={ariaLabel}
          aria-pressed={ariaPressed}
          onClick={(event) => {
            if (onClick) {
              onClick(event);
            }

            if (!visible) {
              showNav();
            } else {
              hideNav();
            }
          }}
          buttonType={buttonType}
          tabIndex={tabIndex}
        >
          {children}
        </Button>
      );
    });