import React, { FC, MouseEventHandler, ReactNode, useContext, useRef, } from 'react' import { ThemeContext } from 'styled-components' import { baseHyperLinkStyles } from '@monorail/helpers/baseStyles' import { convertHSLAMapToCss } from '@monorail/helpers/color' import { flexFlow } from '@monorail/helpers/flex' import { pageSizeMargin } from '@monorail/helpers/size' import styled, { css, ThemeProvider } from '@monorail/helpers/styled-components' import { getThemeColor, getThemeColorBase, GlobalAppThemeInterface, Mode, ThemeColors, } from '@monorail/helpers/theme' import { FontSizes, typographyFont } from '@monorail/helpers/typography' import { isNil } from '@monorail/sharedHelpers/typeGuards' import { CommonComponentType } from '@monorail/types' import { Button } from '@monorail/visualComponents/buttons/Button' import { ButtonDisplay, ButtonSize, } from '@monorail/visualComponents/buttons/buttonTypes' import { BaseLink } from '@monorail/visualComponents/hyperLink/BaseLink' import { HyperLink } from '@monorail/visualComponents/hyperLink/HyperLink' import { Icon } from '@monorail/visualComponents/icon/Icon' import { TabBarContainer } from '@monorail/visualComponents/tabs/TabBar' /* * Styles */ const PageHeaderContainer = styled.div( ({ cssOverrides, hasAboveContent }) => css` ${flexFlow('column')}; background: ${props => convertHSLAMapToCss({ ...getThemeColorBase(ThemeColors.ApplicationPrimary)(props), l: 99, })}; flex-shrink: 0; /* Instead of hiding overflow errors, let's see them and fix them. This was causing buttons to be hidden in error. */ overflow-x: auto; position: relative; /* Has this so that the shadow goes over the content below it. */ z-index: 1; /* Has this so that the shadow goes over the content below it. */ &::before { border-bottom: 1px solid ${getThemeColor(ThemeColors.ApplicationPrimary)}; background: inherit; bottom: 0; content: ''; left: 0; position: absolute; right: 0; top: 0; z-index: -5; } ${TabBarContainer} { padding: 0 24px; ${!hasAboveContent && css` margin-top: -8px; `}; } ${cssOverrides}; `, ) const PageHeaderNavigation = styled.div` ${flexFlow('row')}; ${pageSizeMargin()}; align-items: center; height: 32px; ` const BreadCrumbsContainer = styled.div` ${flexFlow('row')}; align-items: center; &::before { background: ${getThemeColor(ThemeColors.Text200)}; width: 1px; height: 20px; content: ''; margin-right: 12px; } ` export const TitleContainer = styled.div<{ hasAboveContent: boolean }>( ({ hasAboveContent }) => css` ${flexFlow('row')}; ${pageSizeMargin()}; align-items: center; flex-shrink: 0; grid-column: -1 / 1; height: ${hasAboveContent ? 48 : 64}px; justify-content: space-between; `, ) const Title = styled.h1` ${typographyFont(700, FontSizes.Title1)}; color: ${getThemeColor(ThemeColors.Text900)}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; ` const PageName = styled.h5` ${pageSizeMargin({ marginTop: 8, marginBottom: -8 })}; ${typographyFont(500, FontSizes.Title5)}; color: ${getThemeColor(ThemeColors.Text1000)}; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; ` const BreadCrumbLink = styled(HyperLink)` ${baseHyperLinkStyles(ThemeColors.Text500)}; padding: 6px 2px; user-select: none; text-decoration: none; ` /* * Types */ export type BreadCrumbsType = Array<{ title: string path: string }> export type PageHeaderNavigationProps = { breadCrumbs?: BreadCrumbsType } type PageHeaderContainerProps = CommonComponentType & { hasAboveContent: boolean } export type PageHeaderProps = CommonComponentType & PageHeaderNavigationProps & { disableBreadcrumbs?: boolean goBack?: MouseEventHandler | string title: ReactNode pageName?: string actions?: ReactNode } /* * Components */ export const PageHeader: FC = props => { const { actions, breadCrumbs, children, cssOverrides, goBack, pageName, title, disableBreadcrumbs, ...domProps } = props const pageHeaderContainerRef = useRef() const renderBreadCrumbs = () => { if (!breadCrumbs) { return null } return breadCrumbs.map( ( breadCrumb: { title: string path: string }, key, ) => [ {breadCrumb.title} , key !== breadCrumbs.length - 1 && ( ), ], ) } const hasAboveContent = (!isNil(breadCrumbs) || !isNil(goBack) || !isNil(pageName)) && isNil(disableBreadcrumbs) return ( {(!isNil(breadCrumbs) || !isNil(goBack)) && isNil(disableBreadcrumbs) && ( {!isNil(goBack) && typeof goBack === 'string' ? ( ) : ( )} {breadCrumbs && ( {renderBreadCrumbs()} )} )} ({ ...theme, [Mode.Light]: { ...theme[Mode.Light], [ThemeColors.ActionPrimary]: theme[ThemeColors.ApplicationPrimary], [ThemeColors.ActionSecondary]: theme[ThemeColors.ApplicationSecondary], }, })} > <> {pageName && {pageName}} {title} {actions} {children} ) }