Browse Source

Add area customization

The props for styling areas of layouts have been added, with sensible
low-specificity default styles added.
master
TheoryOfNekomata 3 years ago
parent
commit
3cfc87a5da
11 changed files with 251 additions and 116 deletions
  1. +12
    -0
      example/layouts/basic/index.tsx
  2. +42
    -0
      example/layouts/left-sidebar-with-menu/index.tsx
  3. +16
    -0
      example/layouts/left-sidebar/index.tsx
  4. +1
    -0
      example/package.json
  5. +1
    -1
      package.json
  6. +3
    -0
      src/layouts/Basic/index.tsx
  7. +3
    -0
      src/layouts/BasicNarrow/index.tsx
  8. +16
    -5
      src/layouts/LeftSidebar/index.tsx
  9. +106
    -80
      src/layouts/LeftSidebarWithMenu/index.tsx
  10. +14
    -2
      src/layouts/RightSidebarStatic/index.tsx
  11. +37
    -28
      src/widgets/TopBar/index.tsx

+ 12
- 0
example/layouts/basic/index.tsx View File

@@ -1,15 +1,27 @@
import * as React from 'react' import * as React from 'react'
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
import ReactMarkdown from 'react-markdown' import ReactMarkdown from 'react-markdown'
import styled from 'styled-components';
import Brand from '../../components/Brand'; import Brand from '../../components/Brand';
import { Basic } from '../../..'; import { Basic } from '../../..';


const TopBar = styled('div')({
backgroundColor: 'black',
color: 'white',
boxShadow: '0 0 0.25rem rgba(0,0,0,0.25)',
'a': {
color: 'inherit',
textDecoration: 'none',
}
})

