Просмотр исходного кода

Improve styling for responsive views

The styling for mobile has been implemented.
master
TheoryOfNekomata 3 лет назад
Родитель
Сommit
58fa387514
10 измененных файлов: 437 добавлений и 266 удалений
  1. +47
    -9
      src/components/organisms/layouts/LeftSidebar/index.tsx
  2. +208
    -0
      src/components/organisms/layouts/LeftSidebarWithMenu/index.tsx
  3. +14
    -6
      src/components/organisms/layouts/RightSidebar/index.tsx
  4. +63
    -3
      src/components/organisms/widgets/TopBar/index.tsx
  5. +0
    -98
      src/components/organisms/widgets/WideTopBar/index.tsx
  6. +12
    -18
      src/components/templates/LeftSidebarLayout/index.tsx
  7. +75
    -112
      src/components/templates/LeftSidebarWithMenuLayout/index.tsx
  8. +10
    -20
      src/components/templates/RightSidebarLayout/index.tsx
  9. +4
    -0
      src/pages/layouts/left-sidebar/index.tsx
  10. +4
    -0
      src/pages/layouts/left-sidebar/with-menu/index.tsx

+ 47
- 9
src/components/organisms/layouts/LeftSidebar/index.tsx Просмотреть файл

@@ -1,5 +1,15 @@
import styled from 'styled-components';
import WideTopBar from '../../widgets/WideTopBar';
import * as React from 'react';
import styled, {createGlobalStyle} from 'styled-components';
import TopBar from '../../widgets/TopBar';

const DisableScrolling = createGlobalStyle({
'body': {
overflow: 'hidden',
'@media (min-width: 1080px)': {
overflow: 'auto',
},
},
})

const Main = styled('main')({
boxSizing: 'border-box',
@@ -8,14 +18,24 @@ const Main = styled('main')({
},
})

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: 'calc(var(--width-base, 360px) * -1)',
width: 'calc(50% - var(--width-base, 360px) * 0.5)',
left: '-100%',
width: '100%',
height: '100%',
backgroundColor: 'var(--color-bg, white)',
overflow: 'hidden',
@@ -23,23 +43,41 @@ const LeftSidebar = styled('div')({
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,
})

const LeftSidebarLayout = ({
query,
sidebar,
sidebarMain,
sidebarMainOpen,
children,
}) => {
const LeftSidebarComponent = sidebarMainOpen ? OpenLeftSidebar : LeftSidebar

return (
<>
<WideTopBar
{
sidebarMainOpen
&& (
<DisableScrolling />
)
}
<TopBar
wide
query={query}
withMenu
/>
<LeftSidebar>
{sidebar}
</LeftSidebar>
<LeftSidebarComponent>
<SidebarOverflow>
{sidebarMain}
</SidebarOverflow>
</LeftSidebarComponent>
<Main>
{children}
</Main>


+ 208
- 0
src/components/organisms/layouts/LeftSidebarWithMenu/index.tsx Просмотреть файл

@@ -0,0 +1,208 @@
import * as React from 'react';
import styled, { createGlobalStyle } from 'styled-components';
import TopBar from '../../widgets/TopBar';

const DisableScrolling = createGlobalStyle({
'body': {
overflow: 'hidden',
'@media (min-width: 1080px)': {
overflow: 'auto',
},
},
})

const Wrapper = styled('div')({
'--width-base': '360px',
'--size-menu': '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)',
backgroundColor: 'var(--color-bg, white)',
zIndex: 1,
'@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',
},
})

export const SidebarMenuGroup = styled('div')({
display: 'contents',
'@media (min-width: 1080px)': {
width: '100%',
display: 'block',
},
})

export const SidebarMenuItem = styled('a')({
height: 'var(--size-menu, 4rem)',
display: 'flex',
alignItems: 'center',
textDecoration: 'none',
width: 0,
flex: 'auto',
'@media (min-width: 1080px)': {
width: 'auto',
},
})

export const SidebarMenuItemIcon = styled('span')({
display: 'block',
'@media (min-width: 1080px)': {
width: 'var(--size-menu, 4rem)',
height: 'var(--size-menu, 4rem)',
display: 'grid',
placeContent: 'center',
},
})

export 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',
},
})

