From 3c6c64698e65d6bc5ab445a134617922d372ec9f Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 24 Aug 2022 23:24:36 +1000 Subject: [PATCH 01/25] Add PageHeader component --- src/PageHeader/PageHeader.stories.tsx | 60 ++++++++++++++ src/PageHeader/PageHeader.tsx | 110 ++++++++++++++++++++++++++ src/PageHeader/index.ts | 1 + 3 files changed, 171 insertions(+) create mode 100644 src/PageHeader/PageHeader.stories.tsx create mode 100644 src/PageHeader/PageHeader.tsx create mode 100644 src/PageHeader/index.ts diff --git a/src/PageHeader/PageHeader.stories.tsx b/src/PageHeader/PageHeader.stories.tsx new file mode 100644 index 00000000000..4c076e19c7b --- /dev/null +++ b/src/PageHeader/PageHeader.stories.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import {Meta, Story} from '@storybook/react' +import {Button, IconButton, Breadcrumbs} from '..' +import {EyeClosedIcon, SearchIcon, TriangleDownIcon} from '@primer/octicons-react' + +//import {Box, BranchName, Heading, Link, StateLabel, TabNav, Text} from '..' + +import {PageHeader} from './PageHeader' + +const meta: Meta = { + title: 'Layout/PageHeeader', + parameters: { + layout: 'fullscreen', + controls: {expanded: true} + }, + args: {} +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const Template: Story = args => ( + + + Code + + Branches + + + + + +) + +export const Default = Template.bind({}) + +export const FilesPage = () => ( + + + Files + + + + + + + + ... + primer + react + PageHeader + + index.ts + + + + +) + +export default meta diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx new file mode 100644 index 00000000000..2d473368aa1 --- /dev/null +++ b/src/PageHeader/PageHeader.tsx @@ -0,0 +1,110 @@ +import React from 'react' +import {Box} from '..' +import {useResponsiveValue, ResponsiveValue} from '../hooks/useResponsiveValue' +import {SxProp, merge, BetterSystemStyleObject} from '../sx' + +/* 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. +- Header rows should not wrap ever. be small? +- ParentTitle should have a back arrow +- Actions should all align right +- Button size for content actions must icon. Should have href. +- grid or flex? regions or areas? +- Backbutton, TrailingAction only on regular viewport +- Start writing some docs. +- Use 3 dots icon +- I don't think I need a context. There's no dependencies between rows. +- Example with localnav and underlinenav? +*/ + +const REGION_ORDER = { + contextNav: 0, + titleArea: 1, + description: 2, + localNav: 3 +} + +export type PageHeaderProps = SxProp + +const Root: React.FC> = ({children, sx = {}}) => { + const rootStyles = { + marginX: 'auto', + display: 'flex', + flexWrap: 'wrap' + } + return (rootStyles, sx)}>{children} +} + +export type ContextNavProps = { + hidden?: boolean | ResponsiveValue +} & SxProp + +const ContextNav: React.FC> = ({ + children, + sx = {}, + hidden = { + narrow: false, + regular: true, + wide: true + } +}) => { + const isHidden = useResponsiveValue(hidden, false) + const contentNavStyles = { + display: isHidden ? 'none' : 'flex', + flexDirection: 'column', + order: REGION_ORDER.contextNav, + // want same behaviour as PageLayout + flexBasis: 0, + flexGrow: 1, + flexShrink: 1, + minWidth: 1 // Hack to prevent overflowing content from pushing the pane region to the next line + } + return {children} +} +const ParentLink: React.FC> = ({children, sx = {}}) => { + return {children} +} +const ContextNavActions: React.FC> = ({children, sx = {}}) => { + return {children} +} +const TitleArea: React.FC> = ({children, sx = {}}) => { + return {children} +} +const LeadingVisual: React.FC> = ({children, sx = {}}) => { + return {children} +} +const TrailingVisual: React.FC> = ({children, sx = {}}) => { + return {children} +} +const TrailingAction: React.FC> = ({children, sx = {}}) => { + return {children} +} +const BackButton: React.FC> = ({children, sx = {}}) => { + return {children} +} +const Actions: React.FC> = ({children, sx = {}}) => { + return {children} +} +const Summary: React.FC> = ({children, sx = {}}) => { + return {children} +} + +const LocalNav: React.FC> = ({children, sx = {}}) => { + return {children} +} + +export const PageHeader = Object.assign(Root, { + ContextNav, + ParentLink, + ContextNavActions, + TitleArea, + LeadingVisual, + TrailingVisual, + TrailingAction, + BackButton, + Actions, + Summary, + LocalNav +}) diff --git a/src/PageHeader/index.ts b/src/PageHeader/index.ts new file mode 100644 index 00000000000..3e3ee9ffef7 --- /dev/null +++ b/src/PageHeader/index.ts @@ -0,0 +1 @@ +export * from './PageHeader' From 349748e30250d9f090dc50223a54c366057aea06 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Thu, 8 Sep 2022 17:18:40 +1000 Subject: [PATCH 02/25] Use styled system array props --- src/PageHeader/PageHeader.stories.tsx | 11 +++++++---- src/PageHeader/PageHeader.tsx | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/PageHeader/PageHeader.stories.tsx b/src/PageHeader/PageHeader.stories.tsx index 4c076e19c7b..610cc485fca 100644 --- a/src/PageHeader/PageHeader.stories.tsx +++ b/src/PageHeader/PageHeader.stories.tsx @@ -1,10 +1,8 @@ import React from 'react' import {Meta, Story} from '@storybook/react' -import {Button, IconButton, Breadcrumbs} from '..' +import {Box, Button, IconButton, Breadcrumbs} from '..' import {EyeClosedIcon, SearchIcon, TriangleDownIcon} from '@primer/octicons-react' -//import {Box, BranchName, Heading, Link, StateLabel, TabNav, Text} from '..' - import {PageHeader} from './PageHeader' const meta: Meta = { @@ -24,7 +22,12 @@ const Template: Story = args => ( Branches - + + + + + + diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index 2d473368aa1..a920f305622 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -61,7 +61,7 @@ const ContextNav: React.FC> = ({ flexShrink: 1, minWidth: 1 // Hack to prevent overflowing content from pushing the pane region to the next line } - return {children} + return (contentNavStyles, sx)}>{children} } const ParentLink: React.FC> = ({children, sx = {}}) => { return {children} From 2e8af503bbfcd0907cf1fde9e586c5023b9476e8 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Tue, 15 Nov 2022 06:19:52 +1000 Subject: [PATCH 03/25] wip --- src/PageHeader/PageHeader.stories.tsx | 55 ++++++---- src/PageHeader/PageHeader.tsx | 142 +++++++++++++++++++++----- 2 files changed, 150 insertions(+), 47 deletions(-) diff --git a/src/PageHeader/PageHeader.stories.tsx b/src/PageHeader/PageHeader.stories.tsx index 610cc485fca..eae4fe8455e 100644 --- a/src/PageHeader/PageHeader.stories.tsx +++ b/src/PageHeader/PageHeader.stories.tsx @@ -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} @@ -16,36 +17,46 @@ const meta: Meta = { // eslint-disable-next-line @typescript-eslint/no-unused-vars const Template: Story = args => ( - - - Code - - Branches - - - - - - - - - + + + Code + + + + + + + + Branches + + + + + + + + + + + ) -export const Default = Template.bind({}) +export const Playground = Template.bind({}) export const FilesPage = () => ( - + Files - + - - + + ... diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index a920f305622..33a75f7732f 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -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 @@ -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 +} & SxProp const Root: React.FC> = ({children, sx = {}}) => { const rootStyles = { marginX: 'auto', display: 'flex', + flexDirection: 'column', flexWrap: 'wrap' } return (rootStyles, sx)}>{children} } -export type ContextNavProps = { - hidden?: boolean | ResponsiveValue -} & 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> = ({ - children, - sx = {}, - hidden = { +const ContextArea: React.FC> = ({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, @@ -63,29 +70,112 @@ const ContextNav: React.FC> = ({ } return (contentNavStyles, sx)}>{children} } -const ParentLink: React.FC> = ({children, sx = {}}) => { - return {children} + +export type ParentLinkProps = { + href?: string +} & SxProp + +const ParentLink: React.FC> = ({children, sx = {}, href}) => { + return ( + <> + ({display: 'flex', alignItems: 'center'}, sx)} href={href}> + + {children} + + + ) } -const ContextNavActions: React.FC> = ({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> = ({children, sx = {}}) => { return {children} } +const ContextAreaActions: React.FC> = ({children, sx = {}}) => { + return ( + ({display: 'flex', flexDirection: 'row', alignItems: 'center'}, sx)}> + {children} + + ) +} + +// 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> = ({children, sx = {}}) => { - return {children} + return ( + ({display: 'flex', flexDirection: 'row', alignItems: 'center'}, sx)}> + {children} + + ) +} + +export type BackButtonProps = { + hidden?: boolean | ResponsiveValue +} & SxProp +const BackButton: React.FC> = ({ + 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 ( + ) -export const WebHooks = () => ( +export const Webhooks = () => ( - Repository Settings + Repository settings Webhooks - + @@ -87,12 +87,14 @@ export const WebHooks = () => ( ) export const PullRequestPage = () => ( - - + + Pull requests - - PageHeader Component initial layout explorations + + + PageHeader component initial layout explorations extra long pull request title + @@ -105,7 +107,7 @@ export const PullRequestPage = () => ( - + Open @@ -124,7 +126,7 @@ export const PullRequestPage = () => ( - + Conversation @@ -144,7 +146,7 @@ export const PullRequestPage = () => ( ) export const FilesPage = () => ( - + Files @@ -154,7 +156,7 @@ export const FilesPage = () => ( - + ... primer diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index 8634c51d372..7d6456d85b4 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -29,7 +29,7 @@ const Template: Story = args => ( - + From b5f5e00ed33a2734eba8b3e2c6abcf28b052ef86 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Mon, 28 Nov 2022 14:22:39 +1000 Subject: [PATCH 09/25] make ParentLink polymorphic and use as and aria-label --- src/PageHeader/PageHeader.tsx | 103 +++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index e7e930ccc66..c3f78e76128 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -5,6 +5,7 @@ import {SxProp, merge, BetterSystemStyleObject} from '../sx' import Heading from '../Heading' import {ArrowLeftIcon} from '@primer/octicons-react' import Link from '../Link' +import {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic' const REGION_ORDER = { ContextArea: 0, @@ -25,6 +26,7 @@ const onlyVisibleOnNarrowView = { wide: false } +// Default state for the `visible` prop when a sub component is visible on regular and wide viewport const visibleOnRegularView = { narrow: false, regular: true, @@ -33,13 +35,17 @@ const visibleOnRegularView = { // Root // ----------------------------------------------------------------------------- -export type PageHeaderProps = sharedPropTypes +export type PageHeaderProps = { + 'aria-label'?: React.AriaAttributes['aria-label'] + as?: React.ElementType +} & sharedPropTypes const Root: React.FC> = ({children, sx = {}}) => { const rootStyles = { display: 'flex', flexDirection: 'column', gap: '8px', + // 24px for wide and regular, 16px for narrow viewports padding: useResponsiveValue( { narrow: 3, @@ -48,14 +54,13 @@ const Root: React.FC> = ({children, sx }, false ) - // flexWrap: 'wrap' } return (rootStyles, sx)}>{children} } -// PageHeader.ContextArea : Only visible on narrow viewports by default to provide user context of where they are at their journey. `hidden` prop available -// to manage their custom visibility but consumers should be careful to hide this on narrow viewports. -// PageHeader.ContexArea Sub Components: PageHeader.ParentLink, PageHeader.ContextBar, PageHeader.ContextNavActions +// PageHeader.ContextArea : Only visible on narrow viewports by default to provide user context of where they are at their journey. `visible` prop available +// to manage their custom visibility but consumers should be careful if they choose to hide this on narrow viewports. +// PageHeader.ContextArea Sub Components: PageHeader.ParentLink, PageHeader.ContextBar, PageHeader.ContextAreaActions // --------------------------------------------------------------------- const ContextArea: React.FC> = ({ @@ -73,42 +78,60 @@ const ContextArea: React.FC> = ({ } return (contentNavStyles, sx)}>{children} } - -export type ParentLinkProps = { +// adopted from React.AnchorHTMLAttributes +type LinkProps = { + download?: string href?: string -} & PageHeaderProps - -// TODO: add `as` and `aria-label` props -const ParentLink: React.FC> = ({ - children, - sx = {}, - href, - visible = onlyVisibleOnNarrowView -}) => { - const isVisible = useResponsiveValue(visible, false) - return ( - <> - ( - { - display: isVisible ? 'flex' : 'none', - alignItems: 'center', - // min touch target size 44px (20 + (12x2)) - lineHeight: '20px', - paddingY: '12px', - gap: '8px' - }, - sx - )} - href={href} - > - - {children} - - - ) + hrefLang?: string + media?: string + ping?: string + rel?: string + target?: string + type?: string + referrerPolicy?: React.AnchorHTMLAttributes['referrerPolicy'] } +export type ParentLinkProps = PageHeaderProps & LinkProps + +const ParentLink = React.forwardRef( + ( + { + children, + sx = {}, + href, + 'aria-label': ariaLabel = `Back to ${children}`, + as = 'a', + visible = onlyVisibleOnNarrowView + }, + ref + ) => { + const isVisible = useResponsiveValue(visible, false) + return ( + <> + ( + { + display: isVisible ? 'flex' : 'none', + alignItems: 'center', + // min touch target size 44px (20 + (12x2)) + lineHeight: '20px', + paddingY: '12px', + gap: '8px' + }, + sx + )} + href={href} + > + + {children} + + + ) + } +) as PolymorphicForwardRefComponent<'a', ParentLinkProps> // ContextBar // Generic slot for any component above the title region. Use it for custom breadcrumbs and other navigation elements instead of ParentLink. @@ -152,7 +175,7 @@ const ContextAreaActions: React.FC> = ( // PageHeader.TitleArea: The main title area of the page. Visible on all viewports. // PageHeader.TitleArea Sub Components: PageHeader.LeadingAction, PageHeader.LeadingVisual, PageHeader.Title, PageTitle.TrailingVisual, PageHeader.TrailingAction, PageHeader.Actions -// PageHeader.LeadingAction 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 +// PageHeader.LeadingAction and PageHeader.TrailingAction are only visible on regular viewports therefore they come as visible on narrow viewports and their visibility can be managed by their exposed `visible` prop // --------------------------------------------------------------------- const TitleArea: React.FC> = ({children, sx = {}}) => { return ( From 5bc99a780a7b0b59ab06327ed9a30161d8cd24d4 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Mon, 28 Nov 2022 16:45:47 +1000 Subject: [PATCH 10/25] story examples and features --- src/PageHeader/PageHeader.tsx | 2 +- src/PageHeader/examples.stories.tsx | 115 +++++++++------ src/PageHeader/features.stories.tsx | 212 +++++++++++++++++++++++----- 3 files changed, 252 insertions(+), 77 deletions(-) diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index c3f78e76128..a6b387c42dc 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -292,7 +292,7 @@ const TrailingVisual: React.FC> = ({ const TrailingAction: React.FC> = ({ children, sx = {}, - visible = visibleOnRegularView + visible = onlyVisibleOnNarrowView }) => { const isVisible = useResponsiveValue(visible, true) return ({display: isVisible ? 'flex' : 'none'}, sx)}>{children} diff --git a/src/PageHeader/examples.stories.tsx b/src/PageHeader/examples.stories.tsx index f89a44209d1..02af8a22f53 100644 --- a/src/PageHeader/examples.stories.tsx +++ b/src/PageHeader/examples.stories.tsx @@ -1,9 +1,7 @@ import React from 'react' -import {Meta, Story} from '@storybook/react' +import {Meta} from '@storybook/react' import {Button, IconButton, Breadcrumbs, Link, Text, StateLabel, BranchName} from '..' -import Label from '../Label' import { - PencilIcon, KebabHorizontalIcon, GitBranchIcon, CodeIcon, @@ -27,50 +25,67 @@ const meta: Meta = { args: {} } -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const Template: Story = args => ( - - - Code - - - - - - - - - - - Branches - - - - - - - - - - +// See if there is an interest to take this into global params - - - - - - - -) +export const PrimerViewports = { + xsmall: { + name: 'Xsmall', + styles: { + width: '320px', + height: '100%' + } + }, + small: { + name: 'Small', + styles: { + width: '540px', + height: '100%' + } + }, + medium: { + name: 'Medium', + styles: { + width: '768px', + height: '100%' + } + }, + large: { + name: 'Large', + styles: { + width: '1012px', + height: '100%' + } + }, + xlarge: { + name: 'Xlarge', + styles: { + width: '1280px', + height: '100%' + } + }, + xxlarge: { + name: 'XXlarge', + styles: { + width: '1400px', + height: '100%' + } + } +} +const setViewportParamToNarrow = { + viewport: { + viewports: { + ...PrimerViewports + }, + defaultViewport: 'small' + } +} export const Webhooks = () => ( - + Repository settings - + Webhooks @@ -86,6 +101,12 @@ export const Webhooks = () => ( ) +export const WebhooksOnNarrowViewport = () => { + return +} + +WebhooksOnNarrowViewport.parameters = setViewportParamToNarrow + export const PullRequestPage = () => ( @@ -145,6 +166,12 @@ export const PullRequestPage = () => ( ) +export const PullRequestPageOnNarrowViewport = () => { + return +} + +PullRequestPageOnNarrowViewport.parameters = setViewportParamToNarrow + export const FilesPage = () => ( @@ -169,4 +196,10 @@ export const FilesPage = () => ( ) +export const FilesPageOnNarrowViewport = () => { + return +} + +FilesPageOnNarrowViewport.parameters = setViewportParamToNarrow + export default meta diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index 7d6456d85b4..ced0cb1e1fc 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -1,11 +1,10 @@ import React from 'react' import {Meta, Story} from '@storybook/react' -import {Button, IconButton} from '..' -import Label from '../Label' -import {PencilIcon, KebabHorizontalIcon, GitBranchIcon} from '@primer/octicons-react' +import {Button, IconButton, ActionMenu, ActionList} from '..' +import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon} from '@primer/octicons-react' +import {PrimerViewports} from './examples.stories' import {PageHeader} from './PageHeader' -import Hidden from '../Hidden' const meta: Meta = { title: 'Drafts/Components/PageHeader/Features', @@ -17,45 +16,188 @@ const meta: Meta = { } // eslint-disable-next-line @typescript-eslint/no-unused-vars -const Template: Story = args => ( - +// const Template: Story = args => ( +// +// +// +// {args.ParentLink} +// + +// +// {/* +// ... +// primer +// react +// src +// PageHeader +// PageHeader.tsx +// */} +// + +// +// +// +// +// +// +// +// {' '} +// +// +// {} +// +// +// {args.Title} +// +// +// +// +// +// +// +// +// +// +// + +// +// +// +// +// +// +// +// ) + +// export const TitleWithTrailingVisual = Template.bind({}) + +export const TitleWithTrailingAction = () => ( + - Code - - - - + Projects - - - - - - Branches - - - + + Primer Backlog + - + - - - - - - - - - + + + + + + + + + + + + + Rename Title + + + + + + Archive all cards + + + + + + Delete + + + + ) -export const TitleWithLeadingVisual = Template.bind({}) -export const TitleWithTrailingVisual = Template.bind({}) -export const TitleWithTrailingAction = Template.bind({}) +TitleWithTrailingAction.parameters = { + viewport: { + viewports: { + ...PrimerViewports + }, + defaultViewport: 'medium' + } +} + +export const TitleWithTrailingActionOnNarrowViewports = () => { + return +} + +TitleWithTrailingActionOnNarrowViewports.parameters = { + viewport: { + viewports: { + ...PrimerViewports + }, + defaultViewport: 'small' + } +} + +// TODO: Complete the below stories + +export const WithContextBar = TitleWithTrailingAction.bind({}) +export const WithParentLink = TitleWithTrailingAction.bind({}) +export const TitleWithLeadingVisual = TitleWithTrailingAction.bind({}) +export const TitleWithLeadingAction = TitleWithTrailingAction.bind({}) +export const ButtonActionOnNarrowViewports = TitleWithTrailingAction.bind({}) // New +export const ButtonActionOnRegularViewports = TitleWithTrailingAction.bind({}) // New Webhook export default meta From bdb05202e39932901c708ef98c57b39a77901b45 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Mon, 28 Nov 2022 16:48:19 +1000 Subject: [PATCH 11/25] add changeset and delete comment out code --- .changeset/blue-fireants-behave.md | 5 ++ src/PageHeader/features.stories.tsx | 107 +--------------------------- 2 files changed, 7 insertions(+), 105 deletions(-) create mode 100644 .changeset/blue-fireants-behave.md diff --git a/.changeset/blue-fireants-behave.md b/.changeset/blue-fireants-behave.md new file mode 100644 index 00000000000..7f763372b41 --- /dev/null +++ b/.changeset/blue-fireants-behave.md @@ -0,0 +1,5 @@ +--- +'@primer/react': minor +--- + +PageHeader: Draft implementation diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index ced0cb1e1fc..7380a72ab4b 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import {Meta, Story} from '@storybook/react' -import {Button, IconButton, ActionMenu, ActionList} from '..' +import {Meta} from '@storybook/react' +import {IconButton, ActionMenu, ActionList} from '..' import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon} from '@primer/octicons-react' import {PrimerViewports} from './examples.stories' @@ -15,109 +15,6 @@ const meta: Meta = { args: {} } -// eslint-disable-next-line @typescript-eslint/no-unused-vars -// const Template: Story = args => ( -// -// -// -// {args.ParentLink} -// - -// -// {/* -// ... -// primer -// react -// src -// PageHeader -// PageHeader.tsx -// */} -// - -// -// -// -// -// -// -// -// {' '} -// -// -// {} -// -// -// {args.Title} -// -// -// -// -// -// -// -// -// -// -// - -// -// -// -// -// -// -// -// ) - -// export const TitleWithTrailingVisual = Template.bind({}) - export const TitleWithTrailingAction = () => ( From 65425840690567aa5471e376548b95e1f6abede3 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Mon, 28 Nov 2022 16:58:28 +1000 Subject: [PATCH 12/25] do not export viewports as a story --- src/PageHeader/PageHeader.tsx | 8 +++-- src/PageHeader/examples.stories.tsx | 2 +- src/PageHeader/features.stories.tsx | 46 ++++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index a6b387c42dc..0c0575555ce 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -177,10 +177,14 @@ const ContextAreaActions: React.FC> = ( // PageHeader.TitleArea Sub Components: PageHeader.LeadingAction, PageHeader.LeadingVisual, PageHeader.Title, PageTitle.TrailingVisual, PageHeader.TrailingAction, PageHeader.Actions // PageHeader.LeadingAction and PageHeader.TrailingAction are only visible on regular viewports therefore they come as visible on narrow viewports and their visibility can be managed by their exposed `visible` prop // --------------------------------------------------------------------- -const TitleArea: React.FC> = ({children, sx = {}}) => { +const TitleArea: React.FC> = ({children, sx = {}, visible = true}) => { + const isVisible = useResponsiveValue(visible, false) return ( ({display: 'flex', flexDirection: 'row', alignItems: 'center', gap: '8px'}, sx)} + sx={merge( + {display: isVisible ? 'flex' : 'none', flexDirection: 'row', alignItems: 'center', gap: '8px'}, + sx + )} > {children} diff --git a/src/PageHeader/examples.stories.tsx b/src/PageHeader/examples.stories.tsx index 02af8a22f53..439f507022a 100644 --- a/src/PageHeader/examples.stories.tsx +++ b/src/PageHeader/examples.stories.tsx @@ -27,7 +27,7 @@ const meta: Meta = { // See if there is an interest to take this into global params -export const PrimerViewports = { +const PrimerViewports = { xsmall: { name: 'Xsmall', styles: { diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index 7380a72ab4b..b2012e5b230 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -2,7 +2,6 @@ import React from 'react' import {Meta} from '@storybook/react' import {IconButton, ActionMenu, ActionList} from '..' import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon} from '@primer/octicons-react' -import {PrimerViewports} from './examples.stories' import {PageHeader} from './PageHeader' @@ -15,6 +14,51 @@ const meta: Meta = { args: {} } +const PrimerViewports = { + xsmall: { + name: 'Xsmall', + styles: { + width: '320px', + height: '100%' + } + }, + small: { + name: 'Small', + styles: { + width: '540px', + height: '100%' + } + }, + medium: { + name: 'Medium', + styles: { + width: '768px', + height: '100%' + } + }, + large: { + name: 'Large', + styles: { + width: '1012px', + height: '100%' + } + }, + xlarge: { + name: 'Xlarge', + styles: { + width: '1280px', + height: '100%' + } + }, + xxlarge: { + name: 'XXlarge', + styles: { + width: '1400px', + height: '100%' + } + } +} + export const TitleWithTrailingAction = () => ( From 70d387f8c58795a0694773c7144793203ac2af50 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Fri, 2 Dec 2022 14:44:13 +1000 Subject: [PATCH 13/25] rename prop visible->hidden --- src/PageHeader/PageHeader.stories.tsx | 65 +++------------ src/PageHeader/PageHeader.tsx | 112 +++++++++++--------------- src/PageHeader/examples.stories.tsx | 2 +- src/PageHeader/features.stories.tsx | 8 +- 4 files changed, 66 insertions(+), 121 deletions(-) diff --git a/src/PageHeader/PageHeader.stories.tsx b/src/PageHeader/PageHeader.stories.tsx index d02a3f1d14c..483c212a70d 100644 --- a/src/PageHeader/PageHeader.stories.tsx +++ b/src/PageHeader/PageHeader.stories.tsx @@ -269,19 +269,12 @@ const meta: Meta = { const Template: Story = args => ( - - + - + - - {} - + ( regular: args['Title.variant'], wide: args['Title.variant'] }} - visible={args.hasTitle} + hidden={!args.hasTitle} > {args.Title} - + - + - + - + - + - + Conversation diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index b2012e5b230..947e10ee48b 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -71,10 +71,10 @@ export const TitleWithTrailingAction = () => ( - - - - + + + + ) export const Playground = Template.bind({}) diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index 26af657a511..bc6b1d9fdd7 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -43,6 +43,7 @@ const Root: React.FC> = ({children, sx const rootStyles = { display: 'flex', flexDirection: 'column', + // TODO: We used hard-coded values for the spacing and font size in this component. Update them to use new design tokens when they are ready to use. gap: '0.5rem', } return ( @@ -72,18 +73,10 @@ const ContextArea: React.FC> = ({ } return (contentNavStyles, sx)}>{children} } -// adopted from React.AnchorHTMLAttributes -type LinkProps = { - download?: string - href?: string - hrefLang?: string - media?: string - ping?: string - rel?: string - target?: string - type?: string - referrerPolicy?: React.AnchorHTMLAttributes['referrerPolicy'] -} +type LinkProps = Pick< + React.AnchorHTMLAttributes, + 'download' | 'href' | 'hrefLang' | 'media' | 'ping' | 'rel' | 'target' | 'type' | 'referrerPolicy' +> export type ParentLinkProps = PageHeaderProps & LinkProps const ParentLink = React.forwardRef( @@ -165,21 +158,45 @@ const ContextAreaActions: React.FC> = ( ) } +const MEDIUM_TITLE_HEIGHT = '2rem' +const LARGE_TITLE_HEIGHT = '3rem' + +const TitleAreaContext = React.createContext<{ + titleVariant: 'subtitle' | 'medium' | 'large' + titleAreaHeight?: string | number +}>({ + titleVariant: 'medium', + titleAreaHeight: MEDIUM_TITLE_HEIGHT, +}) + +type TitleAreaProps = { + variant?: 'subtitle' | 'medium' | 'large' | ResponsiveValue<'subtitle' | 'medium' | 'large'> +} & PageHeaderProps // PageHeader.TitleArea: The main title area of the page. Visible on all viewports. // PageHeader.TitleArea Sub Components: PageHeader.LeadingAction, PageHeader.LeadingVisual, PageHeader.Title, PageTitle.TrailingVisual, PageHeader.TrailingAction, PageHeader.Actions // PageHeader.LeadingAction and PageHeader.TrailingAction are only visible on regular viewports therefore they come as visible on narrow viewports and their visibility can be managed by their exposed `visible` prop // --------------------------------------------------------------------- -const TitleArea: React.FC> = ({children, sx = {}, hidden = false}) => { + +const TitleArea: React.FC> = ({ + children, + sx = {}, + hidden = false, + variant = 'medium', +}) => { const isHidden = useResponsiveValue(hidden, false) + const currentVariant = useResponsiveValue(variant, 'medium') + const height = currentVariant === 'large' ? LARGE_TITLE_HEIGHT : MEDIUM_TITLE_HEIGHT return ( - ( - {gap: '0.5rem', display: isHidden ? 'none' : 'flex', flexDirection: 'row', alignItems: 'flex-start'}, - sx, - )} - > - {children} - + + ( + {gap: '0.5rem', display: isHidden ? 'none' : 'flex', flexDirection: 'row', alignItems: 'flex-start'}, + sx, + )} + > + {children} + + ) } @@ -189,10 +206,12 @@ const LeadingAction: React.FC> = ({ hidden = hiddenOnNarrow, }) => { const isHidden = useResponsiveValue(hidden, false) + const {titleAreaHeight} = React.useContext(TitleAreaContext) + return ( ( - {display: isHidden ? 'none' : 'flex', alignItems: 'center', height: '2rem'}, + {display: isHidden ? 'none' : 'flex', alignItems: 'center', height: titleAreaHeight}, sx, )} > @@ -203,13 +222,14 @@ const LeadingAction: React.FC> = ({ const LeadingVisual: React.FC> = ({children, sx = {}, hidden = false}) => { const isHidden = useResponsiveValue(hidden, false) + const {titleAreaHeight} = React.useContext(TitleAreaContext) return ( ( { display: isHidden ? 'none' : 'flex', alignItems: 'center', - height: '2rem', + height: titleAreaHeight, }, sx, )} @@ -220,20 +240,13 @@ const LeadingVisual: React.FC> = ({chil } export type TitleProps = { - variant?: 'subtitle' | 'medium' | 'large' | ResponsiveValue<'subtitle' | 'medium' | 'large'> // Check if we need responsive values for heading is so should we update as prop's type for Heading component? as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' } & PageHeaderProps -const Title: React.FC> = ({ - children, - sx = {}, - variant = 'medium', - hidden = false, - as = 'h3', -}) => { - const currentVariant = useResponsiveValue(variant, 'medium') +const Title: React.FC> = ({children, sx = {}, hidden = false, as = 'h3'}) => { const isHidden = useResponsiveValue(hidden, false) + const {titleVariant} = React.useContext(TitleAreaContext) return ( > = ({ large: '2rem', medium: '1.25rem', subtitle: '1.25rem', - }[currentVariant], + }[titleVariant], lineHeight: { large: 1.5, // calc(48/32) medium: 1.6, // calc(32/20) subtitle: 1.6, // calc(32/20) - }[currentVariant], + }[titleVariant], fontWeight: { large: '400', medium: '600', - subtitle: '600', - }[currentVariant], + subtitle: '400', + }[titleVariant], display: isHidden ? 'none' : 'flex', }, sx, @@ -265,13 +278,15 @@ const Title: React.FC> = ({ } const TrailingVisual: React.FC> = ({children, sx = {}, hidden = false}) => { const isHidden = useResponsiveValue(hidden, false) + const {titleAreaHeight} = React.useContext(TitleAreaContext) + return ( ( { display: isHidden ? 'none' : 'flex', alignItems: 'center', - height: '2rem', + height: titleAreaHeight, }, sx, )} @@ -287,10 +302,12 @@ const TrailingAction: React.FC> = ({ hidden = hiddenOnNarrow, }) => { const isHidden = useResponsiveValue(hidden, false) + const {titleAreaHeight} = React.useContext(TitleAreaContext) + return ( ( - {display: isHidden ? 'none' : 'flex', alignItems: 'center', height: '2rem'}, + {display: isHidden ? 'none' : 'flex', alignItems: 'center', height: titleAreaHeight}, sx, )} > @@ -301,6 +318,7 @@ const TrailingAction: React.FC> = ({ const Actions: React.FC> = ({children, sx = {}, hidden = false}) => { const isHidden = useResponsiveValue(hidden, false) + const {titleAreaHeight} = React.useContext(TitleAreaContext) return ( ( @@ -310,7 +328,7 @@ const Actions: React.FC> = ({children, gap: '0.5rem', flexGrow: '1', justifyContent: 'right', - height: '2rem', + height: titleAreaHeight, alignItems: 'center', }, sx, diff --git a/src/PageHeader/examples.stories.tsx b/src/PageHeader/examples.stories.tsx index 31fa5251e40..f84411de157 100644 --- a/src/PageHeader/examples.stories.tsx +++ b/src/PageHeader/examples.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' import {Meta} from '@storybook/react' -import {Button, IconButton, Breadcrumbs, Link, Text, StateLabel, BranchName} from '..' +import {Button, IconButton, Breadcrumbs, Link, Text, StateLabel, BranchName, Box} from '..' import { KebabHorizontalIcon, GitBranchIcon, @@ -81,24 +81,26 @@ const setViewportParamToNarrow = { }, } export const Webhooks = () => ( - - - Repository settings - - - Webhooks - - - - - - - - - - - - + + + + Repository settings + + + Webhooks + + + + + + + + + + + + + ) export const WebhooksOnNarrowViewport = () => { @@ -108,62 +110,64 @@ export const WebhooksOnNarrowViewport = () => { WebhooksOnNarrowViewport.parameters = setViewportParamToNarrow export const PullRequestPage = () => ( - - - Pull requests - - - - PageHeader component initial layout explorations extra long pull request title - - - - - {/* Pop up actions */} - - + + + + Pull requests + + + + PageHeader component initial layout explorations extra long pull request title + + + + + {/* Pop up actions */} + + + + + + + + + + Open - - + + + broccolinisoup + {' '} + wants to merge 3 commits into main from{' '} + broccolinisoup/switch-to-new-underlineNav + + + + + main + + page-header-initial + - - - - Open - - - - broccolinisoup - {' '} - wants to merge 3 commits into main from{' '} - broccolinisoup/switch-to-new-underlineNav - - - - - main - - page-header-initial - - - - - - - Conversation - - - Commits - - - Checks - - - Files Changes - - - - + + + + + Conversation + + + Commits + + + Checks + + + Files Changes + + + + + ) export const PullRequestPageOnNarrowViewport = () => { @@ -173,27 +177,29 @@ export const PullRequestPageOnNarrowViewport = () => { PullRequestPageOnNarrowViewport.parameters = setViewportParamToNarrow export const FilesPage = () => ( - - - Files - - - - - - - - ... - primer - react - src - PageHeader - PageHeader.tsx - - - + + + + Files + + + + + + + + ... + primer + react + src + PageHeader + PageHeader.tsx + + + + ) export const FilesPageOnNarrowViewport = () => { diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index 4d01b17f018..fde9d506ffe 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' import {Meta} from '@storybook/react' import {IconButton, ActionMenu, ActionList} from '..' -import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon} from '@primer/octicons-react' +import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon, Box} from '@primer/octicons-react' import {PageHeader} from './PageHeader' @@ -60,54 +60,56 @@ const PrimerViewports = { } export const TitleWithTrailingAction = () => ( - - - Projects - - - Primer Backlog + + + + Projects + + + Primer Backlog - - - - - + + + + + + + Rename Title + + + + + + Archive all cards + + + + + + Delete + + + + + + + + ) TitleWithTrailingAction.parameters = { From 65834a7769a0865aeed20ce1680ccca223ee3754 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Thu, 8 Dec 2022 17:41:59 +1000 Subject: [PATCH 22/25] remove todo for feature stories --- src/PageHeader/features.stories.tsx | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index fde9d506ffe..9e465c20423 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -134,13 +134,4 @@ TitleWithTrailingActionOnNarrowViewports.parameters = { }, } -// TODO: Complete the below stories - -export const WithContextBar = TitleWithTrailingAction.bind({}) -export const WithParentLink = TitleWithTrailingAction.bind({}) -export const TitleWithLeadingVisual = TitleWithTrailingAction.bind({}) -export const TitleWithLeadingAction = TitleWithTrailingAction.bind({}) -export const ButtonActionOnNarrowViewports = TitleWithTrailingAction.bind({}) // New -export const ButtonActionOnRegularViewports = TitleWithTrailingAction.bind({}) // New Webhook - export default meta From d855974ccf1e8a9e03aff138bcdbd2abe701af69 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Thu, 8 Dec 2022 17:46:09 +1000 Subject: [PATCH 23/25] move Box --- src/PageHeader/features.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PageHeader/features.stories.tsx b/src/PageHeader/features.stories.tsx index 9e465c20423..ccd9c89a351 100644 --- a/src/PageHeader/features.stories.tsx +++ b/src/PageHeader/features.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' import {Meta} from '@storybook/react' -import {IconButton, ActionMenu, ActionList} from '..' -import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon, Box} from '@primer/octicons-react' +import {IconButton, ActionMenu, ActionList, Box} from '..' +import {PencilIcon, KebabHorizontalIcon, ArchiveIcon, TrashIcon} from '@primer/octicons-react' import {PageHeader} from './PageHeader' From 66293159d25aca21a07a51a9efbdb18325d43209 Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Fri, 9 Dec 2022 08:29:27 +1000 Subject: [PATCH 24/25] remove line-height for min touch size and add a comment --- src/PageHeader/PageHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PageHeader/PageHeader.tsx b/src/PageHeader/PageHeader.tsx index bc6b1d9fdd7..4fdc2d705b6 100644 --- a/src/PageHeader/PageHeader.tsx +++ b/src/PageHeader/PageHeader.tsx @@ -103,7 +103,6 @@ const ParentLink = React.forwardRef( { display: isHidden ? 'none' : 'flex', alignItems: 'center', - lineHeight: '2.75rem', // min touch target size 44px (16*2.75) gap: '0.5rem', }, sx, @@ -257,6 +256,7 @@ const Title: React.FC> = ({children, sx = {} medium: '1.25rem', subtitle: '1.25rem', }[titleVariant], + // line-height is calculated with calc(height/font-size) and the below numbers are from @primer/primitives lineHeight: { large: 1.5, // calc(48/32) medium: 1.6, // calc(32/20) From 4e7775822275cebfc0cc44c99aa9b70640e1dc5b Mon Sep 17 00:00:00 2001 From: Armagan Ersoz Date: Fri, 9 Dec 2022 11:21:02 +1000 Subject: [PATCH 25/25] add unit tests and snapshot --- src/PageHeader/PageHeader.test.tsx | 159 ++++++++++++++++ .../__snapshots__/PageHeader.test.tsx.snap | 175 ++++++++++++++++++ 2 files changed, 334 insertions(+) create mode 100644 src/PageHeader/PageHeader.test.tsx create mode 100644 src/PageHeader/__snapshots__/PageHeader.test.tsx.snap diff --git a/src/PageHeader/PageHeader.test.tsx b/src/PageHeader/PageHeader.test.tsx new file mode 100644 index 00000000000..81d726637a2 --- /dev/null +++ b/src/PageHeader/PageHeader.test.tsx @@ -0,0 +1,159 @@ +import React from 'react' +import '@testing-library/jest-dom/extend-expect' +import {render} from '@testing-library/react' +import {PageHeader} from '.' +import MatchMediaMock from 'jest-matchmedia-mock' +import {behavesAsComponent, checkExports, checkStoriesForAxeViolations} from '../utils/testing' +import {act} from 'react-test-renderer' +import {viewportRanges} from '../hooks/useResponsiveValue' +import {IconButton} from '../Button' +import {ChevronLeftIcon, GitBranchIcon, PencilIcon, SidebarExpandIcon} from '@primer/octicons-react' + +let matchmedia: MatchMediaMock +describe('PageHeader', () => { + beforeAll(() => { + matchmedia = new MatchMediaMock() + }) + afterAll(() => { + matchmedia.clear() + }) + behavesAsComponent({ + Component: PageHeader, + options: {skipAs: true, skipSx: true}, + toRender: () => ( + + + + + + + ), + }) + checkExports('PageHeader', { + default: undefined, + PageHeader, + }) + it('renders default layout', () => { + const {container} = render( + + ContextArea + TitleArea + Description + Navigation + , + ) + expect(container).toMatchSnapshot() + }) + it('does not render ContextArea in wide viewport as default', () => { + act(() => { + matchmedia.useMediaQuery(viewportRanges.wide) + }) + + const {getByText} = render( + + ContextArea + TitleArea + Description + Navigation + , + ) + expect(getByText('ContextArea')).not.toBeVisible() + }) + it('respects the hidden prop of ContextArea and renders accordingly', () => { + act(() => { + matchmedia.useMediaQuery(viewportRanges.regular) + }) + + const {getByText} = render( + + + TitleArea + Description + Navigation + , + ) + expect(getByText('ContextArea')).toBeVisible() + }) + it('respects default visibility of LeadingAction and TrailingAction and renders accordingly', () => { + act(() => { + matchmedia.useMediaQuery(viewportRanges.narrow) + }) + const {getByTestId} = render( + + ContextArea + + + + + Title + + + + + + + , + ) + expect(getByTestId('LeadingAction')).not.toBeVisible() + expect(getByTestId('TrailingAction')).not.toBeVisible() + }) + it('respects the title variant prop', () => { + act(() => { + matchmedia.useMediaQuery(viewportRanges.narrow) + }) + const {getByText} = render( + + ContextArea + + Title + + , + ) + expect(getByText('Title')).toHaveStyle('font-size: 2rem') + }) + it("respects the title variant prop and updates the children components' container height accordingly", () => { + act(() => { + matchmedia.useMediaQuery(viewportRanges.narrow) + }) + const {getByText} = render( + + ContextArea + + + Leading Action + + + + Leading Visual + + + Title + + Trailing Action + + + + Trailing Visual + + + + , + ) + + expect(getByText('Leading Visual')).toHaveStyle('height: 3rem') + expect(getByText('Trailing Visual')).toHaveStyle('height: 3rem') + expect(getByText('Leading Action')).toHaveStyle('height: 3rem') + expect(getByText('Trailing Action')).toHaveStyle('height: 3rem') + // add actions here + }) +}) + +checkStoriesForAxeViolations('examples', '../PageHeader/') diff --git a/src/PageHeader/__snapshots__/PageHeader.test.tsx.snap b/src/PageHeader/__snapshots__/PageHeader.test.tsx.snap new file mode 100644 index 00000000000..c21d48ac2da --- /dev/null +++ b/src/PageHeader/__snapshots__/PageHeader.test.tsx.snap @@ -0,0 +1,175 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PageHeader renders consistently 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: 0.5rem; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 0.5rem; + -webkit-order: 0; + -ms-flex-order: 0; + order: 0; +} + +.c2 { + gap: 0.5rem; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 0.5rem; +} + +.c4 { + display: block; +} + +
+
+
+
+
+
+`; + +exports[`PageHeader renders default layout 1`] = ` +.c0 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; + gap: 0.5rem; +} + +.c1 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 0.5rem; + -webkit-order: 0; + -ms-flex-order: 0; + order: 0; +} + +.c2 { + gap: 0.5rem; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; +} + +.c3 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 0.5rem; +} + +.c4 { + display: block; +} + +
+
+
+ ContextArea +
+
+ TitleArea +
+
+ Description +
+
+ Navigation +
+
+
+`;