@@ -13,7 +13,7 @@ | |||
"pridepack" | |||
], | |||
"dependencies": { | |||
"@tesseract-design/goofy-goober": "link:../../../goofy-goober" | |||
"tailwindcss": "^3.3.3" | |||
}, | |||
"devDependencies": { | |||
"@types/node": "^18.0.0", | |||
@@ -1,13 +1 @@ | |||
export enum Span { | |||
NARROW = 'narrow', | |||
NORMAL = 'normal', | |||
WIDE = 'wide', | |||
} | |||
export type LayoutArgs = { | |||
span: Span; | |||
mainSidebarOpen: boolean; | |||
auxiliaryItemsShown: boolean; | |||
} | |||
export { setup, extractCss } from '@tesseract-design/goofy-goober'; | |||
export type Span = 'narrow' | 'normal' | 'wide'; |
@@ -1,3 +1,2 @@ | |||
export * as layouts from './layouts'; | |||
export * as widgets from './widgets'; | |||
export * from './common'; | |||
export * as tailwind from './plugin-tailwind'; |
@@ -1,34 +0,0 @@ | |||
import { css } from '@tesseract-design/goofy-goober'; | |||
import {LayoutArgs, Span} from '../common'; | |||
export const ContentBase = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
` | |||
); | |||
export const ContentContainer = ({ | |||
span, | |||
}: LayoutArgs) => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
margin: 0 auto; | |||
width: 100%; | |||
`, | |||
css.if(span === Span.NARROW)( | |||
css` | |||
max-width: var(--base-width); | |||
` | |||
), | |||
css.if(span === Span.NORMAL)( | |||
css` | |||
max-width: calc(var(--base-width) * 2); | |||
` | |||
), | |||
css.if(span === Span.WIDE)( | |||
css` | |||
max-width: calc(var(--base-width) * 3); | |||
` | |||
), | |||
); |
@@ -1,90 +0,0 @@ | |||
import { css } from '@tesseract-design/goofy-goober'; | |||
import {LayoutArgs} from '../common'; | |||
export const ContentBase = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
padding-left: calc(50% - (var(--base-width) * 0.5)); | |||
` | |||
), | |||
); | |||
export const SidebarOverflow = () => css.cx( | |||
css` | |||
width: 100%; | |||
height: 100%; | |||
overflow: auto; | |||
// overflow: overlay; | |||
position: relative; | |||
z-index: 1; | |||
scrollbar-width: none; | |||
&::-webkit-scrollbar { | |||
display: none; | |||
} | |||
` | |||
) | |||
export const SidebarBase = ({ | |||
mainSidebarOpen, | |||
}: LayoutArgs) => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
position: fixed; | |||
top: 0; | |||
left: -100%; | |||
width: 100%; | |||
height: 100%; | |||
background-color: var(--color-background, white); | |||
& > * { | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: calc(50% - (var(--base-width) * 0.5)); | |||
left: 0; | |||
` | |||
), | |||
css.if(mainSidebarOpen)( | |||
css` | |||
left: 0; | |||
` | |||
), | |||
); | |||
export const SidebarMainContainer = () => css.cx( | |||
css` | |||
width: 100%; | |||
margin: 0 auto; | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
max-width: calc(var(--base-width) * 2); | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: var(--base-width); | |||
margin-right: 0; | |||
` | |||
), | |||
); | |||
export const ContentContainer = () => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
width: 100%; | |||
max-width: calc(var(--base-width) * 2); | |||
margin-right: auto; | |||
margin-left: auto; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
margin-left: 0; | |||
` | |||
), | |||
); |
@@ -1,380 +0,0 @@ | |||
import { css } from '@tesseract-design/goofy-goober'; | |||
import {LayoutArgs} from '../common'; | |||
export const ContentBase = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
padding-bottom: var(--size-menu, 4rem); | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
padding-left: calc(50% - var(--base-width) * 0.5); | |||
padding-bottom: 0; | |||
`, | |||
), | |||
) | |||
export const SidebarBase = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
overflow: hidden; | |||
display: contents; | |||
left: calc(var(--base-width) * -1); | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
position: fixed; | |||
top: 0; | |||
left: 0; | |||
width: calc(50% - var(--base-width) * 0.5); | |||
height: 100%; | |||
display: block; | |||
`, | |||
), | |||
) | |||
export const SidebarMain = ({ | |||
mainSidebarOpen, | |||
}: LayoutArgs) => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
position: fixed; | |||
top: 0; | |||
width: 100%; | |||
height: 100%; | |||
padding-top: inherit; | |||
padding-bottom: var(--size-menu, 4rem); | |||
z-index: 2; | |||
background-color: var(--color-background, white); | |||
> * { | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
background-color: var(--color-background, white); | |||
} | |||
`, | |||
css.dynamic({ | |||
right: mainSidebarOpen ? 0 : '100%', | |||
}), | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
position: absolute; | |||
right: 0; | |||
width: calc(var(--base-width) - var(--size-menu, 4rem)); | |||
margin-left: 0; | |||
padding-bottom: 0; | |||
`, | |||
), | |||
) | |||
export const SidebarMainOverflow = () => css.cx( | |||
css` | |||
width: 100%; | |||
height: 100%; | |||
overflow: auto; /* overflow: overlay */ | |||
scrollbar-width: none; | |||
position: relative; | |||
z-index: 1; | |||
::-webkit-scrollbar { | |||
display: none; | |||
} | |||
` | |||
) | |||
export const SidebarMenu = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
overflow: auto; /* overflow: overlay */ | |||
scrollbar-width: none; | |||
::-webkit-scrollbar { | |||
display: none; | |||
} | |||
position: fixed; | |||
bottom: 0; | |||
left: 0; | |||
width: 100%; | |||
height: var(--size-menu, 4rem); | |||
z-index: 1; | |||
background-color: var(--color-background, white); | |||
> * { | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
background-color: var(--color-background, white); | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
top: 0; | |||
margin-left: auto; | |||
position: absolute; | |||
height: 100%; | |||
padding-top: inherit; | |||
overflow: auto; | |||
z-index: auto; | |||
`, | |||
), | |||
); | |||
export const SidebarMenuSize = () => css.cx( | |||
css` | |||
display: flex; | |||
width: 100%; | |||
height: 100%; | |||
max-width: calc(var(--base-width) * 2); | |||
margin: 0 auto; | |||
position: relative; | |||
z-index: 1; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
max-width: none; | |||
margin-right: 0; | |||
flex-direction: column; | |||
justify-content: space-between; | |||
align-items: flex-end; | |||
`, | |||
), | |||
); | |||
export const SidebarMenuGroup = () => css.cx( | |||
css` | |||
display: contents; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: 100%; | |||
display: block; | |||
`, | |||
), | |||
); | |||
export const MoreItems = ({ | |||
auxiliaryItemsShown, | |||
}: LayoutArgs) => css.cx( | |||
css` | |||
position: fixed; | |||
top: 0; | |||
width: 100%; | |||
height: 100%; | |||
padding-top: var(--height-topbar, 4rem); | |||
padding-bottom: var(--size-menu, 4rem); | |||
z-index: -1; | |||
box-sizing: border-box; | |||
`, | |||
css.dynamic({ | |||
left: auxiliaryItemsShown ? 0 : '-100%', | |||
}), | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
display: contents; | |||
`, | |||
), | |||
); | |||
export const MoreItemsScroll = () => css.cx( | |||
css` | |||
width: 100%; | |||
height: 100%; | |||
overflow: auto; | |||
background-color: var(--color-background, white); | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
display: contents; | |||
`, | |||
), | |||
); | |||
export const MorePrimarySidebarMenuGroup = () => css.cx( | |||
css` | |||
display: contents; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: 100%; | |||
display: block; | |||
flex: auto; | |||
`, | |||
), | |||
); | |||
export const MoreSecondarySidebarMenuGroup = () => css.cx( | |||
css` | |||
display: contents; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: 100%; | |||
display: block; | |||
order: 4; | |||
`, | |||
), | |||
); | |||
export const SidebarMenuItem = () => css.cx( | |||
css` | |||
width: 0; | |||
flex: auto; | |||
height: var(--size-menu, 4rem); | |||
> * { | |||
height: 100%; | |||
display: flex; | |||
align-items: center; | |||
text-decoration: none; | |||
width: 100%; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: auto !important; | |||
flex: 0 1 auto; | |||
> * { | |||
height: auto; | |||
} | |||
` | |||
), | |||
); | |||
export const MoreSidebarMenuItem = () => css.cx( | |||
css` | |||
height: var(--size-menu, 4rem); | |||
display: block; | |||
> * { | |||
height: 100%; | |||
display: flex; | |||
align-items: center; | |||
text-decoration: none; | |||
width: 100%; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: auto !important; | |||
flex: 0 1 auto; | |||
`, | |||
), | |||
); | |||
export const MoreToggleSidebarMenuItem = () => css.cx( | |||
css` | |||
width: 0; | |||
flex: auto; | |||
height: var(--size-menu, 4rem); | |||
> * { | |||
height: 100%; | |||
display: flex; | |||
align-items: center; | |||
text-decoration: none; | |||
width: 100%; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
display: none; | |||
`, | |||
), | |||
); | |||
export const SidebarMenuItemIcon = () => css.cx( | |||
css` | |||
display: block; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: var(--size-menu, 4rem); | |||
height: var(--size-menu, 4rem); | |||
display: grid; | |||
place-content: center; | |||
`, | |||
), | |||
); | |||
export const MoreSidebarMenuItemIcon = () => css.cx( | |||
css` | |||
margin-right: 1rem; | |||
display: block; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
width: var(--size-menu, 4rem); | |||
height: var(--size-menu, 4rem); | |||
display: grid; | |||
place-content: center; | |||
margin-right: 0; | |||
`, | |||
), | |||
); | |||
export const SidebarMenuContainer = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
display: grid; | |||
place-content: center; | |||
width: 100%; | |||
text-align: center; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
display: flex; | |||
justify-content: flex-start; | |||
align-items: center; | |||
margin-left: auto; | |||
padding-right: 1rem; | |||
text-align: left; | |||
box-sizing: border-box; | |||
width: var(--base-width); | |||
`, | |||
), | |||
) | |||
export const MoreSidebarMenuContainer = () => css.cx( | |||
css` | |||
display: flex; | |||
justify-content: flex-start; | |||
align-items: center; | |||
width: calc(var(--base-width) * 2); | |||
margin: 0 auto; | |||
padding: 0 1rem; | |||
text-align: left; | |||
box-sizing: border-box; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
margin-right: 0; | |||
width: var(--base-width); | |||
padding-left: 0; | |||
`, | |||
), | |||
); | |||
export const ContentContainer = () => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
width: 100%; | |||
max-width: calc(var(--base-width) * 2); | |||
margin-right: auto; | |||
margin-left: auto; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
margin-left: 0; | |||
`, | |||
), | |||
); | |||
export const SidebarMainContainer = () => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
width: 100%; | |||
max-width: calc(var(--base-width) * 2); | |||
margin: 0 auto; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
max-width: none; | |||
`, | |||
), | |||
); |
@@ -1,83 +0,0 @@ | |||
import { css } from '@tesseract-design/goofy-goober'; | |||
export const ContentBase = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
padding-right: calc(50% - (var(--base-width) * 0.5)); | |||
` | |||
), | |||
); | |||
export const SidebarBase = () => css.cx( | |||
css` | |||
box-sizing: border-box; | |||
background-color: var(--color-background, white); | |||
`, | |||
// prevent collapse of margin | |||
css` | |||
&::after { | |||
content: ''; | |||
display: block; | |||
padding-bottom: 1px; | |||
margin-top: -1px; | |||
box-sizing: border-box; | |||
} | |||
& > * { | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
position: absolute; | |||
top: 0; | |||
right: 0; | |||
width: calc(50% - var(--base-width) * 0.5); | |||
height: 100%; | |||
`, | |||
), | |||
) | |||
export const SidebarMainContent = () => css.cx( | |||
css` | |||
position: relative; | |||
z-index: 1; | |||
` | |||
) | |||
export const SidebarMainContainer = () => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
width: 100%; | |||
max-width: calc(var(--base-width) * 2); | |||
margin: 0 auto; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
margin-left: 0; | |||
width: var(--base-width); | |||
`, | |||
), | |||
) | |||
export const ContentContainer = () => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
width: 100%; | |||
max-width: calc(var(--base-width) * 2); | |||
margin: 0 auto; | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
margin-right: 0; | |||
`, | |||
), | |||
) | |||
// TODO port from original viewfinder package |
@@ -1,4 +0,0 @@ | |||
export * as Basic from './Basic'; | |||
export * as LeftSidebar from './LeftSidebar'; | |||
export * as LeftSidebarWithMenu from './LeftSidebarWithMenu'; | |||
export * as RightSidebarStatic from './RightSidebarStatic'; |
@@ -0,0 +1,138 @@ | |||
import tailwindPlugin from 'tailwindcss/plugin'; | |||
export interface ViewfinderPluginOptions { | |||
baseWidth?: number; | |||
topbarHeight?: string; | |||
sizeMenu?: string; | |||
colorBackground?: string; | |||
} | |||
export const plugin = tailwindPlugin.withOptions<ViewfinderPluginOptions>( | |||
({ | |||
baseWidth = 360 as const, | |||
topbarHeight = '4rem' as const, | |||
sizeMenu = topbarHeight, | |||
colorBackground = '255 255 255' as const, | |||
} = {} as ViewfinderPluginOptions) => ({ | |||
addBase, | |||
addComponents, | |||
addUtilities, | |||
}) => { | |||
addBase({ | |||
':root': { | |||
'--base-width': `${baseWidth}px`, | |||
'--height-topbar': topbarHeight, | |||
'--size-menu': sizeMenu, | |||
'--color-background': colorBackground, | |||
}, | |||
}); | |||
addBase({ | |||
':root': { | |||
'background-color': 'rgb(var(--color-background))', | |||
}, | |||
}); | |||
addComponents({ | |||
'.topbar': { | |||
height: 'var(--height-topbar, 4rem)', | |||
'& ~ *': { | |||
'padding-top': 'var(--height-topbar, 4rem)', | |||
}, | |||
'& ~ [data-viewfinder="main"] ~ *': { | |||
'padding-top': '0', | |||
}, | |||
'& [data-viewfinder="menu"] > *': { | |||
'width': '100%', | |||
'height': '100%', | |||
'display': 'grid', | |||
'place-content': 'center', | |||
}, | |||
'& [data-viewfinder="user"] > *': { | |||
'width': '100%', | |||
'height': '100%', | |||
'display': 'grid', | |||
'place-content': 'center', | |||
}, | |||
[`@media (min-width: ${baseWidth * 3}px)`]: { | |||
'& ~ [data-viewfinder="main"] ~ *': { | |||
'padding-top': 'var(--height-topbar, 4rem)', | |||
}, | |||
'& [data-viewfinder="menu"] > *': { | |||
'position': 'absolute', | |||
'left': '-999999px', | |||
}, | |||
'& [data-viewfinder="menu"] > *:focus': { | |||
'position': 'static', | |||
}, | |||
}, | |||
}, | |||
}); | |||
addUtilities({ | |||
'.scrollbar-hidden': { | |||
'scrollbar-width': 'none', | |||
'&::-webkit-scrollbar': { | |||
'display': 'none', | |||
}, | |||
}, | |||
}); | |||
addComponents({ | |||
'.left-sidebar-with-menu-base': { | |||
'& [data-viewfinder="menu-item"] > *': { | |||
'height': '100%', | |||
'display': 'flex', | |||
'align-items': 'center', | |||
'text-decoration': 'none', | |||
'width': '100%', | |||
}, | |||
[`@media (min-width: ${baseWidth * 3}px)`]: { | |||
'& [data-viewfinder="menu-item"]': { | |||
'width': 'auto !important', | |||
}, | |||
'& [data-viewfinder="menu-item"] > *': { | |||
'height': 'auto', | |||
}, | |||
}, | |||
}, | |||
}); | |||
}, | |||
({ | |||
baseWidth = 360 as const, | |||
} = {} as ViewfinderPluginOptions) => ({ | |||
theme: { | |||
screens: { | |||
'3xs': `${baseWidth}px`, | |||
'2xs': `${baseWidth * 1.5}px`, | |||
xs: `${baseWidth * 2}px`, | |||
sm: `${baseWidth * 2.5}px`, | |||
md: `${baseWidth * 3}px`, | |||
lg: `${baseWidth * 4}px`, | |||
xl: `${baseWidth * 5}px`, | |||
'2xl': `${baseWidth * 6}px`, | |||
'3xl': `${baseWidth * 7}px`, | |||
}, | |||
extend: { | |||
colors: { | |||
bg: 'rgb(var(--color-background))', | |||
}, | |||
spacing: { | |||
topbar: 'var(--height-topbar, 4rem)', | |||
menu: 'var(--size-menu, var(--height-topbar, 4rem))', | |||
inherit: 'inherit', | |||
}, | |||
maxWidth: { | |||
'screen-3xs': `${baseWidth}px`, | |||
'screen-2xs': `${baseWidth * 1.5}px`, | |||
'screen-xs': `${baseWidth * 2}px`, | |||
'screen-sm': `${baseWidth * 2.5}px`, | |||
'screen-md': `${baseWidth * 3}px`, | |||
'screen-lg': `${baseWidth * 4}px`, | |||
'screen-xl': `${baseWidth * 5}px`, | |||
'screen-2xl': `${baseWidth * 6}px`, | |||
'screen-3xl': `${baseWidth * 7}px`, | |||
}, | |||
minWidth: { | |||
32: '8rem', | |||
}, | |||
}, | |||
}, | |||
}), | |||
); |
@@ -1,125 +0,0 @@ | |||
import { css } from '@tesseract-design/goofy-goober'; | |||
import {LayoutArgs, Span} from '../common'; | |||
export const Base = () => css.cx( | |||
css` | |||
position: fixed; | |||
top: 0; | |||
left: 0; | |||
width: 100%; | |||
height: var(--height-topbar, 4rem); | |||
z-index: 3; | |||
& > * { | |||
display: block; | |||
width: 100%; | |||
height: 100%; | |||
background-color: var(--color-background, white); | |||
} | |||
& ~ * { | |||
padding-top: var(--height-topbar, 4rem); | |||
} | |||
~ main ~ * { | |||
padding-top: 0; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
~ main ~ * { | |||
padding-top: var(--height-topbar, 4rem); | |||
} | |||
` | |||
) | |||
); | |||
export const Container = ({ | |||
span, | |||
}: LayoutArgs) => css.cx( | |||
css` | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
margin: 0 auto; | |||
width: 100%; | |||
height: 100%; | |||
display: flex; | |||
align-items: center; | |||
position: relative; | |||
z-index: 1; | |||
`, | |||
css.if(span === Span.NARROW)( | |||
css` | |||
max-width: var(--base-width); | |||
` | |||
), | |||
css.if(span === Span.NORMAL)( | |||
css` | |||
max-width: calc(var(--base-width) * 2); | |||
` | |||
), | |||
css.if(span === Span.WIDE)( | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
max-width: calc(var(--base-width) * 3); | |||
` | |||
) | |||
), | |||
); | |||
export const CenterContainer = () => css.cx( | |||
css` | |||
flex: auto; | |||
padding: 0 1rem; | |||
box-sizing: border-box; | |||
`, | |||
css.nest(':first-child')( | |||
css` | |||
padding-left: 0; | |||
` | |||
) | |||
) | |||
export const ActionContainer = () => css.cx( | |||
css` | |||
display: flex; | |||
align-items: center; | |||
justify-content: flex-end; | |||
height: 100%; | |||
white-space: nowrap; | |||
`, | |||
css.media('(min-width: 720px)')( | |||
css` | |||
min-width: 8rem; | |||
` | |||
) | |||
); | |||
export const LinkContainer = () => css.cx( | |||
css` | |||
width: var(--height-topbar, 4rem); | |||
height: 100%; | |||
& > * { | |||
width: 100%; | |||
height: 100%; | |||
display: inline-grid; | |||
place-content: center; | |||
} | |||
` | |||
); | |||
export const MenuLinkContainer = () => css.cx( | |||
css` | |||
width: var(--height-topbar, 4rem); | |||
height: 100%; | |||
& > * { | |||
width: 100%; | |||
height: 100%; | |||
display: inline-grid; | |||
place-content: center; | |||
} | |||
`, | |||
css.media('(min-width: 1080px)')( | |||
css` | |||
position: absolute; | |||
left: -999999px; | |||
` | |||
) | |||
); |
@@ -1 +0,0 @@ | |||
export * as TopBar from './TopBar'; |
@@ -1,3 +1,6 @@ | |||
{ | |||
"extends": "next/core-web-vitals" | |||
"extends": "next/core-web-vitals", | |||
"rules": { | |||
"@next/next/no-html-link-for-pages": "off" | |||
} | |||
} |
@@ -2,6 +2,9 @@ | |||
const nextConfig = { | |||
reactStrictMode: true, | |||
swcMinify: true, | |||
experimental: { | |||
optimizeCss: true, | |||
}, | |||
} | |||
module.exports = nextConfig |
@@ -9,8 +9,8 @@ | |||
"lint": "next lint" | |||
}, | |||
"dependencies": { | |||
"@tesseract-design/viewfinder-react": "link:../../react", | |||
"goober": "^2.1.12", | |||
"@tesseract-design/viewfinder-base": "workspace:*", | |||
"@tesseract-design/viewfinder-react": "workspace:*", | |||
"next": "12.2.4", | |||
"react": "18.2.0", | |||
"react-dom": "18.2.0", | |||
@@ -20,8 +20,12 @@ | |||
"@types/node": "18.6.4", | |||
"@types/react": "18.0.15", | |||
"@types/react-dom": "18.0.6", | |||
"autoprefixer": "^10.4.14", | |||
"critters": "^0.0.19", | |||
"eslint": "8.21.0", | |||
"eslint-config-next": "12.2.4", | |||
"postcss": "^8.4.27", | |||
"tailwindcss": "^3.3.3", | |||
"typescript": "4.7.4" | |||
} | |||
} |
@@ -0,0 +1,6 @@ | |||
module.exports = { | |||
plugins: { | |||
tailwindcss: {}, | |||
autoprefixer: {}, | |||
}, | |||
} |
@@ -1,9 +1,11 @@ | |||
import type { AppProps } from 'next/app' | |||
import { setup } from '@tesseract-design/viewfinder-react'; | |||
import * as gooberPrefixer from 'goober/prefixer'; | |||
// import { setup } from '@tesseract-design/viewfinder-react'; | |||
// import * as gooberPrefixer from 'goober/prefixer'; | |||
import * as React from 'react'; | |||
setup(React.createElement, gooberPrefixer.prefix); | |||
import '../tailwind.css'; | |||
// setup(React.createElement, gooberPrefixer.prefix); | |||
const MyApp: React.FC<AppProps> = ({ Component, pageProps }) => <Component {...pageProps} /> | |||
@@ -1,89 +0,0 @@ | |||
import NextDocument, {Html, Head as NextHead, Main, NextScript, DocumentContext} from 'next/document'; | |||
import { extractCss } from '@tesseract-design/viewfinder-react'; | |||
export default class Document extends NextDocument { | |||
static async getInitialProps(ctx: DocumentContext) { | |||
const page = await ctx.renderPage() | |||
const style = extractCss(); | |||
const initialProps = await NextDocument.getInitialProps(ctx) | |||
return { | |||
...initialProps, | |||
...page, | |||
style, | |||
} | |||
} | |||
render() { | |||
const { style: rawStyle } = this.props as Record<string, unknown> | |||
const style = rawStyle as string | |||
return ( | |||
<Html> | |||
<NextHead> | |||
{ | |||
style.length > 0 | |||
&& ( | |||
<style | |||
id="_goober_ssr" | |||
dangerouslySetInnerHTML={{ __html: style }} | |||
/> | |||
) | |||
} | |||
<style> | |||
{` | |||
:root { | |||
--base-width: 360px; | |||
--color-background: white; | |||
} | |||
html, | |||
body { | |||
padding: 0; | |||
margin: 0; | |||
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, | |||
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; | |||
line-height: 1.75; | |||
} | |||
a { | |||
color: inherit; | |||
text-decoration: none; | |||
} | |||
* { | |||
box-sizing: border-box; | |||
} | |||
@media (prefers-color-scheme: dark) { | |||
:root { | |||
--color-background: black; | |||
} | |||
html { | |||
color-scheme: dark; | |||
} | |||
body { | |||
color: white; | |||
background-color: var(--color-background); | |||
} | |||
} | |||
#__next { | |||
display: contents; | |||
background-color: inherit; | |||
} | |||
`} | |||
</style> | |||
</NextHead> | |||
<body> | |||
<Main /> | |||
<NextScript /> | |||
</body> | |||
</Html> | |||
) | |||
} | |||
} |
@@ -1,13 +1,12 @@ | |||
import type {GetServerSideProps, NextPage} from 'next'; | |||
import ReactMarkdown from 'react-markdown'; | |||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||
import {Span} from '@tesseract-design/viewfinder-base'; | |||
import {Brand} from '../../components/Brand'; | |||
import {Image} from '../../components/Image'; | |||
import Link from 'next/link'; | |||
type BaseLayoutPageProps = { | |||
span: Span; | |||
span: 'narrow' | 'normal' | 'wide'; | |||
} | |||
const BasicLayoutPage: NextPage<BaseLayoutPageProps> = ({ | |||
@@ -20,7 +19,7 @@ const BasicLayoutPage: NextPage<BaseLayoutPageProps> = ({ | |||
brand={ | |||
<Brand /> | |||
} | |||
span={span as Span} | |||
span={span} | |||
userLink={ | |||
<Link | |||
href={{ | |||
@@ -36,7 +35,7 @@ const BasicLayoutPage: NextPage<BaseLayoutPageProps> = ({ | |||
} | |||
> | |||
<Layouts.Basic.ContentContainer | |||
span={span as Span} | |||
span={span} | |||
> | |||
<ReactMarkdown | |||
components={{ | |||
@@ -75,7 +74,7 @@ export default BasicLayoutPage | |||
export const getServerSideProps: GetServerSideProps = async (ctx) => { | |||
return { | |||
props: { | |||
span: ctx.query.span ?? Span.NORMAL, | |||
span: ctx.query.span ?? 'normal', | |||
} | |||
} | |||
} |
@@ -68,7 +68,7 @@ const LeftSidebarWithMenuLayoutPage: NextPage<LeftSidebarWithMenuLayoutPageProps | |||
<Layouts.LeftSidebarWithMenu.Root | |||
sidebarBaseWidget={ | |||
<Widgets.LeftSidebarWithMenuBase | |||
span={Span.WIDE} | |||
span="wide" | |||
open={sidebarOpen} | |||
moreItemsOpen={moreItemsOpen} | |||
items={[ | |||
@@ -188,7 +188,7 @@ const LeftSidebarWithMenuLayoutPage: NextPage<LeftSidebarWithMenuLayoutPageProps | |||
User | |||
</Link> | |||
} | |||
span={Span.WIDE} | |||
span="wide" | |||
/> | |||
} | |||
> | |||
@@ -1,6 +1,5 @@ | |||
import type { NextPage } from 'next' | |||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||
import {Span} from '@tesseract-design/viewfinder-base'; | |||
import Link from 'next/link'; | |||
import {Brand} from '../../components/Brand'; | |||
import {Image} from '../../components/Image'; | |||
@@ -20,7 +19,6 @@ const LeftSidebarLayoutPage: NextPage<LeftSidebarLayoutPageProps> = ({ | |||
<Layouts.LeftSidebar.Root | |||
sidebarBaseWidget={ | |||
<Widgets.LeftSidebarBase | |||
span={Span.WIDE} | |||
open={sidebarOpen} | |||
> | |||
<a | |||
@@ -74,7 +72,7 @@ const LeftSidebarLayoutPage: NextPage<LeftSidebarLayoutPageProps> = ({ | |||
}, | |||
}} | |||
> | |||
Menu | |||
Menu | |||
</Link> | |||
} | |||
userLink={ | |||
@@ -85,10 +83,10 @@ const LeftSidebarLayoutPage: NextPage<LeftSidebarLayoutPageProps> = ({ | |||
}, | |||
}} | |||
> | |||
User | |||
User | |||
</Link> | |||
} | |||
span={Span.WIDE} | |||
span="wide" | |||
/> | |||
} | |||
> | |||
@@ -1,6 +1,5 @@ | |||
import type { NextPage } from 'next' | |||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||
import {Span} from '@tesseract-design/viewfinder-base'; | |||
import Link from 'next/link'; | |||
import {Brand} from '../../../components/Brand'; | |||
import {GetServerSideProps} from 'next'; | |||
@@ -68,7 +67,7 @@ const LeftSidebarWithMenuLayoutPage: NextPage<LeftSidebarWithMenuLayoutPageProps | |||
<Layouts.LeftSidebarWithMenu.Root | |||
sidebarBaseWidget={ | |||
<Widgets.LeftSidebarWithMenuBase | |||
span={Span.WIDE} | |||
span="wide" | |||
open={sidebarOpen} | |||
moreItemsOpen={moreItemsOpen} | |||
items={[ | |||
@@ -151,7 +150,7 @@ const LeftSidebarWithMenuLayoutPage: NextPage<LeftSidebarWithMenuLayoutPageProps | |||
User | |||
</Link> | |||
} | |||
span={Span.WIDE} | |||
span="wide" | |||
/> | |||
} | |||
> | |||
@@ -1,6 +1,5 @@ | |||
import type { NextPage } from 'next' | |||
import { Layouts, Widgets } from '@tesseract-design/viewfinder-react'; | |||
import {Span} from '@tesseract-design/viewfinder-base'; | |||
import {Brand} from '../../components/Brand'; | |||
import {Image} from '../../components/Image'; | |||
import ReactMarkdown from 'react-markdown'; | |||
@@ -10,9 +9,7 @@ const RightSidebarStaticLayoutPage: NextPage = () => { | |||
return ( | |||
<Layouts.RightSidebarStatic.Root | |||
sidebarBaseWidget={ | |||
<Widgets.RightSidebarStaticBase | |||
span={Span.WIDE} | |||
> | |||
<Widgets.RightSidebarStaticBase> | |||
<a | |||
href="#foo" | |||
style={{ | |||
@@ -67,7 +64,7 @@ const RightSidebarStaticLayoutPage: NextPage = () => { | |||
User | |||
</Link> | |||
} | |||
span={Span.WIDE} | |||
span="wide" | |||
/> | |||
} | |||
> | |||
@@ -0,0 +1,3 @@ | |||
@tailwind base; | |||
@tailwind components; | |||
@tailwind utilities; |
@@ -0,0 +1,14 @@ | |||
const { tailwind } = require('@tesseract-design/viewfinder-base'); | |||
const { plugin: viewfinderPlugin } = tailwind; | |||
/** @type {import('tailwindcss').Config} */ | |||
module.exports = { | |||
content: [ | |||
'./src/components/**/*.tsx', | |||
'./src/pages/**/*.tsx', | |||
'./node_modules/@tesseract-design/viewfinder-react/dist/**/*.js', | |||
], | |||
plugins: [ | |||
viewfinderPlugin(), | |||
], | |||
} |
@@ -13,7 +13,8 @@ | |||
"pridepack" | |||
], | |||
"dependencies": { | |||
"@tesseract-design/viewfinder-base": "link:../base" | |||
"@tesseract-design/viewfinder-base": "workspace:*", | |||
"clsx": "^2.0.0" | |||
}, | |||
"devDependencies": { | |||
"@testing-library/jest-dom": "^5.16.4", | |||
@@ -1,3 +1,2 @@ | |||
export * as Layouts from './layouts'; | |||
export * as Widgets from './widgets'; | |||
export { setup, extractCss } from '@tesseract-design/viewfinder-base'; |
@@ -1,7 +1,8 @@ | |||
import * as React from 'react'; | |||
import {LayoutArgs, layouts, Span} from '@tesseract-design/viewfinder-base'; | |||
import clsx from 'clsx'; | |||
import { SpanValues as Span } from '@tesseract-design/viewfinder-base'; | |||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||
export interface RootProps extends React.HTMLProps<HTMLDivElement> { | |||
topBarWidget?: React.ReactNode; | |||
} | |||
@@ -12,13 +13,14 @@ export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||
}, ref) => ( | |||
<> | |||
{topBarWidget} | |||
<main | |||
<div | |||
{...etcProps} | |||
className={layouts.Basic.ContentBase()} | |||
data-viewfinder="main" | |||
className="box-border" | |||
ref={ref} | |||
> | |||
{children} | |||
</main> | |||
</div> | |||
</> | |||
)); | |||
@@ -30,22 +32,21 @@ export type ContentContainerProps = Omit<React.HTMLProps<HTMLDivElement>, 'span' | |||
export const ContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||
children, | |||
span = Span.NORMAL, | |||
span = 'normal', | |||
}, ref) => { | |||
const args: LayoutArgs = { | |||
span, | |||
mainSidebarOpen: false, | |||
auxiliaryItemsShown: false, | |||
}; | |||
return ( | |||
<div | |||
className={layouts.Basic.ContentContainer(args)} | |||
className={clsx( | |||
'px-8 box-border mx-auto w-full', | |||
span === 'narrow' && 'max-w-screen-2xs', | |||
span === 'normal' && 'max-w-screen-xs', | |||
span === 'wide' && 'max-w-screen-sm', | |||
)} | |||
ref={ref} | |||
> | |||
{children} | |||
</div> | |||
) | |||
); | |||
}); | |||
ContentContainer.displayName = 'ContentContainer' |
@@ -1,10 +1,9 @@ | |||
import * as React from 'react'; | |||
import {layouts} from '@tesseract-design/viewfinder-base'; | |||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||
export interface RootProps extends React.HTMLProps<HTMLDivElement> { | |||
sidebarBaseWidget?: React.ReactNode; | |||
topBarWidget?: React.ReactNode; | |||
}; | |||
} | |||
export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||
children, | |||
@@ -15,23 +14,24 @@ export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||
<> | |||
{topBarWidget} | |||
{sidebarBaseWidget} | |||
<main | |||
<div | |||
{...etcProps} | |||
ref={ref} | |||
className={layouts.LeftSidebar.ContentBase()} | |||
data-viewfinder="main" | |||
className="box-border md:pl-[calc(50%-(var(--base-width)*0.5))]" | |||
> | |||
{children} | |||
</main> | |||
</div> | |||
</> | |||
)); | |||
export type ContentContainerProps = React.HTMLProps<HTMLDivElement> | |||
export interface ContentContainerProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||
children, | |||
}, ref) => ( | |||
<div | |||
className={layouts.LeftSidebar.ContentContainer()} | |||
className="px-8 box-border w-full max-w-[calc(var(--base-width)*2)] mx-auto md:ml-0" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -40,7 +40,7 @@ export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentCont | |||
MainContentContainer.displayName = 'MainContentContainer' | |||
export type SidebarMainContainerProps = React.HTMLProps<HTMLDivElement> | |||
export interface SidebarMainContainerProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarMainContainerProps>(({ | |||
children, | |||
@@ -48,7 +48,7 @@ export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarM | |||
}, ref) => ( | |||
<div | |||
{...etcProps} | |||
className={layouts.LeftSidebar.SidebarMainContainer()} | |||
className="w-full mx-auto px-8 box-border max-w-[calc(var(--base-width)*2)] md:w-[var(--base-width)] md:mr-0" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -1,7 +1,6 @@ | |||
import * as React from 'react'; | |||
import {layouts} from '@tesseract-design/viewfinder-base'; | |||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||
export interface RootProps extends React.HTMLProps<HTMLDivElement> { | |||
sidebarBaseWidget?: React.ReactNode; | |||
topBarWidget?: React.ReactNode; | |||
}; | |||
@@ -15,23 +14,24 @@ export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||
<> | |||
{topBarWidget} | |||
{sidebarBaseWidget} | |||
<main | |||
<div | |||
{...etcProps} | |||
ref={ref} | |||
className={layouts.LeftSidebarWithMenu.ContentBase()} | |||
data-viewfinder="main" | |||
className="box-border pb-menu md:pb-0 md:pl-[calc(50%-(var(--base-width)*0.5))]" | |||
> | |||
{children} | |||
</main> | |||
</div> | |||
</> | |||
)); | |||
export type ContentContainerProps = React.HTMLProps<HTMLDivElement> | |||
export interface ContentContainerProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||
children, | |||
}, ref) => ( | |||
<div | |||
className={layouts.LeftSidebarWithMenu.ContentContainer()} | |||
className="px-8 box-border w-full max-w-[calc(var(--base-width)*2)] mx-auto md:ml-0" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -40,7 +40,7 @@ export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentCont | |||
MainContentContainer.displayName = 'MainContentContainer' | |||
export type SidebarMainContainerProps = React.HTMLProps<HTMLDivElement> | |||
export interface SidebarMainContainerProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarMainContainerProps>(({ | |||
children, | |||
@@ -48,7 +48,7 @@ export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarM | |||
}, ref) => ( | |||
<div | |||
{...etcProps} | |||
className={layouts.LeftSidebarWithMenu.SidebarMainContainer()} | |||
className="px-8 box-border w-full max-w-[calc(var(--base-width)*2)] mx-auto md:max-w-none" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -57,7 +57,7 @@ export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarM | |||
SidebarContentContainer.displayName = 'SidebarMainContainer'; | |||
export type SidebarMenuItemIconProps = React.HTMLProps<HTMLSpanElement> | |||
export interface SidebarMenuItemIconProps extends React.HTMLProps<HTMLSpanElement> {} | |||
export const SidebarMenuItemIcon = React.forwardRef<HTMLSpanElement, SidebarMenuItemIconProps>(({ | |||
children, | |||
@@ -65,7 +65,7 @@ export const SidebarMenuItemIcon = React.forwardRef<HTMLSpanElement, SidebarMenu | |||
}, ref) => ( | |||
<span | |||
{...etcProps} | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuItemIcon()} | |||
className="block md:w-menu md:h-menu md:flex md:justify-center md:items-center" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -80,7 +80,7 @@ export const SidebarMenuContainer = React.forwardRef<HTMLSpanElement, SidebarMai | |||
}, ref) => ( | |||
<span | |||
{...etcProps} | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuContainer()} | |||
className="box-border flex flex-col justify-center items-center w-full text-center md:justify-start md:ml-auto md:text-left md:w-[var(--base-width)] md:flex-row" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -96,7 +96,7 @@ export const MoreSidebarMenuItemIcon = React.forwardRef<HTMLSpanElement, Sidebar | |||
}, ref) => ( | |||
<span | |||
{...etcProps} | |||
className={layouts.LeftSidebarWithMenu.MoreSidebarMenuItemIcon()} | |||
className="block mr-4 md:w-menu md:h-menu md:flex md:justify-center md:items-center md:mr-0" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -111,7 +111,7 @@ export const MoreSidebarMenuContainer = React.forwardRef<HTMLSpanElement, Sideba | |||
}, ref) => ( | |||
<span | |||
{...etcProps} | |||
className={layouts.LeftSidebarWithMenu.MoreSidebarMenuContainer()} | |||
className="flex justify-start items-center w-[calc(var(--base-width)*2)] mx-auto px-8 text-left box-border md:mr-0 md:w-[var(--base-width)] md:pl-0" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -1,7 +1,6 @@ | |||
import * as React from 'react'; | |||
import {layouts} from '@tesseract-design/viewfinder-base'; | |||
export type RootProps = React.HTMLProps<HTMLDivElement> & { | |||
export interface RootProps extends React.HTMLProps<HTMLDivElement> { | |||
sidebarBaseWidget?: React.ReactNode; | |||
topBarWidget?: React.ReactNode; | |||
}; | |||
@@ -14,34 +13,37 @@ export const Root = React.forwardRef<HTMLDivElement, RootProps>(({ | |||
}, ref) => ( | |||
<> | |||
{topBarWidget} | |||
<main | |||
<div | |||
{...etcProps} | |||
ref={ref} | |||
className={layouts.RightSidebarStatic.ContentBase()} | |||
data-viewfinder="main" | |||
className="box-border md:pr-[calc(50%-(var(--base-width)*0.5))]" | |||
> | |||
{children} | |||
</main> | |||
</div> | |||
{sidebarBaseWidget} | |||
</> | |||
)) | |||
Root.displayName = 'Root'; | |||
export type ContentContainerProps = React.HTMLProps<HTMLDivElement> | |||
export interface ContentContainerProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const MainContentContainer = React.forwardRef<HTMLDivElement, ContentContainerProps>(({ | |||
children, | |||
}, ref) => ( | |||
<div | |||
className={layouts.RightSidebarStatic.ContentContainer()} | |||
className="px-8 box-border w-full max-w-[calc(var(--base-width)*2)] mx-auto md:mr-0" | |||
ref={ref} | |||
> | |||
{children} | |||
</div> | |||
)); | |||
MainContentContainer.displayName = 'MainContentContainer' | |||
MainContentContainer.displayName = 'MainContentContainer'; | |||
export type SidebarMainContainerProps = React.HTMLProps<HTMLDivElement> | |||
export interface SidebarMainContainerProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarMainContainerProps>(({ | |||
children, | |||
@@ -49,7 +51,7 @@ export const SidebarContentContainer = React.forwardRef<HTMLDivElement, SidebarM | |||
}, ref) => ( | |||
<div | |||
{...etcProps} | |||
className={layouts.RightSidebarStatic.SidebarMainContainer()} | |||
className="px-8 box-border w-full max-w-[calc(var(--base-width)*2)] mx-auto md:ml-0 md:w-[var(--base-width)]" | |||
ref={ref} | |||
> | |||
{children} | |||
@@ -1,35 +1,29 @@ | |||
import * as React from 'react'; | |||
import {LayoutArgs, layouts, Span} from '@tesseract-design/viewfinder-base'; | |||
import clsx from 'clsx'; | |||
export type LeftSidebarBaseProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||
span?: Span, | |||
} | |||
export interface LeftSidebarBaseProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const LeftSidebarBase = React.forwardRef<HTMLDivElement, LeftSidebarBaseProps>(({ | |||
children, | |||
span = Span.WIDE, | |||
open = false, | |||
...etcProps | |||
}, ref) => { | |||
const args: LayoutArgs = { | |||
span, | |||
mainSidebarOpen: open, | |||
auxiliaryItemsShown: false, | |||
}; | |||
return ( | |||
<div | |||
className={layouts.LeftSidebar.SidebarBase(args)} | |||
className={clsx( | |||
'box-border fixed top-0 -left-full w-full h-full bg-bg md:left-0 md:w-[calc(50%-(var(--base-width)*0.5))] scrollbar-hidden', | |||
open && 'left-0', | |||
)} | |||
{...etcProps} | |||
ref={ref} | |||
> | |||
<div | |||
className={layouts.LeftSidebar.SidebarOverflow()} | |||
className="w-full h-full overflow-auto relative z-[1]" | |||
> | |||
{children} | |||
</div> | |||
</div> | |||
) | |||
); | |||
}); | |||
LeftSidebarBase.displayName = 'LeftSidebarBase' |
@@ -1,7 +1,8 @@ | |||
// TODO figure out how to refactor left sidebar with menu widget | |||
import * as React from 'react'; | |||
import {LayoutArgs, layouts, Span} from '@tesseract-design/viewfinder-base'; | |||
import {SpanValues as Span} from '@tesseract-design/viewfinder-base'; | |||
import clsx from 'clsx'; | |||
type BaseMenuItem = { | |||
label: React.ReactNode, | |||
@@ -26,7 +27,7 @@ export type LeftSidebarWithMenuBaseProps = Omit<React.HTMLProps<HTMLDivElement>, | |||
export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSidebarWithMenuBaseProps>(({ | |||
children, | |||
span = Span.WIDE, | |||
span = 'wide', | |||
open = false, | |||
items: sidebarMenuItems = [], | |||
linkComponent: LinkComponent = 'a', | |||
@@ -35,12 +36,6 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
moreItemsOpen = false, | |||
...etcProps | |||
}, ref) => { | |||
const args: LayoutArgs = { | |||
span, | |||
mainSidebarOpen: open, | |||
auxiliaryItemsShown: moreItemsOpen, | |||
}; | |||
const primarySidebarMenuItems = sidebarMenuItems.filter(s => !s.secondary) | |||
const secondarySidebarMenuItems = sidebarMenuItems.filter(s => s.secondary) | |||
@@ -63,24 +58,26 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
return ( | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarBase()} | |||
className="left-sidebar-with-menu-base box-border overflow-hidden contents left-[calc(var(--base-width)*-1)] md:fixed md:top-0 md:left-0 md:w-[calc(50%-var(--base-width)*0.5)] md:h-full md:block" | |||
{...etcProps} | |||
ref={ref} | |||
> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarMenu()} | |||
data-viewfinder="menu" | |||
className="box-border scrollbar-hidden overflow-auto fixed bottom-0 left-0 w-full h-menu z-[3] bg-bg md:top-0 md:ml-auto md:absolute md:h-full md:pt-inherit md:overflow-auto md:z-auto" | |||
> | |||
<div> | |||
<div className="w-full h-full bg-bg"> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuSize()} | |||
className="flex w-full h-full max-w-[calc(var(--base-width)*2)] mx-auto relative z-[1] md:max-w-none md:mr-0 md:flex-col md:justify-between md:items-end" | |||
> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuGroup()} | |||
className="contents md:w-full md:block" | |||
> | |||
{visiblePrimarySidebarMenuItems.map(({ id, ...item }) => ( | |||
<span | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuItem()} | |||
key={id} | |||
key={id} | |||
className="w-0 flex-auto h-menu md:flex-shrink-0 md:flex-grow" | |||
data-viewfinder="menu-item" | |||
> | |||
<LinkComponent | |||
{...item} | |||
@@ -89,18 +86,22 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
))} | |||
</div> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.MoreItems(args)} | |||
className={clsx( | |||
'fixed top-0 w-full h-full pt-topbar pb-menu -z-[1] box-border md:contents', | |||
moreItemsOpen ? 'left-0': '-left-full', | |||
)} | |||
> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.MoreItemsScroll()} | |||
className="w-full h-full overflow-auto bg-bg md:contents" | |||
> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.MorePrimarySidebarMenuGroup()} | |||
className="contents md:w-full md:block md:flex-auto" | |||
> | |||
{morePrimarySidebarMenuItems.map(({ id, ...item }) => ( | |||
<span | |||
className={layouts.LeftSidebarWithMenu.MoreSidebarMenuItem()} | |||
key={id} | |||
key={id} | |||
data-viewfinder="menu-item" | |||
className="h-menu block md:flex-shrink-0 md:flex-grow md:flex-auto" | |||
> | |||
<MoreLinkComponent | |||
{...item} | |||
@@ -109,12 +110,13 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
))} | |||
</div> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.MoreSecondarySidebarMenuGroup()} | |||
className="contents md:w-full md:block md:order-4" | |||
> | |||
{moreSecondarySidebarMenuItems.map(({ id, ...item }) => ( | |||
<span | |||
className={layouts.LeftSidebarWithMenu.MoreSidebarMenuItem()} | |||
key={id} | |||
key={id} | |||
data-viewfinder="menu-item" | |||
className="h-menu block md:flex-shrink-0 md:flex-grow md:flex-auto" | |||
> | |||
<MoreLinkComponent | |||
{...item} | |||
@@ -126,10 +128,11 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
</div> | |||
{hasMoreSidebarMenuItems && ( | |||
<span | |||
className={layouts.LeftSidebarWithMenu.MoreToggleSidebarMenuItem()} | |||
className="contents md:hidden" | |||
> | |||
<span | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuItem()} | |||
className="w-0 flex-auto h-menu md:flex-shrink-0 md:flex-grow md:flex-auto" | |||
data-viewfinder="menu-item" | |||
> | |||
<LinkComponent | |||
{...moreLinkItem} | |||
@@ -139,12 +142,13 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
)} | |||
{visibleSecondarySidebarMenuItems.length > 0 && ( | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuGroup()} | |||
className="contents md:w-full md:block" | |||
> | |||
{visibleSecondarySidebarMenuItems.map(({ id, ...item }) => ( | |||
<span | |||
className={layouts.LeftSidebarWithMenu.SidebarMenuItem()} | |||
key={id} | |||
key={id} | |||
className="w-0 flex-auto h-menu md:flex-shrink-0 md:flex-grow md:flex-auto" | |||
data-viewfinder="menu-item" | |||
> | |||
<LinkComponent | |||
{...item} | |||
@@ -158,10 +162,14 @@ export const LeftSidebarWithMenuBase = React.forwardRef<HTMLDivElement, LeftSide | |||
</div> | |||
{children && ( | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarMain(args)} | |||
className={clsx( | |||
'box-border fixed top-0 w-full h-full pt-inherit pb-menu z-[2] bg-bg', | |||
open ? 'right-0': 'right-full', | |||
'md:absolute md:right-0 md:ml-0 md:pb-0 md:w-[calc(var(--base-width)-var(--size-menu,4rem))]' | |||
)} | |||
> | |||
<div | |||
className={layouts.LeftSidebarWithMenu.SidebarMainOverflow()} | |||
className="bg-bg w-full h-full overflow-auto scrollbar-hidden relative z-[1]" | |||
> | |||
{children} | |||
</div> | |||
@@ -1,22 +1,18 @@ | |||
import * as React from 'react'; | |||
import {layouts, Span} from '@tesseract-design/viewfinder-base'; | |||
export type RightSidebarStaticBaseProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||
span?: Span, | |||
} | |||
export interface RightSidebarStaticBaseProps extends React.HTMLProps<HTMLDivElement> {} | |||
export const RightSidebarStaticBase = React.forwardRef<HTMLDivElement, RightSidebarStaticBaseProps>(({ | |||
children, | |||
span = Span.WIDE, | |||
...etcProps | |||
}, ref) => ( | |||
<div | |||
className={layouts.RightSidebarStatic.SidebarBase()} | |||
className="box-border bg-bg after:pb-[1px] after:-mt-[1px] after:box-border md:pr-[calc(50%-(var(--base-width)*0.5)] md:absolute md:top-0 md:right-0 md:h-full md:w-[calc(50%-(var(--base-width)*0.5))]" | |||
{...etcProps} | |||
ref={ref} | |||
> | |||
<div | |||
className={layouts.RightSidebarStatic.SidebarMainContent()} | |||
className="w-full h-full relative z-[1]" | |||
> | |||
{children} | |||
</div> | |||
@@ -1,7 +1,8 @@ | |||
import * as React from 'react'; | |||
import {LayoutArgs, Span, widgets} from '@tesseract-design/viewfinder-base'; | |||
import clsx from 'clsx'; | |||
import { SpanValues as Span } from '@tesseract-design/viewfinder-base'; | |||
export type TopBarProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||
export interface TopBarProps extends Omit<React.HTMLProps<HTMLDivElement>, 'span'> { | |||
span?: Span, | |||
brand?: React.ReactNode, | |||
menuLink?: React.ReactNode, | |||
@@ -9,26 +10,28 @@ export type TopBarProps = Omit<React.HTMLProps<HTMLDivElement>, 'span'> & { | |||
} | |||
export const TopBar = React.forwardRef<HTMLDivElement, TopBarProps>(({ | |||
span = Span.NORMAL, | |||
span = 'normal', | |||
brand, | |||
menuLink, | |||
userLink, | |||
children, | |||
...etcProps | |||
}, ref) => { | |||
const args: LayoutArgs = { | |||
span, | |||
mainSidebarOpen: false, | |||
auxiliaryItemsShown: false, | |||
}; | |||
return ( | |||
<div className={widgets.TopBar.Base()}> | |||
<div className={clsx( | |||
'fixed top-0 left-0 w-full z-[3] topbar', | |||
)}> | |||
<div | |||
{...etcProps} | |||
ref={ref} | |||
className="w-full h-full bg-bg" | |||
> | |||
<div className={widgets.TopBar.Container(args)}> | |||
<div className={clsx( | |||
'px-8 box-border mx-auto w-full h-full flex items-center relative z-[1]', | |||
span === 'narrow' && 'max-w-screen-2xs', | |||
span === 'normal' && 'max-w-screen-xs', | |||
span === 'wide' && 'max-w-screen-md', | |||
)}> | |||
{ | |||
Boolean(brand as unknown) | |||
&& ( | |||
@@ -37,14 +40,17 @@ export const TopBar = React.forwardRef<HTMLDivElement, TopBarProps>(({ | |||
</div> | |||
) | |||
} | |||
<div className={widgets.TopBar.CenterContainer()}> | |||
<div className="flex-auto px-8 box-border first:pl-0"> | |||
{children} | |||
</div> | |||
<div className={widgets.TopBar.ActionContainer()}> | |||
<div className="flex items-center justify-end h-full whitespace-nowrap sm:min-w-32"> | |||
{ | |||
Boolean(menuLink as unknown) | |||
&& ( | |||
<div className={widgets.TopBar.MenuLinkContainer()}> | |||
<div | |||
data-viewfinder="menu" | |||
className="w-topbar h-full" | |||
> | |||
{menuLink} | |||
</div> | |||
) | |||
@@ -52,7 +58,10 @@ export const TopBar = React.forwardRef<HTMLDivElement, TopBarProps>(({ | |||
{ | |||
Boolean(userLink as unknown) | |||
&& ( | |||
<div className={widgets.TopBar.LinkContainer()}> | |||
<div | |||
data-viewfinder="user" | |||
className="w-topbar h-full" | |||
> | |||
{userLink} | |||
</div> | |||
) | |||
@@ -0,0 +1,2 @@ | |||
packages: | |||
- 'packages/**' |