Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
broccolinisoup committed Nov 14, 2022
1 parent 1a5e9d3 commit dcddea7
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 47 deletions.
55 changes: 33 additions & 22 deletions src/PageHeader/PageHeader.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react'
import {Meta, Story} from '@storybook/react'
import {Box, Button, IconButton, Breadcrumbs} from '..'
import {EyeClosedIcon, SearchIcon, TriangleDownIcon} from '@primer/octicons-react'
import {Button, IconButton, Breadcrumbs} from '..'
import {EyeClosedIcon, SearchIcon, TriangleDownIcon, KebabHorizontalIcon, GitBranchIcon} from '@primer/octicons-react'

import {PageHeader} from './PageHeader'
import Hidden from '../Hidden'

const meta: Meta = {
title: 'Layout/PageHeeader',
title: 'Drafts/Components/PageHeader',
parameters: {
layout: 'fullscreen',
controls: {expanded: true}
Expand All @@ -16,36 +17,46 @@ const meta: Meta = {

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Template: Story = args => (
<PageHeader>
<PageHeader.ContextNav>
<PageHeader.ParentLink>Code</PageHeader.ParentLink>
</PageHeader.ContextNav>
<PageHeader.TitleArea>Branches</PageHeader.TitleArea>
<PageHeader.Actions>
<Box sx={{display: ['none', 'inline']}}>
<Button variant="primary">New Branch</Button>
</Box>
<Box sx={{display: ['inline', 'none']}}>
<Button variant="primary">New</Button>
</Box>
<IconButton aria-label="Search" icon={SearchIcon} />
</PageHeader.Actions>
<PageHeader sx={{padding: 2}}>
<PageHeader.ContextArea>
<PageHeader.ParentLink href="http://github.com">Code</PageHeader.ParentLink>
<PageHeader.ContextAreaActions>
<Button size="small" leadingIcon={GitBranchIcon}>
Main
</Button>
<IconButton size="small" aria-label="More" icon={KebabHorizontalIcon} />
</PageHeader.ContextAreaActions>
</PageHeader.ContextArea>
<PageHeader.TitleArea>
<PageHeader.BackButton />
<PageHeader.Title variant="large">Branches</PageHeader.Title>
<PageHeader.Actions>
<Hidden on={['narrow']}>
<Button variant="primary">New Branch</Button>
</Hidden>

<Hidden on={['regular', 'wide']}>
<Button variant="primary">New</Button>
</Hidden>
<IconButton aria-label="More" icon={KebabHorizontalIcon} />
</PageHeader.Actions>
</PageHeader.TitleArea>
</PageHeader>
)

export const Default = Template.bind({})
export const Playground = Template.bind({})

export const FilesPage = () => (
<PageHeader>
<PageHeader.ContextNav>
<PageHeader.ContextArea>
<PageHeader.ParentLink>Files</PageHeader.ParentLink>
<PageHeader.ContextNavActions>
<PageHeader.ContextAreaActions>
<Button variant="outline" leadingIcon={EyeClosedIcon} size="small" trailingIcon={TriangleDownIcon}>
main
</Button>
<IconButton aria-label="Search" icon={SearchIcon} />
</PageHeader.ContextNavActions>
</PageHeader.ContextNav>
</PageHeader.ContextAreaActions>
</PageHeader.ContextArea>
<PageHeader.TitleArea>
<Breadcrumbs>
<Breadcrumbs.Item href="/">...</Breadcrumbs.Item>
Expand Down
142 changes: 117 additions & 25 deletions src/PageHeader/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import React from 'react'
import {Box} from '..'
import {useResponsiveValue, ResponsiveValue} from '../hooks/useResponsiveValue'
import {SxProp, merge, BetterSystemStyleObject} from '../sx'
import Heading from '../Heading'
import {IconButton} from '../Button'
import {ChevronLeftIcon} from '@primer/octicons-react'
import Link from '../Link'

/* Todos (will be deleted soon)
Reference figma - https://www.figma.com/file/Ee0OrXuOLXMDqUW83EnDHP/PageHeader-(FY23-Q1)?node-id=2%3A2259
- ContextNav should only be visible in narrow.
- ContextArea should only be visible in narrow.
- Header rows should not wrap ever. be small?
- ParentTitle should have a back arrow
- Actions should all align right
Expand All @@ -20,41 +24,44 @@ Reference figma - https://www.figma.com/file/Ee0OrXuOLXMDqUW83EnDHP/PageHeader-(
*/

const REGION_ORDER = {
contextNav: 0,
ContextArea: 0,
titleArea: 1,
description: 2,
localNav: 3
}

export type PageHeaderProps = SxProp
export type PageHeaderProps = {
hidden?: boolean | ResponsiveValue<boolean>
} & SxProp

const Root: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
const rootStyles = {
marginX: 'auto',
display: 'flex',
flexDirection: 'column',
flexWrap: 'wrap'
}
return <Box sx={merge<BetterSystemStyleObject>(rootStyles, sx)}>{children}</Box>
}

export type ContextNavProps = {
hidden?: boolean | ResponsiveValue<boolean>
} & SxProp
// PageHeader.ContextArea : Only visible on narrow viewports to provide user context of where they are at their journey.
// PageHeader.ContexArea Sub Components: PageHeader.ParentLink, PageHeader.ContextBar, PageHeader.ContextNavActions
// ---------------------------------------------------------------------
export type ContextAreaProps = SxProp

const ContextNav: React.FC<React.PropsWithChildren<ContextNavProps>> = ({
children,
sx = {},
hidden = {
const ContextArea: React.FC<React.PropsWithChildren<ContextAreaProps>> = ({children, sx = {}}) => {
const isContextAreaHidden = {
narrow: false,
regular: true,
wide: true
}
}) => {
const isHidden = useResponsiveValue(hidden, false)
const isHidden = useResponsiveValue(isContextAreaHidden, false)
const contentNavStyles = {
display: isHidden ? 'none' : 'flex',
flexDirection: 'column',
order: REGION_ORDER.contextNav,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
order: REGION_ORDER.ContextArea,
// want same behaviour as PageLayout
flexBasis: 0,
flexGrow: 1,
Expand All @@ -63,29 +70,112 @@ const ContextNav: React.FC<React.PropsWithChildren<ContextNavProps>> = ({
}
return <Box sx={merge<BetterSystemStyleObject>(contentNavStyles, sx)}>{children}</Box>
}
const ParentLink: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>

export type ParentLinkProps = {
href?: string
} & SxProp

const ParentLink: React.FC<React.PropsWithChildren<ParentLinkProps>> = ({children, sx = {}, href}) => {
return (
<>
<Link muted sx={merge<BetterSystemStyleObject>({display: 'flex', alignItems: 'center'}, sx)} href={href}>
<ChevronLeftIcon />
{children}
</Link>
</>
)
}
const ContextNavActions: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {

// Generic slot for any component above the title region. Use it for custom breadcrumbs and other navigation elements instead of ParentLink.
const ContextBar: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
}
const ContextAreaActions: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return (
<Box sx={merge<BetterSystemStyleObject>({display: 'flex', flexDirection: 'row', alignItems: 'center'}, sx)}>
{children}
</Box>
)
}

// PageHeader.TitleArea: The main title area of the page. Visible on all viewports.
// PageHeader.TitleArea Sub Components: PageHeader.BackButton, PageHeader.LeadingVisual, PageHeader.Title, PageTitle.TrailingVisual, PageHeader.TrailingActions, PageHeader.Actions
// PageHeader.BackButton and PageHeader.TrailingAction are only visible on regular viewports therefore they come as hidden on narrow viewports and their visibility can be managed by their exposed `hidden` prop
// ---------------------------------------------------------------------
const TitleArea: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
return (
<Box sx={merge<BetterSystemStyleObject>({display: 'flex', flexDirection: 'row', alignItems: 'center'}, sx)}>
{children}
</Box>
)
}

export type BackButtonProps = {
hidden?: boolean | ResponsiveValue<boolean>
} & SxProp
const BackButton: React.FC<React.PropsWithChildren<BackButtonProps>> = ({
sx = {},
hidden = {
narrow: true,
regular: false,
wide: false
}
}) => {
// Default is hidden in narrow viewport but exposed as an API to allow consumers to override
const isHidden = useResponsiveValue(hidden, true)
return (
<IconButton
hidden={isHidden}
sx={merge<BetterSystemStyleObject>(
{
display: isHidden ? 'none' : 'flex'
},
sx
)}
icon={ChevronLeftIcon}
aria-label="Back"
variant="invisible"
/>
)
}
const LeadingVisual: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
}

export type TitleProps = {
variant?: 'subtitle' | 'medium' | 'large'
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
}
const Title: React.FC<React.PropsWithChildren<PageHeaderProps & TitleProps>> = ({
children,
sx = {},
variant = 'large',
as = 'h1'
}) => {
return (
// Not sure about h1 - check with design and a11y
<Heading
as={as}
sx={merge<BetterSystemStyleObject>(
{
fontSize: variant === 'large' ? 6 : variant === 'medium' ? 5 : 4
},
sx
)}
>
{children}
</Heading>
)
}
const TrailingVisual: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
}
const TrailingAction: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
}
const BackButton: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
}

const Actions: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
return <Box sx={merge<BetterSystemStyleObject>({display: 'flex', flexDirection: 'row'}, sx)}>{children}</Box>
}
const Summary: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children, sx = {}}) => {
return <Box sx={sx}>{children}</Box>
Expand All @@ -96,14 +186,16 @@ const LocalNav: React.FC<React.PropsWithChildren<PageHeaderProps>> = ({children,
}

export const PageHeader = Object.assign(Root, {
ContextNav,
ContextArea,
ParentLink,
ContextNavActions,
ContextBar,
ContextAreaActions,
TitleArea,
BackButton,
LeadingVisual,
Title,
TrailingVisual,
TrailingAction,
BackButton,
Actions,
Summary,
LocalNav
Expand Down

0 comments on commit dcddea7

Please sign in to comment.