Skip to content

Commit 2d4f136

Browse files
committed
refactor: UI/UX 디자인 개편 (pytorch.org 스타일 정렬)
- 고정 헤더 + 스크롤 인식 투명도 전환 (useRef 기반, 리렌더 방지) - CSS 변수 --header-height로 헤더/네비 오프셋 디커플링 - 히어로 섹션 축소: 모바일에서 검색창이 폴드 위에 표시 - 알파벳 네비게이션 헤더 아래 sticky 고정 - 카드 스타일: pytorch.org 컨벤션 (border, hover lift) - 단일 의미 용어 아코디언 없이 직접 렌더링 (MeaningContent 추출) - 콘텐츠 영역 최대 너비 1300px, 시노님 칩 오버플로 방지
1 parent 92dd5bc commit 2d4f136

8 files changed

Lines changed: 264 additions & 184 deletions

File tree

src/components/AlphabetNavigation.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ export function AlphabetNavigation({ onLetterClick, onClearFilter, activeLetter
1515
aria-label="알파벳 탐색"
1616
sx={{
1717
position: 'sticky',
18-
top: 0,
18+
top: 'var(--header-height)',
1919
zIndex: 10,
20-
backgroundColor: 'rgba(250,250,250,0.9)',
20+
backgroundColor: 'rgba(247,247,248,0.92)',
2121
backdropFilter: 'blur(8px)',
2222
borderBottom: '1px solid rgba(0,0,0,0.08)',
2323
py: 1.5,

src/components/HeroSection.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ export function HeroSection({ totalTerms, totalMeanings, query, onQueryChange }:
1313
return (
1414
<Box
1515
sx={{
16-
background: 'linear-gradient(135deg, #ee4c2c 0%, #1a1a1a 100%)',
16+
background: 'linear-gradient(135deg, #ee4c2c 0%, #2D2D2D 100%)',
1717
color: 'white',
18-
pt: { xs: 10, md: 11 },
19-
pb: { xs: 4, md: 5 },
20-
mb: 4,
18+
pt: { xs: 8, md: 9 },
19+
pb: { xs: 3, md: 4 },
20+
mb: 0,
2121
}}
2222
>
2323
<Container maxWidth="md">
@@ -30,11 +30,8 @@ export function HeroSection({ totalTerms, totalMeanings, query, onQueryChange }:
3030
>
3131
AI/ML 용어집
3232
</Typography>
33-
<Typography variant="h6" align="center" sx={{ mb: 2, opacity: 0.95 }}>
34-
AI/ML 한국어 번역 표준화
35-
</Typography>
36-
<Typography variant="body2" align="center" sx={{ mb: 3, opacity: 0.85 }}>
37-
{totalTerms} 용어 · {totalMeanings} 의미
33+
<Typography variant="body1" align="center" sx={{ mb: 3, opacity: 0.9 }}>
34+
AI/ML 한국어 번역 표준화 · {totalTerms} 용어 · {totalMeanings} 의미
3835
</Typography>
3936
<Box sx={{ maxWidth: 600, mx: 'auto' }}>
4037
<TextField

src/components/Layout.tsx

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react'
1+
import React, { useRef, useEffect } from 'react'
22
import { AppBar, Toolbar, Typography, Container, Box, IconButton, Link, Button } from '@mui/material'
33
import GitHubIcon from '@mui/icons-material/GitHub'
44
import SearchIcon from '@mui/icons-material/Search'
@@ -12,6 +12,22 @@ export function Layout({ children }: LayoutProps): React.ReactNode {
1212
const navigate = useNavigate()
1313
const location = useLocation()
1414
const isHomePage = location.pathname === '/' || location.pathname === ''
15+
const appBarRef = useRef<HTMLDivElement>(null)
16+
17+
useEffect(() => {
18+
if (!isHomePage) return
19+
20+
const handleScroll = () => {
21+
if (!appBarRef.current) return
22+
const scrolled = window.scrollY > 60
23+
appBarRef.current.style.backgroundColor = scrolled ? '#262626' : 'transparent'
24+
appBarRef.current.style.boxShadow = scrolled ? '0 2px 8px rgba(0,0,0,0.15)' : 'none'
25+
}
26+
27+
window.addEventListener('scroll', handleScroll, { passive: true })
28+
handleScroll()
29+
return () => window.removeEventListener('scroll', handleScroll)
30+
}, [isHomePage])
1531

1632
const handleSearchClick = () => {
1733
if (isHomePage) {
@@ -24,12 +40,13 @@ export function Layout({ children }: LayoutProps): React.ReactNode {
2440
return (
2541
<Box sx={{ display: 'flex', flexDirection: 'column', minHeight: '100vh' }}>
2642
<AppBar
27-
position={isHomePage ? 'absolute' : 'static'}
28-
elevation={isHomePage ? 0 : 2}
43+
ref={appBarRef}
44+
position="fixed"
45+
elevation={0}
2946
sx={{
3047
backgroundColor: isHomePage ? 'transparent' : '#262626',
31-
width: '100%',
32-
zIndex: isHomePage ? 20 : undefined,
48+
transition: 'background-color 0.3s ease, box-shadow 0.3s ease',
49+
zIndex: 20,
3350
}}
3451
>
3552
<Toolbar>
@@ -41,10 +58,19 @@ export function Layout({ children }: LayoutProps): React.ReactNode {
4158
>
4259
AI/ML 용어집
4360
</Typography>
44-
<IconButton color="inherit" onClick={handleSearchClick} aria-label="검색" sx={{ mr: 0.5 }}>
61+
<IconButton
62+
color="inherit"
63+
onClick={handleSearchClick}
64+
aria-label="검색"
65+
sx={{ mr: 0.5, minHeight: 44, minWidth: 44 }}
66+
>
4567
<SearchIcon />
4668
</IconButton>
47-
<Button color="inherit" onClick={() => navigate('/about')} sx={{ mr: 1 }}>
69+
<Button
70+
color="inherit"
71+
onClick={() => navigate('/about')}
72+
sx={{ mr: 1, minHeight: 44 }}
73+
>
4874
소개
4975
</Button>
5076
<IconButton
@@ -53,24 +79,25 @@ export function Layout({ children }: LayoutProps): React.ReactNode {
5379
target="_blank"
5480
rel="noopener noreferrer"
5581
aria-label="GitHub 저장소"
82+
sx={{ minHeight: 44, minWidth: 44 }}
5683
>
5784
<GitHubIcon />
5885
</IconButton>
5986
</Toolbar>
6087
</AppBar>
6188

62-
<Box component="main" sx={{ flex: 1 }}>
89+
<Box component="main" sx={{ flex: 1, pt: 'var(--header-height)' }}>
6390
{isHomePage ? (
6491
children
6592
) : (
66-
<Container sx={{ py: 4 }}>{children}</Container>
93+
<Container maxWidth="lg" sx={{ py: 4, px: { xs: 2, md: 3 } }}>{children}</Container>
6794
)}
6895
</Box>
6996

7097
<Box
7198
component="footer"
7299
sx={{
73-
py: 3,
100+
py: 2.5,
74101
px: 2,
75102
mt: 'auto',
76103
bgcolor: '#262626',

src/components/TermCard.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export function TermCard({ term, hasDuplicateTranslation, query }: TermCardProps
9191
label={firstSynonym}
9292
size="small"
9393
variant="outlined"
94+
sx={{ maxWidth: 120, '& .MuiChip-label': { overflow: 'hidden', textOverflow: 'ellipsis' } }}
9495
/>
9596
)}
9697
</Box>

src/index.css

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
:root {
2+
--header-height: 56px;
3+
}
4+
5+
@media (min-width: 600px) {
6+
:root {
7+
--header-height: 64px;
8+
}
9+
}
10+
11+
html {
12+
scroll-behavior: smooth;
13+
}
14+
115
body {
216
margin: 0;
317
font-family: "Pretendard Variable", "Pretendard", "Noto Sans KR", sans-serif;

src/pages/SearchPage.tsx

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useMemo, useCallback } from 'react'
22
import { useSearchParams } from 'react-router-dom'
3-
import { Grid, Typography, Box, Skeleton, Button } from '@mui/material'
3+
import { Grid, Typography, Box, Skeleton, Button, Container } from '@mui/material'
44
import SearchOffIcon from '@mui/icons-material/SearchOff'
55
import AddIcon from '@mui/icons-material/Add'
66
import { Layout } from '../components/Layout'
@@ -90,45 +90,45 @@ export function SearchPage(): React.ReactNode {
9090
activeLetter={selectedLetter}
9191
/>
9292

93-
<Box sx={{ px: 2, mb: 2 }}>
94-
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 1 }}>
95-
<Typography variant="body2" color="text.secondary">
96-
{finalFilteredTerms.length}개의 용어 표시 중
97-
</Typography>
98-
<Button
99-
variant="text"
100-
size="small"
101-
startIcon={<AddIcon />}
102-
href="https://github.com/PyTorchKorea/kr-terms-poc/issues/new?template=new-term.yml"
103-
target="_blank"
104-
rel="noopener noreferrer"
105-
>
106-
새 용어 요청
107-
</Button>
93+
<Container maxWidth="lg" sx={{ px: { xs: 2, md: 3 } }}>
94+
<Box sx={{ mb: 2 }}>
95+
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 1 }}>
96+
<Typography variant="body2" color="text.secondary">
97+
{finalFilteredTerms.length}개의 용어 표시 중
98+
</Typography>
99+
<Button
100+
variant="text"
101+
size="small"
102+
startIcon={<AddIcon />}
103+
href="https://github.com/PyTorchKorea/kr-terms-poc/issues/new?template=new-term.yml"
104+
target="_blank"
105+
rel="noopener noreferrer"
106+
>
107+
새 용어 요청
108+
</Button>
109+
</Box>
108110
</Box>
109-
</Box>
110111

111-
{finalFilteredTerms.length === 0 ? (
112-
<Box sx={{ textAlign: 'center', py: 8 }}>
113-
<SearchOffIcon sx={{ fontSize: 64, color: 'text.disabled', mb: 2 }} />
114-
<Typography variant="h6" color="text.secondary" gutterBottom>
115-
검색 결과가 없습니다
116-
</Typography>
117-
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
118-
다른 검색어를 시도하거나, 알파벳 탐색으로 용어를 찾아보세요
119-
</Typography>
120-
<Button
121-
variant="contained"
122-
startIcon={<AddIcon />}
123-
href="https://github.com/PyTorchKorea/kr-terms-poc/issues/new?template=new-term.yml"
124-
target="_blank"
125-
rel="noopener noreferrer"
126-
>
127-
찾으시는 용어가 없나요? 새 용어를 요청하세요
128-
</Button>
129-
</Box>
130-
) : (
131-
<Box sx={{ px: 2 }}>
112+
{finalFilteredTerms.length === 0 ? (
113+
<Box sx={{ textAlign: 'center', py: 8 }}>
114+
<SearchOffIcon sx={{ fontSize: 64, color: 'text.disabled', mb: 2 }} />
115+
<Typography variant="h6" color="text.secondary" gutterBottom>
116+
검색 결과가 없습니다
117+
</Typography>
118+
<Typography variant="body2" color="text.secondary" sx={{ mb: 3 }}>
119+
다른 검색어를 시도하거나, 알파벳 탐색으로 용어를 찾아보세요
120+
</Typography>
121+
<Button
122+
variant="contained"
123+
startIcon={<AddIcon />}
124+
href="https://github.com/PyTorchKorea/kr-terms-poc/issues/new?template=new-term.yml"
125+
target="_blank"
126+
rel="noopener noreferrer"
127+
>
128+
찾으시는 용어가 없나요? 새 용어를 요청하세요
129+
</Button>
130+
</Box>
131+
) : (
132132
<Grid container spacing={3}>
133133
{finalFilteredTerms.map((term) => {
134134
const duplicates = statistics.duplicateTranslations.get(term.meanings[0].korean)
@@ -140,8 +140,8 @@ export function SearchPage(): React.ReactNode {
140140
)
141141
})}
142142
</Grid>
143-
</Box>
144-
)}
143+
)}
144+
</Container>
145145
</Layout>
146146
)
147147
}

0 commit comments

Comments
 (0)