Skip to content

Commit be4261e

Browse files
sync: from private repo (938895e61f9a5f71e0b668df3eeb8178fbb59044)
1 parent e4901db commit be4261e

6 files changed

Lines changed: 169 additions & 55 deletions

File tree

web/src/App.css

Lines changed: 103 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@
2323
======================================== */
2424
.unified-search-bar {
2525
position: absolute;
26-
top: 16px;
27-
left: 12px;
28-
right: 12px;
26+
top: 10px;
27+
left: 10px;
28+
right: 10px;
2929
z-index: 400;
3030
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
3131
}
@@ -34,11 +34,11 @@
3434
.search-bar-idle {
3535
display: flex;
3636
align-items: center;
37-
gap: 12px;
37+
gap: 10px;
3838
background: #fff;
39-
border-radius: 28px;
40-
padding: 8px 14px 8px 8px;
41-
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.08);
39+
border-radius: 24px;
40+
padding: 7px 12px 7px 7px;
41+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12), 0 1px 3px rgba(0, 0, 0, 0.08);
4242
cursor: text;
4343
transition: box-shadow 0.2s ease, transform 0.2s ease;
4444
}
@@ -53,8 +53,8 @@
5353

5454
/* 앱 아이콘 (좌측) */
5555
.search-bar-icon {
56-
width: 40px;
57-
height: 40px;
56+
width: 34px;
57+
height: 34px;
5858
border-radius: 50%;
5959
overflow: hidden;
6060
flex-shrink: 0;
@@ -87,8 +87,8 @@
8787
display: flex;
8888
align-items: center;
8989
justify-content: center;
90-
width: 32px;
91-
height: 32px;
90+
width: 28px;
91+
height: 28px;
9292
border-radius: 50%;
9393
background: #f5f5f5;
9494
transition: background 0.2s;
@@ -99,8 +99,8 @@
9999
}
100100

101101
.search-bar-search-icon svg {
102-
width: 18px;
103-
height: 18px;
102+
width: 16px;
103+
height: 16px;
104104
fill: #888;
105105
}
106106

@@ -128,16 +128,16 @@
128128
/* 검색 결과 개수 */
129129
.search-bar-count {
130130
font-size: 0.85rem;
131-
color: #888;
132-
font-weight: 500;
131+
color: var(--brand-color);
132+
font-weight: 600;
133133
flex-shrink: 0;
134134
margin-left: auto;
135135
}
136136

137137
/* Idle 상태 X 버튼 (검색 모드일 때) */
138138
.search-bar-clear-idle {
139-
width: 32px;
140-
height: 32px;
139+
width: 28px;
140+
height: 28px;
141141
border: none;
142142
background: #f0f0f0;
143143
border-radius: 50%;
@@ -147,17 +147,25 @@
147147
justify-content: center;
148148
flex-shrink: 0;
149149
transition: all 0.2s;
150-
margin-left: 8px;
150+
margin-left: 4px;
151+
}
152+
153+
.search-bar-clear-idle svg {
154+
fill: #999;
151155
}
152156

153157
.search-bar-clear-idle:hover {
154-
background: #e5e5e5;
158+
background: #e0e0e0;
155159
}
156160

157161
.search-bar-clear-idle:hover svg {
158162
fill: #666;
159163
}
160164

165+
.search-bar-clear-idle:active {
166+
transform: scale(0.9);
167+
}
168+
161169
.search-bar-menu {
162170
width: 36px;
163171
height: 36px;
@@ -787,11 +795,44 @@
787795
border-radius: 20px 20px 0 0;
788796
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.15);
789797
padding: 20px;
790-
padding-top: 16px;
798+
padding-top: 8px;
791799
position: relative;
792800
animation: slideUp 0.3s ease-out;
793801
}
794802

