This implements the router based on Next.js for left-sidebar-with-menu layout. In addition, the other layouts have been genericized for wider framework support, although the underlying API is still based on Next.js components.master
@@ -0,0 +1,20 @@ | |||
import NextLink from 'next/link' | |||
const Link = ({ href, as, prefetch, replace, shallow, component: Component = 'a', ...etcProps }) => { | |||
return ( | |||
<NextLink | |||
href={href} | |||
as={as} | |||
passHref | |||
replace={replace} | |||
shallow={shallow} | |||
prefetch={prefetch} | |||
> | |||
<Component | |||
{...etcProps} | |||
/> | |||
</NextLink> | |||
) | |||
} | |||
export default Link |
@@ -1,20 +1,62 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components'; | |||
import TopBar from '../../widgets/TopBar'; | |||
import {UrlObject} from 'url'; | |||
const Main = styled('main')({ | |||
boxSizing: 'border-box', | |||
}) | |||
export const Container = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
margin: '0 auto', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
width: '100%', | |||
}) | |||
type Props = { | |||
query?: string, | |||
brand?: React.ReactNode, | |||
onSearch?: React.FormEventHandler, | |||
searchLabel?: string, | |||
searchName?: string, | |||
searchHint?: string, | |||
linkComponent?: React.ElementType, | |||
menuLink?: UrlObject, | |||
userLink?: UrlObject, | |||
menuLinkLabel?: string, | |||
userLinkLabel?: string, | |||
} | |||
const BasicLayout: React.FC<Props> = ({ query, children }) => { | |||
const BasicLayout: React.FC<Props> = ({ | |||
query, | |||
children, | |||
brand, | |||
onSearch, | |||
searchLabel, | |||
searchName, | |||
searchHint, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
}) => { | |||
return ( | |||
<> | |||
<TopBar | |||
query={query} | |||
brand={brand} | |||
onSearch={onSearch} | |||
searchHint={searchHint} | |||
searchLabel={searchLabel} | |||
searchName={searchName} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
/> | |||
<Main> | |||
{children} | |||
@@ -1,6 +1,7 @@ | |||
import * as React from 'react'; | |||
import styled, {createGlobalStyle} from 'styled-components'; | |||
import TopBar from '../../widgets/TopBar'; | |||
import {UrlObject} from 'url'; | |||
const DisableScrolling = createGlobalStyle({ | |||
'body': { | |||
@@ -52,11 +53,61 @@ const OpenLeftSidebar = styled(LeftSidebar)({ | |||
left: 0, | |||
}) | |||
const LeftSidebarLayout = ({ | |||
export const SidebarContainer = styled('div')({ | |||
margin: '0 auto', | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
'@media (min-width: 1080px)': { | |||
width: 'var(--width-base, 360px)', | |||
marginRight: 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, | |||
}, | |||
}) | |||
type Props = { | |||
query?: string, | |||
onSearch?: React.FormEventHandler, | |||
searchLabel?: string, | |||
searchName?: string, | |||
searchHint?: string, | |||
brand?: React.ReactNode, | |||
linkComponent?: React.ElementType, | |||
sidebarMain?: React.ReactChild, | |||
sidebarMainOpen?: boolean, | |||
menuLink?: UrlObject, | |||
userLink?: UrlObject, | |||
menuLinkLabel?: string, | |||
userLinkLabel?: string, | |||
} | |||
const LeftSidebarLayout: React.FC<Props> = ({ | |||
query, | |||
sidebarMain, | |||
sidebarMainOpen, | |||
children, | |||
onSearch, | |||
searchLabel, | |||
searchName, | |||
searchHint, | |||
brand, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
}) => { | |||
const LeftSidebarComponent = sidebarMainOpen ? OpenLeftSidebar : LeftSidebar | |||
@@ -72,6 +123,16 @@ const LeftSidebarLayout = ({ | |||
wide | |||
query={query} | |||
withMenu | |||
onSearch={onSearch} | |||
searchHint={searchHint} | |||
searchLabel={searchLabel} | |||
searchName={searchName} | |||
brand={brand} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
/> | |||
<LeftSidebarComponent> | |||
<SidebarOverflow> | |||
@@ -1,6 +1,8 @@ | |||
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': { | |||
@@ -14,6 +16,7 @@ const DisableScrolling = createGlobalStyle({ | |||
const Wrapper = styled('div')({ | |||
'--width-base': '360px', | |||
'--size-menu': '4rem', | |||
'--height-topbar': '4rem', | |||
}) | |||
const Main = styled('main')({ | |||
@@ -86,8 +89,8 @@ const SidebarMenu = styled('div')({ | |||
left: 0, | |||
width: '100%', | |||
height: 'var(--size-menu, 4rem)', | |||
backgroundColor: 'var(--color-bg, white)', | |||
zIndex: 1, | |||
backgroundColor: 'var(--color-bg, white)', | |||
'@media (prefers-color-scheme: dark)': { | |||
backgroundColor: 'var(--color-bg, black)', | |||
}, | |||
@@ -117,7 +120,7 @@ const SidebarMenuSize = styled('div')({ | |||
}, | |||
}) | |||
export const SidebarMenuGroup = styled('div')({ | |||
const SidebarMenuGroup = styled('div')({ | |||
display: 'contents', | |||
'@media (min-width: 1080px)': { | |||
width: '100%', | |||
@@ -125,19 +128,85 @@ export const SidebarMenuGroup = styled('div')({ | |||
}, | |||
}) | |||
export const SidebarMenuItem = styled('a')({ | |||
height: 'var(--size-menu, 4rem)', | |||
display: 'flex', | |||
alignItems: 'center', | |||
textDecoration: 'none', | |||
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)': { | |||
width: 'auto', | |||
display: 'none', | |||
}, | |||
}) | |||
export const SidebarMenuItemIcon = styled('span')({ | |||
const SidebarMenuItemIcon = styled('span')({ | |||
display: 'block', | |||
'@media (min-width: 1080px)': { | |||
width: 'var(--size-menu, 4rem)', | |||
@@ -147,7 +216,19 @@ export const SidebarMenuItemIcon = styled('span')({ | |||
}, | |||
}) | |||
export const SidebarMenuContainer = styled('span')({ | |||
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', | |||
@@ -161,22 +242,117 @@ export const SidebarMenuContainer = styled('span')({ | |||
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, | |||
}, | |||
}) | |||
const LeftSidebarWithMenuLayout = ({ | |||
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, | |||
sidebarMenu, | |||
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 | |||
(sidebarMainOpen || moreItemsOpen) | |||
&& ( | |||
<DisableScrolling /> | |||
) | |||
@@ -186,11 +362,158 @@ const LeftSidebarWithMenuLayout = ({ | |||
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> | |||
{sidebarMenu} | |||
<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%', | |||
}} | |||
> | |||
<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> | |||
@@ -1,5 +1,7 @@ | |||
import * as React from 'react'; | |||
import styled from 'styled-components'; | |||
import TopBar from '../../widgets/TopBar'; | |||
import {UrlObject} from 'url'; | |||
const Main = styled('main')({ | |||
boxSizing: 'border-box', | |||
@@ -32,22 +34,80 @@ const RightSidebar = styled('div')({ | |||
}, | |||
}) | |||
const RightSidebarLayout = ({ | |||
export const SidebarContainer = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
width: '100%', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
margin: '0 auto', | |||
'@media (min-width: 1080px)': { | |||
width: 'var(--width-base, 360px)', | |||
marginLeft: 0, | |||
}, | |||
}) | |||
export const Container = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
width: '100%', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
margin: '0 auto', | |||
'@media (min-width: 1080px)': { | |||
marginRight: 0, | |||
}, | |||
}) | |||
type Props = { | |||
query?: string, | |||
onSearch?: React.FormEventHandler, | |||
searchLabel?: string, | |||
searchName?: string, | |||
searchHint?: string, | |||
brand?: React.ReactNode, | |||
linkComponent?: React.ElementType, | |||
sidebarMain?: React.ReactChild, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel?: string, | |||
userLinkLabel?: string, | |||
} | |||
const RightSidebarLayout: React.FC<Props> = ({ | |||
query, | |||
sidebar, | |||
sidebarMain, | |||
children, | |||
brand, | |||
linkComponent, | |||
searchHint, | |||
searchName, | |||
searchLabel, | |||
onSearch, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
}) => { | |||
return ( | |||
<> | |||
<TopBar | |||
query={query} | |||
wide | |||
brand={brand} | |||
linkComponent={linkComponent} | |||
searchHint={searchHint} | |||
searchName={searchName} | |||
searchLabel={searchLabel} | |||
onSearch={onSearch} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
/> | |||
<Main> | |||
{children} | |||
</Main> | |||
<RightSidebar> | |||
{sidebar} | |||
{sidebarMain} | |||
</RightSidebar> | |||
</> | |||
) | |||
@@ -1,17 +1,16 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components' | |||
import * as T from '@tesseract-design/react-common' | |||
import {UrlObject} from 'url'; | |||
const Base = styled('div')({ | |||
'--width-base': '360px', | |||
'--height-topbar': '4rem', | |||
position: 'fixed', | |||
top: 0, | |||
left: 0, | |||
width: '100%', | |||
height: 'var(--height-topbar, 4rem)', | |||
backgroundColor: 'var(--color-bg, white)', | |||
zIndex: 1, | |||
zIndex: 2, | |||
'@media (prefers-color-scheme: dark)': { | |||
backgroundColor: 'var(--color-bg, black)', | |||
}, | |||
@@ -56,6 +55,9 @@ const SearchContainer = styled('form')({ | |||
flex: 'auto', | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
':first-child': { | |||
paddingLeft: 0, | |||
}, | |||
}) | |||
const UserContainer = styled('div')({ | |||
@@ -67,21 +69,13 @@ const UserContainer = styled('div')({ | |||
}, | |||
}) | |||
const UserLink = styled('a')({ | |||
width: 'var(--height-topbar, 4rem)', | |||
height: '100%', | |||
display: 'inline-grid', | |||
placeContent: 'center', | |||
}) | |||
const MenuUserLink = styled(UserLink)({ | |||
const MenuUserLinkContainer = styled('span')({ | |||
'@media (min-width: 1080px)': { | |||
position: 'absolute', | |||
left: -999999, | |||
}, | |||
}) | |||
type Props = { | |||
query?: string, | |||
onSearch?: React.FormEventHandler, | |||
@@ -90,6 +84,12 @@ type Props = { | |||
searchHint?: string, | |||
wide?: boolean, | |||
withMenu?: boolean, | |||
brand?: React.ReactNode, | |||
linkComponent?: React.ElementType, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel?: string, | |||
userLinkLabel?: string, | |||
} | |||
const TopBar: React.FC<Props> = ({ | |||
@@ -100,14 +100,25 @@ const TopBar: React.FC<Props> = ({ | |||
searchHint = 'e.g. keywords, names…', | |||
wide, | |||
withMenu, | |||
brand, | |||
linkComponent: LinkComponent = 'a', | |||
menuLink, | |||
menuLinkLabel = 'Menu', | |||
userLink, | |||
userLinkLabel = 'Guest', | |||
}) => { | |||
const ContainerComponent = wide ? WideContainer : Container | |||
return ( | |||
<Base> | |||
<ContainerComponent> | |||
<BrandContainer> | |||
Brand | |||
</BrandContainer> | |||
{ | |||
Boolean(brand) | |||
&& ( | |||
<BrandContainer> | |||
{brand} | |||
</BrandContainer> | |||
) | |||
} | |||
<SearchContainer | |||
onSubmit={onSearch} | |||
> | |||
@@ -130,22 +141,38 @@ const TopBar: React.FC<Props> = ({ | |||
{ | |||
withMenu | |||
&& ( | |||
<MenuUserLink | |||
href="?sidebar" | |||
> | |||
<T.Icon | |||
name="menu" | |||
label="Guest" | |||
/> | |||
</MenuUserLink> | |||
<MenuUserLinkContainer> | |||
<LinkComponent | |||
href={menuLink} | |||
style={{ | |||
width: 'var(--height-topbar, 4rem)', | |||
height: '100%', | |||
display: 'inline-grid', | |||
placeContent: 'center', | |||
}} | |||
> | |||
<T.Icon | |||
name="menu" | |||
label={menuLinkLabel} | |||
/> | |||
</LinkComponent> | |||
</MenuUserLinkContainer> | |||
) | |||
} | |||
<UserLink> | |||
<LinkComponent | |||
href={userLink} | |||
style={{ | |||
width: 'var(--height-topbar, 4rem)', | |||
height: '100%', | |||
display: 'inline-grid', | |||
placeContent: 'center', | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label="Guest" | |||
label={userLinkLabel} | |||
/> | |||
</UserLink> | |||
</LinkComponent> | |||
</UserContainer> | |||
</ContainerComponent> | |||
</Base> | |||
@@ -1,26 +1,34 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components' | |||
import Basic from '../../organisms/layouts/Basic' | |||
import Basic, { Container } from '../../organisms/layouts/Basic' | |||
import DummyContent from '../../molecules/DummyContent'; | |||
const Container = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
margin: '0 auto', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
width: '100%', | |||
}) | |||
import {UrlObject} from 'url'; | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
} | |||
const BasicLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
}) => { | |||
return ( | |||
<Basic | |||
brand="Brand" | |||
query={query} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
> | |||
<Container> | |||
<DummyContent /> | |||
@@ -1,41 +1,37 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components'; | |||
import LeftSidebarLayout from '../../organisms/layouts/LeftSidebar'; | |||
import LeftSidebarLayout, { SidebarContainer, Container } from '../../organisms/layouts/LeftSidebar'; | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
const SidebarContainer = styled('div')({ | |||
margin: '0 auto', | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
'@media (min-width: 1080px)': { | |||
width: 'var(--width-base, 360px)', | |||
marginRight: 0, | |||
}, | |||
}) | |||
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, | |||
}, | |||
}) | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
sidebarMainOpen: boolean, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
} | |||
const LeftSidebarLayoutTemplate = ({ | |||
const LeftSidebarLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
sidebarMainOpen, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
}) => { | |||
return ( | |||
<LeftSidebarLayout | |||
brand="Brand" | |||
query={query} | |||
sidebarMainOpen={sidebarMainOpen} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
sidebarMain={ | |||
<SidebarContainer> | |||
<DummyContent /> | |||
@@ -1,102 +1,145 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components'; | |||
import * as T from '@tesseract-design/react-common'; | |||
import LeftSidebarWithMenuLayout, { | |||
SidebarMenuItemIcon, | |||
SidebarMenuContainer, | |||
SidebarMenuGroup, | |||
SidebarMenuItem, | |||
Container, | |||
SidebarMainContainer, | |||
} from '../../organisms/layouts/LeftSidebarWithMenu'; | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
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, | |||
}, | |||
}) | |||
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 Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
sidebarMainOpen: boolean, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
moreItemsOpen: boolean, | |||
} | |||
const LeftSidebarLayoutTemplate = ({ | |||
const LeftSidebarLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
sidebarMainOpen, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
moreItemsOpen, | |||
}) => { | |||
return ( | |||
<LeftSidebarWithMenuLayout | |||
brand="Brand" | |||
moreItemsOpen={moreItemsOpen} | |||
query={query} | |||
linkComponent={linkComponent} | |||
sidebarMainOpen={sidebarMainOpen} | |||
sidebarMain={ | |||
<SidebarMainContainer> | |||
<DummyContent /> | |||
</SidebarMainContainer> | |||
} | |||
sidebarMenu={ | |||
<> | |||
<SidebarMenuGroup> | |||
<SidebarMenuItem> | |||
<SidebarMenuContainer> | |||
<SidebarMenuItemIcon> | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
</SidebarMenuItemIcon> | |||
Hello | |||
</SidebarMenuContainer> | |||
</SidebarMenuItem> | |||
<SidebarMenuItem> | |||
<SidebarMenuContainer> | |||
<SidebarMenuItemIcon> | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
</SidebarMenuItemIcon> | |||
Hello | |||
</SidebarMenuContainer> | |||
</SidebarMenuItem> | |||
<SidebarMenuItem> | |||
<SidebarMenuContainer> | |||
<SidebarMenuItemIcon> | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
</SidebarMenuItemIcon> | |||
Hello | |||
</SidebarMenuContainer> | |||
</SidebarMenuItem> | |||
</SidebarMenuGroup> | |||
<SidebarMenuGroup> | |||
<SidebarMenuItem> | |||
<SidebarMenuContainer> | |||
<SidebarMenuItemIcon> | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
</SidebarMenuItemIcon> | |||
World | |||
</SidebarMenuContainer> | |||
</SidebarMenuItem> | |||
</SidebarMenuGroup> | |||
</> | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
sidebarMenuItems={ | |||
[ | |||
{ | |||
id: '1', | |||
label: 'P1', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '2', | |||
label: 'P2', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '3', | |||
label: 'P3', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '100', | |||
label: 'P4', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '101', | |||
label: 'P5', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '4', | |||
label: 'S1', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
secondary: true, | |||
}, | |||
{ | |||
id: '5', | |||
label: 'S2', | |||
url: { | |||
href: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
secondary: true, | |||
}, | |||
] | |||
} | |||
> | |||
<Container> | |||
@@ -1,38 +1,35 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components'; | |||
import RightSidebarLayout from '../../organisms/layouts/RightSidebar'; | |||
import RightSidebarLayout, { SidebarContainer, Container } from '../../organisms/layouts/RightSidebar'; | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
const SidebarContainer = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
width: '100%', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
margin: '0 auto', | |||
'@media (min-width: 1080px)': { | |||
width: 'var(--width-base, 360px)', | |||
marginLeft: 0, | |||
}, | |||
}) | |||
const Container = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
width: '100%', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
margin: '0 auto', | |||
'@media (min-width: 1080px)': { | |||
marginRight: 0, | |||
}, | |||
}) | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
} | |||
const RightSidebarLayoutTemplate = ({ | |||
const RightSidebarLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
}) => { | |||
return ( | |||
<RightSidebarLayout | |||
brand="Brand" | |||
query={query} | |||
sidebar={ | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
sidebarMain={ | |||
<SidebarContainer> | |||
<DummyContent /> | |||
</SidebarContainer> | |||
@@ -1,5 +1,6 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../components/templates/BasicLayout' | |||
import Link from '../../../components/molecules/Link'; | |||
type Props = { | |||
query: string, | |||
@@ -10,7 +11,22 @@ const Page: NextPage<Props> = ({ | |||
}) => { | |||
return ( | |||
<Template | |||
linkComponent={Link} | |||
query={query} | |||
menuLink={{ | |||
query: { | |||
q: query, | |||
sidebar: '', | |||
} | |||
}} | |||
menuLinkLabel="Menu" | |||
userLink={{ | |||
pathname: '/profile', | |||
query: { | |||
q: query, | |||
}, | |||
}} | |||
userLinkLabel="User" | |||
/> | |||
) | |||
} | |||
@@ -25,4 +41,3 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
} | |||
} | |||
} | |||
@@ -1,5 +1,6 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../components/templates/LeftSidebarLayout' | |||
import Link from '../../../components/molecules/Link'; | |||
type Props = { | |||
query: string, | |||
@@ -14,6 +15,21 @@ const Page: NextPage<Props> = ({ | |||
<Template | |||
query={query} | |||
sidebarMainOpen={sidebarMainOpen} | |||
linkComponent={Link} | |||
menuLink={{ | |||
query: { | |||
q: query, | |||
sidebar: '', | |||
} | |||
}} | |||
menuLinkLabel="Menu" | |||
userLink={{ | |||
pathname: '/profile', | |||
query: { | |||
q: query, | |||
}, | |||
}} | |||
userLinkLabel="User" | |||
/> | |||
) | |||
} | |||
@@ -1,19 +1,38 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../../components/templates/LeftSidebarWithMenuLayout' | |||
import Link from '../../../../components/molecules/Link'; | |||
type Props = { | |||
query: string, | |||
sidebarMainOpen: boolean, | |||
moreItemsOpen: boolean, | |||
} | |||
const Page: NextPage<Props> = ({ | |||
query, | |||
sidebarMainOpen, | |||
moreItemsOpen, | |||
}) => { | |||
return ( | |||
<Template | |||
query={query} | |||
sidebarMainOpen={sidebarMainOpen} | |||
linkComponent={Link} | |||
menuLink={{ | |||
query: { | |||
q: query, | |||
sidebar: '', | |||
} | |||
}} | |||
menuLinkLabel="Menu" | |||
userLink={{ | |||
pathname: '/profile', | |||
query: { | |||
q: query, | |||
}, | |||
}} | |||
userLinkLabel="User" | |||
moreItemsOpen={moreItemsOpen} | |||
/> | |||
) | |||
} | |||
@@ -26,6 +45,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
props: { | |||
query, | |||
sidebarMainOpen: 'sidebar' in ctx.query, | |||
moreItemsOpen: 'more' in ctx.query, | |||
} | |||
} | |||
} | |||
@@ -1,5 +1,6 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../components/templates/RightSidebarLayout' | |||
import Link from '../../../components/molecules/Link'; | |||
type Props = { | |||
query: string, | |||
@@ -10,7 +11,22 @@ const Page: NextPage<Props> = ({ | |||
}) => { | |||
return ( | |||
<Template | |||
linkComponent={Link} | |||
query={query} | |||
menuLink={{ | |||
query: { | |||
q: query, | |||
sidebar: '', | |||
} | |||
}} | |||
menuLinkLabel="Menu" | |||
userLink={{ | |||
pathname: '/profile', | |||
query: { | |||
q: query, | |||
}, | |||
}} | |||
userLinkLabel="User" | |||
/> | |||
) | |||
} | |||