const Page = () => { const Page = () => {
return ( return (
<Basic.Layout <Basic.Layout
brand={ brand={
<Brand /> <Brand />
} }
topBarComponent={TopBar}
topBarCenter={ topBarCenter={
<form <form
style={{ style={{


+ 42
- 0
example/layouts/left-sidebar-with-menu/index.tsx View File

@@ -3,6 +3,46 @@ import * as ReactDOM from 'react-dom';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import Brand from '../../components/Brand'; import Brand from '../../components/Brand';
import { LeftSidebarWithMenu } from '../../..'; import { LeftSidebarWithMenu } from '../../..';
import styled from 'styled-components';

const SidebarMenuComponent = styled('div')({
'::after': {
content: "''",
position: 'absolute',
top: 0,
right: 0,
height: '100%',
width: '0.0625rem',
backgroundColor: 'currentcolor',
opacity: 0.25,
pointerEvents: 'none',
}
})

const SidebarMainComponent = styled('div')({
'::before': {
content: "''",
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '0.0625rem',
backgroundColor: 'currentcolor',
opacity: 0.25,
pointerEvents: 'none',
},
'::after': {
content: "''",
position: 'absolute',
top: 0,
right: 0,
height: '100%',
width: '0.0625rem',
backgroundColor: 'currentcolor',
opacity: 0.25,
pointerEvents: 'none',
}
})


const Page = () => { const Page = () => {
const [sidebarMainOpen, setSidebarMainOpen] = React.useState(location.hash === '#sidebar') const [sidebarMainOpen, setSidebarMainOpen] = React.useState(location.hash === '#sidebar')
@@ -23,6 +63,8 @@ const Page = () => {
return ( return (
<LeftSidebarWithMenu.Layout <LeftSidebarWithMenu.Layout
moreItemsOpen={moreItemsOpen} moreItemsOpen={moreItemsOpen}
sidebarMainComponent={SidebarMainComponent}
sidebarMenuComponent={SidebarMenuComponent}
sidebarMenuItems={[ sidebarMenuItems={[
{ {
id: 'foo', id: 'foo',


+ 16
- 0
example/layouts/left-sidebar/index.tsx View File

@@ -1,9 +1,24 @@
import * as React from 'react' import * as React from 'react'
import * as ReactDOM from 'react-dom'; import * as ReactDOM from 'react-dom';
import ReactMarkdown from 'react-markdown'; import ReactMarkdown from 'react-markdown';
import styled from 'styled-components';
import Brand from '../../components/Brand'; import Brand from '../../components/Brand';
import { LeftSidebar } from '../../..'; import { LeftSidebar } from '../../..';


const SidebarMainComponent = styled('div')({
'::after': {
content: "''",
position: 'absolute',
top: 0,
right: 0,
height: '100%',
width: '0.0625rem',
backgroundColor: 'currentcolor',
opacity: 0.5,
pointerEvents: 'none',
}
})

const Page = () => { const Page = () => {
const [sidebarMainOpen, setSidebarMainOpen] = React.useState(location.hash === '#sidebar') const [sidebarMainOpen, setSidebarMainOpen] = React.useState(location.hash === '#sidebar')


@@ -78,6 +93,7 @@ const Page = () => {
</a> </a>
</> </>
} }
sidebarMainComponent={SidebarMainComponent}
> >
<LeftSidebar.ContentContainer> <LeftSidebar.ContentContainer>
<ReactMarkdown <ReactMarkdown


+ 1
- 0
example/package.json View File

@@ -11,6 +11,7 @@
"alias": { "alias": {
"react": "../node_modules/react", "react": "../node_modules/react",
"react-dom": "../node_modules/react-dom/profiling", "react-dom": "../node_modules/react-dom/profiling",
"styled-components": "../node_modules/styled-components",
"scheduler/tracing": "../node_modules/scheduler/tracing-profiling" "scheduler/tracing": "../node_modules/scheduler/tracing-profiling"
}, },
"devDependencies": { "devDependencies": {


+ 1
- 1
package.json View File

@@ -1,5 +1,5 @@
{ {
"version": "0.2.1",
"version": "0.2.2",
"license": "MIT", "license": "MIT",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",


+ 3
- 0
src/layouts/Basic/index.tsx View File

@@ -23,12 +23,14 @@ type Props = {
brand?: React.ReactNode, brand?: React.ReactNode,
userLink?: React.ReactNode, userLink?: React.ReactNode,
topBarCenter?: React.ReactChild, topBarCenter?: React.ReactChild,
topBarComponent?: React.ElementType,
} }


export const Layout: React.FC<Props> = ({ export const Layout: React.FC<Props> = ({
brand, brand,
userLink, userLink,
topBarCenter, topBarCenter,
topBarComponent = 'div',
children, children,
}) => { }) => {
return ( return (
@@ -44,6 +46,7 @@ export const Layout: React.FC<Props> = ({
<TopBar <TopBar
brand={brand} brand={brand}
userLink={userLink} userLink={userLink}
baseComponent={topBarComponent}
> >
{topBarCenter} {topBarCenter}
</TopBar> </TopBar>


+ 3
- 0
src/layouts/BasicNarrow/index.tsx View File

@@ -23,12 +23,14 @@ type Props = {
brand?: React.ReactNode, brand?: React.ReactNode,
userLink?: React.ReactNode, userLink?: React.ReactNode,
topBarCenter?: React.ReactChild, topBarCenter?: React.ReactChild,
topBarComponent?: React.ElementType,
} }


export const Layout: React.FC<Props> = ({ export const Layout: React.FC<Props> = ({
brand, brand,
userLink, userLink,
topBarCenter, topBarCenter,
topBarComponent = 'div',
children, children,
}) => { }) => {
return ( return (
@@ -45,6 +47,7 @@ export const Layout: React.FC<Props> = ({
span="narrow" span="narrow"
brand={brand} brand={brand}
userLink={userLink} userLink={userLink}
baseComponent={topBarComponent}
> >
{topBarCenter} {topBarCenter}
</TopBar> </TopBar>


+ 16
- 5
src/layouts/LeftSidebar/index.tsx View File

@@ -42,8 +42,12 @@ const SidebarBase = styled('div')({
left: '-100%', left: '-100%',
width: '100%', width: '100%',
height: '100%', height: '100%',
overflow: 'hidden',
backgroundColor: 'var(--color-bg, white)',
'> *': {
display: 'block',
width: '100%',
height: '100%',
backgroundColor: 'white',
},
[minWidthFactor(3)]: { [minWidthFactor(3)]: {
width: `calc(50% - ${configVar('base-width')} * 0.5)`, width: `calc(50% - ${configVar('base-width')} * 0.5)`,
left: 0, left: 0,
@@ -86,6 +90,8 @@ type Props = {
menuLink?: React.ReactNode, menuLink?: React.ReactNode,
userLink?: React.ReactNode, userLink?: React.ReactNode,
topBarCenter?: React.ReactChild, topBarCenter?: React.ReactChild,
topBarComponent?: React.ElementType,
sidebarMainComponent?: React.ElementType,
} }


export const Layout: React.FC<Props> = ({ export const Layout: React.FC<Props> = ({
@@ -96,6 +102,8 @@ export const Layout: React.FC<Props> = ({
userLink, userLink,
topBarCenter, topBarCenter,
children, children,
topBarComponent: TopBarComponent = 'div',
sidebarMainComponent: SidebarMainComponent = 'div',
}) => { }) => {
const LeftSidebarComponent = sidebarMainOpen ? OpenSidebarBase : SidebarBase const LeftSidebarComponent = sidebarMainOpen ? OpenSidebarBase : SidebarBase


@@ -113,13 +121,16 @@ export const Layout: React.FC<Props> = ({
brand={brand} brand={brand}
menuLink={menuLink} menuLink={menuLink}
userLink={userLink} userLink={userLink}
baseComponent={TopBarComponent}
> >
{topBarCenter} {topBarCenter}
</TopBar> </TopBar>
<LeftSidebarComponent> <LeftSidebarComponent>
<SidebarOverflow>
{sidebarMain}
</SidebarOverflow>
<SidebarMainComponent>
<SidebarOverflow>
{sidebarMain}
</SidebarOverflow>
</SidebarMainComponent>
</LeftSidebarComponent> </LeftSidebarComponent>
<ContentBase> <ContentBase>
{children} {children}


+ 106
- 80
src/layouts/LeftSidebarWithMenu/index.tsx View File

@@ -31,7 +31,6 @@ const SidebarBase = styled('div')({
overflow: 'hidden', overflow: 'hidden',
display: 'contents', display: 'contents',
left: `calc(${configVar('base-width')} * -1)`, left: `calc(${configVar('base-width')} * -1)`,
backgroundColor: 'var(--color-bg, white)',
[minWidthFactor(3)]: { [minWidthFactor(3)]: {
position: 'fixed', position: 'fixed',
top: 0, top: 0,
@@ -49,15 +48,8 @@ const SidebarMain = styled('div')({
right: '100%', right: '100%',
width: '100%', width: '100%',
height: '100%', height: '100%',
overflow: 'auto',
// overflow: 'overlay',
paddingTop: 'inherit', paddingTop: 'inherit',
paddingBottom: 'var(--size-menu, 4rem)', paddingBottom: 'var(--size-menu, 4rem)',
scrollbarWidth: 'none',
'::-webkit-scrollbar': {
display: 'none',
},
backgroundColor: 'var(--color-bg, white)',
[minWidthFactor(3)]: { [minWidthFactor(3)]: {
position: 'absolute', position: 'absolute',
right: 0, right: 0,
@@ -65,6 +57,23 @@ const SidebarMain = styled('div')({
marginLeft: 'auto', marginLeft: 'auto',
paddingBottom: 0, paddingBottom: 0,
}, },
'> *': {
display: 'block',
width: '100%',
height: '100%',
backgroundColor: 'white',
},
})

const SidebarMainOverflow = styled('div')({
width: '100%',
height: '100%',
overflow: 'auto',
// overflow: 'overlay',
scrollbarWidth: 'none',
'::-webkit-scrollbar': {
display: 'none',
},
}) })


const OpenSidebarMain = styled(SidebarMain)({ const OpenSidebarMain = styled(SidebarMain)({
@@ -85,7 +94,12 @@ const SidebarMenu = styled('div')({
width: '100%', width: '100%',
height: 'var(--size-menu, 4rem)', height: 'var(--size-menu, 4rem)',
zIndex: 1, zIndex: 1,
backgroundColor: 'var(--color-bg, white)',
'> *': {
display: 'block',
width: '100%',
height: '100%',
backgroundColor: 'white',
},
[minWidthFactor(3)]: { [minWidthFactor(3)]: {
top: 0, top: 0,
marginLeft: 'auto', marginLeft: 'auto',
@@ -130,7 +144,6 @@ const MoreItems = styled('div')({
paddingBottom: 'var(--size-menu, 4rem)', paddingBottom: 'var(--size-menu, 4rem)',
zIndex: -1, zIndex: -1,
boxSizing: 'border-box', boxSizing: 'border-box',
backgroundColor: 'var(--color-bg, white)',
[minWidthFactor(3)]: { [minWidthFactor(3)]: {
display: 'contents', display: 'contents',
}, },
@@ -306,6 +319,9 @@ type Props = {
moreLinkComponent: React.ElementType, moreLinkComponent: React.ElementType,
linkComponent: React.ElementType, linkComponent: React.ElementType,
topBarCenter?: React.ReactChild, topBarCenter?: React.ReactChild,
topBarComponent?: React.ElementType,
sidebarMainComponent?: React.ElementType,
sidebarMenuComponent?: React.ElementType,
} }


export const Layout: React.FC<Props> = ({ export const Layout: React.FC<Props> = ({
@@ -321,6 +337,9 @@ export const Layout: React.FC<Props> = ({
linkComponent: LinkComponent, linkComponent: LinkComponent,
topBarCenter, topBarCenter,
children, children,
topBarComponent: TopBarComponent = 'div',
sidebarMainComponent: SidebarMainWrapperComponent = 'div',
sidebarMenuComponent: SidebarMenuComponent = 'div',
}) => { }) => {
const SidebarMainComponent = sidebarMainOpen ? OpenSidebarMain : SidebarMain const SidebarMainComponent = sidebarMainOpen ? OpenSidebarMain : SidebarMain
const MoreItemsComponent = moreItemsOpen ? OpenMoreItems : MoreItems const MoreItemsComponent = moreItemsOpen ? OpenMoreItems : MoreItems
@@ -363,6 +382,7 @@ export const Layout: React.FC<Props> = ({
brand={brand} brand={brand}
menuLink={sidebarMain ? menuLink : undefined} menuLink={sidebarMain ? menuLink : undefined}
userLink={userLink} userLink={userLink}
baseComponent={TopBarComponent}
> >
{topBarCenter} {topBarCenter}
</TopBar> </TopBar>
@@ -370,70 +390,11 @@ export const Layout: React.FC<Props> = ({
} }
<SidebarBase> <SidebarBase>
<SidebarMenu> <SidebarMenu>
<SidebarMenuSize>
<SidebarMenuGroup>
{visiblePrimarySidebarMenuItems.map((item) => {
return (
<SidebarMenuItem
key={item.id}
>
<LinkComponent
{...item}
/>
</SidebarMenuItem>
)
})}
</SidebarMenuGroup>
<MoreItemsComponent>
<MoreItemsScroll>
<MorePrimarySidebarMenuGroup>
{morePrimarySidebarMenuItems.map((item) => {
return (
<MoreSidebarMenuItem
key={item.id}
>
<MoreLinkComponent
{...item}
/>
</MoreSidebarMenuItem>
)
})}
</MorePrimarySidebarMenuGroup>
<MoreSecondarySidebarMenuGroup>
{moreSecondarySidebarMenuItems.map((item) => {
return (
<MoreSidebarMenuItem
key={item.id}
>
<MoreLinkComponent
{...item}
/>
</MoreSidebarMenuItem>
)
})}
</MoreSecondarySidebarMenuGroup>
</MoreItemsScroll>
</MoreItemsComponent>
{
(
morePrimarySidebarMenuItems.length > 0
|| moreSecondarySidebarMenuItems.length > 0
)
&& (
<MoreToggleSidebarMenuItem>
<SidebarMenuItem>
<LinkComponent
{...moreLinkMenuItem}
/>
</SidebarMenuItem>
</MoreToggleSidebarMenuItem>
)
}
{
visibleSecondarySidebarMenuItems.length > 0
&& (
<SidebarMenuGroup>
{visibleSecondarySidebarMenuItems.map((item) => (
<SidebarMenuComponent>
<SidebarMenuSize>
<SidebarMenuGroup>
{visiblePrimarySidebarMenuItems.map((item) => {
return (
<SidebarMenuItem <SidebarMenuItem
key={item.id} key={item.id}
> >
@@ -441,17 +402,82 @@ export const Layout: React.FC<Props> = ({
{...item} {...item}
/> />
</SidebarMenuItem> </SidebarMenuItem>
))}
</SidebarMenuGroup>
)
}
</SidebarMenuSize>
)
})}
</SidebarMenuGroup>
<MoreItemsComponent>
<MoreItemsScroll>
<MorePrimarySidebarMenuGroup>
{morePrimarySidebarMenuItems.map((item) => {
return (
<MoreSidebarMenuItem
key={item.id}
>
<MoreLinkComponent
{...item}
/>
</MoreSidebarMenuItem>
)
})}
</MorePrimarySidebarMenuGroup>
<MoreSecondarySidebarMenuGroup>
{moreSecondarySidebarMenuItems.map((item) => {
return (
<MoreSidebarMenuItem
key={item.id}
>
<MoreLinkComponent
{...item}
/>
</MoreSidebarMenuItem>
)
})}
</MoreSecondarySidebarMenuGroup>
</MoreItemsScroll>
</MoreItemsComponent>
{
(
morePrimarySidebarMenuItems.length > 0
|| moreSecondarySidebarMenuItems.length > 0
)
&& (
<MoreToggleSidebarMenuItem>
<SidebarMenuItem>
<LinkComponent
{...moreLinkMenuItem}
/>
</SidebarMenuItem>
</MoreToggleSidebarMenuItem>
)
}
{
visibleSecondarySidebarMenuItems.length > 0
&& (
<SidebarMenuGroup>
{visibleSecondarySidebarMenuItems.map((item) => (
<SidebarMenuItem
key={item.id}
>
<LinkComponent
{...item}
/>
</SidebarMenuItem>
))}
</SidebarMenuGroup>
)
}
</SidebarMenuSize>
</SidebarMenuComponent>
</SidebarMenu> </SidebarMenu>
{ {
(sidebarMain as unknown) (sidebarMain as unknown)
&& ( && (
<SidebarMainComponent> <SidebarMainComponent>
{sidebarMain}
<SidebarMainWrapperComponent>
<SidebarMainOverflow>
{sidebarMain}
</SidebarMainOverflow>
</SidebarMainWrapperComponent>
</SidebarMainComponent> </SidebarMainComponent>
) )
} }


+ 14
- 2
src/layouts/RightSidebarStatic/index.tsx View File

@@ -25,7 +25,12 @@ const SidebarBase = styled('div')({
marginTop: -1, marginTop: -1,
boxSizing: 'border-box', boxSizing: 'border-box',
}, },
backgroundColor: 'var(--color-bg, white)',
'> *': {
display: 'block',
width: '100%',
height: '100%',
backgroundColor: 'white',
},
[minWidthFactor(3)]: { [minWidthFactor(3)]: {
position: 'absolute', position: 'absolute',
top: 0, top: 0,
@@ -63,6 +68,8 @@ type Props = {
sidebarMain: React.ReactChild, sidebarMain: React.ReactChild,
userLink?: React.ReactNode, userLink?: React.ReactNode,
topBarCenter?: React.ReactChild, topBarCenter?: React.ReactChild,
topBarComponent?: React.ElementType,
sidebarMainComponent?: React.ElementType,
} }


export const Layout: React.FC<Props> = ({ export const Layout: React.FC<Props> = ({
@@ -71,6 +78,8 @@ export const Layout: React.FC<Props> = ({
userLink, userLink,
topBarCenter, topBarCenter,
children, children,
topBarComponent: TopBarComponent = 'div',
sidebarMainComponent: SidebarMainComponent = 'div',
}) => { }) => {
return ( return (
<> <>
@@ -86,6 +95,7 @@ export const Layout: React.FC<Props> = ({
span="wide" span="wide"
brand={brand} brand={brand}
userLink={userLink} userLink={userLink}
baseComponent={TopBarComponent}
> >
{topBarCenter} {topBarCenter}
</TopBar> </TopBar>
@@ -95,7 +105,9 @@ export const Layout: React.FC<Props> = ({
{children} {children}
</ContentBase> </ContentBase>
<SidebarBase> <SidebarBase>
{sidebarMain}
<SidebarMainComponent>
{sidebarMain}
</SidebarMainComponent>
</SidebarBase> </SidebarBase>
</> </>
) )


+ 37
- 28
src/widgets/TopBar/index.tsx View File

@@ -10,7 +10,12 @@ const Base = styled('div')({
width: '100%', width: '100%',
height: 'var(--height-topbar, 4rem)', height: 'var(--height-topbar, 4rem)',
zIndex: 2, zIndex: 2,
backgroundColor: 'var(--color-bg, white)',
'> *': {
display: 'block',
width: '100%',
height: '100%',
backgroundColor: 'white',
},
'~ *': { '~ *': {
paddingTop: 'var(--height-topbar, 4rem)', paddingTop: 'var(--height-topbar, 4rem)',
}, },
@@ -97,6 +102,7 @@ type Props = {
brand?: React.ReactNode, brand?: React.ReactNode,
menuLink?: React.ReactNode, menuLink?: React.ReactNode,
userLink?: React.ReactNode, userLink?: React.ReactNode,
baseComponent?: React.ElementType,
} }


const TopBar: React.FC<Props> = ({ const TopBar: React.FC<Props> = ({
@@ -105,41 +111,44 @@ const TopBar: React.FC<Props> = ({
menuLink, menuLink,
userLink, userLink,
children, children,
baseComponent: BaseComponent = 'div',
}) => { }) => {
const { [span as keyof typeof CONTAINER_COMPONENTS]: ContainerComponent = Container } = CONTAINER_COMPONENTS const { [span as keyof typeof CONTAINER_COMPONENTS]: ContainerComponent = Container } = CONTAINER_COMPONENTS
return ( return (
<Base> <Base>
<ContainerComponent>
{
Boolean(brand as unknown)
&& (
<BrandContainer>
{brand}
</BrandContainer>
)
}
<CenterContainer>
{children}
</CenterContainer>
<ActionContainer>
{
Boolean(menuLink as unknown)
&& (
<MenuLinkContainer>
{menuLink}
</MenuLinkContainer>
)
}
<BaseComponent>
<ContainerComponent>
{ {
Boolean(userLink as unknown)
Boolean(brand as unknown)
&& ( && (
<LinkContainer>
{userLink}
</LinkContainer>
<BrandContainer>
{brand}
</BrandContainer>
) )
} }
</ActionContainer>
</ContainerComponent>
<CenterContainer>
{children}
</CenterContainer>
<ActionContainer>
{
Boolean(menuLink as unknown)
&& (
<MenuLinkContainer>
{menuLink}
</MenuLinkContainer>
)
}
{
Boolean(userLink as unknown)
&& (
<LinkContainer>
{userLink}
</LinkContainer>
)
}
</ActionContainer>
</ContainerComponent>
</BaseComponent>
</Base> </Base>
) )
} }


Loading…
Cancel
Save