803+
/* 드래그 핸들 (모바일 전용) */
804+
.bottom-sheet-handle {
805+
display: flex;
806+
justify-content: center;
807+
align-items: center;
808+
padding: 4px 0 8px;
809+
cursor: grab;
810+
touch-action: none;
811+
min-height: 20px;
812+
}
813+
814+
.bottom-sheet-handle:active {
815+
cursor: grabbing;
816+
}
817+
818+
.bottom-sheet-handle-bar {
819+
width: 40px;
820+
height: 5px;
821+
background: #d0d0d0;
822+
border-radius: 3px;
823+
}
824+
825+
/* PC에서 핸들 숨김 */
826+
@media (min-width: 768px) {
827+
.bottom-sheet-handle {
828+
display: none;
829+
}
830+
831+
.bottom-sheet-content {
832+
padding-top: 16px;
833+
}
834+
}
835+
795836
@keyframes slideUp {
796837
from {
797838
transform: translateY(100%);
@@ -956,7 +997,7 @@
956997
}
957998

958999
.bottom-sheet-list {
959-
max-height: 280px;
1000+
max-height: 220px; /* 2개 완전 표시 + 3번째 일부 노출 */
9601001
overflow-y: auto;
9611002
}
9621003

@@ -1548,27 +1589,26 @@
15481589
}
15491590

15501591
.info-modal-section {
1551-
margin-bottom: 16px;
1592+
margin-bottom: 20px;
15521593
}
15531594

15541595
.info-modal-section h3 {
1555-
font-size: 0.85rem;
1596+
font-size: 0.9rem;
15561597
font-weight: 600;
1557-
color: #999;
1558-
margin: 0 0 6px 0;
1559-
text-transform: uppercase;
1560-
letter-spacing: 0.5px;
1598+
color: #666;
1599+
margin: 0 0 8px 0;
1600+
letter-spacing: -0.2px;
15611601
}
15621602

15631603
.info-modal-section p {
15641604
font-size: 0.95rem;
15651605
color: #333;
15661606
margin: 0;
1567-
line-height: 1.5;
1607+
line-height: 1.65;
15681608
}
15691609

15701610
.info-modal-section a {
1571-
color: var(--brand-color);
1611+
color: #E07A20;
15721612
text-decoration: none;
15731613
font-weight: 500;
15741614
}
@@ -1583,21 +1623,22 @@
15831623
}
15841624

15851625
.info-modal-disclaimer {
1586-
margin-top: 20px;
1587-
padding: 12px;
1588-
background: #f8f8f8;
1589-
border-radius: 10px;
1626+
margin-top: 24px;
1627+
padding: 14px 16px;
1628+
background: #FFF8F0;
1629+
border-radius: 12px;
1630+
border-left: 3px solid var(--brand-color);
15901631
}
15911632

15921633
.info-modal-disclaimer p {
15931634
font-size: 0.8rem;
1594-
color: #888;
1635+
color: #666;
15951636
margin: 0;
1596-
line-height: 1.5;
1637+
line-height: 1.6;
15971638
}
15981639

15991640
.info-modal-footer {
1600-
padding: 16px 24px 24px;
1641+
padding: 16px 24px calc(24px + env(safe-area-inset-bottom, 0));
16011642
}
16021643

16031644
.info-modal-btn {
@@ -1617,3 +1658,29 @@
16171658
opacity: 0.9;
16181659
transform: translateY(-1px);
16191660
}
1661+
1662+
.info-modal-developer {
1663+
margin-top: 16px;
1664+
text-align: left;
1665+
}
1666+
1667+
.info-modal-developer span {
1668+
display: block;
1669+
font-size: 0.8rem;
1670+
color: #888;
1671+
margin-bottom: 2px;
1672+
}
1673+
1674+
.info-modal-developer a {
1675+
display: inline-flex;
1676+
align-items: center;
1677+
gap: 4px;
1678+
font-size: 0.8rem;
1679+
color: #999;
1680+
text-decoration: none;
1681+
}
1682+
1683+
.info-modal-developer a:hover {
1684+
color: #666;
1685+
text-decoration: underline;
1686+
}

web/src/components/BottomSheet.jsx

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,64 @@
1+
import { useState, useRef } from 'react'
12
import { BUSINESS_TYPE_FILTERS } from '../constants/categories'
23
import { getCategoryColor } from '../utils/category'
34
import { extractRoadName, extractBuildingNumber } from '../utils/address'
45

