Merge pull request #18 from tmshv/fix/pager-update

New Pager
This commit is contained in:
tmshv authored and GitHub committed 2020-02-18 23:59:23 +03:00
commit 29c2a53c54
17 files changed
+303 -191

No files matched your search

+1 -1
View File
@@ -4,7 +4,7 @@ const withSass = require('@zeit/next-sass')
module.exports = withCss(withSass({
exportTrailingSlash: true,
env: {
APP_ARTICLES_PAGE_SIZE: 15,
APP_ARTICLES_PAGE_SIZE: 12,
},
webpack(config) {
config.resolve.modules.push(__dirname)
+3 -3
View File
@@ -38,14 +38,14 @@ export const App: React.FC<IAppProps> = props => {
/>
)}
>
<section className={cx('content', `content_${props.layout}`, {
<div className={cx('content', `content_${props.layout}`, {
'content--padding-top--menu': props.menuPadding,
'reduced-motion': motionDisabled,
})}>
{props.children}
</section>
</div>
<Comments />
{/* <Comments /> */}
</Wrapper>
</ConfigContext.Provider>
)
+31 -111
View File
@@ -1,123 +1,43 @@
import * as React from 'react'
import './styles.css'
import cx from 'classnames'
import { Date } from './Date'
interface IImage {
alt: string
src: string
srcSet: Array<{ url: string, density: number }>
}
import { IImage } from 'src/types'
import Link from 'next/link'
export interface IArticleCardProps {
style?: React.CSSProperties
article: any
preview?: IImage
}
export const ArticleCard: React.FC<IArticleCardProps> = ({ article, ...props }) => (
<section className="ArticleCard">
<style jsx>{`
.ArticleCard {
--article-card-width: 30%;
--article-card-image-height: 15em;
--article-card-margin: var(--double-margin) var(--single-margin);
<div className="ArticleCard" style={props.style}>
<Link href={article.url}>
<a className="invisible">
<div className="ArticleCard-image">
{!props.preview ? null : (
<picture>
<img
className={cx({ opa: false })}
alt={props.preview.alt}
src={props.preview.src}
srcSet={props.preview.srcSet.map(({ url, density }) => `${url} ${density}x`).join(' ')}
/>
</picture >
)}
</div>
display: flex;
flex-direction: column;
<div className="ArticleCard-body">
{article.title}
margin: var(--article-card-margin);
width: var(--article-card-width);
min-width: 15em;
max-width: 20em;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
overflow: hidden;
}
.ArticleCard > a {
display: block;
position: relative;
}
.ArticleCard-image {
overflow: hidden;
position: relative;
width: 100%;
height: var(--article-card-image-height);
}
.ArticleCard-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: all 150ms ease-out;
position: absolute;
top: 0;
left: 0;
}
.ArticleCard-body {
z-index: 1000;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
height: 5em;
padding: .75em 1em;
}
.ArticleCard:hover img {
width: 105%;
height: 105%;
top: -2.5%;
left: -2.5%;
}
// Tablet
@media screen and (min-width: var(--tablet-min-width)) and (max-width: var(--tablet-max-width)) {
.ArticleCard {
--article-card-image-height: 12em;
}
}
// Mobile
@media (max-width: 31.25em) {
.ArticleCard {
--article-card-width: 100%;
--article-card-margin: var(--single-margin) 0;
}
}
`}</style>
<a className="invisible" href={article.url}>
<div className="ArticleCard-image">
{!props.preview ? null : (
<picture>
<img
className={cx({ opa: false })}
alt={props.preview.alt}
src={props.preview.src}
srcSet={props.preview.srcSet.map(({ url, density }) => `${url} ${density}x`).join(' ')}
/>
</picture >
)}
</div>
<div className="ArticleCard-body">
{article.title}
{!article.date ? null : (
<Date>
{article.date}
</Date>
)}
</div>
</a>
</section>
{!article.date ? null : (
<Date>
{article.date}
</Date>
)}
</div>
</a>
</Link>
</div>
)
+91
View File
@@ -0,0 +1,91 @@
.ArticleCard {
--article-card-image-height: 15em;
display: flex;
flex-direction: column;
border-radius: var(--radius);
box-shadow: var(--shadow);
/* box-shadow: 0 0 0 1px var(--color-shadow); */
overflow: hidden;
transition: box-shadow 150ms;
}
.ArticleCard:hover {
box-shadow: var(--shadow-active);
}
.ArticleCard > a {
display: block;
position: relative;
}
.ArticleCard-image {
overflow: hidden;
position: relative;
width: 100%;
height: var(--article-card-image-height);
}
.ArticleCard-image img {
width: 100%;
height: 100%;
object-fit: cover;
transition: all 150ms ease-out;
position: absolute;
top: 0;
left: 0;
}
.ArticleCard-body {
position: relative;
z-index: 1000;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
height: 5em;
background-color: white;
padding: 0 var(--size-m) var(--size-m);
}
.ArticleCard-body:before {
position: absolute;
content: '';
background-color: white;
border-radius: var(--radius) var(--radius) 0 0 ;
width: 100%;
height: var(--radius);
top: calc(var(--radius) * -1);
left: 0;
}
.ArticleCard:hover img {
width: 104%;
height: 104%;
top: -2%;
left: -2%;
}
/* Tablet */
@media screen and (min-width: var(--tablet-min-width)) and (max-width: var(--tablet-max-width)) {
.ArticleCard {
--article-card-image-height: 12em;
}
}
/* Mobile */
@media (max-width: 31.25em) {
.ArticleCard {
}
}
+23 -24
View File
@@ -1,28 +1,21 @@
import Paginator from './Paginator'
import { ArticleCard } from './ArticleCard'
import { Pager } from './Pager'
import { CardGrid } from './CardGrid'
import { IArticle } from 'src/types'
export interface IArticleCardListProps {
articles: any[]
articles: IArticle[]
nextPage: number | null
prevPage: number | null
}
export const ArticleCardList:React.FC<IArticleCardListProps> = ({ articles, nextPage, prevPage }) => (
<div>
<style jsx>{`
.body {
display: flex;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
}
`}</style>
{!prevPage ? null : (
<Paginator url={`/articles/${prevPage}`} type="top" />
)}
<div className={'body'}>
export const ArticleCardList: React.FC<IArticleCardListProps> = ({ articles, nextPage, prevPage, ...props }) => (
<>
<CardGrid
style={{
marginBottom: 'var(--size-m)',
}}
>
{articles.map((article, i) => {
const preview = {
alt: article.title,
@@ -30,18 +23,24 @@ export const ArticleCardList:React.FC<IArticleCardListProps> = ({ articles, next
srcSet: article.preview.set,
}
const gridColumn = article.featured ? 'span 2' : 'auto'
return (
<ArticleCard
key={i}
article={article}
preview={preview}
preview={preview as any}
style={{
gridColumn
}}
/>
)
})}
</div>
</CardGrid>
{!nextPage ? null : (
<Paginator url={`/articles/${nextPage}`} type="bottom" />
)}
</div>
<Pager
nextHref={nextPage ? `/articles/${nextPage}` : null}
prevHref={prevPage ? `/articles/${prevPage}` : null}
/>
</>
)
+25
View File
@@ -0,0 +1,25 @@
import './styles.css'
import Link from 'next/link'
export type ButtonProps = {
style?: React.CSSProperties
href?: string
}
export const Button: React.FC<ButtonProps> = props => {
if (props.href) {
return (
<Link href={props.href}>
<a className={'button invisible'} style={props.style}>
{props.children}
</a>
</Link>
)
}
return (
<button className={'button'} style={props.style}>
{props.children}
</button>
)
}
+25
View File
@@ -0,0 +1,25 @@
.button {
border: none;
font-size: var(--font-size-default);
text-align: center;
margin-top: var(--size-m);
margin-bottom: var(--size-m);
margin-left: 1px;
margin-right: 1px;
padding: var(--size-s) var(--size-m);
border-radius: 100px;
background-color: var(--color-back);
box-shadow: 0 0 0 1px var(--color-shadow);
transition: box-shadow 150ms;
outline: none;
cursor: pointer;
}
.button:hover {
box-shadow: var(--shadow-active);
}
+13
View File
@@ -0,0 +1,13 @@
import './styles.css'
export type CardGridProps = {
style?: React.CSSProperties
}
export const CardGrid: React.FC<CardGridProps> = props => {
return (
<section className={'card-grid'} style={props.style}>
{props.children}
</section>
)
}
+21
View File
@@ -0,0 +1,21 @@
.card-grid {
--min-cell-size: 240px;
display: grid;
/* grid-template-columns: 1fr 1fr 1fr; */
grid-template-columns: repeat(auto-fill, minmax(var(--min-cell-size), 1fr));
grid-auto-rows: 1fr;
grid-gap: var(--size-xl) var(--size-l);
}
/* .card-grid > *:first-child {
grid-row: 1 / 1;
grid-column: 1 / 1;
} */
@media screen and (max-width: 31.25em) {
.card-grid {
grid-template-columns: 1fr;
/* grid-template-columns: auto; */
grid-gap: var(--size-l) 0;
}
}
+20
View File
@@ -0,0 +1,20 @@
import { Block, BlockProps } from '../Block'
import { Button } from '../Button'
import { Spacer } from '../Spacer'
export type PagerProps = Omit<BlockProps, 'direction'> & {
nextHref: string | null
prevHref: string | null
}
export const Pager: React.FC<PagerProps> = ({ prevHref, nextHref, ...props }) => (
<Block {...props} direction={'horizontal'}>
{!prevHref ? null : (
<Button href={prevHref}>Предыдущая страница</Button>
)}
<Spacer />
{!nextHref ? null : (
<Button href={nextHref}>Следущая страница</Button>
)}
</Block>
)
-21
View File
@@ -1,21 +0,0 @@
const React = require('react')
const text = ['↑', '↓']
const linkText = ['Предыдущая страница', 'Следующая страница']
const i = type => type === 'top'
? 0
: 1
const Icon = ({children}) => (
<span className="Paginator-Icon">{children}</span>
)
const Paginator = ({url, type}) => (
<div className="Paginator">
<Icon>{text[i(type)]}</Icon>
<a href={url}>{linkText[i(type)]}</a>
</div>
)
module.exports = Paginator
+6 -1
View File
@@ -21,11 +21,16 @@ export const Wrapper: React.FC<WrapperProps> = props => (
.content {
flex: 1;
}
main {
display: flex;
justify-content: center;
}
`}</style>
{props.header}
<main className={'content'}>
<main>
{props.children}
</main>
+11 -3
View File
@@ -23,10 +23,12 @@
--tablet-min-width: 31.25em;
--tablet-max-width: 64em;
/* CONTENT */
--content-full: 100%;
--content-wide: 90%;
--content-semi-wide: 70%;
--content-thin: 60%;
--content-width: var(--content-full);
--embed-video-ratio: 56.25%;
@@ -53,6 +55,7 @@
--magenta-color: rgb(214, 39, 246);
--red-color: rgb(246, 27, 20);
--gray-color: rgb(153, 154, 160);
--color-shadow: rgba(27, 51, 88, 0.15);
--inactive-link-color: var(--light-color);
@@ -71,7 +74,12 @@
--size-s: 0.5em;
--size-m: 1em;
--size-l: 2em;
--size-xl: 5em;
--size-xl: 3em;
/* EFFECTS */
--radius: 15px;
--shadow: 0 0 8px var(--color-shadow);
--shadow-active: 0 4px 16px var(--color-shadow);
/* MARGINS */
--small-margin: 0.2em;
@@ -149,9 +157,9 @@ a:active {
border-width: 2px;
}
a:visited {
/* a:visited {
color: #a4059c;
}
} */
a.invisible {
border-bottom: none;
-10
View File
@@ -1,10 +0,0 @@
.Paginator {
text-align: center;
font-size: var(--font-size-second);
margin: var(--single-margin) 0;
}
.Paginator-Icon {
margin: 0 10px;
}
+18 -16
View File
@@ -1,25 +1,27 @@
.content {
margin: 0 auto 1em;
// margin: 0 auto 1em;
&.content_full {
width: var(--content-full);
}
width: var(--content-width);
}
&.content_wide {
width: var(--content-wide);
}
.content_full {
--content-width: var(--content-full);
}
&.content_semi-wide {
width: var(--content-semi-wide);
}
.content_wide {
--content-width: var(--content-wide);
}
&.content_thin {
width: var(--content-thin);
}
.content_semi-wide {
--content-width: var(--content-semi-wide);
}
&.content--padding-top--menu {
padding-top: var(--menu-thickness);
}
.content_thin {
--content-width: var(--content-thin);
}
.content--padding-top--menu {
padding-top: var(--menu-thickness);
}
// Animation on load
-1
View File
@@ -6,7 +6,6 @@
@import "components/schedule-table";
@import "components/footer-links";
@import "components/Article";
@import "components/Paginator";
@import "components/album";
@import "components/ArticleTags";
+15
View File
@@ -23,3 +23,18 @@ export interface IMeta {
twitterSite: string
twitterCreator: string
}
export interface IImage {
alt: string
src: string
srcSet: Array<{ url: string, density: number }>
set: any // TODO
}
export interface IArticle {
id: string
featured: boolean
url: string
title: string
preview: IImage
}