The layouts have been extracted to a separate package (@tesseract-design/viewfinder) which can be found in the Modal Pack Registry.master
@@ -1,5 +1,6 @@ | |||
body { | |||
margin: 0; | |||
/* overflow: overlay; */ | |||
} | |||
h1 { | |||
@@ -0,0 +1,41 @@ | |||
import Link from '../Link' | |||
import styled from 'styled-components' | |||
const BrandBase = styled(Link)({ | |||
display: 'block', | |||
textDecoration: 'none', | |||
fontSize: '1.5rem', | |||
fontWeight: 'bold', | |||
fontStretch: '75%', | |||
textTransform: 'uppercase', | |||
width: '2rem', | |||
textAlign: 'center', | |||
'@media (min-width: 720px)': { | |||
width: '8rem', | |||
textAlign: 'left', | |||
}, | |||
}) | |||
const Hide = styled('span')({ | |||
display: 'none', | |||
'@media (min-width: 720px)': { | |||
display: 'inline', | |||
}, | |||
}) | |||
const Brand = () => { | |||
return ( | |||
<BrandBase | |||
href={{ | |||
pathname: '/', | |||
}} | |||
> | |||
B | |||
<Hide> | |||
rand | |||
</Hide> | |||
</BrandBase> | |||
) | |||
} | |||
export default Brand |
@@ -1,6 +1,25 @@ | |||
import * as React from 'react' | |||
import NextLink from 'next/link' | |||
import {UrlObject} from 'url'; | |||
const Link = ({ href, as, prefetch, replace, shallow, component: Component = 'a', ...etcProps }) => { | |||
type Props = { | |||
href: UrlObject, | |||
as?: UrlObject, | |||
prefetch?: boolean, | |||
replace?: boolean, | |||
shallow?: boolean, | |||
component?: React.ElementType, | |||
} | |||
const Link: React.FC<Props> = ({ | |||
href, | |||
as, | |||
prefetch, | |||
replace, | |||
shallow, | |||
component: Component = 'a', | |||
...etcProps | |||
}) => { | |||
return ( | |||
<NextLink | |||
href={href} | |||
@@ -1,68 +0,0 @@ | |||
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, | |||
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} | |||
</Main> | |||
</> | |||
) | |||
} | |||
export default BasicLayout |
@@ -1,149 +0,0 @@ | |||
import * as React from 'react'; | |||
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 Main = styled('main')({ | |||
boxSizing: 'border-box', | |||
'@media (min-width: 1080px)': { | |||
paddingLeft: 'calc(50% - var(--width-base, 360px) * 0.5)', | |||
}, | |||
}) | |||
const SidebarOverflow = styled('div')({ | |||
width: '100%', | |||
height: '100%', | |||
overflow: 'auto', | |||
scrollbarWidth: 'none', | |||
'::-webkit-scrollbar': { | |||
display: 'none', | |||
}, | |||
}) | |||
const LeftSidebar = styled('div')({ | |||
'--width-base': '360px', | |||
'--size-menu': '4rem', | |||
boxSizing: 'border-box', | |||
position: 'fixed', | |||
top: 0, | |||
left: '-100%', | |||
width: '100%', | |||
height: '100%', | |||
backgroundColor: 'var(--color-bg, white)', | |||
overflow: 'hidden', | |||
'@media (prefers-color-scheme: dark)': { | |||
backgroundColor: 'var(--color-bg, black)', | |||
}, | |||
'@media (min-width: 1080px)': { | |||
width: 'calc(50% - var(--width-base, 360px) * 0.5)', | |||
left: 0, | |||
}, | |||
}) | |||
const OpenLeftSidebar = styled(LeftSidebar)({ | |||
left: 0, | |||
}) | |||
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 | |||
return ( | |||
<> | |||
{ | |||
sidebarMainOpen | |||
&& ( | |||
<DisableScrolling /> | |||
) | |||
} | |||
<TopBar | |||
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> | |||
{sidebarMain} | |||
</SidebarOverflow> | |||
</LeftSidebarComponent> | |||
<Main> | |||
{children} | |||
</Main> | |||
</> | |||
) | |||
} | |||
export default LeftSidebarLayout |
@@ -1,532 +0,0 @@ | |||
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 |
@@ -1,116 +0,0 @@ | |||
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', | |||
'@media (min-width: 1080px)': { | |||
paddingRight: 'calc(50% - var(--width-base, 360px) * 0.5)', | |||
}, | |||
}) | |||
const RightSidebar = styled('div')({ | |||
'--width-base': '360px', | |||
boxSizing: 'border-box', | |||
backgroundColor: 'var(--color-bg, white)', | |||
// prevent collapse of margin | |||
'::after': { | |||
content: "''", | |||
display: 'block', | |||
paddingBottom: 1, | |||
marginTop: -1, | |||
boxSizing: 'border-box', | |||
}, | |||
'@media (prefers-color-scheme: dark)': { | |||
backgroundColor: 'var(--color-bg, black)', | |||
}, | |||
'@media (min-width: 1080px)': { | |||
position: 'absolute', | |||
top: 0, | |||
right: 0, | |||
width: 'calc(50% - var(--width-base, 360px) * 0.5)', | |||
height: '100%', | |||
}, | |||
}) | |||
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, | |||
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> | |||
{sidebarMain} | |||
</RightSidebar> | |||
</> | |||
) | |||
} | |||
export default RightSidebarLayout |
@@ -1,183 +0,0 @@ | |||
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')({ | |||
position: 'fixed', | |||
top: 0, | |||
left: 0, | |||
width: '100%', | |||
height: 'var(--height-topbar, 4rem)', | |||
backgroundColor: 'var(--color-bg, white)', | |||
zIndex: 2, | |||
'@media (prefers-color-scheme: dark)': { | |||
backgroundColor: 'var(--color-bg, black)', | |||
}, | |||
'~ *': { | |||
paddingTop: 'var(--height-topbar, 4rem)', | |||
}, | |||
'~ main ~ *': { | |||
paddingTop: 0, | |||
}, | |||
'@media (min-width: 1080px)': { | |||
'~ main ~ *': { | |||
paddingTop: 'var(--height-topbar, 4rem)', | |||
}, | |||
}, | |||
}) | |||
const Container = styled('div')({ | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
margin: '0 auto', | |||
maxWidth: 'calc(var(--width-base, 360px) * 2)', | |||
width: '100%', | |||
height: '100%', | |||
display: 'flex', | |||
alignItems: 'center', | |||
}) | |||
const WideContainer = styled(Container)({ | |||
'@media (min-width: 1080px)': { | |||
maxWidth: 'calc(var(--width-base, 360px) * 3)', | |||
}, | |||
}) | |||
const BrandContainer = styled('div')({ | |||
width: '6rem', | |||
'@media (min-width: 720px)': { | |||
width: '8rem', | |||
}, | |||
}) | |||
const SearchContainer = styled('form')({ | |||
flex: 'auto', | |||
padding: '0 1rem', | |||
boxSizing: 'border-box', | |||
':first-child': { | |||
paddingLeft: 0, | |||
}, | |||
}) | |||
const UserContainer = styled('div')({ | |||
textAlign: 'right', | |||
height: '100%', | |||
whiteSpace: 'nowrap', | |||
'@media (min-width: 720px)': { | |||
minWidth: '8rem', | |||
}, | |||
}) | |||
const MenuUserLinkContainer = styled('span')({ | |||
'@media (min-width: 1080px)': { | |||
position: 'absolute', | |||
left: -999999, | |||
}, | |||
}) | |||
type Props = { | |||
query?: string, | |||
onSearch?: React.FormEventHandler, | |||
searchLabel?: string, | |||
searchName?: string, | |||
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> = ({ | |||
query, | |||
onSearch, | |||
searchLabel = 'Search', | |||
searchName = 'q', | |||
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> | |||
{ | |||
Boolean(brand) | |||
&& ( | |||
<BrandContainer> | |||
{brand} | |||
</BrandContainer> | |||
) | |||
} | |||
<SearchContainer | |||
onSubmit={onSearch} | |||
> | |||
<T.TextInput | |||
name={searchName} | |||
label={searchLabel} | |||
hint={searchHint} | |||
defaultValue={query} | |||
border | |||
alternate | |||
indicator={ | |||
<T.Icon | |||
name="search" | |||
label="" | |||
/> | |||
} | |||
/> | |||
</SearchContainer> | |||
<UserContainer> | |||
{ | |||
withMenu | |||
&& ( | |||
<MenuUserLinkContainer> | |||
<LinkComponent | |||
href={menuLink} | |||
style={{ | |||
width: 'var(--height-topbar, 4rem)', | |||
height: '100%', | |||
display: 'inline-grid', | |||
placeContent: 'center', | |||
}} | |||
shallow | |||
> | |||
<T.Icon | |||
name="menu" | |||
label={menuLinkLabel} | |||
/> | |||
</LinkComponent> | |||
</MenuUserLinkContainer> | |||
) | |||
} | |||
<LinkComponent | |||
href={userLink} | |||
style={{ | |||
width: 'var(--height-topbar, 4rem)', | |||
height: '100%', | |||
display: 'inline-grid', | |||
placeContent: 'center', | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label={userLinkLabel} | |||
/> | |||
</LinkComponent> | |||
</UserContainer> | |||
</ContainerComponent> | |||
</Base> | |||
) | |||
} | |||
export default TopBar |
@@ -1,39 +1,65 @@ | |||
import * as React from 'react' | |||
import Basic, { Container } from '../../organisms/layouts/Basic' | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
import * as T from '@tesseract-design/react-common' | |||
import { Basic } from '@tesseract-design/viewfinder' | |||
import Link from '../../molecules/Link' | |||
import DummyContent from '../../molecules/DummyContent' | |||
import Brand from '../../molecules/Brand' | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
searchQueryKey: string, | |||
searchLabel: string, | |||
searchHint: string, | |||
popupQueryKey: string, | |||
userPopupQueryValue: string, | |||
} | |||
const BasicLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
searchQueryKey, | |||
searchLabel, | |||
searchHint, | |||
popupQueryKey, | |||
userPopupQueryValue, | |||
}) => { | |||
return ( | |||
<Basic | |||
brand="Brand" | |||
query={query} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
<Basic.Layout | |||
brand={ | |||
<Brand /> | |||
} | |||
topBarCenter={ | |||
<form> | |||
<T.TextInput | |||
name={searchQueryKey} | |||
label={searchLabel} | |||
hint={searchHint} | |||
defaultValue={query} | |||
border | |||
alternate | |||
/> | |||
</form> | |||
} | |||
userLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[popupQueryKey]: userPopupQueryValue, | |||
}, | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label={userLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
> | |||
<Container> | |||
<Basic.ContentContainer> | |||
<DummyContent /> | |||
</Container> | |||
</Basic> | |||
</Basic.ContentContainer> | |||
</Basic.Layout> | |||
) | |||
} | |||
@@ -1,8 +1,9 @@ | |||
import * as React from 'react' | |||
import styled from 'styled-components' | |||
import Basic, { Container } from '../../organisms/layouts/Basic' | |||
import Link from '../../molecules/Link'; | |||
import {UrlObject} from 'url'; | |||
import * as T from '@tesseract-design/react-common' | |||
import { Basic } from '@tesseract-design/viewfinder' | |||
import Link from '../../molecules/Link' | |||
import Brand from '../../molecules/Brand' | |||
const LinkContainer = styled('nav')({ | |||
margin: '1rem 0', | |||
@@ -62,32 +63,56 @@ const StyledLink = styled(Link)({ | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
searchQueryKey: string, | |||
searchLabel: string, | |||
searchHint: string, | |||
popupQueryKey: string, | |||
userPopupQueryValue: string, | |||
} | |||
const IndexTemplate: React.FC<Props> = ({ | |||
query, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
searchQueryKey, | |||
searchLabel, | |||
searchHint, | |||
popupQueryKey, | |||
userPopupQueryValue, | |||
}) => { | |||
return ( | |||
<Basic | |||
brand="Brand" | |||
query={query} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
<Basic.Layout | |||
brand={ | |||
<Brand /> | |||
} | |||
topBarCenter={ | |||
<form> | |||
<T.TextInput | |||
name={searchQueryKey} | |||
label={searchLabel} | |||
hint={searchHint} | |||
defaultValue={query} | |||
border | |||
alternate | |||
/> | |||
</form> | |||
} | |||
userLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[popupQueryKey]: userPopupQueryValue, | |||
}, | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label={userLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
> | |||
<Container> | |||
<Basic.ContentContainer> | |||
<h1> | |||
Welcome | |||
</h1> | |||
@@ -110,13 +135,13 @@ const IndexTemplate: React.FC<Props> = ({ | |||
</StyledLink> | |||
<StyledLink | |||
href={{ | |||
pathname: '/layouts/right-sidebar' | |||
pathname: '/layouts/right-sidebar-static' | |||
}} | |||
> | |||
Right Sidebar | |||
Right Sidebar (static) | |||
<PreviewWrapper> | |||
<Preview | |||
src="/layouts/right-sidebar" | |||
src="/layouts/right-sidebar-static" | |||
scrolling="no" | |||
/> | |||
</PreviewWrapper> | |||
@@ -139,7 +164,7 @@ const IndexTemplate: React.FC<Props> = ({ | |||
pathname: '/layouts/left-sidebar/with-menu' | |||
}} | |||
> | |||
Left Sidebar (w/ menu) | |||
Left Sidebar (with menu) | |||
<PreviewWrapper> | |||
<Preview | |||
src="/layouts/left-sidebar/with-menu" | |||
@@ -148,8 +173,8 @@ const IndexTemplate: React.FC<Props> = ({ | |||
</PreviewWrapper> | |||
</StyledLink> | |||
</LinkContainer> | |||
</Container> | |||
</Basic> | |||
</Basic.ContentContainer> | |||
</Basic.Layout> | |||
) | |||
} | |||
@@ -1,47 +1,91 @@ | |||
import * as React from 'react' | |||
import LeftSidebarLayout, { SidebarContainer, Container } from '../../organisms/layouts/LeftSidebar'; | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
import * as T from '@tesseract-design/react-common' | |||
import { LeftSidebar } from '@tesseract-design/viewfinder' | |||
import DummyContent from '../../molecules/DummyContent' | |||
import Link from '../../molecules/Link' | |||
import Brand from '../../molecules/Brand' | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
sidebarMainOpen: boolean, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
searchQueryKey: string, | |||
searchLabel: string, | |||
searchHint: string, | |||
popupQueryKey: string, | |||
userPopupQueryValue: string, | |||
sidebarQueryKey: string, | |||
} | |||
const LeftSidebarLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
sidebarMainOpen, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
searchQueryKey, | |||
searchLabel, | |||
searchHint, | |||
popupQueryKey, | |||
userPopupQueryValue, | |||
sidebarQueryKey, | |||
}) => { | |||
return ( | |||
<LeftSidebarLayout | |||
brand="Brand" | |||
query={query} | |||
<LeftSidebar.Layout | |||
brand={ | |||
<Brand /> | |||
} | |||
sidebarMainOpen={sidebarMainOpen} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
topBarCenter={ | |||
<form> | |||
<T.TextInput | |||
name={searchQueryKey} | |||
label={searchLabel} | |||
hint={searchHint} | |||
defaultValue={query} | |||
border | |||
alternate | |||
/> | |||
</form> | |||
} | |||
menuLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[sidebarQueryKey]: '', | |||
}, | |||
}} | |||
> | |||
<T.Icon | |||
name="menu" | |||
label={menuLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
userLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[popupQueryKey]: userPopupQueryValue, | |||
}, | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label={userLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
sidebarMain={ | |||
<SidebarContainer> | |||
<LeftSidebar.SidebarContainer> | |||
<DummyContent /> | |||
</SidebarContainer> | |||
</LeftSidebar.SidebarContainer> | |||
} | |||
> | |||
<Container> | |||
<LeftSidebar.ContentContainer> | |||
<DummyContent /> | |||
</Container> | |||
</LeftSidebarLayout> | |||
</LeftSidebar.ContentContainer> | |||
</LeftSidebar.Layout> | |||
) | |||
} | |||
@@ -1,151 +1,139 @@ | |||
import * as React from 'react' | |||
import * as T from '@tesseract-design/react-common'; | |||
import LeftSidebarWithMenuLayout, { | |||
Container, | |||
SidebarMainContainer, | |||
} from '../../organisms/layouts/LeftSidebarWithMenu'; | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
import * as T from '@tesseract-design/react-common' | |||
import { LeftSidebarWithMenu } from '@tesseract-design/viewfinder' | |||
import DummyContent from '../../molecules/DummyContent' | |||
import Link from '../../molecules/Link' | |||
import Brand from '../../molecules/Brand' | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
sidebarMainOpen: boolean, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
moreItemsOpen: boolean, | |||
searchQueryKey: string, | |||
searchLabel: string, | |||
searchHint: string, | |||
popupQueryKey: string, | |||
moreQueryKey: string, | |||
sidebarQueryKey: string, | |||
moreLinkLabel: string, | |||
sidebarMenuItems: LeftSidebarWithMenu.MenuItem[], | |||
userPopupQueryValue: string, | |||
} | |||
const LeftSidebarLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
sidebarMainOpen, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
moreItemsOpen, | |||
searchQueryKey, | |||
searchLabel, | |||
searchHint, | |||
popupQueryKey, | |||
moreQueryKey, | |||
sidebarQueryKey, | |||
moreLinkLabel, | |||
sidebarMenuItems, | |||
userPopupQueryValue, | |||
}) => { | |||
return ( | |||
<LeftSidebarWithMenuLayout | |||
brand="Brand" | |||
moreItemsOpen={moreItemsOpen} | |||
query={query} | |||
linkComponent={linkComponent} | |||
sidebarMainOpen={sidebarMainOpen} | |||
sidebarMain={ | |||
<SidebarMainContainer> | |||
<DummyContent /> | |||
</SidebarMainContainer> | |||
<LeftSidebarWithMenu.Layout | |||
brand={ | |||
<Brand /> | |||
} | |||
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', | |||
topBarCenter={ | |||
<form> | |||
<T.TextInput | |||
name={searchQueryKey} | |||
label={searchLabel} | |||
hint={searchHint} | |||
defaultValue={query} | |||
border | |||
alternate | |||
/> | |||
</form> | |||
} | |||
menuLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[sidebarQueryKey]: '', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
secondary: true, | |||
}, | |||
{ | |||
id: '5', | |||
label: 'S2', | |||
url: { | |||
href: '/hello', | |||
}} | |||
> | |||
<T.Icon | |||
name="menu" | |||
label={menuLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
userLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[popupQueryKey]: userPopupQueryValue, | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
secondary: true, | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label={userLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
moreLinkMenuItem={{ | |||
label: moreLinkLabel, | |||
url: { | |||
query: { | |||
[moreQueryKey]: '', | |||
}, | |||
] | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="more-horizontal" | |||
label="" | |||
/> | |||
), | |||
}} | |||
moreItemsOpen={moreItemsOpen} | |||
moreLinkComponent={({ url, icon, label, }) => ( | |||
<Link | |||
href={url} | |||
> | |||
<LeftSidebarWithMenu.MoreSidebarMenuContainer> | |||
<LeftSidebarWithMenu.MoreSidebarMenuItemIcon> | |||
{icon} | |||
</LeftSidebarWithMenu.MoreSidebarMenuItemIcon> | |||
{label} | |||
</LeftSidebarWithMenu.MoreSidebarMenuContainer> | |||
</Link> | |||
)} | |||
linkComponent={({ url, icon, label, }) => ( | |||
<Link | |||
href={url} | |||
> | |||
<LeftSidebarWithMenu.SidebarMenuContainer> | |||
<LeftSidebarWithMenu.SidebarMenuItemIcon> | |||
{icon} | |||
</LeftSidebarWithMenu.SidebarMenuItemIcon> | |||
{label} | |||
</LeftSidebarWithMenu.SidebarMenuContainer> | |||
</Link> | |||
)} | |||
sidebarMainOpen={sidebarMainOpen} | |||
sidebarMain={ | |||
<LeftSidebarWithMenu.SidebarMainContainer> | |||
<DummyContent /> | |||
</LeftSidebarWithMenu.SidebarMainContainer> | |||
} | |||
sidebarMenuItems={sidebarMenuItems} | |||
> | |||
<Container> | |||
<LeftSidebarWithMenu.ContentContainer> | |||
<DummyContent /> | |||
</Container> | |||
</LeftSidebarWithMenuLayout> | |||
</LeftSidebarWithMenu.ContentContainer> | |||
</LeftSidebarWithMenu.Layout> | |||
) | |||
} | |||
@@ -1,44 +1,70 @@ | |||
import * as React from 'react' | |||
import RightSidebarLayout, { SidebarContainer, Container } from '../../organisms/layouts/RightSidebar'; | |||
import DummyContent from '../../molecules/DummyContent'; | |||
import {UrlObject} from 'url'; | |||
import * as T from '@tesseract-design/react-common' | |||
import { RightSidebarStatic } from '@tesseract-design/viewfinder' | |||
import DummyContent from '../../molecules/DummyContent' | |||
import Link from '../../molecules/Link' | |||
import Brand from '../../molecules/Brand' | |||
type Props = { | |||
query: string, | |||
linkComponent: React.ElementType, | |||
menuLink: UrlObject, | |||
userLink: UrlObject, | |||
menuLinkLabel: string, | |||
userLinkLabel: string, | |||
searchQueryKey: string, | |||
searchLabel: string, | |||
searchHint: string, | |||
popupQueryKey: string, | |||
userPopupQueryValue: string, | |||
} | |||
const RightSidebarLayoutTemplate: React.FC<Props> = ({ | |||
query, | |||
linkComponent, | |||
menuLinkLabel, | |||
menuLink, | |||
userLink, | |||
userLinkLabel, | |||
searchQueryKey, | |||
searchLabel, | |||
searchHint, | |||
popupQueryKey, | |||
userPopupQueryValue, | |||
}) => { | |||
return ( | |||
<RightSidebarLayout | |||
brand="Brand" | |||
query={query} | |||
linkComponent={linkComponent} | |||
menuLink={menuLink} | |||
menuLinkLabel={menuLinkLabel} | |||
userLink={userLink} | |||
userLinkLabel={userLinkLabel} | |||
<RightSidebarStatic.Layout | |||
brand={ | |||
<Brand /> | |||
} | |||
topBarCenter={ | |||
<form> | |||
<T.TextInput | |||
name={searchQueryKey} | |||
label={searchLabel} | |||
hint={searchHint} | |||
defaultValue={query} | |||
border | |||
alternate | |||
/> | |||
</form> | |||
} | |||
userLink={ | |||
<Link | |||
href={{ | |||
query: { | |||
[popupQueryKey]: userPopupQueryValue, | |||
}, | |||
}} | |||
> | |||
<T.Icon | |||
name="user" | |||
label={userLinkLabel} | |||
/> | |||
</Link> | |||
} | |||
sidebarMain={ | |||
<SidebarContainer> | |||
<RightSidebarStatic.SidebarContainer> | |||
<DummyContent /> | |||
</SidebarContainer> | |||
</RightSidebarStatic.SidebarContainer> | |||
} | |||
> | |||
<Container> | |||
<RightSidebarStatic.ContentContainer> | |||
<DummyContent /> | |||
</Container> | |||
</RightSidebarLayout> | |||
</RightSidebarStatic.ContentContainer> | |||
</RightSidebarStatic.Layout> | |||
) | |||
} | |||
@@ -1,7 +1,7 @@ | |||
import Head from 'next/head' | |||
import Link from '../components/molecules/Link'; | |||
import Template from '../components/templates/Index'; | |||
import {GetServerSideProps, NextPage} from 'next'; | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import {USER} from '../utilities/popups' | |||
import {QUERY, POPUP} from '../utilities/queryKeys' | |||
import Template from '../components/templates/Index' | |||
type Props = { | |||
query: string, | |||
@@ -12,22 +12,13 @@ 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" | |||
searchQueryKey={QUERY} | |||
searchLabel="Search" | |||
searchHint="e.g. keywords, names…" | |||
popupQueryKey={POPUP} | |||
userPopupQueryValue={USER} | |||
/> | |||
) | |||
} | |||
@@ -35,7 +26,7 @@ const Page: NextPage<Props> = ({ | |||
export default Page | |||
export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
const { q: query = '', } = ctx.query | |||
const { [QUERY]: query = '', } = ctx.query | |||
return { | |||
props: { | |||
query, | |||
@@ -1,6 +1,7 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../components/templates/BasicLayout' | |||
import Link from '../../../components/molecules/Link'; | |||
import {USER} from '../../../utilities/popups' | |||
import {POPUP, QUERY} from '../../../utilities/queryKeys' | |||
type Props = { | |||
query: string, | |||
@@ -11,22 +12,13 @@ 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" | |||
searchQueryKey={QUERY} | |||
searchLabel="Search" | |||
searchHint="e.g. keywords, names…" | |||
popupQueryKey={POPUP} | |||
userPopupQueryValue={USER} | |||
/> | |||
) | |||
} | |||
@@ -34,7 +26,7 @@ const Page: NextPage<Props> = ({ | |||
export default Page | |||
export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
const { q: query = '', } = ctx.query | |||
const { [QUERY]: query = '', } = ctx.query | |||
return { | |||
props: { | |||
query, | |||
@@ -1,6 +1,7 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../components/templates/LeftSidebarLayout' | |||
import Link from '../../../components/molecules/Link'; | |||
import {POPUP, QUERY, SIDEBAR} from '../../../utilities/queryKeys' | |||
import {USER} from '../../../utilities/popups' | |||
type Props = { | |||
query: string, | |||
@@ -15,21 +16,14 @@ 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" | |||
searchQueryKey={QUERY} | |||
searchLabel="Search" | |||
searchHint="e.g. keywords, names…" | |||
popupQueryKey={POPUP} | |||
userPopupQueryValue={USER} | |||
menuLinkLabel="Menu" | |||
sidebarQueryKey={SIDEBAR} | |||
/> | |||
) | |||
} | |||
@@ -37,7 +31,7 @@ const Page: NextPage<Props> = ({ | |||
export default Page | |||
export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
const { q: query = '', } = ctx.query | |||
const { [QUERY]: query = '', } = ctx.query | |||
return { | |||
props: { | |||
query, | |||
@@ -1,6 +1,9 @@ | |||
import * as React from 'react' | |||
import * as T from '@tesseract-design/react-common' | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../../components/templates/LeftSidebarWithMenuLayout' | |||
import Link from '../../../../components/molecules/Link'; | |||
import {MORE, POPUP, QUERY, SIDEBAR} from '../../../../utilities/queryKeys' | |||
import {USER} from '../../../../utilities/popups' | |||
type Props = { | |||
query: string, | |||
@@ -16,23 +19,113 @@ const Page: NextPage<Props> = ({ | |||
return ( | |||
<Template | |||
query={query} | |||
sidebarMainOpen={sidebarMainOpen} | |||
linkComponent={Link} | |||
menuLink={{ | |||
query: { | |||
q: query, | |||
sidebar: '', | |||
} | |||
}} | |||
menuLinkLabel="Menu" | |||
userLink={{ | |||
pathname: '/profile', | |||
query: { | |||
q: query, | |||
}, | |||
}} | |||
moreQueryKey={MORE} | |||
userLinkLabel="User" | |||
searchQueryKey={QUERY} | |||
searchLabel="Search" | |||
searchHint="e.g. keywords, names…" | |||
popupQueryKey={POPUP} | |||
userPopupQueryValue={USER} | |||
menuLinkLabel="Menu" | |||
sidebarQueryKey={SIDEBAR} | |||
sidebarMainOpen={sidebarMainOpen} | |||
moreLinkLabel="More" | |||
moreItemsOpen={moreItemsOpen} | |||
sidebarMenuItems={[ | |||
{ | |||
id: '1', | |||
label: 'P1', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '2', | |||
label: 'P2', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '3', | |||
label: 'P3', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '100', | |||
label: 'P4', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '101', | |||
label: 'P5', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
}, | |||
{ | |||
id: '4', | |||
label: 'S1', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
secondary: true, | |||
}, | |||
{ | |||
id: '5', | |||
label: 'S2', | |||
url: { | |||
pathname: '/hello', | |||
}, | |||
icon: ( | |||
<T.Icon | |||
name="square" | |||
label="" | |||
/> | |||
), | |||
secondary: true, | |||
}, | |||
]} | |||
/> | |||
) | |||
} | |||
@@ -1,6 +1,7 @@ | |||
import {GetServerSideProps, NextPage} from 'next' | |||
import Template from '../../../components/templates/RightSidebarLayout' | |||
import Link from '../../../components/molecules/Link'; | |||
import {POPUP, QUERY} from '../../../utilities/queryKeys' | |||
import {USER} from '../../../utilities/popups' | |||
type Props = { | |||
query: string, | |||
@@ -11,22 +12,13 @@ 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" | |||
searchQueryKey={QUERY} | |||
searchLabel="Search" | |||
searchHint="e.g. keywords, names…" | |||
popupQueryKey={POPUP} | |||
userPopupQueryValue={USER} | |||
/> | |||
) | |||
} | |||
@@ -34,7 +26,7 @@ const Page: NextPage<Props> = ({ | |||
export default Page | |||
export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
const { q: query = '', } = ctx.query | |||
const { [QUERY]: query = '', } = ctx.query | |||
return { | |||
props: { | |||
query, |
@@ -0,0 +1 @@ | |||
export const USER = 'user' |
@@ -0,0 +1,7 @@ | |||
export const QUERY = 'q' | |||
export const POPUP = 'popup' | |||
export const SIDEBAR = 'sidebar' | |||
export const MORE = 'more' |