added responsive features
This commit is contained in:
@@ -30,7 +30,7 @@ interface BorderProps {
|
||||
isBottom?: boolean;
|
||||
}
|
||||
|
||||
export const ANNOUNCEMENT_BANNER_HEIGHT = '12rem';
|
||||
export const ANNOUNCEMENT_BANNER_HEIGHT = '14rem';
|
||||
|
||||
export const AnnouncementBanner: React.StatelessComponent<Props> = (props: Props) => {
|
||||
const { heading, subline, mainCta, secondaryCta } = props;
|
||||
@@ -43,9 +43,9 @@ export const AnnouncementBanner: React.StatelessComponent<Props> = (props: Props
|
||||
<CustomHeading>{heading}</CustomHeading>
|
||||
|
||||
{subline && (
|
||||
<Paragraph color={colors.white} isMuted={0.5} isNoMargin={true}>
|
||||
<CustomParagraph color={colors.white} isMuted={0.5} isNoMargin={true}>
|
||||
{subline}
|
||||
</Paragraph>
|
||||
</CustomParagraph>
|
||||
)}
|
||||
</Column>
|
||||
<ColumnCta>
|
||||
@@ -72,15 +72,17 @@ export const AnnouncementBanner: React.StatelessComponent<Props> = (props: Props
|
||||
)}
|
||||
|
||||
{secondaryCta && (
|
||||
<Button
|
||||
color={colors.white}
|
||||
href={secondaryCta.href}
|
||||
onClick={secondaryCta.onClick}
|
||||
target={secondaryCta.shouldOpenInNewTab ? '_blank' : ''}
|
||||
isTransparent={true}
|
||||
>
|
||||
{secondaryCta.text}
|
||||
</Button>
|
||||
<SecondaryButtonWrapper>
|
||||
<Button
|
||||
color={colors.white}
|
||||
href={secondaryCta.href}
|
||||
onClick={secondaryCta.onClick}
|
||||
target={secondaryCta.shouldOpenInNewTab ? '_blank' : ''}
|
||||
isTransparent={true}
|
||||
>
|
||||
{secondaryCta.text}
|
||||
</Button>
|
||||
</SecondaryButtonWrapper>
|
||||
)}
|
||||
</ButtonWrap>
|
||||
</ColumnCta>
|
||||
@@ -93,6 +95,13 @@ interface CustomSectionProps extends SectionProps {
|
||||
dismissed: boolean;
|
||||
}
|
||||
|
||||
const SecondaryButtonWrapper = styled.div`
|
||||
display: inline-block;
|
||||
@media (max-width: 56rem) {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const BannerContentWrapper = styled.div`
|
||||
max-width: 1200px;
|
||||
display: flex;
|
||||
@@ -101,6 +110,15 @@ const BannerContentWrapper = styled.div`
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
@media (max-width: 56rem) {
|
||||
flex-direction: column;
|
||||
}
|
||||
`;
|
||||
|
||||
const CustomParagraph = styled(Paragraph)`
|
||||
@media (max-width: 56rem) {
|
||||
display: none;
|
||||
}
|
||||
`;
|
||||
|
||||
const CustomSection = styled(Section)<CustomSectionProps>`
|
||||
@@ -151,22 +169,22 @@ const CustomHeading = styled.h2`
|
||||
|
||||
const ButtonWrap = styled.div`
|
||||
display: inline-block;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
* + * {
|
||||
margin-left: 15px;
|
||||
}
|
||||
& > button,
|
||||
a {
|
||||
margin: 0 12px;
|
||||
}
|
||||
& *:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
& *:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
a,
|
||||
button {
|
||||
display: block;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
* + * {
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
& > button,
|
||||
a {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -185,7 +203,8 @@ const Border = styled.div<BorderProps>`
|
||||
top: ${props => !props.isBottom && 0};
|
||||
bottom: ${props => props.isBottom && 0};
|
||||
transform: translate(-112px);
|
||||
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
@media (max-width: 768px) {
|
||||
width: calc(100% + 82px);
|
||||
height: 40px;
|
||||
|
||||
@@ -93,7 +93,7 @@ const SectionBase = styled.section<SectionProps>`
|
||||
width: ${props => !props.isFullWidth && 'calc(100% - 60px)'};
|
||||
max-width: 1500px;
|
||||
margin: 0 auto;
|
||||
padding: ${props => (!!props.padding && props.padding) || (props.isPadded && '120px 0')};
|
||||
padding: ${props => props.isPadded && '120px 0'};
|
||||
background-color: ${props => props.theme[`${props.bgColor}BgColor`] || props.bgColor};
|
||||
position: relative;
|
||||
overflow: ${props => !props.isFullWidth && 'hidden'};
|
||||
|
||||
@@ -56,8 +56,4 @@ const InputWrapper = styled.div<InputProps>`
|
||||
position: relative;
|
||||
width: ${props => props.width || '100%'};
|
||||
border-bottom: 1px solid #d5d5d5;
|
||||
@media (max-width: 768px) {
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -10,7 +10,14 @@ import { Section } from 'ts/components/newLayout';
|
||||
import { SiteWrap } from 'ts/components/siteWrap';
|
||||
import { Heading } from 'ts/components/text';
|
||||
import { Input as SearchInput } from 'ts/components/ui/search_textfield';
|
||||
import { BY_NAME_ORDERINGS, EDITORIAL, FILTERS, ORDERINGS, PROJECTS } from 'ts/pages/explore/explore_content';
|
||||
import {
|
||||
AVAILABLE_ASSET_DATAS,
|
||||
BY_NAME_ORDERINGS,
|
||||
EDITORIAL,
|
||||
FILTERS,
|
||||
ORDERINGS,
|
||||
PROJECTS,
|
||||
} from 'ts/pages/explore/explore_content';
|
||||
import { ExploreSettingsDropdown } from 'ts/pages/explore/explore_dropdown';
|
||||
import { ExploreGrid } from 'ts/pages/explore/explore_grid';
|
||||
import { EXPLORE_STATE_DIALOGS, ExploreGridDialogTile } from 'ts/pages/explore/explore_grid_state_tile';
|
||||
@@ -70,7 +77,7 @@ export class Explore extends React.Component<ExploreProps> {
|
||||
<SiteWrap theme="light">
|
||||
<DocumentTitle {...documentConstants.EXPLORE} />
|
||||
<ExploreHero query={this.state.query} onSearch={this._setNewQuery} />
|
||||
<Section padding={'0 0 60px 0'} maxWidth={'1150px'}>
|
||||
<Section isPadded={false} padding={'0 0 60px 0'} maxWidth={'1150px'}>
|
||||
<ExploreToolBar
|
||||
onFilterClick={this._setFilter}
|
||||
filters={this.state.filters}
|
||||
@@ -115,7 +122,6 @@ export class Explore extends React.Component<ExploreProps> {
|
||||
|
||||
private readonly _onOrdering = async (newValue: string): Promise<void> => {
|
||||
this.setState({ tilesOrdering: newValue });
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
const newTiles = await this._generateTilesWithModifier(this.state.tiles, ExploreTilesModifiers.Ordering, {
|
||||
tilesOrdering: newValue as ExploreTilesOrdering,
|
||||
});
|
||||
@@ -127,7 +133,6 @@ export class Explore extends React.Component<ExploreProps> {
|
||||
};
|
||||
|
||||
private readonly _onAnalytics = (project: ExploreProject, action: ExploreAnalyticAction): void => {
|
||||
// Do Something
|
||||
switch (action) {
|
||||
case ExploreAnalyticAction.InstantClick:
|
||||
analytics.track('Explore - Instant - Clicked', { name: project.name });
|
||||
@@ -174,7 +179,6 @@ export class Explore extends React.Component<ExploreProps> {
|
||||
};
|
||||
|
||||
private readonly _changeSearchResults = async (query: string): Promise<void> => {
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
const searchedTiles = await this._generateTilesWithModifier(this.state.tiles, ExploreTilesModifiers.Search, {
|
||||
query,
|
||||
filter: this.state.filters.find(f => f.active),
|
||||
@@ -196,7 +200,6 @@ export class Explore extends React.Component<ExploreProps> {
|
||||
if (_.filter(updatedFilters, f => f.active).length === 0) {
|
||||
await this._setFilter('all');
|
||||
} else {
|
||||
// tslint:disable-next-line:no-floating-promises
|
||||
const newTiles = await this._generateTilesWithModifier(
|
||||
this.state.tiles,
|
||||
_.isEmpty(this.state.query) ? ExploreTilesModifiers.Filter : ExploreTilesModifiers.Search,
|
||||
@@ -284,14 +287,17 @@ export class Explore extends React.Component<ExploreProps> {
|
||||
const tiles = rawProjects.map((e: ExploreProject) => {
|
||||
const exploreProject = _.assign({}, e);
|
||||
if (!!exploreProject.instant) {
|
||||
exploreProject.instant = _.assign({}, exploreProject.instant, {
|
||||
availableAssetDatas: AVAILABLE_ASSET_DATAS,
|
||||
});
|
||||
exploreProject.onInstantClick = this._launchInstantAsync.bind(this, exploreProject.instant);
|
||||
}
|
||||
exploreProject.onAnalytics = this._onAnalytics.bind(this, exploreProject);
|
||||
return {
|
||||
name: e.name,
|
||||
exploreProject,
|
||||
visibility: ExploreTileVisibility.Visible,
|
||||
width: ExploreTileWidth.OneThird,
|
||||
onAnalytics: this._onAnalytics.bind(this, exploreProject),
|
||||
};
|
||||
});
|
||||
const orderedTiles = await this._generateTilesWithModifier(tiles, ExploreTilesModifiers.Ordering, {
|
||||
@@ -307,6 +313,23 @@ const ExploreHeroContentWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 100px 0;
|
||||
@media (max-width: 36rem) {
|
||||
display: block;
|
||||
padding: 50px 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const ExploreSearchInputWrapper = styled.div`
|
||||
width: 22rem;
|
||||
@media (max-width: 52rem) {
|
||||
width: 16rem;
|
||||
}
|
||||
@media (max-width: 36rem) {
|
||||
margin-top: 10px;
|
||||
padding-left: 5px;
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
interface ExploreHeroProps {
|
||||
@@ -319,12 +342,14 @@ const ExploreHero = (props: ExploreHeroProps) => {
|
||||
props.onSearch(e.target.value);
|
||||
};
|
||||
return (
|
||||
<Section maxWidth={'1150px'} padding={'50px 0 50px 0'}>
|
||||
<Section maxWidth={'1150px'} isPadded={false}>
|
||||
<ExploreHeroContentWrapper>
|
||||
<Heading isNoMargin={true} size="large">
|
||||
Explore 0x
|
||||
</Heading>
|
||||
<SearchInput value={props.query} onChange={onChange} width={'22rem'} placeholder="Search..." />
|
||||
<ExploreSearchInputWrapper>
|
||||
<SearchInput value={props.query} onChange={onChange} placeholder="Search..." />
|
||||
</ExploreSearchInputWrapper>
|
||||
</ExploreHeroContentWrapper>
|
||||
</Section>
|
||||
);
|
||||
@@ -333,11 +358,17 @@ const ExploreHero = (props: ExploreHeroProps) => {
|
||||
const ExploreToolBarWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@media (max-width: 36rem) {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
const ExploreToolBarContentWrapper = styled.div`
|
||||
display: flex;
|
||||
padding-bottom: 2rem;
|
||||
@media (max-width: 36rem) {
|
||||
display: none;
|
||||
}
|
||||
& > * {
|
||||
margin: 0 0.3rem;
|
||||
}
|
||||
|
||||
@@ -126,3 +126,13 @@ export const BY_NAME_ORDERINGS: { [s: string]: string[] } = {
|
||||
[ExploreTilesOrdering.RecentlyAdded]: ['veil', 'boxswap', 'emoon', 'paradex', 'radar_relay', 'openrelay'],
|
||||
[ExploreTilesOrdering.Alphabetical]: ['veil', 'boxswap', 'emoon', 'paradex', 'radar_relay', 'openrelay'],
|
||||
};
|
||||
|
||||
export const AVAILABLE_ASSET_DATAS: string[] = [
|
||||
'0xf47261b000000000000000000000000089d24a6b4ccb1b6faa2625fe562bdd9a23260359', // DAI
|
||||
'0xf47261b0000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
|
||||
'0xf47261b00000000000000000000000000d8775f648430679a709e98d2b0cb6250d2887ef', // BAT
|
||||
'0xf47261b000000000000000000000000005f4a42e251f2d52b8ed15e9fedaacfcef1fad27', // ZIL
|
||||
'0xf47261b00000000000000000000000000f5d2fb29fb7d3cfee444a200298f468908cc942', // MANA
|
||||
'0xf47261b00000000000000000000000000abdace70d3790235af448c88547603b945604ea', // DNT
|
||||
'0xf47261b000000000000000000000000041e5560054824ea6b0732e656e3ad64e20e94e45', // CVC
|
||||
];
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { Icon } from 'ts/components/icon';
|
||||
import { Heading } from 'ts/components/text';
|
||||
import { Switch } from 'ts/components/ui/switch';
|
||||
import { ExploreTagButton } from 'ts/pages/explore/explore_tag_button';
|
||||
import { colors } from 'ts/style/colors';
|
||||
import { ExploreTilesOrdering, ExploreTilesOrderingMetadata } from 'ts/types';
|
||||
import { ExploreFilterMetadata, ExploreTilesOrdering, ExploreTilesOrderingMetadata } from 'ts/types';
|
||||
|
||||
const OrderingListWrapper = styled.ul`
|
||||
export const OrderingListWrapper = styled.ul`
|
||||
list-style-type: none;
|
||||
`;
|
||||
|
||||
@@ -16,7 +15,7 @@ interface OrderingListItemProps {
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
const OrderingListItem = styled.li<OrderingListItemProps>`
|
||||
export const OrderingListItem = styled.li<OrderingListItemProps>`
|
||||
margin-bottom: 12px;
|
||||
cursor: pointer;
|
||||
color: ${props => (props.active ? colors.brandLight : colors.grey)};
|
||||
@@ -26,13 +25,17 @@ const OrderingListItem = styled.li<OrderingListItemProps>`
|
||||
}
|
||||
`;
|
||||
|
||||
const ExploreSettingsDropdownButton = ({}) => {
|
||||
interface ExploreSettingsDropdownButtonProps {
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export const ExploreSettingsDropdownButton = (props: ExploreSettingsDropdownButtonProps) => {
|
||||
return (
|
||||
<ExploreTagButton disableHover={true}>
|
||||
<SettingsIconWrapper>
|
||||
<Icon color={colors.grey} name="settings" size={16} />
|
||||
</SettingsIconWrapper>
|
||||
Sort
|
||||
{props.title || 'Sort'}
|
||||
</ExploreTagButton>
|
||||
);
|
||||
};
|
||||
@@ -45,17 +48,17 @@ const SettingsIconWrapper = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const SettingsWrapper = styled.div`
|
||||
export const SettingsWrapper = styled.div`
|
||||
position: relative;
|
||||
|
||||
@media (min-width: 800px) {
|
||||
&:hover > div {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: opacity 0.35s, transform 0.35s, visibility 0s;
|
||||
}
|
||||
@media (max-width: 36rem) {
|
||||
display: none;
|
||||
}
|
||||
&:hover > div {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: opacity 0.35s, transform 0.35s, visibility 0s;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -63,7 +66,7 @@ interface DropdownWrapInterface {
|
||||
width?: number;
|
||||
}
|
||||
|
||||
const DropdownWrap = styled.div<DropdownWrapInterface>`
|
||||
export const DropdownWrap = styled.div<DropdownWrapInterface>`
|
||||
width: ${props => props.width || 280}px;
|
||||
margin-top: calc(16px - 2rem);
|
||||
padding: 16px 24px;
|
||||
@@ -120,67 +123,147 @@ export interface ExploreSettingsDropdownProps {
|
||||
onOrdering: (newValue: string) => void;
|
||||
onEditorial?: (newValue: boolean) => void;
|
||||
editorial?: boolean;
|
||||
filters: ExploreFilterMetadata[];
|
||||
onFilterClick(filterName: string, active: boolean): void;
|
||||
}
|
||||
|
||||
export class ExploreSettingsDropdown extends React.Component<ExploreSettingsDropdownProps> {
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
<SettingsWrapper>
|
||||
<ExploreSettingsDropdownButton />
|
||||
<DropdownWrap>
|
||||
<DropdownContentWrapper>
|
||||
{!!this.props.onEditorial &&
|
||||
<div>
|
||||
<Switch
|
||||
isChecked={this.props.editorial}
|
||||
onToggle={this.props.onEditorial}
|
||||
label="Editorial"
|
||||
/>
|
||||
<Heading asElement="h4" size={14} color="inherit" marginBottom="0" isMuted={0.35}>
|
||||
Editorial content reflects the views of the 0x core team.
|
||||
</Heading>
|
||||
</div>}
|
||||
<OrderingWrapper>
|
||||
{/* <Heading asElement="h4" size={14} color="inherit" marginBottom="16px" isMuted={0.35}>
|
||||
Ordering
|
||||
</Heading> */}
|
||||
<OrderingListWrapper>
|
||||
{this.props.orderings.map(o => {
|
||||
const onClick = () => this.props.onOrdering(o.ordering);
|
||||
return (
|
||||
<OrderingListItem
|
||||
onClick={onClick}
|
||||
active={this.props.activeOrdering === o.ordering}
|
||||
key={o.ordering}
|
||||
>
|
||||
{o.label}
|
||||
</OrderingListItem>
|
||||
);
|
||||
})}
|
||||
</OrderingListWrapper>
|
||||
</OrderingWrapper>
|
||||
</DropdownContentWrapper>
|
||||
</DropdownWrap>
|
||||
</SettingsWrapper>
|
||||
<>
|
||||
<ExploreSettingsFullDropdown {...this.props} />
|
||||
<ExploreMobileSettingsDropdown {...this.props} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const DropdownContentWrapper = styled.div``;
|
||||
const ExploreSettingsFullDropdown = (props: ExploreSettingsDropdownProps) => {
|
||||
return (
|
||||
<SettingsWrapper>
|
||||
<ExploreSettingsDropdownButton />
|
||||
<DropdownWrap>
|
||||
<DropdownContentWrapper>
|
||||
{!!props.onEditorial && (
|
||||
<div>
|
||||
<Switch isChecked={props.editorial} onToggle={props.onEditorial} label="Editorial" />
|
||||
<Heading asElement="h4" size={14} color="inherit" marginBottom="0" isMuted={0.35}>
|
||||
Editorial content reflects the views of the 0x core team.
|
||||
</Heading>
|
||||
</div>
|
||||
)}
|
||||
<OrderingWrapper>
|
||||
<OrderingListWrapper>
|
||||
{props.orderings.map(o => {
|
||||
const onClick = () => props.onOrdering(o.ordering);
|
||||
return (
|
||||
<OrderingListItem
|
||||
onClick={onClick}
|
||||
active={props.activeOrdering === o.ordering}
|
||||
key={o.ordering}
|
||||
>
|
||||
{o.label}
|
||||
</OrderingListItem>
|
||||
);
|
||||
})}
|
||||
</OrderingListWrapper>
|
||||
</OrderingWrapper>
|
||||
</DropdownContentWrapper>
|
||||
</DropdownWrap>
|
||||
</SettingsWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const OrderingWrapper = styled.div`
|
||||
export const DropdownContentWrapper = styled.div``;
|
||||
|
||||
export const OrderingWrapper = styled.div`
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
// padding-top: 20px;
|
||||
// margin-bottom: 20px;
|
||||
// &:before {
|
||||
// content: '';
|
||||
// width: 100%;
|
||||
// height: 1px;
|
||||
// background-color: ${props => props.theme.dropdownColor};
|
||||
// opacity: 0.15;
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0;
|
||||
// }
|
||||
`;
|
||||
|
||||
const MobileSettingsWrapper = styled(SettingsWrapper)`
|
||||
display: none;
|
||||
@media (max-width: 36rem) {
|
||||
display: block;
|
||||
& > button {
|
||||
width: 100%;
|
||||
}
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
`;
|
||||
|
||||
const MobileDropdownWrap = styled(DropdownWrap)`
|
||||
width: 100%;
|
||||
margin-top: 0;
|
||||
left: 0;
|
||||
&:after,
|
||||
&:before {
|
||||
left: 50%;
|
||||
}
|
||||
`;
|
||||
|
||||
interface ExploreMobileSettingsDropdownProps extends ExploreSettingsDropdownProps {
|
||||
filters: ExploreFilterMetadata[];
|
||||
onFilterClick(filterName: string, active: boolean): void;
|
||||
}
|
||||
|
||||
export const ExploreMobileSettingsDropdown = (props: ExploreMobileSettingsDropdownProps) => {
|
||||
return (
|
||||
<MobileSettingsWrapper>
|
||||
<ExploreSettingsDropdownButton title="Filter + Sort" />
|
||||
<MobileDropdownWrap>
|
||||
<DropdownContentWrapper>
|
||||
<OrderingWrapper>
|
||||
<Heading asElement="h4" size={14} color="inherit" marginBottom="16px" isMuted={0.35}>
|
||||
Filter
|
||||
</Heading>
|
||||
<OrderingListWrapper>
|
||||
{props.filters.map(f => {
|
||||
const onClick = () => props.onFilterClick(f.name, !f.active);
|
||||
return (
|
||||
<OrderingListItem onClick={onClick} active={f.active} key={f.name}>
|
||||
{f.label}
|
||||
</OrderingListItem>
|
||||
);
|
||||
})}
|
||||
</OrderingListWrapper>
|
||||
</OrderingWrapper>
|
||||
<BottomOrderingWrapper>
|
||||
<Heading asElement="h4" size={14} color="inherit" marginBottom="16px" isMuted={0.35}>
|
||||
Sort
|
||||
</Heading>
|
||||
<OrderingListWrapper>
|
||||
{props.orderings.map(o => {
|
||||
const onClick = () => props.onOrdering(o.ordering);
|
||||
return (
|
||||
<OrderingListItem
|
||||
onClick={onClick}
|
||||
active={props.activeOrdering === o.ordering}
|
||||
key={o.ordering}
|
||||
>
|
||||
{o.label}
|
||||
</OrderingListItem>
|
||||
);
|
||||
})}
|
||||
</OrderingListWrapper>
|
||||
</BottomOrderingWrapper>
|
||||
</DropdownContentWrapper>
|
||||
</MobileDropdownWrap>
|
||||
</MobileSettingsWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const BottomOrderingWrapper = styled(OrderingWrapper)`
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
&:before {
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background-color: ${props => props.theme.dropdownColor};
|
||||
opacity: 0.15;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -3,17 +3,44 @@ import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { ExploreGridTile } from 'ts/pages/explore/explore_grid_tile';
|
||||
import { ExploreTile, ExploreTileVisibility, ExploreTileWidth } from 'ts/types';
|
||||
import { ExploreTile, ExploreTileGridWidth, ExploreTileVisibility, ExploreTileWidth } from 'ts/types';
|
||||
|
||||
const EXPLORE_TILE_COL_WIDTH: { [ExploreTileWidth: string]: { [ExploreTileGridWidth: number]: number } } = {
|
||||
[ExploreTileWidth.OneThird]: {
|
||||
[ExploreTileGridWidth.ThreeColumn]: 2,
|
||||
[ExploreTileGridWidth.TwoColumn]: 2,
|
||||
[ExploreTileGridWidth.OneColumn]: 2,
|
||||
},
|
||||
[ExploreTileWidth.FullWidth]: {
|
||||
[ExploreTileGridWidth.ThreeColumn]: 6,
|
||||
[ExploreTileGridWidth.TwoColumn]: 4,
|
||||
[ExploreTileGridWidth.OneColumn]: 2,
|
||||
},
|
||||
[ExploreTileWidth.Half]: {
|
||||
[ExploreTileGridWidth.ThreeColumn]: 3,
|
||||
[ExploreTileGridWidth.TwoColumn]: 4,
|
||||
[ExploreTileGridWidth.OneColumn]: 2,
|
||||
},
|
||||
[ExploreTileWidth.TwoThirds]: {
|
||||
[ExploreTileGridWidth.ThreeColumn]: 4,
|
||||
[ExploreTileGridWidth.TwoColumn]: 4,
|
||||
[ExploreTileGridWidth.OneColumn]: 2,
|
||||
},
|
||||
};
|
||||
|
||||
export interface ExptoreGridProps {
|
||||
tiles: ExploreTile[];
|
||||
}
|
||||
|
||||
interface RicherExploreGridListTile extends ExploreTile {
|
||||
interface ExploreGridTilePosition {
|
||||
gridStart: number;
|
||||
gridEnd: number;
|
||||
}
|
||||
|
||||
interface RicherExploreGridListTile extends ExploreTile {
|
||||
tilePositions: { [ExploreTileGridWidth: number]: ExploreGridTilePosition };
|
||||
}
|
||||
|
||||
export class ExploreGrid extends React.Component<ExptoreGridProps> {
|
||||
public render(): React.ReactNode {
|
||||
return (
|
||||
@@ -21,13 +48,13 @@ export class ExploreGrid extends React.Component<ExptoreGridProps> {
|
||||
{this._prepareTiles().map(t => {
|
||||
if (!!t.exploreProject) {
|
||||
return (
|
||||
<ExploreGridTileWrapper key={t.name} gridStart={t.gridStart} gridEnd={t.gridEnd}>
|
||||
<ExploreGridTileWrapper key={t.name} tilePositions={t.tilePositions}>
|
||||
<ExploreGridTile {...t.exploreProject} />
|
||||
</ExploreGridTileWrapper>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<ExploreGridTileWrapper key={t.name} gridStart={t.gridStart} gridEnd={t.gridEnd}>
|
||||
<ExploreGridTileWrapper key={t.name} tilePositions={t.tilePositions}>
|
||||
{!!t.component && t.component}
|
||||
</ExploreGridTileWrapper>
|
||||
);
|
||||
@@ -42,18 +69,32 @@ export class ExploreGrid extends React.Component<ExptoreGridProps> {
|
||||
return this._generateGridValues(visibleTiles);
|
||||
};
|
||||
|
||||
private readonly _generateGridValues = (tiles: ExploreTile[]): RicherExploreGridListTile[] => {
|
||||
private readonly _generateGridPositions = (
|
||||
tiles: RicherExploreGridListTile[],
|
||||
width: ExploreTileGridWidth,
|
||||
): RicherExploreGridListTile[] => {
|
||||
let gridEndCounter = 1;
|
||||
const richerTiles = tiles.map(t => {
|
||||
if (gridEndCounter + t.width > ExploreTileWidth.FullWidth + 1) {
|
||||
const newTiles = tiles.map(t => {
|
||||
if (gridEndCounter + EXPLORE_TILE_COL_WIDTH[t.width][width] > width + 1) {
|
||||
gridEndCounter = 1;
|
||||
}
|
||||
const gridStart = gridEndCounter;
|
||||
const gridEnd = gridEndCounter + t.width;
|
||||
const gridEnd = gridEndCounter + EXPLORE_TILE_COL_WIDTH[t.width][width];
|
||||
gridEndCounter = gridEnd;
|
||||
const newTile = _.assign({ gridStart, gridEnd }, t);
|
||||
return newTile as RicherExploreGridListTile;
|
||||
const newTilePositions = _.assign({}, t.tilePositions);
|
||||
newTilePositions[width] = { gridStart, gridEnd };
|
||||
return _.assign({}, t, { tilePositions: newTilePositions }) as RicherExploreGridListTile;
|
||||
});
|
||||
return newTiles;
|
||||
};
|
||||
|
||||
private readonly _generateGridValues = (tiles: ExploreTile[]): RicherExploreGridListTile[] => {
|
||||
let richerTiles = tiles.map(t => {
|
||||
return _.assign({ tilePositions: {} }, t) as RicherExploreGridListTile;
|
||||
});
|
||||
richerTiles = this._generateGridPositions(richerTiles, ExploreTileGridWidth.ThreeColumn);
|
||||
richerTiles = this._generateGridPositions(richerTiles, ExploreTileGridWidth.TwoColumn);
|
||||
richerTiles = this._generateGridPositions(richerTiles, ExploreTileGridWidth.OneColumn);
|
||||
return richerTiles;
|
||||
};
|
||||
}
|
||||
@@ -61,27 +102,34 @@ export class ExploreGrid extends React.Component<ExptoreGridProps> {
|
||||
interface ExploreGridListProps {}
|
||||
|
||||
interface ExploreGridTileWrapperProps {
|
||||
gridStart: number;
|
||||
gridEnd: number;
|
||||
tilePositions: { [ExploreTileGridWidth: number]: ExploreGridTilePosition };
|
||||
}
|
||||
|
||||
const ExploreGridTileWrapper = styled.div<ExploreGridTileWrapperProps>`
|
||||
grid-column-start: ${props => props.gridStart};
|
||||
grid-column-end: ${props => props.gridEnd};
|
||||
grid-column-start: ${props => props.tilePositions[ExploreTileGridWidth.ThreeColumn].gridStart};
|
||||
grid-column-end: ${props => props.tilePositions[ExploreTileGridWidth.ThreeColumn].gridEnd};
|
||||
@media (max-width: 56rem) {
|
||||
grid-column-start: ${props => props.tilePositions[ExploreTileGridWidth.TwoColumn].gridStart};
|
||||
grid-column-end: ${props => props.tilePositions[ExploreTileGridWidth.TwoColumn].gridEnd};
|
||||
}
|
||||
@media (max-width: 36rem) {
|
||||
grid-column-start: ${props => props.tilePositions[ExploreTileGridWidth.OneColumn].gridStart};
|
||||
grid-column-end: ${props => props.tilePositions[ExploreTileGridWidth.OneColumn].gridEnd};
|
||||
}
|
||||
`;
|
||||
|
||||
const ExploreGridList = styled.div<ExploreGridListProps>`
|
||||
display: grid;
|
||||
grid-template-columns: repeat(${ExploreTileWidth.FullWidth}, 1fr);
|
||||
grid-template-columns: repeat(${ExploreTileGridWidth.ThreeColumn}, 1fr);
|
||||
grid-column-gap: 1.5rem;
|
||||
grid-row-gap: 1.5rem;
|
||||
& > * {
|
||||
align-self: stretch;
|
||||
}
|
||||
@media (max-width: 56rem) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-columns: repeat(${ExploreTileGridWidth.TwoColumn}, 1fr);
|
||||
}
|
||||
@media (max-width: 36rem) {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
grid-template-columns: repeat(${ExploreTileGridWidth.OneColumn}, 1fr);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -306,10 +306,16 @@ export enum ExploreTileVisibility {
|
||||
}
|
||||
|
||||
export enum ExploreTileWidth {
|
||||
OneThird = 2,
|
||||
FullWidth = 6,
|
||||
Half = 3,
|
||||
TwoThirds = 4,
|
||||
OneThird = 'ONE_THIRD',
|
||||
FullWidth = 'FULL_WIDTH',
|
||||
Half = 'HALF',
|
||||
TwoThirds = 'TWO_THIRDS',
|
||||
}
|
||||
|
||||
export enum ExploreTileGridWidth {
|
||||
ThreeColumn = 6,
|
||||
TwoColumn = 4,
|
||||
OneColumn = 2,
|
||||
}
|
||||
|
||||
export interface ExploreTile {
|
||||
|
||||
Reference in New Issue
Block a user