Skip to content

Commit

Permalink
feat: #153 v5 top bar update docs (#240)
Browse files Browse the repository at this point in the history
* fix: update default top-bar popover y offset

* feat: update docs to include different viewport
  • Loading branch information
nurm717123 authored Dec 13, 2024
1 parent 76eb8dc commit 9066a35
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 556 deletions.
10 changes: 5 additions & 5 deletions src/components/top-bar/styles.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { styled } from '@linaria/react'
import { isDesktop, isDesktopOrBelow, isTablet, isTabletOrBelow } from '../../styles/media'
import { isBelowWideScreen, isTablet, isBelowDesktop, isWideScreen } from '../../styles/media'
import { ElButtonGroup } from '../button-group'
import { css } from '@linaria/core'

Expand Down Expand Up @@ -34,7 +34,7 @@ export const ElTopBar = styled.div`
border-bottom: var(--border-default, 1px) solid var(--outline-default, #e5e9ed);
background: var(--fill-white, #fff);
${isDesktopOrBelow} {
${isBelowWideScreen} {
padding: var(--spacing-2, 8px) var(--spacing-4, 16px);
${ElTopBarLogo} {
Expand All @@ -46,7 +46,7 @@ export const ElTopBar = styled.div`
}
}
${isTabletOrBelow} {
${isBelowDesktop} {
${ElTopBarProfile} {
display: none;
}
Expand All @@ -66,13 +66,13 @@ export const ElTopBarMobileNav = styled.div`
display: inline-block;
padding-right: var(--spacing-2, 8px);
${isDesktop} {
${isWideScreen} {
display: none;
}
`

export const elTopBarMenuPopover = css`
// To adjust the menu popover's Y offset so it appears below the top bar instead of directly below the button.
// The "important" rule is used to override the Menu's auto-anchor yOffset.
top: 44px !important;
top: var(--spacing-10) !important;
`
19 changes: 10 additions & 9 deletions src/components/top-bar/top-bar.mdx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { Canvas, Controls, Meta } from '@storybook/blocks'
import { RenderHtmlMarkup } from '../../storybook/render-html-markup'
import * as TopBarStories from './top-bar.stories'
import { GuidelinesImage } from '../../storybook/figma'

<Meta of={TopBarStories} />

<GuidelinesImage name="TopBar" />
# Top bar

## Styles Only Usage
Top bar component is part of the element's navigation, It is composed of several components to easily create a top navigation structure.

To display `TopBar` with vanilla usage, you will need to compose your component using `.el-top-bar, .el-top-bar-main-nav, .el-top-bar-search, .el-top-bar-secondary-nav, and .el-top-bar-profile` classes as the example below.
## Default

<Canvas of={TopBarStories.StylesOnlyUsage} />
To display `TopBar` with vanilla usage, you will need to compose your component using `.el-top-bar, .el-top-bar-main-nav, .el-top-bar-search, .el-top-bar-secondary-nav, and .el-top-bar-profile` classes or respective component for each class for React usage as the example below.

<RenderHtmlMarkup of={TopBarStories.StylesOnlyUsage} />
<Canvas of={TopBarStories.Default} />

<RenderHtmlMarkup of={TopBarStories.Default} />

## React Usage

In React version, you will need to use `TopBar` compound component to compose the `TopBar` as shown below.
In the React usage, you can utilize `CSSContainerQuery` component to conditionally render the Main navigation section based on the viewport size, as demonstrated below (on wider screens all buttons should visible).

<Canvas of={TopBarStories.ReactUsage} />
<Canvas of={TopBarStories.ResponsiveMainNav} />

<RenderHtmlMarkup of={TopBarStories.ReactUsage} />
<RenderHtmlMarkup of={TopBarStories.ResponsiveMainNav} />
248 changes: 153 additions & 95 deletions src/components/top-bar/top-bar.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,124 +1,127 @@
import { figmaDesignUrls } from '#src/storybook/figma/index'
import type { Meta, StoryObj } from '@storybook/react'
import { ElAvatar } from '../avatar'
import { AvatarButton, ElAvatarButton } from '../avatar-button'
import { AvatarButton } from '../avatar-button'
import { elIcon } from '../button'
import { CSSContainerQuery } from '../container-query/container-query'
import { Icon } from '../icon'
import { ElMenu, ElMenuItemAnchor, ElMenuItemButton, ElMenuList, ElMenuPopover, Menu } from '../menu'
import { ElNavDropdownButton, NavDropdownButton } from '../nav-dropdown-button'
import { ElButtonNavIconItem, NavIconItem } from '../nav-icon-item'
import { ElNavItemAnchor, ElNavItemLabelContainer, NavItem } from '../nav-item'
import { Menu } from '../menu'
import { NavDropdownButton } from '../nav-dropdown-button'
import { NavIconItem } from '../nav-icon-item'
import { NavItem } from '../nav-item'
import { NavSearchButton } from '../nav-search-button/nav-search-button'
import {
ElNavSearchButton,
ElNavSearchButtonContainer,
ElNavSearchButtonIcon,
ElNavSearchButtonPlaceholder,
ElNavSearchButtonShortcutText,
} from '../nav-search-button/styles'
import { ReapitLogo } from '../reapit-logo'
import reapitLogoIconUrl from '../reapit-logo/icons/brand-reapit.svg'
import MenuIcon from './icons/menu-icon.svg?react'
import {
ElTopBar,
ElTopBarLogo,
ElTopBarMainNav,
ElTopBarMobileNav,
ElTopBarProfile,
ElTopBarSearch,
ElTopBarSecondaryNav,
elTopBarMenuPopover,
} from './styles'
import { elTopBarMenuPopover } from './styles'
import { TopBar } from './top-bar'
import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'

const viewports: typeof INITIAL_VIEWPORTS = {
superWideScreen: {
name: 'Super Wide Screen',
type: 'desktop',
styles: {
width: '1920px',
height: '1500px',
},
},
wideScreen: {
name: 'Wide Screen',
type: 'desktop',
styles: {
width: '1440px',
height: '900px',
},
},
desktop: {
name: 'Desktop',
type: 'desktop',
styles: {
width: '1024px',
height: '900px',
},
},
ipad11p: INITIAL_VIEWPORTS.ipad11p,
iphone14: INITIAL_VIEWPORTS.iphone14,
}

export default {
title: 'Components/Top bar',
component: TopBar,
parameters: {
viewport: { defaultViewport: 'responsive', viewports },
},
} as Meta<typeof TopBar>

export const StylesOnlyUsage: StoryObj<typeof TopBar> = {
type Story = StoryObj<typeof TopBar>

export const Default: Story = {
// NOTE: this version is without `CSSContainerQuery` so the non react user doesn't see it in the docs
render: () => {
return (
<nav>
<ElTopBar>
<ElTopBarLogo href="/">
<img src={reapitLogoIconUrl} />
</ElTopBarLogo>
<ElTopBarMainNav>
<ElNavItemAnchor href="#">
<ElNavItemLabelContainer>Button 1</ElNavItemLabelContainer>
</ElNavItemAnchor>
<ElNavItemAnchor href="#">
<ElNavItemLabelContainer>Button 2</ElNavItemLabelContainer>
</ElNavItemAnchor>
<ElMenu>
<ElNavDropdownButton aria-haspopup="true" aria-expanded="true" role="button" type="button">
More
<Icon icon={'chevronUp'} intent="default" fontSize="1rem" />
</ElNavDropdownButton>
<ElMenuPopover className={elTopBarMenuPopover}>
<ElMenuList>
<ElMenuItemButton role="menuitem">Button 3</ElMenuItemButton>
<ElMenuItemButton role="menuitem">Button 4</ElMenuItemButton>
<ElMenuItemAnchor href="/#" role="menuitem">
Button 5
</ElMenuItemAnchor>
</ElMenuList>
</ElMenuPopover>
</ElMenu>
</ElTopBarMainNav>

<ElTopBarSearch>
<ElNavSearchButtonContainer>
<ElButtonNavIconItem>
<Icon icon="search" />
</ElButtonNavIconItem>
<ElNavSearchButton>
<ElNavSearchButtonIcon aria-hidden="true" />
<ElNavSearchButtonPlaceholder>Search</ElNavSearchButtonPlaceholder>
<ElNavSearchButtonShortcutText>Ctrl + K</ElNavSearchButtonShortcutText>
</ElNavSearchButton>
</ElNavSearchButtonContainer>
</ElTopBarSearch>

<ElTopBarSecondaryNav>
<ElButtonNavIconItem>
<Icon icon="star" aria-label="secondary nav item example" />
</ElButtonNavIconItem>
<ElButtonNavIconItem>
<Icon icon="star" aria-label="secondary nav item example" />
</ElButtonNavIconItem>
<ElButtonNavIconItem>
<Icon icon="star" aria-label="secondary nav item example" />
</ElButtonNavIconItem>
</ElTopBarSecondaryNav>
<TopBar>
<TopBar.Logo href="/">
<ReapitLogo />
</TopBar.Logo>
<TopBar.MainNav>
<NavItem href="/">Button 1</NavItem>
<NavItem href="/">Button 2</NavItem>
<Menu>
<Menu.Trigger>
{({ getTriggerProps, isOpen }) => (
<NavDropdownButton {...getTriggerProps()} isOpen={isOpen}>
More
</NavDropdownButton>
)}
</Menu.Trigger>
<Menu.Popover className={elTopBarMenuPopover}>
<Menu.List>
<Menu.Item href="/">Button 3</Menu.Item>
<Menu.Item href="/">Button 4</Menu.Item>
<Menu.Item href="/">Button 5</Menu.Item>
</Menu.List>
</Menu.Popover>
</Menu>
</TopBar.MainNav>
<TopBar.Search>
<NavSearchButton />
</TopBar.Search>

<ElTopBarMobileNav>
<ElButtonNavIconItem>
<MenuIcon className={elIcon} />
</ElButtonNavIconItem>
</ElTopBarMobileNav>
<TopBar.SecondaryNav>
<NavIconItem aria-label="secondary nav item example" icon={<Icon icon="star" />} />
<NavIconItem aria-label="secondary nav item example" icon={<Icon icon="star" />} />
<NavIconItem aria-label="secondary nav item example" icon={<Icon icon="star" />} />
</TopBar.SecondaryNav>
<TopBar.MobileNav>
<NavIconItem aria-label="mobile secondary nav trigger" icon={<MenuIcon className={elIcon} />} />
</TopBar.MobileNav>

<ElTopBarProfile>
<ElAvatarButton aria-label="user navigation menu">
<ElAvatar data-size="small" data-shape="circle" data-colour="purple">
AD
</ElAvatar>
</ElAvatarButton>
</ElTopBarProfile>
</ElTopBar>
</nav>
<TopBar.Profile>
<Menu data-alignment="right">
<Menu.Trigger>
{({ getTriggerProps, isOpen }) => <AvatarButton {...getTriggerProps()} isOpen={isOpen} label="AD" />}
</Menu.Trigger>
<Menu.Popover className={elTopBarMenuPopover}>
<Menu.List>
<Menu.Item href="/">User menu 1</Menu.Item>
<Menu.Item href="/">User menu 2</Menu.Item>
<Menu.Item href="/">User menu 3</Menu.Item>
</Menu.List>
</Menu.Popover>
</Menu>
</TopBar.Profile>
</TopBar>
)
},
parameters: {
design: {
type: 'figma',
url: figmaDesignUrls.appBar,
allowFullscreen: true,
},
},
}
export const ReactUsage: StoryObj<typeof TopBar> = {

export const ResponsiveMainNav: Story = {
render: () => {
return (
<TopBar>
Expand Down Expand Up @@ -166,12 +169,22 @@ export const ReactUsage: StoryObj<typeof TopBar> = {
</TopBar.MobileNav>

<TopBar.Profile>
<AvatarButton label="AD" />
<Menu data-alignment="right">
<Menu.Trigger>
{({ getTriggerProps, isOpen }) => <AvatarButton {...getTriggerProps()} isOpen={isOpen} label="AD" />}
</Menu.Trigger>
<Menu.Popover className={elTopBarMenuPopover}>
<Menu.List>
<Menu.Item href="/">User menu 1</Menu.Item>
<Menu.Item href="/">User menu 2</Menu.Item>
<Menu.Item href="/">User menu 3</Menu.Item>
</Menu.List>
</Menu.Popover>
</Menu>
</TopBar.Profile>
</TopBar>
)
},

parameters: {
design: {
type: 'figma',
Expand All @@ -180,3 +193,48 @@ export const ReactUsage: StoryObj<typeof TopBar> = {
},
},
}

export const Mobile: Story = {
render: ResponsiveMainNav.render,
parameters: {
...ResponsiveMainNav.parameters,
viewport: { defaultViewport: 'iphone14' },
},
}

export const Tablet: Story = {
render: ResponsiveMainNav.render,
parameters: {
...ResponsiveMainNav.parameters,
viewport: { defaultViewport: 'ipad11p' },
},
}
export const Desktop: Story = {
render: ResponsiveMainNav.render,
parameters: {
...ResponsiveMainNav.parameters,
viewport: {
defaultViewport: 'desktop',
},
},
}

export const WideScreen: Story = {
render: ResponsiveMainNav.render,
parameters: {
...ResponsiveMainNav.parameters,
viewport: {
defaultViewport: 'wideScreen',
},
},
}

export const SuperWideScreen: Story = {
render: ResponsiveMainNav.render,
parameters: {
...ResponsiveMainNav.parameters,
viewport: {
defaultViewport: 'superWideScreen',
},
},
}
3 changes: 1 addition & 2 deletions src/storybook/figma/guidelines-images/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import Accordion from './accordion.svg'
import ButtonGroup from './button-group.svg'
import TopBar from './top-bar.svg'

// TODO: can delete this, as we're not planning to use Design Guidelines docs as a documentation for developer
export { Accordion }
export { TopBar }
export { ButtonGroup }
442 changes: 0 additions & 442 deletions src/storybook/figma/guidelines-images/top-bar.svg

This file was deleted.

2 changes: 1 addition & 1 deletion src/storybook/figma/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const GuidelinesImage: FC<GuidelinesImageProps> = ({ name }) => (

export const figmaDesignUrls = {
appBar:
'https://www.figma.com/design/6CaivqdlTX0UkFYJkpBKDu/Reapit-DS?node-id=428-7209&node-type=frame&t=RHaBJeesRCccFe53-0',
'https://www.figma.com/design/XJ6qcAV8gHscsUodqJMNEF/Reapit-Elements-production-ready-components?node-id=16-4840&m=dev',
accordion: 'https://www.figma.com/design/6CaivqdlTX0UkFYJkpBKDu/Reapit-DS?node-id=141-4180&t=k8kHuB2wp3KZoKMw-4',
buttonGroup: 'https://www.figma.com/design/6CaivqdlTX0UkFYJkpBKDu/Reapit-DS?node-id=428-7408&t=8GcgX59FmafMRAda-4',
}
4 changes: 2 additions & 2 deletions src/styles/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export const isWideScreen = '@media screen and (min-width: 1440px)'
export const isSuperWideScreen = '@media screen and (min-width: 1920px)'
export const is4KScreen = '@media screen and (min-width: 2560px)'

export const isDesktopOrBelow = '@media screen and (max-width: 1024px)'
export const isTabletOrBelow = '@media screen and (max-width: 768px)'
export const isBelowWideScreen = '@media screen and (max-width: 1439px)'
export const isBelowDesktop = '@media screen and (max-width: 1023px) '

0 comments on commit 9066a35

Please sign in to comment.