const LeftSidebarWithMenuLayout = ({
query,
children,
sidebarMain,
sidebarMenu,
sidebarMainOpen,
}) => {
const SidebarMainComponent = sidebarMainOpen ? OpenSidebarMain : SidebarMain

return (
<>
{
sidebarMainOpen
&& (
<DisableScrolling />
)
}
<Wrapper>
<TopBar
withMenu
query={query}
wide
/>
<LeftSidebar>
<SidebarMenu>
<SidebarMenuSize>
{sidebarMenu}
</SidebarMenuSize>
</SidebarMenu>
<SidebarMainComponent>
{sidebarMain}
</SidebarMainComponent>
</LeftSidebar>
<Main>
{children}
</Main>
</Wrapper>
</>
)
}

export default LeftSidebarWithMenuLayout

+ 14
- 6
src/components/organisms/layouts/RightSidebar/index.tsx Просмотреть файл

@@ -1,5 +1,5 @@
import styled from 'styled-components';
import WideTopBar from '../../widgets/WideTopBar';
import TopBar from '../../widgets/TopBar';

const Main = styled('main')({
boxSizing: 'border-box',
@@ -12,12 +12,19 @@ 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: 'fixed',
position: 'absolute',
top: 0,
right: 0,
width: 'calc(50% - var(--width-base, 360px) * 0.5)',
@@ -25,15 +32,16 @@ const RightSidebar = styled('div')({
},
})

const LeftSidebarLayout = ({
const RightSidebarLayout = ({
query,
sidebar,
children,
}) => {
return (
<>
<WideTopBar
<TopBar
query={query}
wide
/>
<Main>
{children}
@@ -45,4 +53,4 @@ const LeftSidebarLayout = ({
)
}

export default LeftSidebarLayout
export default RightSidebarLayout

+ 63
- 3
src/components/organisms/widgets/TopBar/index.tsx Просмотреть файл

@@ -18,6 +18,14 @@ const Base = styled('div')({
'~ *': {
paddingTop: 'var(--height-topbar, 4rem)',
},
'~ main ~ *': {
paddingTop: 0,
},
'@media (min-width: 1080px)': {
'~ main ~ *': {
paddingTop: 'var(--height-topbar, 4rem)',
},
},
})

const Container = styled('div')({
@@ -31,6 +39,12 @@ const Container = styled('div')({
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)': {
@@ -46,17 +60,36 @@ const SearchContainer = styled('form')({

const UserContainer = styled('div')({
textAlign: 'right',
height: '100%',
whiteSpace: 'nowrap',
'@media (min-width: 720px)': {
minWidth: '8rem',
},
})

const UserLink = styled('a')({
width: 'var(--height-topbar, 4rem)',
height: '100%',
display: 'inline-grid',
placeContent: 'center',
})

const MenuUserLink = styled(UserLink)({
'@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,
}

const TopBar: React.FC<Props> = ({
@@ -65,10 +98,13 @@ const TopBar: React.FC<Props> = ({
searchLabel = 'Search',
searchName = 'q',
searchHint = 'e.g. keywords, names…',
wide,
withMenu,
}) => {
const ContainerComponent = wide ? WideContainer : Container
return (
<Base>
<Container>
<ContainerComponent>
<BrandContainer>
Brand
</BrandContainer>
@@ -82,12 +118,36 @@ const TopBar: React.FC<Props> = ({
defaultValue={query}
border
alternate
indicator={
<T.Icon
name="search"
label=""
/>
}
/>
</SearchContainer>
<UserContainer>
User
{
withMenu
&& (
<MenuUserLink
href="?sidebar"
>
<T.Icon
name="menu"
label="Guest"
/>
</MenuUserLink>
)
}
<UserLink>
<T.Icon
name="user"
label="Guest"
/>
</UserLink>
</UserContainer>
</Container>
</ContainerComponent>
</Base>
)
}


+ 0
- 98
src/components/organisms/widgets/WideTopBar/index.tsx Просмотреть файл

@@ -1,98 +0,0 @@
import * as React from 'react'
import styled from 'styled-components'
import * as T from '@tesseract-design/react-common'

const Base = styled('div')({
'--width-base': '360px',
'--height-topbar': '4rem',
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: 'var(--height-topbar, 4rem)',
backgroundColor: 'var(--color-bg, white)',
zIndex: 1,
'@media (prefers-color-scheme: dark)': {
backgroundColor: 'var(--color-bg, black)',
},
'~ *': {
paddingTop: 'var(--height-topbar, 4rem)',
},
})

const Container = styled('div')({
padding: '0 1rem',
boxSizing: 'border-box',
margin: '0 auto',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
maxWidth: 'calc(var(--width-base, 360px) * 2)',
'@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',
})

const UserContainer = styled('div')({
textAlign: 'right',
'@media (min-width: 720px)': {
minWidth: '8rem',
},
})

type Props = {
query?: string,
onSearch?: React.FormEventHandler,
searchLabel?: string,
searchName?: string,
searchHint?: string,
}

const TopBar: React.FC<Props> = ({
query,
onSearch,
searchLabel = 'Search',
searchName = 'q',
searchHint = 'e.g. keywords, names…',
}) => {
return (
<Base>
<Container>
<BrandContainer>
Brand
</BrandContainer>
<SearchContainer
onSubmit={onSearch}
>
<T.TextInput
name={searchName}
label={searchLabel}
hint={searchHint}
defaultValue={query}
border
alternate
/>
</SearchContainer>
<UserContainer>
User
</UserContainer>
</Container>
</Base>
)
}

export default TopBar

+ 12
- 18
src/components/templates/LeftSidebarLayout/index.tsx Просмотреть файл

@@ -3,21 +3,15 @@ import styled from 'styled-components';
import LeftSidebarLayout from '../../organisms/layouts/LeftSidebar';
import DummyContent from '../../molecules/DummyContent';

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

const SidebarContainer = styled('div')({
width: 'var(--width-base, 360px)',
marginLeft: 'auto',
margin: '0 auto',
padding: '0 1rem',
boxSizing: 'border-box',
maxWidth: 'calc(var(--width-base, 360px) * 2)',
'@media (min-width: 1080px)': {
width: 'var(--width-base, 360px)',
marginRight: 0,
},
})

const Container = styled('div')({
@@ -36,16 +30,16 @@ const Container = styled('div')({

const LeftSidebarLayoutTemplate = ({
query,
sidebarMainOpen,
}) => {
return (
<LeftSidebarLayout
query={query}
sidebar={
<SidebarOverflow>
<SidebarContainer>
<DummyContent />
</SidebarContainer>
</SidebarOverflow>
sidebarMainOpen={sidebarMainOpen}
sidebarMain={
<SidebarContainer>
<DummyContent />
</SidebarContainer>
}
>
<Container>


+ 75
- 112
src/components/templates/LeftSidebarWithMenuLayout/index.tsx Просмотреть файл

@@ -1,75 +1,14 @@
import * as React from 'react'
import styled from 'styled-components';
import LeftSidebarLayout from '../../organisms/layouts/LeftSidebar';
import * as T from '@tesseract-design/react-common';
import LeftSidebarWithMenuLayout, {
SidebarMenuItemIcon,
SidebarMenuContainer,
SidebarMenuGroup,
SidebarMenuItem,
} from '../../organisms/layouts/LeftSidebarWithMenu';
import DummyContent from '../../molecules/DummyContent';

const SidebarMenuGroup = styled('div')({
width: '100%',
})

const SidebarMenuItem = styled('a')({
height: 'var(--size-menu, 4rem)',
display: 'flex',
alignItems: 'center',
textDecoration: 'none',
})

const SidebarMenuItemIcon = styled('span')({
width: 'var(--size-menu, 4rem)',
height: 'var(--size-menu, 4rem)',
display: 'grid',
placeContent: 'center',
})

const SidebarMenu = styled('div')({
top: 0,
marginLeft: 'auto',
position: 'absolute',
height: '100%',
width: '100%',
paddingTop: 'inherit',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'flex-end',
boxSizing: 'border-box',
overflow: 'auto',
scrollbarWidth: 'none',
'::-webkit-scrollbar': {
display: 'none',
},
})

const SidebarMenuContainer = styled('span')({
width: 'var(--width-base, 360px)',
marginLeft: 'auto',
paddingRight: '1rem',
boxSizing: 'border-box',
display: 'flex',
alignItems: 'center',
})

const SidebarMain = styled('div')({
width: 'calc(var(--width-base, 360px) - var(--size-menu, 4rem))',
marginLeft: 'auto',
height: '100%',
padding: '0 1rem',
paddingTop: 'inherit',
boxSizing: 'border-box',
overflow: 'auto',
position: 'absolute',
top: 0,
right: 0,
scrollbarWidth: 'none',
backgroundColor: 'var(--color-bg, white)',
'@media (prefers-color-scheme: dark)': {
backgroundColor: 'var(--color-bg, black)',
},
'::-webkit-scrollbar': {
display: 'none',
},
})

const Container = styled('div')({
padding: '0 1rem',
boxSizing: 'border-box',
@@ -83,63 +22,87 @@ const Container = styled('div')({
},
})

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',
},
})

const LeftSidebarLayoutTemplate = ({
query,
sidebarMainOpen,
}) => {
return (
<LeftSidebarLayout
<LeftSidebarWithMenuLayout
query={query}
sidebar={
sidebarMainOpen={sidebarMainOpen}
sidebarMain={
<SidebarMainContainer>
<DummyContent />
</SidebarMainContainer>
}
sidebarMenu={
<>
<SidebarMenu>
<SidebarMenuGroup>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
A
</SidebarMenuItemIcon>
Hello
</SidebarMenuContainer>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
B
</SidebarMenuItemIcon>
Hello
</SidebarMenuContainer>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
C
</SidebarMenuItemIcon>
Hello
</SidebarMenuContainer>
</SidebarMenuItem>
</SidebarMenuGroup>
<SidebarMenuGroup>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
D
</SidebarMenuItemIcon>
World
</SidebarMenuContainer>
</SidebarMenuItem>
</SidebarMenuGroup>
</SidebarMenu>
<SidebarMain>
<DummyContent />
</SidebarMain>
<SidebarMenuGroup>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
<T.Icon
name="square"
label=""
/>
</SidebarMenuItemIcon>
Hello
</SidebarMenuContainer>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
<T.Icon
name="square"
label=""
/>
</SidebarMenuItemIcon>
Hello
</SidebarMenuContainer>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
<T.Icon
name="square"
label=""
/>
</SidebarMenuItemIcon>
Hello
</SidebarMenuContainer>
</SidebarMenuItem>
</SidebarMenuGroup>
<SidebarMenuGroup>
<SidebarMenuItem>
<SidebarMenuContainer>
<SidebarMenuItemIcon>
<T.Icon
name="square"
label=""
/>
</SidebarMenuItemIcon>
World
</SidebarMenuContainer>
</SidebarMenuItem>
</SidebarMenuGroup>
</>
}
>
<Container>
<DummyContent />
</Container>
</LeftSidebarLayout>
</LeftSidebarWithMenuLayout>
)
}



+ 10
- 20
src/components/templates/RightSidebarLayout/index.tsx Просмотреть файл

@@ -3,49 +3,39 @@ import styled from 'styled-components';
import RightSidebarLayout from '../../organisms/layouts/RightSidebar';
import DummyContent from '../../molecules/DummyContent';

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

const SidebarContainer = styled('div')({
padding: '0 1rem',
boxSizing: 'border-box',
width: '100%',
maxWidth: 'calc(var(--width-base, 360px) * 2)',
margin: '0 auto',
'@media (min-width: 1080px)': {
width: 'var(--width-base, 360px)',
marginLeft: 0,
},
})

const Container = styled('div')({
padding: '0 1rem',
boxSizing: 'border-box',

width: '100%',
maxWidth: 'calc(var(--width-base, 360px) * 2)',
marginRight: 'auto',
marginLeft: 'auto',
margin: '0 auto',
'@media (min-width: 1080px)': {
marginRight: 0,
},
})

const LeftSidebarLayoutTemplate = ({
const RightSidebarLayoutTemplate = ({
query,
}) => {
return (
<RightSidebarLayout
query={query}
sidebar={
<SidebarOverflow>
<SidebarContainer>
<DummyContent />
</SidebarContainer>
</SidebarOverflow>
<SidebarContainer>
<DummyContent />
</SidebarContainer>
}
>
<Container>
@@ -55,4 +45,4 @@ const LeftSidebarLayoutTemplate = ({
)
}

export default LeftSidebarLayoutTemplate
export default RightSidebarLayoutTemplate

+ 4
- 0
src/pages/layouts/left-sidebar/index.tsx Просмотреть файл

@@ -3,14 +3,17 @@ import Template from '../../../components/templates/LeftSidebarLayout'

type Props = {
query: string,
sidebarMainOpen: boolean,
}

const Page: NextPage<Props> = ({
query,
sidebarMainOpen,
}) => {
return (
<Template
query={query}
sidebarMainOpen={sidebarMainOpen}
/>
)
}
@@ -22,6 +25,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
return {
props: {
query,
sidebarMainOpen: 'sidebar' in ctx.query,
}
}
}


+ 4
- 0
src/pages/layouts/left-sidebar/with-menu/index.tsx Просмотреть файл

@@ -3,14 +3,17 @@ import Template from '../../../../components/templates/LeftSidebarWithMenuLayout

type Props = {
query: string,
sidebarMainOpen: boolean,
}

const Page: NextPage<Props> = ({
query,
sidebarMainOpen,
}) => {
return (
<Template
query={query}
sidebarMainOpen={sidebarMainOpen}
/>
)
}
@@ -22,6 +25,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
return {
props: {
query,
sidebarMainOpen: 'sidebar' in ctx.query,
}
}
}


Загрузка…
Отмена
Сохранить