summaryrefslogtreecommitdiffstats
path: root/src/components/PostPreview
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2021-12-16 18:22:08 +0100
committerArmand Philippot <git@armandphilippot.com>2021-12-16 18:22:08 +0100
commit0ef4f77954ba54b52b96c70a8bffe96804bd222d (patch)
tree7fe68b05271625f72f750786e1a94b71942d2cd5 /src/components/PostPreview
parenta4f865224e0e395c7e29bb3b7279a5101b554d2c (diff)
chore: display featuredImage and meta on posts list
Diffstat (limited to 'src/components/PostPreview')
-rw-r--r--src/components/PostPreview/PostPreview.module.scss125
-rw-r--r--src/components/PostPreview/PostPreview.tsx61
2 files changed, 186 insertions, 0 deletions
diff --git a/src/components/PostPreview/PostPreview.module.scss b/src/components/PostPreview/PostPreview.module.scss
new file mode 100644
index 0000000..d188b18
--- /dev/null
+++ b/src/components/PostPreview/PostPreview.module.scss
@@ -0,0 +1,125 @@
+@use "@styles/abstracts/functions" as fun;
+@use "@styles/abstracts/mixins" as mix;
+
+.wrapper {
+ padding: var(--spacing-sm) var(--spacing-sm) var(--spacing-md);
+ border: fun.convert-px(1) solid var(--color-border);
+ border-radius: fun.convert-px(3);
+ box-shadow: fun.convert-px(1) fun.convert-px(1) 0 0 var(--color-shadow),
+ fun.convert-px(1) fun.convert-px(1) fun.convert-px(3) 0 var(--color-shadow);
+ transition: all 0.2s ease-in-out 0s, border 0s;
+
+ &:hover,
+ &:focus-within {
+ box-shadow: fun.convert-px(2) fun.convert-px(2) 0 0
+ var(--color-shadow-light),
+ fun.convert-px(3) fun.convert-px(3) fun.convert-px(3) 0
+ var(--color-shadow-light),
+ fun.convert-px(3) fun.convert-px(3) fun.convert-px(5) fun.convert-px(1)
+ var(--color-shadow-lighter);
+ transform: scale(1.01);
+ }
+}
+
+.cover {
+ width: auto;
+ height: fun.convert-px(100);
+ margin: 0 auto var(--spacing-sm);
+ position: relative;
+ border: fun.convert-px(1) solid var(--color-border);
+}
+
+.read-more {
+ display: block;
+ width: max-content;
+ margin: var(--spacing-md) auto var(--spacing-lg);
+ padding: var(--spacing-2xs) var(--spacing-sm);
+ background: var(--color-bg);
+ border: fun.convert-px(3) solid var(--color-primary);
+ border-radius: fun.convert-px(3);
+ box-shadow: fun.convert-px(1) fun.convert-px(1) fun.convert-px(1)
+ var(--color-shadow-light),
+ fun.convert-px(1) fun.convert-px(2) fun.convert-px(2) fun.convert-px(-2)
+ var(--color-shadow-light),
+ fun.convert-px(3) fun.convert-px(4) fun.convert-px(5) fun.convert-px(-4)
+ var(--color-shadow-light);
+ color: var(--color-primary);
+ font-weight: 600;
+ text-decoration: none;
+ transition: all 0.3s ease-in-out 0s;
+
+ .icon {
+ width: fun.convert-px(20);
+ margin-left: var(--spacing-2xs);
+ fill: var(--color-primary);
+ transition: all 0.25s ease-in-out 0s;
+ }
+
+ &:hover,
+ &:focus {
+ text-decoration: underline var(--color-primary) fun.convert-px(2);
+
+ .icon {
+ margin-left: var(--spacing-xs);
+ transform: scaleX(1.3);
+ }
+ }
+
+ &:active {
+ color: var(--color-primary-dark);
+ text-decoration: none;
+
+ .icon {
+ margin-left: 0;
+ transform: scaleX(0);
+ width: 0;
+ }
+ }
+}
+
+@include mix.media("screen") {
+ @include mix.dimensions("xs") {
+ .read-more {
+ font-size: var(--font-size-sm);
+ }
+ }
+
+ @include mix.dimensions("sm") {
+ .wrapper {
+ display: grid;
+ grid-template-columns: minmax(0, 3fr) minmax(0, 1fr);
+ grid-template-rows: repeat(3, max-content);
+ column-gap: var(--spacing-md);
+ }
+
+ .cover {
+ grid-column: 2;
+ grid-row: 1;
+ margin: 0 0 var(--spacing-sm);
+ }
+
+ .header {
+ grid-column: 1;
+ grid-row: 1;
+ }
+
+ .meta {
+ grid-column: 2;
+ grid-row: 2 / 4;
+ }
+
+ .body {
+ grid-column: 1;
+ grid-row: 2;
+ }
+
+ .footer {
+ grid-column: 1;
+ grid-row: 3;
+ }
+
+ .read-more {
+ margin: 0;
+ }
+ }
+}
diff --git a/src/components/PostPreview/PostPreview.tsx b/src/components/PostPreview/PostPreview.tsx
new file mode 100644
index 0000000..8f3e0da
--- /dev/null
+++ b/src/components/PostPreview/PostPreview.tsx
@@ -0,0 +1,61 @@
+import PostMeta from '@components/PostMeta/PostMeta';
+import { t } from '@lingui/macro';
+import { ArticlePreview } from '@ts/types/articles';
+import Link from 'next/link';
+import ArrowRightIcon from '@assets/images/icon-arrow-right.svg';
+import styles from './PostPreview.module.scss';
+import Image from 'next/image';
+
+const PostPreview = ({
+ post,
+ TitleTag,
+}: {
+ post: ArticlePreview;
+ TitleTag: keyof JSX.IntrinsicElements;
+}) => {
+ return (
+ <article className={styles.wrapper}>
+ {post.featuredImage && (
+ <div className={styles.cover}>
+ <Image
+ src={post.featuredImage.sourceUrl}
+ alt={post.featuredImage.altText}
+ layout="fill"
+ objectFit="contain"
+ />
+ </div>
+ )}
+ <header className={styles.header}>
+ <TitleTag>
+ <Link href={`/article/${post.slug}`}>
+ <a>{post.title}</a>
+ </Link>
+ </TitleTag>
+ </header>
+ <div
+ className={styles.body}
+ dangerouslySetInnerHTML={{ __html: post.content }}
+ ></div>
+ <footer className={styles.footer}>
+ <Link href={post.slug}>
+ <a className={styles['read-more']}>
+ {t`Read more`}
+ <span className="screen-reader-text">
+ {' '}
+ {t({ message: `about ${post.title}`, comment: 'Post title' })}
+ </span>
+ <ArrowRightIcon className={styles.icon} />
+ </a>
+ </Link>
+ </footer>
+ <PostMeta
+ commentCount={post.commentCount}
+ publicationDate={post.date.publication}
+ updateDate={post.date.update}
+ thematics={post.thematics}
+ />
+ </article>
+ );
+};
+
+export default PostPreview;