summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorArmand Philippot <git@armandphilippot.com>2022-01-15 23:08:25 +0100
committerArmand Philippot <git@armandphilippot.com>2022-01-15 23:28:24 +0100
commit6f46e54e382bf3f535f27ebead18c2bdf4628e49 (patch)
tree3285800f7c08afe25ebcf985bd5f643bdf7fc603 /src
parent4d0b13d22be1297c91316d5e52c8fb30ded5c7dd (diff)
chore(comments): handle comment reply
Diffstat (limited to 'src')
-rw-r--r--src/components/Comment/Comment.tsx31
-rw-r--r--src/components/CommentForm/CommentForm.module.scss13
-rw-r--r--src/components/CommentForm/CommentForm.tsx35
-rw-r--r--src/components/CommentsList/CommentsList.tsx12
-rw-r--r--src/components/Form/Form.module.scss6
-rw-r--r--src/components/Notice/Notice.module.scss16
-rw-r--r--src/pages/article/[slug].tsx3
7 files changed, 92 insertions, 24 deletions
diff --git a/src/components/Comment/Comment.tsx b/src/components/Comment/Comment.tsx
index 6a4abce..e0a65f3 100644
--- a/src/components/Comment/Comment.tsx
+++ b/src/components/Comment/Comment.tsx
@@ -1,19 +1,29 @@
import { Button } from '@components/Buttons';
+import CommentForm from '@components/CommentForm/CommentForm';
import { t } from '@lingui/macro';
import { Comment as CommentData } from '@ts/types/comments';
import Image from 'next/image';
import Link from 'next/link';
import { useRouter } from 'next/router';
+import { useEffect, useRef, useState } from 'react';
import styles from './Comment.module.scss';
const Comment = ({
+ articleId,
comment,
isNested = false,
}: {
+ articleId: number;
comment: CommentData;
isNested?: boolean;
}) => {
const router = useRouter();
+ const [isReply, setIsReply] = useState<boolean>(false);
+ const firstFieldRef = useRef<HTMLInputElement>(null);
+
+ useEffect(() => {
+ firstFieldRef.current && firstFieldRef.current.focus();
+ });
const getCommentAuthor = () => {
return comment.author.url ? (
@@ -71,14 +81,31 @@ const Comment = ({
></div>
{!isNested && (
<footer className={styles.footer}>
- <Button clickHandler={() => ''}>{t`Reply`}</Button>
+ <Button
+ clickHandler={() => setIsReply((prev) => !prev)}
+ >{t`Reply`}</Button>
</footer>
)}
</article>
+ {isReply && (
+ <CommentForm
+ ref={firstFieldRef}
+ articleId={articleId}
+ parentId={comment.commentId}
+ isReply={isReply}
+ />
+ )}
{comment.replies.length > 0 && (
<ol className={styles.list}>
{comment.replies.map((reply) => {
- return <Comment key={reply.id} comment={reply} isNested={true} />;
+ return (
+ <Comment
+ articleId={articleId}
+ key={reply.id}
+ comment={reply}
+ isNested={true}
+ />
+ );
})}
</ol>
)}
diff --git a/src/components/CommentForm/CommentForm.module.scss b/src/components/CommentForm/CommentForm.module.scss
index 2330ca2..922923a 100644
--- a/src/components/CommentForm/CommentForm.module.scss
+++ b/src/components/CommentForm/CommentForm.module.scss
@@ -3,6 +3,19 @@
.wrapper {
width: min(calc(100vw - (var(--spacing-md) * 2)), fun.convert-px(500));
margin: auto;
+
+ &--reply {
+ width: 100%;
+ margin-top: var(--spacing-sm);
+ padding: var(--spacing-md);
+ position: relative;
+ background: var(--color-bg);
+ border: fun.convert-px(1) solid var(--color-border-light);
+ box-shadow: fun.convert-px(3) fun.convert-px(3) 0 0
+ var(--color-shadow-lighter),
+ fun.convert-px(4) fun.convert-px(4) fun.convert-px(3) fun.convert-px(-2)
+ var(--color-shadow-light);
+ }
}
.title {
diff --git a/src/components/CommentForm/CommentForm.tsx b/src/components/CommentForm/CommentForm.tsx
index ea02306..1ed219c 100644
--- a/src/components/CommentForm/CommentForm.tsx
+++ b/src/components/CommentForm/CommentForm.tsx
@@ -3,16 +3,21 @@ import { Form, FormItem, Input, TextArea } from '@components/Form';
import Notice from '@components/Notice/Notice';
import { t } from '@lingui/macro';
import { createComment } from '@services/graphql/mutations';
-import { useState } from 'react';
+import { ForwardedRef, forwardRef, useState } from 'react';
import styles from './CommentForm.module.scss';
-const CommentForm = ({
- articleId,
- parentId = 0,
-}: {
- articleId: number;
- parentId?: number;
-}) => {
+const CommentForm = (
+ {
+ articleId,
+ parentId = 0,
+ isReply = false,
+ }: {
+ articleId: number;
+ parentId?: number;
+ isReply?: boolean;
+ },
+ ref: ForwardedRef<HTMLInputElement>
+) => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [website, setWebsite] = useState('');
@@ -57,10 +62,17 @@ const CommentForm = ({
}
};
+ const wrapperClasses = `${styles.wrapper} ${
+ isReply ? styles['wrapper--reply'] : ''
+ }`;
+
return (
- <div className={styles.wrapper}>
+ <div className={wrapperClasses}>
<h2 className={styles.title}>{t`Leave a comment`}</h2>
- <Form submitHandler={submitHandler}>
+ <Form
+ submitHandler={submitHandler}
+ modifier={isReply ? 'centered' : undefined}
+ >
<FormItem>
<Input
id="commenter-name"
@@ -69,6 +81,7 @@ const CommentForm = ({
required={true}
value={name}
setValue={setName}
+ ref={ref}
/>
</FormItem>
<FormItem>
@@ -111,4 +124,4 @@ const CommentForm = ({
);
};
-export default CommentForm;
+export default forwardRef(CommentForm);
diff --git a/src/components/CommentsList/CommentsList.tsx b/src/components/CommentsList/CommentsList.tsx
index 3a1c57e..bdca00b 100644
--- a/src/components/CommentsList/CommentsList.tsx
+++ b/src/components/CommentsList/CommentsList.tsx
@@ -3,10 +3,18 @@ import Comment from '@components/Comment/Comment';
import { t } from '@lingui/macro';
import styles from './CommentsList.module.scss';
-const CommentsList = ({ comments }: { comments: CommentData[] }) => {
+const CommentsList = ({
+ articleId,
+ comments,
+}: {
+ articleId: number;
+ comments: CommentData[];
+}) => {
const getCommentsList = () => {
return comments.map((comment) => {
- return <Comment key={comment.id} comment={comment} />;
+ return (
+ <Comment key={comment.id} articleId={articleId} comment={comment} />
+ );
});
};
diff --git a/src/components/Form/Form.module.scss b/src/components/Form/Form.module.scss
index 577c3c8..92dbb36 100644
--- a/src/components/Form/Form.module.scss
+++ b/src/components/Form/Form.module.scss
@@ -8,6 +8,12 @@
display: flex;
flex-flow: row nowrap;
}
+
+ &--centered {
+ max-width: 45ch;
+ margin-left: auto;
+ margin-right: auto;
+ }
}
.item {
diff --git a/src/components/Notice/Notice.module.scss b/src/components/Notice/Notice.module.scss
index deae4e4..aa7175c 100644
--- a/src/components/Notice/Notice.module.scss
+++ b/src/components/Notice/Notice.module.scss
@@ -7,22 +7,22 @@
padding: var(--spacing-2xs) var(--spacing-xs);
&--error {
- border-color: var(--color-error);
- color: var(--color-error);
+ border-color: var(--color-token-red);
+ color: var(--color-token-red);
}
&--info {
- border-color: var(--color-info);
- color: var(--color-info);
+ border-color: var(--color-token-blue);
+ color: var(--color-token-blue);
}
&--success {
- border-color: var(--color-success);
- color: var(--color-success);
+ border-color: var(--color-token-green);
+ color: var(--color-token-green);
}
&--warning {
- border-color: var(--color-warning);
- color: var(--color-warning);
+ border-color: var(--color-token-orange);
+ color: var(--color-token-orange);
}
}
diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx
index 509be4f..477503e 100644
--- a/src/pages/article/[slug].tsx
+++ b/src/pages/article/[slug].tsx
@@ -24,6 +24,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
author,
comments,
content,
+ databaseId,
dates,
intro,
seo,
@@ -71,7 +72,7 @@ const SingleArticle: NextPageWithLayout<ArticleProps> = ({ post }) => {
<Sharing title={title} excerpt={intro} />
</Sidebar>
<section className={styles.comments}>
- <CommentsList comments={comments} />
+ <CommentsList articleId={databaseId} comments={comments} />
<CommentForm articleId={post.databaseId} />
</section>
</article>