init Filters menu and generalize TransBack component
This commit is contained in:
parent
3a36996b24
commit
50ca77105f
27
src/components/elements/Button.js
Normal file
27
src/components/elements/Button.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import {Medium} from "../../utils/fonts";
|
||||||
|
|
||||||
|
const ButtonStyle = styled(Medium)`
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: ${({width}) => width ? width : '64px'};
|
||||||
|
height: ${({height}) => height ? height : '28px'};
|
||||||
|
border-radius: 12px;
|
||||||
|
background-color: ${({theme, backgroundColor}) => backgroundColor ? backgroundColor : theme.colors.green};
|
||||||
|
color: ${({theme, color}) => color ? color : theme.colors.white};
|
||||||
|
box-shadow: ${({theme}) => theme.buttonShadow};
|
||||||
|
cursor: pointer;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Button = (props) => {
|
||||||
|
return (
|
||||||
|
<ButtonStyle onClick={props.handler} width={props.width} height={props.height}
|
||||||
|
color={props.color} backgroundColor={props.backgroundColor}>
|
||||||
|
{props.children}
|
||||||
|
</ButtonStyle>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Button;
|
44
src/components/elements/Filters.js
Normal file
44
src/components/elements/Filters.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {FlexColumn, FlexRow, TransBack} from "../../utils/containers";
|
||||||
|
import Button from "./Button";
|
||||||
|
import theme from "../../utils/theme";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
const FiltersStyle = styled(FlexColumn)`
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
overflow-y: scroll;
|
||||||
|
width: 240px;
|
||||||
|
min-height: 626px;
|
||||||
|
height: 100vh;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 56px 16px 14px 24px;
|
||||||
|
box-shadow: ${({theme}) => theme.filtersShadow};
|
||||||
|
background-color: ${({theme}) => theme.colors.white};
|
||||||
|
transition: transform 0.5s ease-in-out;
|
||||||
|
z-index: 3;
|
||||||
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
const Filters = (props) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TransBack backgroundColor={theme.colors.dark03} translateX={props.translateX}
|
||||||
|
opacity={props.opacity} onClick={props.toggleFiltersMenu}/>
|
||||||
|
<FiltersStyle translateX={props.translateX} gap='16px'>
|
||||||
|
<FlexRow gap='16px' margin='14px 0 0 0'>
|
||||||
|
<Button as='button' width='64px' height='28px'>
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
<Button as='button' width='64px' height='28px'
|
||||||
|
backgroundColor={theme.colors.dark}>
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
</FlexRow>
|
||||||
|
</FiltersStyle>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Filters;
|
@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import {Container, FlexColumn, FlexRow, Svg} from "../../utils/containers";
|
import {FlexColumn, FlexRow, Svg, TransBack} from "../../utils/containers";
|
||||||
import {Menu} from "../../utils/fonts";
|
import {Menu} from "../../utils/fonts";
|
||||||
import loginIco from '../../assets/login_ico.svg';
|
import loginIco from '../../assets/login_ico.svg';
|
||||||
import registerIco from '../../assets/register_ico.svg';
|
import registerIco from '../../assets/register_ico.svg';
|
||||||
@ -44,21 +44,10 @@ const MobileNavMenuStyle = styled(FlexColumn)`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const TransBack = styled(Container)`
|
|
||||||
position: fixed;
|
|
||||||
top: 42px;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
transition: transform 0.3s ease-in-out;
|
|
||||||
`
|
|
||||||
|
|
||||||
const MobileNavMenu = (props) => {
|
const MobileNavMenu = (props) => {
|
||||||
return (
|
return (
|
||||||
<TransBack translateY={props.translateY} onClick={props.toggleNavMenu}>
|
<TransBack transition='transform' alignmentX='flex-start' top='42px'
|
||||||
|
translateY={props.translateY} onClick={props.toggleNavMenu}>
|
||||||
<MobileNavMenuStyle as='ul'>
|
<MobileNavMenuStyle as='ul'>
|
||||||
<FlexRow as={Link} to='/' gap='16px'>
|
<FlexRow as={Link} to='/' gap='16px'>
|
||||||
<Svg width='16px' height='16px' src={loginIco}/>
|
<Svg width='16px' height='16px' src={loginIco}/>
|
||||||
|
@ -36,7 +36,7 @@ const Search = (props) => {
|
|||||||
<SearchStyle>
|
<SearchStyle>
|
||||||
<Svg src={loopIco}/>
|
<Svg src={loopIco}/>
|
||||||
<Body as='input' onChange={(event) => props.searchQueryHandler(event)}/>
|
<Body as='input' onChange={(event) => props.searchQueryHandler(event)}/>
|
||||||
<Svg as='button' src={filtersIco}/>
|
<Svg as='button' src={filtersIco} onClick={props.toggleFiltersMenu}/>
|
||||||
</SearchStyle>
|
</SearchStyle>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,12 @@ import MiniChallenge from "../components/elements/MiniChallenge";
|
|||||||
import Pager from "../components/elements/Pager";
|
import Pager from "../components/elements/Pager";
|
||||||
import challengesResp from "../prototypeData/challenges";
|
import challengesResp from "../prototypeData/challenges";
|
||||||
import {ELEMENTS_PER_PAGE} from "../utils/globals";
|
import {ELEMENTS_PER_PAGE} from "../utils/globals";
|
||||||
|
import Filters from "../components/elements/Filters";
|
||||||
|
|
||||||
const Challenges = () => {
|
const Challenges = () => {
|
||||||
const [pageNr, setPageNr] = React.useState(1);
|
const [pageNr, setPageNr] = React.useState(1);
|
||||||
const [challenges, setChallenges] = React.useState(challengesResp);
|
const [challenges, setChallenges] = React.useState(challengesResp);
|
||||||
|
const [filtersMenu, setFiltersMenu] = React.useState(false);
|
||||||
|
|
||||||
const calcPages = () => {
|
const calcPages = () => {
|
||||||
return Math.ceil(challenges.length / ELEMENTS_PER_PAGE);
|
return Math.ceil(challenges.length / ELEMENTS_PER_PAGE);
|
||||||
@ -60,14 +62,22 @@ const Challenges = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const toggleFiltersMenu = () => {
|
||||||
|
let newFiltersMenu = !filtersMenu;
|
||||||
|
setFiltersMenu(newFiltersMenu);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<Filters translateX={filtersMenu ? '0' : '100vw'} opacity={filtersMenu ? '1' : '0'}
|
||||||
|
toggleFiltersMenu={toggleFiltersMenu}/>
|
||||||
<FlexColumn as='main' alignmentY='flex-start' width='100%'
|
<FlexColumn as='main' alignmentY='flex-start' width='100%'
|
||||||
minHeight='100vh' padding='90px 0 32px 0'>
|
minHeight='100vh' padding='90px 0 32px 0'>
|
||||||
<FlexColumn alignmentX='flex-start' width='80%'>
|
<FlexColumn alignmentX='flex-start' width='80%'>
|
||||||
<H1 as='h1' margin='0 0 20px 0'>
|
<H1 as='h1' margin='0 0 20px 0'>
|
||||||
Challenges
|
Challenges
|
||||||
</H1>
|
</H1>
|
||||||
<Search searchQueryHandler={searchQueryHandler}/>
|
<Search searchQueryHandler={searchQueryHandler} toggleFiltersMenu={toggleFiltersMenu}/>
|
||||||
<FlexColumn width='100%'>
|
<FlexColumn width='100%'>
|
||||||
<Grid margin='32px 0' gridGap='32px 0'>
|
<Grid margin='32px 0' gridGap='32px 0'>
|
||||||
{renderChallenges()}
|
{renderChallenges()}
|
||||||
@ -77,6 +87,7 @@ const Challenges = () => {
|
|||||||
<Pager pageNr={pageNr} pages={calcPages()}
|
<Pager pageNr={pageNr} pages={calcPages()}
|
||||||
nextPage={nextPage} previousPage={previousPage}/>
|
nextPage={nextPage} previousPage={previousPage}/>
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ const colors = {
|
|||||||
white: '#FCFCFC',
|
white: '#FCFCFC',
|
||||||
green: '#1B998B',
|
green: '#1B998B',
|
||||||
dark: '#343434',
|
dark: '#343434',
|
||||||
|
dark03: 'rgba(52, 52, 52, 0.3)',
|
||||||
dark05: 'rgba(52, 52, 52, 0.5)',
|
dark05: 'rgba(52, 52, 52, 0.5)',
|
||||||
dark08: 'rgba(52, 52, 52, 0.8)',
|
dark08: 'rgba(52, 52, 52, 0.8)',
|
||||||
};
|
};
|
||||||
|
@ -52,4 +52,15 @@ const Svg = styled(Container)`
|
|||||||
height: ${({height}) => height ? height : '16px'};
|
height: ${({height}) => height ? height : '16px'};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export {Container, FlexRow, FlexColumn, Grid, Svg};
|
const TransBack = styled(FlexRow)`
|
||||||
|
position: fixed;
|
||||||
|
top: ${({top}) => top ? top : '0'};
|
||||||
|
left: ${({left}) => left ? left : '0'};
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
transition: ${({transition}) => transition ? transition : 'opacity'} 0.3s ease-in-out;
|
||||||
|
background-color: ${({theme, backgroundColor}) => backgroundColor ? backgroundColor : 'transparent'};
|
||||||
|
z-index: 2;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export {Container, FlexRow, FlexColumn, Grid, Svg, TransBack};
|
@ -6,7 +6,10 @@ const theme = {
|
|||||||
mobile: '(max-width: 768px)',
|
mobile: '(max-width: 768px)',
|
||||||
desktop: '(min-width: 769px)',
|
desktop: '(min-width: 769px)',
|
||||||
shadow: '1px 2px 4px rgba(52, 52, 52, 0.25)',
|
shadow: '1px 2px 4px rgba(52, 52, 52, 0.25)',
|
||||||
navShadow: '0 1px 2px rgba(52, 52, 52, 0.25)'
|
navShadow: '0 1px 2px rgba(52, 52, 52, 0.25)',
|
||||||
|
buttonShadow: '0 4px 4px rgba(52, 52, 52, 0.25)',
|
||||||
|
filtersShadow: '-4px 4px 4px rgba(52, 52, 52, 0.25)'
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default theme;
|
export default theme;
|
Loading…
Reference in New Issue
Block a user