mirror of
https://github.com/kremalicious/blog.git
synced 2025-01-03 18:35:07 +01:00
changes
This commit is contained in:
parent
96f43a4fb0
commit
71feac2ea8
@ -19,7 +19,7 @@ module.exports = {
|
||||
rss: '/feed.xml',
|
||||
jsonfeed: '/feed.json',
|
||||
typekitID: 'msu4qap',
|
||||
itemsPerPage: 18,
|
||||
itemsPerPage: 25,
|
||||
repoContentPath: 'https://github.com/kremalicious/blog/tree/main/content',
|
||||
menu: [
|
||||
{
|
||||
|
@ -4,9 +4,8 @@
|
||||
.title {
|
||||
padding-left: 0.2rem;
|
||||
padding-right: 0.2rem;
|
||||
color: $brand-grey-light;
|
||||
margin-top: $spacer / 2;
|
||||
margin-bottom: 0;
|
||||
margin-bottom: $spacer / 6;
|
||||
font-size: $font-size-base;
|
||||
transition: color 0.2s ease-out;
|
||||
}
|
||||
@ -19,18 +18,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.time {
|
||||
font-style: italic;
|
||||
font-size: $font-size-small;
|
||||
color: $text-color-light;
|
||||
}
|
||||
|
||||
.empty {
|
||||
@include media-frame;
|
||||
|
||||
height: 100%;
|
||||
min-height: 80px;
|
||||
display: block;
|
||||
min-height: 95px;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAACaADAAQAAAABAAAACQAAAAAvQpmhAAAAHElEQVQYGWNgoBL4T8gcggoIGcBA0ASCCmhsBQBhFwX7u70C8QAAAABJRU5ErkJggg==);
|
||||
|
||||
a:hover & {
|
||||
border-color: $link-color;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-md) {
|
||||
min-height: 110px;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { Image } from '../atoms/Image'
|
||||
import { Post } from '../../@types/Post'
|
||||
import PostTitle from '../templates/Post/Title'
|
||||
import styles from './PostTeaser.module.scss'
|
||||
import Time from '../atoms/Time'
|
||||
|
||||
export const postTeaserQuery = graphql`
|
||||
fragment PostTeaser on MarkdownRemark {
|
||||
@ -13,6 +14,7 @@ export const postTeaserQuery = graphql`
|
||||
type
|
||||
title
|
||||
linkurl
|
||||
updated
|
||||
image {
|
||||
childImageSharp {
|
||||
...ImageFluidThumb
|
||||
@ -22,6 +24,7 @@ export const postTeaserQuery = graphql`
|
||||
}
|
||||
fields {
|
||||
slug
|
||||
date
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -33,8 +36,8 @@ export default function PostTeaser({
|
||||
post: Partial<Post>
|
||||
toggleSearch?: () => void
|
||||
}): ReactElement {
|
||||
const { image, title, type } = post.frontmatter
|
||||
const { slug } = post.fields
|
||||
const { image, title, type, updated } = post.frontmatter
|
||||
const { slug, date } = post.fields
|
||||
|
||||
return (
|
||||
<Link
|
||||
@ -42,16 +45,23 @@ export default function PostTeaser({
|
||||
to={slug}
|
||||
onClick={toggleSearch && toggleSearch}
|
||||
>
|
||||
{image && (
|
||||
{image ? (
|
||||
<Image
|
||||
title={type === 'photo' ? title : null}
|
||||
fluid={image.childImageSharp.fluid}
|
||||
alt={title}
|
||||
original={image.childImageSharp.original}
|
||||
/>
|
||||
) : (
|
||||
<span className={styles.empty} />
|
||||
)}
|
||||
|
||||
<PostTitle slug={slug} title={title} className={styles.title} />
|
||||
{date && (
|
||||
<div className={styles.time}>
|
||||
<Time date={date} />
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
@ -11,3 +11,7 @@
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.posts h1 {
|
||||
font-size: $font-size-h3;
|
||||
}
|
||||
|
39
src/components/templates/Posts.module.scss
Normal file
39
src/components/templates/Posts.module.scss
Normal file
@ -0,0 +1,39 @@
|
||||
@import 'variables';
|
||||
@import 'mixins';
|
||||
|
||||
.hentry {
|
||||
@include divider;
|
||||
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding-top: $spacer * 2;
|
||||
padding-bottom: $spacer * 2;
|
||||
|
||||
:global(.gatsby-image-wrapper) {
|
||||
max-height: 100vh;
|
||||
}
|
||||
|
||||
@media (min-width: $screen-md) {
|
||||
padding-top: $spacer * 4;
|
||||
padding-bottom: $spacer * 4;
|
||||
}
|
||||
}
|
||||
|
||||
.archivetitle {
|
||||
@include divider;
|
||||
|
||||
font-size: $font-size-h3;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
padding-bottom: $spacer * $line-height;
|
||||
|
||||
span {
|
||||
color: $brand-grey-light;
|
||||
padding-right: $spacer / 12;
|
||||
font-size: $font-size-base;
|
||||
}
|
||||
}
|
||||
|
||||
.paginationTitle {
|
||||
composes: archivetitle;
|
||||
}
|
28
src/components/templates/Posts.test.tsx
Normal file
28
src/components/templates/Posts.test.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import { createHistory, createMemorySource } from '@reach/router'
|
||||
|
||||
import Posts from './Posts'
|
||||
import data from '../../../jest/__fixtures__/posts.json'
|
||||
|
||||
describe('Post', () => {
|
||||
const history = createHistory(createMemorySource('/photos'))
|
||||
|
||||
const pageContext = {
|
||||
tag: 'hello',
|
||||
slug: '/hello',
|
||||
currentPageNumber: 2,
|
||||
numPages: 20
|
||||
}
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const { container } = render(
|
||||
<Posts
|
||||
data={data}
|
||||
pageContext={pageContext}
|
||||
location={history.location}
|
||||
/>
|
||||
)
|
||||
expect(container.firstChild).toBeInTheDocument()
|
||||
})
|
||||
})
|
123
src/components/templates/Posts.tsx
Normal file
123
src/components/templates/Posts.tsx
Normal file
@ -0,0 +1,123 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Link, graphql } from 'gatsby'
|
||||
import { Post } from '../../@types/Post'
|
||||
import Pagination from '../molecules/Pagination'
|
||||
import Featured from '../molecules/Featured'
|
||||
import PostTitle from './Post/Title'
|
||||
import PostLead from './Post/Lead'
|
||||
import PostContent from './Post/Content'
|
||||
import PostMore from './Post/More'
|
||||
import PostLinkActions from './Post/LinkActions'
|
||||
import SEO from '../atoms/SEO'
|
||||
import styles from './Posts.module.scss'
|
||||
import { Image } from '../atoms/Image'
|
||||
|
||||
export default function Posts({
|
||||
data,
|
||||
location,
|
||||
pageContext
|
||||
}: {
|
||||
data: any
|
||||
location: Location
|
||||
pageContext: {
|
||||
tag: string
|
||||
slug: string
|
||||
currentPageNumber: number
|
||||
numPages: number
|
||||
}
|
||||
}): ReactElement {
|
||||
const edges = data.allMarkdownRemark.edges
|
||||
const { tag, currentPageNumber, numPages } = pageContext
|
||||
|
||||
const PostsList = edges.map(({ node }: { node: Post }) => {
|
||||
const { type, linkurl, title, image } = node.frontmatter
|
||||
const { slug } = node.fields
|
||||
|
||||
return (
|
||||
<article className={styles.hentry} key={node.id}>
|
||||
{type !== 'photo' && (
|
||||
<PostTitle type={type} slug={slug} linkurl={linkurl} title={title} />
|
||||
)}
|
||||
|
||||
{image && (
|
||||
<Link to={slug} title={title}>
|
||||
<Image
|
||||
title={type === 'photo' ? title : null}
|
||||
fluid={image.childImageSharp.fluid}
|
||||
alt={title}
|
||||
original={image.childImageSharp.original}
|
||||
/>
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{type === 'post' && (
|
||||
<>
|
||||
<PostLead post={node} index />
|
||||
<PostMore to={slug}>Continue Reading</PostMore>
|
||||
</>
|
||||
)}
|
||||
|
||||
{type === 'link' && (
|
||||
<>
|
||||
<PostContent post={node} />
|
||||
<PostLinkActions slug={slug} linkurl={linkurl} />
|
||||
</>
|
||||
)}
|
||||
</article>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO />
|
||||
{location.pathname === '/' && <Featured />}
|
||||
{tag && (
|
||||
<h1 className={styles.archivetitle}>
|
||||
<span>#</span>
|
||||
{tag}
|
||||
</h1>
|
||||
)}
|
||||
{numPages > 1 && currentPageNumber > 1 && (
|
||||
<h2
|
||||
className={styles.paginationTitle}
|
||||
>{`Page ${currentPageNumber} / ${numPages}`}</h2>
|
||||
)}
|
||||
{PostsList}
|
||||
{numPages > 1 && <Pagination pageContext={pageContext} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const postsQuery = graphql`
|
||||
query($tag: String, $skip: Int, $limit: Int) {
|
||||
allMarkdownRemark(
|
||||
filter: { frontmatter: { tags: { eq: $tag } } }
|
||||
sort: { order: DESC, fields: [fields___date] }
|
||||
skip: $skip
|
||||
limit: $limit
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
html
|
||||
excerpt(pruneLength: 250)
|
||||
frontmatter {
|
||||
title
|
||||
type
|
||||
linkurl
|
||||
image {
|
||||
childImageSharp {
|
||||
...ImageFluid
|
||||
}
|
||||
}
|
||||
tags
|
||||
}
|
||||
fields {
|
||||
slug
|
||||
date(formatString: "MMMM DD, YYYY")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
@ -24,11 +24,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
.articles:first-of-type h1 {
|
||||
font-size: $font-size-h3;
|
||||
}
|
||||
|
||||
.articlesLast {
|
||||
margin-top: $spacer * 1.5;
|
||||
|
||||
@media (min-width: $screen-sm) {
|
||||
gap: $spacer * 1.5;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.photos {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
||||
@media (min-width: $screen-sm) {
|
||||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||
gap: $spacer * 1.5;
|
||||
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,26 +1,34 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import { graphql, PageProps } from 'gatsby'
|
||||
import React, { ReactElement } from 'react'
|
||||
import { Post } from '../@types/Post'
|
||||
import styles from './index.module.scss'
|
||||
import Featured from '../components/molecules/Featured'
|
||||
import { PhotoThumb } from '../components/templates/Photos'
|
||||
import SEO from '../components/atoms/SEO'
|
||||
import PostTeaser from '../components/molecules/PostTeaser'
|
||||
import { PhotoThumb } from '../components/templates/Photos'
|
||||
import PostMore from '../components/templates/Post/More'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
export default function Home(props: PageProps): ReactElement {
|
||||
return (
|
||||
<>
|
||||
<SEO />
|
||||
<section className={styles.section}>
|
||||
<h2 className={styles.title}>
|
||||
Latest Articles <PostMore to="/archive">All Articles</PostMore>
|
||||
</h2>
|
||||
|
||||
<div className={styles.articles}>
|
||||
{(props.data as any).latestArticles.edges.map(
|
||||
({ node }: { node: Post }) => (
|
||||
{(props.data as any).latestArticles.edges
|
||||
.slice(0, 2)
|
||||
.map(({ node }: { node: Post }) => (
|
||||
<PostTeaser key={node.id} post={node} />
|
||||
)
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
<div className={`${styles.articles} ${styles.articlesLast}`}>
|
||||
{(props.data as any).latestArticles.edges
|
||||
.slice(2, 8)
|
||||
.map(({ node }: { node: Post }) => (
|
||||
<PostTeaser key={node.id} post={node} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -46,7 +54,7 @@ export const homeQuery = graphql`
|
||||
latestArticles: allMarkdownRemark(
|
||||
filter: { frontmatter: { type: { ne: "photo" } } }
|
||||
sort: { order: DESC, fields: [fields___date] }
|
||||
limit: 6
|
||||
limit: 8
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
@ -58,7 +66,7 @@ export const homeQuery = graphql`
|
||||
latestPhotos: allMarkdownRemark(
|
||||
filter: { frontmatter: { type: { eq: "photo" } } }
|
||||
sort: { order: DESC, fields: [fields___date] }
|
||||
limit: 15
|
||||
limit: 12
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
|
Loading…
Reference in New Issue
Block a user