fix(responsive): Phase 3 spec compliance 수정
- Blog: 태그 필터 칩 바 모바일 가로 스크롤 추가 - BlogMarketing: FAB 전 탭에서 표시 + 대시보드 480px 1컬럼 - Subscription: PullToRefresh refreshKey 패턴 적용, FAB→공고 목록 탭 이동 - Todo: FAB 라벨 "할일 추가"로 spec 일치 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -142,7 +142,7 @@
|
|||||||
.bm-header h1 { font-size: 1.2rem; }
|
.bm-header h1 { font-size: 1.2rem; }
|
||||||
.bm-status { display: none; }
|
.bm-status { display: none; }
|
||||||
.bm-tab { padding: 6px 10px; font-size: 0.8rem; }
|
.bm-tab { padding: 6px 10px; font-size: 0.8rem; }
|
||||||
.bm-dash-cards { grid-template-columns: repeat(2, 1fr); }
|
.bm-dash-cards { grid-template-columns: 1fr; }
|
||||||
.bm-research-form { flex-direction: column; }
|
.bm-research-form { flex-direction: column; }
|
||||||
.bm-analysis-card__scores { gap: 10px; }
|
.bm-analysis-card__scores { gap: 10px; }
|
||||||
.bm-write-actions { flex-direction: column; }
|
.bm-write-actions { flex-direction: column; }
|
||||||
|
|||||||
@@ -137,9 +137,7 @@ export default function BlogMarketing() {
|
|||||||
{tab === 'write' && <WriteTab />}
|
{tab === 'write' && <WriteTab />}
|
||||||
{tab === 'posts' && <PostsTab />}
|
{tab === 'posts' && <PostsTab />}
|
||||||
|
|
||||||
{tab === 'research' && (
|
|
||||||
<FAB onClick={() => setTab('research')} label="키워드 분석" />
|
<FAB onClick={() => setTab('research')} label="키워드 분석" />
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</PullToRefresh>
|
</PullToRefresh>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -490,6 +490,13 @@
|
|||||||
|
|
||||||
.blog-list.is-visible .blog-category-filter {
|
.blog-list.is-visible .blog-category-filter {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blog-list.is-visible .blog-category-filter > * {
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.blog-list.is-visible .blog-pagination {
|
.blog-list.is-visible .blog-pagination {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { apiGet, apiPost, apiPut, apiDelete } from '../../api';
|
|||||||
import { useIsMobile } from '../../hooks/useIsMobile';
|
import { useIsMobile } from '../../hooks/useIsMobile';
|
||||||
import PullToRefresh from '../../components/PullToRefresh';
|
import PullToRefresh from '../../components/PullToRefresh';
|
||||||
import FAB from '../../components/FAB';
|
import FAB from '../../components/FAB';
|
||||||
import MobileSheet from '../../components/MobileSheet';
|
|
||||||
import './Subscription.css';
|
import './Subscription.css';
|
||||||
|
|
||||||
// ── 상수 ───────────────────────────────────────────────────────────────────────
|
// ── 상수 ───────────────────────────────────────────────────────────────────────
|
||||||
@@ -1302,19 +1301,18 @@ function ProfileTab() {
|
|||||||
function Subscription() {
|
function Subscription() {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const [activeTab, setActiveTab] = useState(0);
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
const [filterSheetOpen, setFilterSheetOpen] = useState(false);
|
const [refreshKey, setRefreshKey] = useState(0);
|
||||||
|
|
||||||
|
const handleRefresh = useCallback(async () => {
|
||||||
|
setRefreshKey(k => k + 1);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleFABClick = useCallback(() => {
|
const handleFABClick = useCallback(() => {
|
||||||
if (activeTab === 0) {
|
setActiveTab(1); // 공고 목록 탭으로 이동
|
||||||
// DashboardTab — open filter sheet or scroll to collect
|
}, []);
|
||||||
setFilterSheetOpen(true);
|
|
||||||
} else {
|
|
||||||
setFilterSheetOpen(true);
|
|
||||||
}
|
|
||||||
}, [activeTab]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PullToRefresh onRefresh={useCallback(async () => {}, [])}>
|
<PullToRefresh onRefresh={handleRefresh}>
|
||||||
<div className="sub">
|
<div className="sub">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="sub-header">
|
<div className="sub-header">
|
||||||
@@ -1344,42 +1342,13 @@ function Subscription() {
|
|||||||
|
|
||||||
{/* Body */}
|
{/* Body */}
|
||||||
<div className="sub-body">
|
<div className="sub-body">
|
||||||
{activeTab === 0 && <DashboardTab />}
|
{activeTab === 0 && <DashboardTab key={`dash-${refreshKey}`} />}
|
||||||
{activeTab === 1 && <AnnouncementsTab />}
|
{activeTab === 1 && <AnnouncementsTab key={`ann-${refreshKey}`} />}
|
||||||
{activeTab === 2 && <MatchesTab />}
|
{activeTab === 2 && <MatchesTab key={`match-${refreshKey}`} />}
|
||||||
{activeTab === 3 && <ProfileTab />}
|
{activeTab === 3 && <ProfileTab key={`prof-${refreshKey}`} />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MobileSheet
|
<FAB onClick={handleFABClick} label="공고 목록" />
|
||||||
open={filterSheetOpen}
|
|
||||||
onClose={() => setFilterSheetOpen(false)}
|
|
||||||
title="필터"
|
|
||||||
snap="half"
|
|
||||||
>
|
|
||||||
<div style={{ padding: '8px 0' }}>
|
|
||||||
<p style={{ fontSize: '0.85rem', color: 'var(--text-muted)', marginBottom: 12 }}>
|
|
||||||
탭을 선택하여 원하는 화면으로 이동하세요.
|
|
||||||
</p>
|
|
||||||
{TABS.map((tab, i) => (
|
|
||||||
<button
|
|
||||||
key={tab}
|
|
||||||
onClick={() => { setActiveTab(i); setFilterSheetOpen(false); }}
|
|
||||||
style={{
|
|
||||||
display: 'block', width: '100%', padding: '12px 16px',
|
|
||||||
textAlign: 'left', background: activeTab === i ? 'rgba(244,63,94,0.1)' : 'transparent',
|
|
||||||
border: 'none', borderRadius: 8, cursor: 'pointer',
|
|
||||||
color: activeTab === i ? '#f43f5e' : 'var(--text-primary)',
|
|
||||||
fontSize: '0.9rem', fontWeight: activeTab === i ? 700 : 400,
|
|
||||||
marginBottom: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tab}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</MobileSheet>
|
|
||||||
|
|
||||||
<FAB onClick={handleFABClick} label="공고 등록" />
|
|
||||||
</div>
|
</div>
|
||||||
</PullToRefresh>
|
</PullToRefresh>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ const Todo = () => {
|
|||||||
className="button primary"
|
className="button primary"
|
||||||
onClick={() => setFormOpen((v) => !v)}
|
onClick={() => setFormOpen((v) => !v)}
|
||||||
>
|
>
|
||||||
{formOpen ? '취소' : '+ 태스크 추가'}
|
{formOpen ? '취소' : '+ 할일 추가'}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -383,12 +383,12 @@ const Todo = () => {
|
|||||||
<MobileSheet
|
<MobileSheet
|
||||||
open={addSheetOpen}
|
open={addSheetOpen}
|
||||||
onClose={() => { setAddSheetOpen(false); setForm(emptyForm); }}
|
onClose={() => { setAddSheetOpen(false); setForm(emptyForm); }}
|
||||||
title="태스크 추가"
|
title="할일 추가"
|
||||||
>
|
>
|
||||||
{addForm}
|
{addForm}
|
||||||
</MobileSheet>
|
</MobileSheet>
|
||||||
|
|
||||||
<FAB onClick={() => setAddSheetOpen(true)} label="태스크 추가" />
|
<FAB onClick={() => setAddSheetOpen(true)} label="할일 추가" />
|
||||||
</div>
|
</div>
|
||||||
</PullToRefresh>
|
</PullToRefresh>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user