diff --git a/package.json b/package.json
index 221842f8..784257be 100644
--- a/package.json
+++ b/package.json
@@ -30,6 +30,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-icons": "^4.2.0",
+ "react-responsive": "^9.0.0-beta.4",
"url-loader": "^4.1.1"
},
"browserslist": {
diff --git a/src/components/WikiDetail/DetailFullSize.tsx b/src/components/WikiDetail/DetailFullSize.tsx
new file mode 100644
index 00000000..6e6d01cc
--- /dev/null
+++ b/src/components/WikiDetail/DetailFullSize.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+import { WikiWord } from '../../types';
+
+type DetailFullSizeProps = {
+ selectedWord: WikiWord | null;
+ onClose: () => void;
+};
+
+export default function DetailFullSize({ onClose }: DetailFullSizeProps) {
+ return <>DetailFullSize>;
+}
diff --git a/src/components/WikiDetail/DetailModal.tsx b/src/components/WikiDetail/DetailModal.tsx
new file mode 100644
index 00000000..c010e5f8
--- /dev/null
+++ b/src/components/WikiDetail/DetailModal.tsx
@@ -0,0 +1,86 @@
+import React from 'react';
+import styled from '@emotion/styled';
+import { WikiWord } from '../../types';
+
+type DetailModalProps = {
+ selectedWord: WikiWord | null;
+ onClose: () => void;
+};
+
+export default function DetailModal({
+ selectedWord,
+ onClose,
+}: DetailModalProps) {
+ const { name, description, content } = selectedWord;
+
+ return (
+ onClose()}>
+ {
+ e.stopPropagation();
+ }}
+ >
+
+ {name}
+
+ {description}
+ {content && (
+ <>
+
+ {content}
+ >
+ )}
+
+
+ );
+}
+
+const Dimmed = styled.div`
+ position: fixed;
+ z-index: 100;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100vh;
+ background-color: rgba(0, 0, 0, 0.6);
+`;
+
+const Modal = styled.div`
+ background-color: #ffffff;
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ max-width: 800px;
+ min-width: 500px;
+ padding: 40px;
+ border-radius: 12px;
+ box-shadow: rgba(0, 0, 0, 0.28) 0 8px 28px;
+ overflow: hidden;
+`;
+
+const DetailHeader = styled.header`
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 1rem;
+
+ svg {
+ font-size: 1.5rem;
+ }
+`;
+
+const DetailTitle = styled.h2`
+ margin-bottom: 0;
+`;
+
+const Description = styled.div`
+ font-weight: 500;
+`;
+
+const Line = styled.div`
+ border-top: 1px solid var(--ifm-color-gray-300);
+ margin: 20px 0 30px;
+`;
+
+const Content = styled.div``;
diff --git a/src/components/WikiDetail/index.tsx b/src/components/WikiDetail/index.tsx
new file mode 100644
index 00000000..27698f92
--- /dev/null
+++ b/src/components/WikiDetail/index.tsx
@@ -0,0 +1,38 @@
+import React, { useEffect } from 'react';
+import { useMediaQuery } from 'react-responsive';
+import DetailModal from './DetailModal';
+import DetailFullSize from './DetailFullSize';
+import { WikiWord } from '../../types';
+
+type WikiDetailInnerProps = WikiDetailProps;
+
+function WikiDetailInner({ selectedWord, onClose }: WikiDetailInnerProps) {
+ const isMobile = useMediaQuery({
+ query: '(max-width: 500px)',
+ });
+
+ useEffect(() => {
+ return () => {
+ // Todo: Clean State
+ };
+ }, []);
+
+ return isMobile ? (
+
+ ) : (
+
+ );
+}
+
+type WikiDetailProps = {
+ selectedWord: WikiWord | null;
+ onClose: () => void;
+};
+
+export default function WikiDetail({ selectedWord, onClose }: WikiDetailProps) {
+ return (
+ selectedWord && (
+
+ )
+ );
+}
diff --git a/src/components/WikiTable/WikiTable.tsx b/src/components/WikiTable/WikiTable.tsx
index 4e38d02c..de2da93c 100644
--- a/src/components/WikiTable/WikiTable.tsx
+++ b/src/components/WikiTable/WikiTable.tsx
@@ -1,16 +1,26 @@
-import React, { useEffect } from 'react';
+import React, { Dispatch, SetStateAction } from 'react';
import WikiTableRow from './WikiTableRow';
import usePagination from '../../hooks/usePagination';
-export default function WikiTable({ words = [] }: { words: string[] }) {
+export default function WikiTable({
+ words = [],
+ setSelectedWord,
+}: {
+ words: string[];
+ setSelectedWord: Dispatch>;
+}) {
const { onPrevious, onNext, currentPage, result, isLastPage, isFirstPage } =
usePagination({
source: words,
offset: 2,
});
+ const handleRowClick = word => {
+ setSelectedWord(word);
+ };
+
return (
<>
{currentPage}
@@ -29,7 +39,11 @@ export default function WikiTable({ words = [] }: { words: string[] }) {
{result.map(word => (
-
+ handleRowClick(word)}
+ key={word.name}
+ {...word}
+ />
))}
diff --git a/src/components/WikiTable/WikiTableRow.tsx b/src/components/WikiTable/WikiTableRow.tsx
index 13e8be63..3081ff05 100644
--- a/src/components/WikiTable/WikiTableRow.tsx
+++ b/src/components/WikiTable/WikiTableRow.tsx
@@ -2,9 +2,17 @@ import React from 'react';
import { WikiWord } from '../../types';
-export default function WikiTableRow({ name, description }: WikiWord) {
+type WikiWordType = WikiWord & {
+ handleRowClick: () => void;
+};
+
+export default function WikiTableRow({
+ name,
+ description,
+ handleRowClick,
+}: WikiWordType) {
return (
-
+
{name} |
{description} |
diff --git a/src/pages/wiki/index.js b/src/pages/wiki/index.js
index 5689cfae..4b05b6c9 100644
--- a/src/pages/wiki/index.js
+++ b/src/pages/wiki/index.js
@@ -8,12 +8,15 @@ import WikiSearch from '../../components/WikiSearch';
import useSearch from '../../hooks/useSearch';
import words from '../../../wiki.json';
+import WikiDetail from '../../components/WikiDetail';
export default function Wiki() {
const { siteConfig } = useDocusaurusContext();
const [keyword, setKeyword] = useState('');
+ const [selectedWord, setSelectedWord] = useState(null);
const { result: searchResult, onSearch } = useSearch(words);
+
useEffect(() => {
onSearch(keyword);
}, [keyword]);
@@ -26,7 +29,11 @@ export default function Wiki() {
용어사전
-
+
+ setSelectedWord(null)}
+ />
);
diff --git a/src/types/WikiWord.ts b/src/types/WikiWord.ts
index 660ed1c8..03f54d7a 100644
--- a/src/types/WikiWord.ts
+++ b/src/types/WikiWord.ts
@@ -1,4 +1,5 @@
export type WikiWord = {
name: string;
description: string;
+ content?: string;
};
diff --git a/yarn.lock b/yarn.lock
index 7feb4b4b..791d74f2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3434,6 +3434,11 @@ css-loader@^5.1.1:
schema-utils "^3.0.0"
semver "^7.3.5"
+css-mediaquery@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0"
+ integrity sha1-aiw3NEkoYYYxxUvTPO3TAdoYvqA=
+
css-minimizer-webpack-plugin@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.0.2.tgz#8fadbdf10128cb40227bff275a4bb47412534245"
@@ -5328,6 +5333,11 @@ human-signals@^2.1.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+hyphenate-style-name@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
+ integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
+
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@@ -6299,6 +6309,13 @@ markdown-escapes@^1.0.0:
resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535"
integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==
+matchmediaquery@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/matchmediaquery/-/matchmediaquery-0.3.1.tgz#8247edc47e499ebb7c58f62a9ff9ccf5b815c6d7"
+ integrity sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==
+ dependencies:
+ css-mediaquery "^0.1.2"
+
mdast-squeeze-paragraphs@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-4.0.0.tgz#7c4c114679c3bee27ef10b58e2e015be79f1ef97"
@@ -7563,7 +7580,7 @@ prompts@^2.4.1:
kleur "^3.0.3"
sisteransi "^1.0.5"
-prop-types@^15.5.0, prop-types@^15.6.2, prop-types@^15.7.2:
+prop-types@^15.5.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -7797,6 +7814,16 @@ react-loadable@^5.5.0:
dependencies:
prop-types "^15.5.0"
+react-responsive@^9.0.0-beta.4:
+ version "9.0.0-beta.4"
+ resolved "https://registry.yarnpkg.com/react-responsive/-/react-responsive-9.0.0-beta.4.tgz#90c1f1a4048971497ca9795068af6803eabc0ddb"
+ integrity sha512-jQSs5kIi38T39Ku98r8s75jM6JAaNEeVrHPHTrL2EYWuv8nusV3KRQcZZ4VlfwndIRedxmpb4T8FXA9ltlCFiw==
+ dependencies:
+ hyphenate-style-name "^1.0.0"
+ matchmediaquery "^0.3.0"
+ prop-types "^15.6.1"
+ shallow-equal "^1.2.1"
+
react-router-config@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988"
@@ -8478,6 +8505,11 @@ shallow-clone@^3.0.0:
dependencies:
kind-of "^6.0.2"
+shallow-equal@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/shallow-equal/-/shallow-equal-1.2.1.tgz#4c16abfa56043aa20d050324efa68940b0da79da"
+ integrity sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"