|
- import * as React from 'react';
- import * as T from '@tesseract-design/react-common';
- import styled, { createGlobalStyle } from 'styled-components';
- import TopBar from '../../widgets/TopBar';
- import {UrlObject} from 'url';
-
- const DisableScrolling = createGlobalStyle({
- 'body': {
- overflow: 'hidden',
- '@media (min-width: 1080px)': {
- overflow: 'auto',
- },
- },
- })
-
- const Wrapper = styled('div')({
- '--width-base': '360px',
- '--size-menu': '4rem',
- '--height-topbar': '4rem',
- })
-
- const Main = styled('main')({
- boxSizing: 'border-box',
- paddingBottom: 'var(--size-menu, 4rem)',
- '@media (min-width: 1080px)': {
- paddingLeft: 'calc(50% - var(--width-base, 360px) * 0.5)',
- paddingBottom: 0,
- },
- })
-
- const LeftSidebar = styled('div')({
- boxSizing: 'border-box',
- backgroundColor: 'var(--color-bg, white)',
- overflow: 'hidden',
- display: 'contents',
- left: 'calc(var(--width-base, 360px) * -1)',
- '@media (prefers-color-scheme: dark)': {
- backgroundColor: 'var(--color-bg, black)',
- },
- '@media (min-width: 1080px)': {
- position: 'fixed',
- top: 0,
- left: 0,
- width: 'calc(50% - var(--width-base, 360px) * 0.5)',
- height: '100%',
- display: 'block',
- },
- })
-
- const SidebarMain = styled('div')({
- scrollbarWidth: 'none',
- backgroundColor: 'var(--color-bg, white)',
- boxSizing: 'border-box',
- position: 'fixed',
- top: 0,
- right: '100%',
- width: '100%',
- height: '100%',
- overflow: 'auto',
- paddingTop: 'inherit',
- paddingBottom: 'var(--size-menu, 4rem)',
- '@media (prefers-color-scheme: dark)': {
- backgroundColor: 'var(--color-bg, black)',
- },
- '::-webkit-scrollbar': {
- display: 'none',
- },
- '@media (min-width: 1080px)': {
- position: 'absolute',
- right: 0,
- width: 'calc(var(--width-base, 360px) - var(--size-menu, 4rem))',
- marginLeft: 'auto',
- paddingBottom: 0,
- },
- })
-
- const OpenSidebarMain = styled(SidebarMain)({
- right: 0,
- })
-
- const SidebarMenu = styled('div')({
- boxSizing: 'border-box',
- scrollbarWidth: 'none',
- '::-webkit-scrollbar': {
- display: 'none',
- },
- position: 'fixed',
- bottom: 0,
- left: 0,
- width: '100%',
- height: 'var(--size-menu, 4rem)',
- zIndex: 1,
- backgroundColor: 'var(--color-bg, white)',
- '@media (prefers-color-scheme: dark)': {
- backgroundColor: 'var(--color-bg, black)',
- },
- '@media (min-width: 1080px)': {
- top: 0,
- marginLeft: 'auto',
- position: 'absolute',
- height: '100%',
- paddingTop: 'inherit',
- overflow: 'auto',
- zIndex: 'auto',
- },
- })
-
- const SidebarMenuSize = styled('div')({
- display: 'flex',
- width: '100%',
- height: '100%',
- maxWidth: 'calc(var(--width-base, 360px) * 2)',
- margin: '0 auto',
- '@media (min-width: 1080px)': {
- maxWidth: 'none',
- marginRight: 0,
- flexDirection: 'column',
- justifyContent: 'space-between',
- alignItems: 'flex-end',
- },
- })
-
- const SidebarMenuGroup = styled('div')({
- display: 'contents',
- '@media (min-width: 1080px)': {
- width: '100%',
- display: 'block',
- },
- })
-
- const MoreItems = styled('div')({
- position: 'fixed',
- top: 0,
- left: '-100%',
- width: '100%',
- height: '100%',
- paddingTop: 'var(--height-topbar, 4rem)',
- paddingBottom: 'var(--size-menu, 4rem)',
- backgroundColor: 'var(--color-bg, white)',
- zIndex: -1,
- boxSizing: 'border-box',
- '@media (prefers-color-scheme: dark)': {
- backgroundColor: 'var(--color-bg, black)',
- },
- '@media (min-width: 1080px)': {
- display: 'contents',
- },
- })
-
- const OpenMoreItems = styled(MoreItems)({
- left: 0,
- })
-
- const MoreItemsScroll = styled('div')({
- width: '100%',
- height: '100%',
- overflow: 'auto',
- '@media (min-width: 1080px)': {
- display: 'contents',
- },
- })
-
- const MorePrimarySidebarMenuGroup = styled(SidebarMenuGroup)({
- '@media (min-width: 1080px)': {
- flex: 'auto',
- },
- })
-
- const MoreSecondarySidebarMenuGroup = styled(SidebarMenuGroup)({
- '@media (min-width: 1080px)': {
- order: 4,
- },
- })
-
- const SidebarMenuItem = styled('span')({
- width: 0,
- flex: 'auto',
- height: 'var(--size-menu, 4rem)',
- '> *': {
- height: '100%',
- },
- '@media (min-width: 1080px)': {
- width: 'auto !important',
- flex: '0 1 auto',
- '> *': {
- height: 'auto',
- }
- },
- })
-
- const MoreSidebarMenuItem = styled('span')({
- display: 'block',
- height: 'var(--size-menu, 4rem)',
- '> *': {
- height: '100%',
- },
- '@media (min-width: 1080px)': {
- width: 'auto !important',
- flex: '0 1 auto',
- },
- })
-
- const MoreToggleSidebarMenuItem = styled(SidebarMenuItem)({
- '@media (min-width: 1080px)': {
- display: 'none',
- },
- })
-
- const SidebarMenuItemIcon = styled('span')({
- display: 'block',
- '@media (min-width: 1080px)': {
- width: 'var(--size-menu, 4rem)',
- height: 'var(--size-menu, 4rem)',
- display: 'grid',
- placeContent: 'center',
- },
- })
-
- const MoreSidebarMenuItemIcon = styled('span')({
- marginRight: '1rem',
- display: 'block',
- '@media (min-width: 1080px)': {
- width: 'var(--size-menu, 4rem)',
- height: 'var(--size-menu, 4rem)',
- display: 'grid',
- placeContent: 'center',
- marginRight: 0,
- },
- })
-
- const SidebarMenuContainer = styled('span')({
- boxSizing: 'border-box',
- display: 'grid',
- placeContent: 'center',
- width: '100%',
- textAlign: 'center',
- '@media (min-width: 1080px)': {
- display: 'flex',
- justifyContent: 'flex-start',
- alignItems: 'center',
- width: 'var(--width-base, 360px)',
- marginLeft: 'auto',
- paddingRight: '1rem',
- textAlign: 'left',
- boxSizing: 'border-box',
- },
- })
-
- const MoreSidebarMenuContainer = styled('div')({
- display: 'flex',
- justifyContent: 'flex-start',
- alignItems: 'center',
- width: 'calc(var(--width-base, 360px) * 2)',
- margin: '0 auto',
- padding: '0 1rem',
- textAlign: 'left',
- boxSizing: 'border-box',
- '@media (min-width: 1080px)': {
- marginRight: 0,
- width: 'var(--width-base, 360px)',
- paddingLeft: 0,
- },
- })
-
- export const Container = styled('div')({
- padding: '0 1rem',
- boxSizing: 'border-box',
-
- width: '100%',
- maxWidth: 'calc(var(--width-base, 360px) * 2)',
- marginRight: 'auto',
- marginLeft: 'auto',
- '@media (min-width: 1080px)': {
- marginLeft: 0,
- },
- })
-
- export const SidebarMainContainer = styled('div')({
- padding: '0 1rem',
- boxSizing: 'border-box',
- width: '100%',
- maxWidth: 'calc(var(--width-base, 360px) * 2)',
- margin: '0 auto',
- '@media (min-width: 1080px)': {
- maxWidth: 'none',
- },
- })
-
- type MenuItem = {
- id: string,
- label: string,
- url: UrlObject,
- secondary?: boolean,
- icon: React.ReactChild,
- }
-
- type Props = {
- query?: string,
- onSearch?: React.FormEventHandler,
- searchLabel?: string,
- searchName?: string,
- searchHint?: string,
- brand?: React.ReactNode,
- linkComponent?: React.ElementType,
- sidebarMain?: React.ReactChild,
- sidebarMenuItems?: MenuItem[],
- sidebarMainOpen?: boolean,
- menuLink?: UrlObject,
- userLink?: UrlObject,
- menuLinkLabel?: string,
- userLinkLabel?: string,
- moreItemsOpen?: boolean,
- }
-
- const LeftSidebarWithMenuLayout: React.FC<Props> = ({
- query,
- children,
- sidebarMain,
- sidebarMenuItems,
- sidebarMainOpen,
- brand,
- onSearch,
- searchLabel,
- searchName,
- searchHint,
- linkComponent: LinkComponent = 'a',
- menuLinkLabel,
- menuLink,
- userLink,
- userLinkLabel,
- moreItemsOpen,
- }) => {
- const SidebarMainComponent = sidebarMainOpen ? OpenSidebarMain : SidebarMain
- const MoreItemsComponent = moreItemsOpen ? OpenMoreItems : MoreItems
- const primarySidebarMenuItems = sidebarMenuItems.filter(s => !s.secondary)
- const secondarySidebarMenuItems = sidebarMenuItems.filter(s => s.secondary)
-
-
- const visibleSecondarySidebarMenuItems = secondarySidebarMenuItems.slice(0, 1)
- const moreSecondarySidebarMenuItems = secondarySidebarMenuItems.slice(1)
- const visiblePrimarySidebarMenuItems = (
- visibleSecondarySidebarMenuItems.length === 1
- ? primarySidebarMenuItems.slice(0, 3)
- : primarySidebarMenuItems.slice(0, 4)
- )
- const morePrimarySidebarMenuItems = (
- visibleSecondarySidebarMenuItems.length === 1
- ? primarySidebarMenuItems.slice(3)
- : primarySidebarMenuItems.slice(4)
- )
-
- return (
- <>
- {
- (sidebarMainOpen || moreItemsOpen)
- && (
- <DisableScrolling />
- )
- }
- <Wrapper>
- <TopBar
- withMenu
- query={query}
- wide
- brand={brand}
- onSearch={onSearch}
- linkComponent={LinkComponent}
- searchHint={searchHint}
- searchLabel={searchLabel}
- searchName={searchName}
- menuLink={menuLink}
- menuLinkLabel={menuLinkLabel}
- userLink={userLink}
- userLinkLabel={userLinkLabel}
- />
- <LeftSidebar>
- <SidebarMenu>
- <SidebarMenuSize>
- <SidebarMenuGroup>
- {visiblePrimarySidebarMenuItems.map((item) => {
- return (
- <SidebarMenuItem
- key={item.id}
- >
- <LinkComponent
- href={item.url}
- style={{
- display: 'flex',
- alignItems: 'center',
- textDecoration: 'none',
- width: '100%',
- }}
- >
- <SidebarMenuContainer>
- <SidebarMenuItemIcon>
- {item.icon}
- </SidebarMenuItemIcon>
- {item.label}
- </SidebarMenuContainer>
- </LinkComponent>
- </SidebarMenuItem>
- )
- })}
- </SidebarMenuGroup>
- <MoreItemsComponent>
- <MoreItemsScroll>
- <MorePrimarySidebarMenuGroup>
- {morePrimarySidebarMenuItems.map((item) => {
- return (
- <MoreSidebarMenuItem
- key={item.id}
- >
- <LinkComponent
- href={item.url}
- style={{
- display: 'flex',
- alignItems: 'center',
- textDecoration: 'none',
- width: '100%',
- }}
- >
- <MoreSidebarMenuContainer>
- <MoreSidebarMenuItemIcon>
- {item.icon}
- </MoreSidebarMenuItemIcon>
- {item.label}
- </MoreSidebarMenuContainer>
- </LinkComponent>
- </MoreSidebarMenuItem>
- )
- })}
- </MorePrimarySidebarMenuGroup>
- <MoreSecondarySidebarMenuGroup>
- {moreSecondarySidebarMenuItems.map((item) => {
- return (
- <MoreSidebarMenuItem
- key={item.id}
- >
- <LinkComponent
- href={item.url}
- style={{
- display: 'flex',
- alignItems: 'center',
- textDecoration: 'none',
- width: '100%',
- }}
- >
- <MoreSidebarMenuContainer>
- <MoreSidebarMenuItemIcon>
- {item.icon}
- </MoreSidebarMenuItemIcon>
- {item.label}
- </MoreSidebarMenuContainer>
- </LinkComponent>
- </MoreSidebarMenuItem>
- )
- })}
- </MoreSecondarySidebarMenuGroup>
- </MoreItemsScroll>
- </MoreItemsComponent>
- <MoreToggleSidebarMenuItem>
- <SidebarMenuItem>
- <LinkComponent
- href={{
- query: {
- more: '',
- }
- }}
- style={{
- display: 'flex',
- alignItems: 'center',
- textDecoration: 'none',
- width: '100%',
- }}
- shallow
- >
- <SidebarMenuContainer>
- <SidebarMenuItemIcon>
- <T.Icon
- name="more-horizontal"
- label=""
- />
- </SidebarMenuItemIcon>
- More
- </SidebarMenuContainer>
- </LinkComponent>
- </SidebarMenuItem>
- </MoreToggleSidebarMenuItem>
- {
- visibleSecondarySidebarMenuItems.length > 0
- && (
- <SidebarMenuGroup>
- {visibleSecondarySidebarMenuItems.map((item, i) => (
- <SidebarMenuItem
- key={item.id}
- >
- <LinkComponent
- href={item.url}
- style={{
- display: 'flex',
- alignItems: 'center',
- textDecoration: 'none',
- width: '100%',
- }}
- >
- <SidebarMenuContainer>
- <SidebarMenuItemIcon>
- {item.icon}
- </SidebarMenuItemIcon>
- {item.label}
- </SidebarMenuContainer>
- </LinkComponent>
- </SidebarMenuItem>
- ))}
- </SidebarMenuGroup>
- )
- }
- </SidebarMenuSize>
- </SidebarMenu>
- <SidebarMainComponent>
- {sidebarMain}
- </SidebarMainComponent>
- </LeftSidebar>
- <Main>
- {children}
- </Main>
- </Wrapper>
- </>
- )
- }
-
- export default LeftSidebarWithMenuLayout
|