@spaced-out/ui-design-system
Version:
Sense UI components library
345 lines (331 loc) • 8.19 kB
Flow
// @flow strict
import * as React from 'react';
import classify from '../../utils/classify';
import {UnstyledButton} from '../Button';
import {ConditionalWrapper} from '../ConditionalWrapper';
import {Icon} from '../Icon';
import type {BaseLinkProps} from '../Link';
import {Link} from '../Link';
import type {StatusSemanticType} from '../StatusIndicator';
import {StatusIndicator} from '../StatusIndicator';
import {BodyMedium, SubTitleSmall, TEXT_COLORS} from '../Text';
import type {BaseTooltipProps} from '../Tooltip';
import {Tooltip} from '../Tooltip';
import css from './SideMenuLink.module.css';
export const MENU_NAME_LIST = Object.freeze({
dashboard: {
title: 'Dashboard',
iconName: 'house',
iconType: 'duotone',
},
engage: {
title: 'Engage',
iconName: 'bullseye-pointer',
iconType: 'duotone',
},
journeys: {
title: 'Journeys',
iconName: 'bullseye-pointer',
iconType: 'duotone',
},
automation: {
title: 'Automation',
iconName: 'bullseye-pointer',
iconType: 'duotone',
},
trm: {
title: 'TRM',
iconName: 'screen-users',
iconType: 'duotone',
},
analytics: {
title: 'Analytics & Data',
iconName: 'chart-column',
iconType: 'duotone',
},
messaging: {
title: 'Messaging',
iconName: 'messages',
iconType: 'duotone',
},
messages: {
title: 'Messaging',
iconName: 'messages',
iconType: 'duotone',
},
chatbot: {
title: 'Chatbot',
iconName: 'message-bot',
iconType: 'duotone',
},
referral: {
title: 'Referrals',
iconName: 'user-check',
iconType: 'duotone',
},
referrals: {
title: 'Referrals',
iconName: 'user-check',
iconType: 'duotone',
},
records: {
title: 'Records',
iconName: 'folder-open',
iconType: 'duotone',
},
'database-cleanup': {
title: 'Bulk Cleanup',
iconName: 'retweet',
iconType: 'duotone',
},
support: {
title: 'Support',
iconName: 'headset',
iconType: 'duotone',
},
audit: {
title: 'Audit',
iconName: 'print-magnifying-glass',
iconType: 'duotone',
},
schedule: {
title: 'Timeline',
iconName: 'timeline',
iconType: 'duotone',
},
people: {
title: 'People',
iconName: 'people-group',
iconType: 'duotone',
},
contacts: {
title: 'Contacts',
iconName: 'address-card',
iconType: 'duotone',
},
meetings: {
title: 'Meetings',
iconName: 'calendars',
iconType: 'duotone',
},
contacts3: {
title: 'Contacts',
iconName: 'browser',
iconType: 'duotone',
},
senseai: {
title: 'AI Copilot',
iconName: 'sparkles',
iconType: 'duotone',
},
'sense-jd-ai': {
title: 'Jd generator',
iconName: 'sparkles',
iconType: 'duotone',
},
tracking: {
title: 'Tracking',
iconName: 'user-check',
iconType: 'duotone',
},
jobs: {
title: 'Jobs',
iconName: 'briefcase',
iconType: 'duotone',
},
drive: {
title: 'Events',
iconName: 'briefcase',
iconType: 'duotone',
},
conversations: {
title: 'Conversations',
iconName: 'message-smile',
iconType: 'duotone',
},
pages: {
title: 'Pages',
iconName: 'pager',
iconType: 'duotone',
},
sourcing: {
title: 'Sourcing',
iconName: 'browser',
iconType: 'duotone',
},
earnings: {
title: 'Earnings',
iconName: 'wallet',
iconType: 'duotone',
},
settings: {
title: 'Settings',
iconName: 'gear',
iconType: 'duotone',
},
configuration: {
title: 'Configuration',
iconName: 'gear',
iconType: 'duotone',
},
supportLinks: {
title: 'Support Links',
iconName: 'circle-question',
iconType: 'duotone',
},
voiceflow: {
title: 'Voiceflow',
iconName: 'phone-volume',
iconType: 'duotone',
},
broadcast: {
title: 'Broadcast',
iconName: 'bullhorn',
iconType: 'duotone',
},
liveAgentTransfer: {
title: 'Live Agent Transfer',
iconName: 'user-headset',
iconType: 'duotone',
},
dataManagement: {
title: 'Data Management',
iconName: 'database',
iconType: 'duotone',
},
});
type ClassNames = $ReadOnly<{wrapper?: string}>;
export type SideMenuLinkProps = {
classNames?: ClassNames,
children?: React.Node,
customTitle?: string,
pageNameKey: string,
disabled?: boolean,
hovered?: boolean,
selectedValue?: string,
opened?: boolean,
onChange?: (e: SyntheticEvent<HTMLElement>, newValue: string) => mixed,
tabIndex?: number,
tooltip?: BaseTooltipProps,
isGroupMenuLink?: boolean,
to?: string,
rightSlot?: React.Node,
linkComponent?: React.AbstractComponent<BaseLinkProps, ?HTMLAnchorElement>,
status?: StatusSemanticType,
...
};
export const SideMenuLink: React$AbstractComponent<
SideMenuLinkProps,
HTMLButtonElement,
> = React.forwardRef<SideMenuLinkProps, HTMLButtonElement>(
(
{
classNames,
pageNameKey,
disabled,
opened,
selectedValue,
onChange,
tabIndex = 0,
tooltip,
isGroupMenuLink = false,
linkComponent: LinkComponent,
rightSlot,
to,
customTitle,
status,
...restButtonProps
}: SideMenuLinkProps,
ref,
): React.Node => {
const selected = selectedValue === pageNameKey;
const inActive = !onChange;
const onChangeHandler = (e: SyntheticEvent<HTMLElement>) => {
onChange && onChange(e, pageNameKey);
};
const linkTitle = customTitle || MENU_NAME_LIST[pageNameKey].title;
return (
<ConditionalWrapper
condition={to !== undefined}
wrapper={(children) => (
<Link
to={to}
tabIndex={-1}
linkComponent={LinkComponent}
className={classify(css.linkComponent, {
[css.closed]: !opened,
})}
onClick={onChangeHandler}
>
{children}
</Link>
)}
>
<ConditionalWrapper
condition={Boolean(!opened && !inActive)}
wrapper={(children) => (
<Tooltip body={linkTitle} {...tooltip}>
{children}
</Tooltip>
)}
>
<UnstyledButton
{...restButtonProps}
className={classify(
css.linkWrapper,
{
[css.selected]: selected,
[css.disabled]: disabled,
[css.inActive]: inActive,
[css.closed]: !opened,
},
classNames?.wrapper,
)}
onClick={onChangeHandler}
ref={ref}
tabIndex={disabled ? -1 : tabIndex}
disabled={disabled}
key={pageNameKey}
>
{pageNameKey && MENU_NAME_LIST[pageNameKey] ? (
<div className={css.iconContainer}>
{status && (
<StatusIndicator
status={status}
classNames={{
wrapper: css.statusIndicatorBlock,
}}
/>
)}
<Icon
type={MENU_NAME_LIST[pageNameKey].iconType}
name={MENU_NAME_LIST[pageNameKey].iconName}
size="medium"
color={TEXT_COLORS.inverseSecondary}
className={css.menuIcon}
/>
</div>
) : null}
{opened ? (
<div className={css.menuLabelContainer}>
{pageNameKey && MENU_NAME_LIST[pageNameKey] ? (
isGroupMenuLink ? (
<SubTitleSmall className={css.groupMenuLinkText}>
{linkTitle}
</SubTitleSmall>
) : (
<BodyMedium className={css.menuLinkText}>
{linkTitle}
</BodyMedium>
)
) : null}
{rightSlot ? rightSlot : null}
</div>
) : null}
</UnstyledButton>
</ConditionalWrapper>
</ConditionalWrapper>
);
},
);
SideMenuLink.displayName = 'SideMenuLink';