nexxtway/react-rainbow

View on GitHub
src/components/VerticalItem/index.js

Summary

Maintainability
C
1 day
Test Coverage
/* eslint-disable no-script-url, react/prop-types, react/jsx-props-no-spreading */
import React from 'react';
import PropTypes from 'prop-types';
import { Consumer as NavigationConsumer } from '../VerticalNavigation/context';
import { Consumer as SectionConsumer } from '../VerticalSection/context';
import { Consumer as SectionOverflowConsumer } from '../VerticalSectionOverflow/context';
import RenderIf from '../RenderIf';
import StyledLi from './styled/li';
import StyledAnchor from './styled/anchor';
import StyledIcon from './styled/icon';
import StyledButton from './styled/button';
import ItemContent from './itemContent';

function Item(props) {
    const {
        label,
        icon,
        name,
        href,
        onClick,
        notification,
        className,
        style,
        selectedItem,
        onSelect,
        entityHeaderId,
        isExpanded,
    } = props;
    const isSelected = name === selectedItem;

    const getAriaCurrent = () => {
        if (isSelected) {
            return 'page';
        }
        return undefined;
    };

    const hanldeOnClick = event => {
        onClick(event);
        onSelect(event, name);
    };

    const resolveTabIndex = () => {
        if (isExpanded === false) {
            return -1;
        }
        return 0;
    };

    return (
        <StyledLi
            className={className}
            style={style}
            data-active={isSelected}
            isSelected={isSelected}
            data-id="vertical-item"
        >
            <RenderIf isTrue={href}>
                <StyledAnchor
                    data-id="vertical-item-clickable-element"
                    className="rainbow-vertical-item_action"
                    href={href}
                    onClick={hanldeOnClick}
                    aria-describedby={entityHeaderId}
                    aria-current={getAriaCurrent()}
                    tabIndex={resolveTabIndex()}
                    isSelected={isSelected}
                >
                    <RenderIf isTrue={icon}>
                        <StyledIcon>{icon}</StyledIcon>
                    </RenderIf>
                    <ItemContent label={label} notification={notification} />
                </StyledAnchor>
            </RenderIf>
            <RenderIf isTrue={!href}>
                <StyledButton
                    data-id="vertical-item-clickable-element"
                    className="rainbow-vertical-item_action"
                    onClick={hanldeOnClick}
                    aria-describedby={entityHeaderId}
                    aria-current={getAriaCurrent()}
                    tabIndex={resolveTabIndex()}
                    isSelected={isSelected}
                >
                    <RenderIf isTrue={icon}>
                        <StyledIcon>{icon}</StyledIcon>
                    </RenderIf>
                    <ItemContent label={label} notification={notification} />
                </StyledButton>
            </RenderIf>
        </StyledLi>
    );
}

/**
 * A text-only link within VerticalNavigationSection or VerticalNavigationOverflow.
 * @category Layout
 */
export default function VerticalItem(props) {
    return (
        <NavigationConsumer>
            {context => (
                <SectionConsumer>
                    {entityHeaderId => (
                        <SectionOverflowConsumer>
                            {isExpanded => (
                                <Item
                                    {...props}
                                    {...context}
                                    entityHeaderId={entityHeaderId}
                                    isExpanded={isExpanded}
                                />
                            )}
                        </SectionOverflowConsumer>
                    )}
                </SectionConsumer>
            )}
        </NavigationConsumer>
    );
}

VerticalItem.propTypes = {
    /** The text displayed for the navigation item. */
    label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
    /** A unique identifier for the navigation item. */
    name: PropTypes.string,
    /** The icon to show if it is passed. It must be a svg icon or a font icon. */
    icon: PropTypes.node,
    /** The URL of the page that the navigation item goes to. */
    href: PropTypes.string,
    /** The notification comoponent to display on the right. */
    notification: PropTypes.node,
    /** Event fired when the item is clicked. */
    onClick: PropTypes.func,
    /** A CSS class for the outer element, in addition to the component's base classes. */
    className: PropTypes.string,
    /** An object with custom style applied for the outer element. */
    style: PropTypes.object,
};

VerticalItem.defaultProps = {
    label: '',
    name: undefined,
    icon: undefined,
    href: undefined,
    onClick: () => {},
    notification: null,
    className: undefined,
    style: undefined,
};