56
export function BottomSheet({ merchants, onClose }) {
7+
const [dragY, setDragY] = useState(0)
8+
const [isDragging, setIsDragging] = useState(false)
9+
const startY = useRef(0)
10+
const contentRef = useRef(null)
11+
612
if (!merchants) return null
713

814
const isSingle = merchants.length === 1
915

16+
// 터치/마우스 시작
17+
const handleDragStart = (e) => {
18+
setIsDragging(true)
19+
startY.current = e.touches ? e.touches[0].clientY : e.clientY
20+
}
21+
22+
// 터치/마우스 이동
23+
const handleDragMove = (e) => {
24+
if (!isDragging) return
25+
const currentY = e.touches ? e.touches[0].clientY : e.clientY
26+
const diff = currentY - startY.current
27+
// 아래로만 드래그 가능
28+
if (diff > 0) {
29+
setDragY(diff)
30+
}
31+
}
32+
33+
// 터치/마우스 끝
34+
const handleDragEnd = () => {
35+
setIsDragging(false)
36+
// 100px 이상 드래그하면 닫기
37+
if (dragY > 100) {
38+
onClose()
39+
}
40+
setDragY(0)
41+
}
42+
1043
return (
1144
<div className={`bottom-sheet ${merchants ? 'open' : ''}`}>
12-
<div className="bottom-sheet-content">
45+
<div
46+
ref={contentRef}
47+
className="bottom-sheet-content"
48+
style={{
49+
transform: dragY > 0 ? `translateY(${dragY}px)` : undefined,
50+
transition: isDragging ? 'none' : 'transform 0.2s ease-out'
51+
}}
52+
>
53+
{/* 드래그 핸들 (모바일 전용) */}
54+
<div
55+
className="bottom-sheet-handle"
56+
onTouchStart={handleDragStart}
57+
onTouchMove={handleDragMove}
58+
onTouchEnd={handleDragEnd}
59+
>
60+
<div className="bottom-sheet-handle-bar" />
61+
</div>
1362
<button className="bottom-sheet-close" onClick={onClose}>
1463
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
1564
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>

web/src/components/InfoModal.jsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,6 @@ export function InfoModal({ forceOpen = false, onClose }) {
6868
>
6969
공공데이터포털 - 성남시 아동사랑카드 가맹점 현황
7070
</a>
71-
<br />
72-
<span className="info-modal-license">공공누리 1유형 (출처표시)</span>
73-
</p>
74-
</div>
75-
76-
<div className="info-modal-section">
77-
<h3>개발자</h3>
78-
<p>
79-
<a
80-
href="https://github.com/Origogi"
81-
target="_blank"
82-
rel="noopener noreferrer"
83-
>
84-
Origogi (김정태)
85-
</a>
8671
</p>
8772
</div>
8873

@@ -92,6 +77,16 @@ export function InfoModal({ forceOpen = false, onClose }) {
9277
가맹점 정보는 실제와 다를 수 있으니 방문 전 확인을 권장합니다.
9378
</p>
9479
</div>
80+
81+
<div className="info-modal-developer">
82+
<span>문의 및 피드백</span>
83+
<a href="mailto:rlawjdxo1212@naver.com">
84+
<svg viewBox="0 0 24 24" width="12" height="12" fill="currentColor">
85+
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/>
86+
</svg>
87+
rlawjdxo1212@naver.com (개발자)
88+
</a>
89+
</div>
9590
</div>
9691

9792
{/* 푸터 */}

web/src/components/SearchBar.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ export const SearchBar = forwardRef(function SearchBar({
5959
e.stopPropagation()
6060
onClearApplied()
6161
}}
62+
aria-label="검색 초기화"
6263
>
63-
<svg viewBox="0 0 24 24" width="18" height="18" fill="#999">
64+
<svg viewBox="0 0 24 24" width="16" height="16">
6465
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
6566
</svg>
6667
</button>

web/src/hooks/useFilters.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ export function useFilters(initialFilters = ['음식점'], onFilterChange) {
3939

4040
// 카테고리 선택 바텀시트 열기
4141
const openCategorySheet = useCallback(() => {
42+
onFilterChange?.() // 바텀시트 닫기
4243
setShowCategorySheet(true)
43-
}, [])
44+
}, [onFilterChange])
4445

4546
// 카테고리 선택 바텀시트 닫기
4647
const closeCategorySheet = useCallback(() => {

0 commit comments

Comments
 (0)