Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
.DS_Store
dist
.vite
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,36 @@
# Wikisite
드립위키 사이트의 깃허브입니다.

React.js로 구현한 드립위키 실험 프로젝트입니다. 위키의 기본적인 레이아웃과 주요 페이지의 초기 구조를 제공합니다.

## 개발 환경 실행

```bash
npm install
npm run dev
```

## 프로젝트 구조

```
Wikisite
├── index.html
├── package.json
├── src
│ ├── App.jsx
│ ├── main.jsx
│ ├── components
│ ├── data
│ ├── pages
│ └── styles
└── vite.config.js
```

## 제공되는 주요 페이지

- **대문(Home)**: 소개 문구와 추천 문서 카드.
- **최근 변경**: 더미 데이터를 기반으로 최근 편집 리스트 표시.
- **랜덤 문서**: 랜덤으로 문서를 선택하여 요약을 보여줍니다.
- **소개**: 위키의 목적과 참여 방법 안내.
- **개별 문서**: 문서 제목과 요약을 보여주고 본문은 향후 작성을 위해 비워둡니다.

향후 실제 데이터 연동, 검색 기능, 편집 기능 등을 추가해 위키 경험을 확장할 수 있습니다.
13 changes: 13 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>드립위키</title>
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "wikisite",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.2.0",
"vite": "^5.2.0"
}
}
15 changes: 15 additions & 0 deletions public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Routes, Route, Navigate } from 'react-router-dom';
import Layout from './components/Layout.jsx';
import Home from './pages/Home.jsx';
import RecentChanges from './pages/RecentChanges.jsx';
import RandomPage from './pages/RandomPage.jsx';
import About from './pages/About.jsx';
import Page from './pages/Page.jsx';
import wikiPages from './data/wikiPages.js';

const App = () => {
return (
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/recent" element={<RecentChanges />} />
<Route path="/random" element={<RandomPage />} />
<Route path="/about" element={<About />} />
<Route path="/page/:slug" element={<Page pages={wikiPages} />} />
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</Layout>
);
};

export default App;
32 changes: 32 additions & 0 deletions src/components/Header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { NavLink } from 'react-router-dom';
import styles from './Header.module.css';

const Header = () => {
return (
<header className={styles.header}>
<div className={styles.brand}>
<span className={styles.logo} aria-hidden>📚</span>
<div>
<h1 className={styles.title}>드립위키</h1>
<p className={styles.subtitle}>모두가 참여하는 지식 저장소</p>
</div>
</div>
<nav className={styles.nav}>
<NavLink to="/" end className={({ isActive }) => (isActive ? styles.active : '')}>
대문
</NavLink>
<NavLink to="/recent" className={({ isActive }) => (isActive ? styles.active : '')}>
최근 변경
</NavLink>
<NavLink to="/random" className={({ isActive }) => (isActive ? styles.active : '')}>
랜덤 문서
</NavLink>
<NavLink to="/about" className={({ isActive }) => (isActive ? styles.active : '')}>
소개
</NavLink>
</nav>
</header>
);
};

export default Header;
65 changes: 65 additions & 0 deletions src/components/Header.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1.75rem min(1200px, 92vw);
margin: 0 auto;
}

.brand {
display: flex;
align-items: center;
gap: 1rem;
}

.logo {
font-size: 2.5rem;
}

.title {
font-size: 1.75rem;
margin: 0;
color: var(--color-text-primary);
}

.subtitle {
margin: 0;
color: var(--color-text-secondary);
font-size: 0.95rem;
}

.nav {
display: flex;
gap: 1rem;
font-weight: 600;
}

.nav a {
color: var(--color-text-secondary);
text-decoration: none;
padding: 0.5rem 0.75rem;
border-radius: 999px;
transition: background 0.2s ease, color 0.2s ease;
}

.nav a:hover {
background: var(--color-surface);
color: var(--color-text-primary);
}

.active {
background: var(--color-primary);
color: white !important;
}

@media (max-width: 720px) {
.header {
flex-direction: column;
align-items: flex-start;
gap: 1.25rem;
}

.nav {
flex-wrap: wrap;
}
}
26 changes: 26 additions & 0 deletions src/components/Layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import PropTypes from 'prop-types';
import { Outlet } from 'react-router-dom';
import Header from './Header.jsx';
import Sidebar from './Sidebar.jsx';
import styles from './Layout.module.css';

const Layout = ({ children }) => {
return (
<div className={styles.appShell}>
<Header />
<div className={styles.body}>
<Sidebar />
<main className={styles.content}>{children ?? <Outlet />}</main>
</div>
<footer className={styles.footer}>
© {new Date().getFullYear()} 드립위키. 모두의 지식이 모이는 곳.
</footer>
</div>
);
};

Layout.propTypes = {
children: PropTypes.node
};

export default Layout;
42 changes: 42 additions & 0 deletions src/components/Layout.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.appShell {
display: flex;
flex-direction: column;
min-height: 100vh;
background: var(--color-background);
color: var(--color-text-primary);
}

.body {
flex: 1;
display: grid;
grid-template-columns: 280px 1fr;
gap: 2rem;
width: min(1200px, 92vw);
margin: 2rem auto;
}

.content {
background: var(--color-surface);
border-radius: 16px;
padding: 2.5rem;
box-shadow: var(--shadow-elevation);
}

.footer {
margin-top: auto;
padding: 1.5rem 0;
text-align: center;
font-size: 0.875rem;
color: var(--color-text-secondary);
border-top: 1px solid var(--color-border);
}

@media (max-width: 960px) {
.body {
grid-template-columns: 1fr;
}

.content {
order: 2;
}
}
48 changes: 48 additions & 0 deletions src/components/Sidebar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { NavLink } from 'react-router-dom';
import wikiPages from '../data/wikiPages.js';
import styles from './Sidebar.module.css';

const Sidebar = () => {
return (
<aside className={styles.sidebar}>
<div className={styles.section}>
<h2>문서 탐색</h2>
<input className={styles.searchInput} type="search" placeholder="문서 검색 (준비중)" disabled />
</div>
<div className={styles.section}>
<h2>주요 문서</h2>
<ul className={styles.pageList}>
{wikiPages.slice(0, 5).map((page) => (
<li key={page.slug}>
<NavLink to={`/page/${page.slug}`} className={({ isActive }) => (isActive ? styles.active : '')}>
{page.title}
</NavLink>
</li>
))}
</ul>
</div>
<div className={styles.section}>
<h2>바로가기</h2>
<ul className={styles.links}>
<li>
<NavLink to="/recent" className={({ isActive }) => (isActive ? styles.active : '')}>
최근 변경
</NavLink>
</li>
<li>
<NavLink to="/random" className={({ isActive }) => (isActive ? styles.active : '')}>
랜덤 문서
</NavLink>
</li>
<li>
<NavLink to="/about" className={({ isActive }) => (isActive ? styles.active : '')}>
위키 소개
</NavLink>
</li>
</ul>
</div>
</aside>
);
};

export default Sidebar;
Loading