fix(study/sources): 모바일 카테고리 진입 — drawer + breadcrumb
증상: 모바일에서 좌측 트리 hidden md:block 으로 숨겨져 정렬된 최근
자료 외에는 원하는 카테고리를 찾기 어려움.
Fix:
- 헤더 아래 모바일 전용 (md:hidden) 카테고리 진입 바:
· "카테고리" 버튼 (FolderTree 아이콘) — 좌측 drawer 띄움
· breadcrumb: 전체 / 가스기사 / 01_유체역학 / 01_basics
각 segment 클릭 시 해당 path 로 즉시 이동
· 가로 스크롤 (overflow-x-auto) — 깊은 path 도 자연스럽게
- aside 좌측 트리 모바일 drawer 화:
· mobileTreeOpen state. fixed left-0 top-0 bottom-0 w-72 max-w-[85vw]
· 백드롭 클릭 / X 버튼 / 카테고리 선택 시 자동 닫기
· 데스크톱(md+)에선 기존 normal layout 유지
- navigateAndClose 헬퍼 — 카테고리 클릭 시 navigate + close 한 번에
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
import { api } from '$lib/api';
|
||||
import { addToast } from '$lib/stores/toast';
|
||||
import {
|
||||
ChevronRight, ChevronDown, FolderOpen, BookOpen, ArrowLeft,
|
||||
ChevronRight, ChevronDown, FolderOpen, BookOpen, ArrowLeft, FolderTree, X,
|
||||
} from 'lucide-svelte';
|
||||
import DocumentCard from '$lib/components/DocumentCard.svelte';
|
||||
import EmptyState from '$lib/components/ui/EmptyState.svelte';
|
||||
@@ -124,33 +124,98 @@
|
||||
function toggleExpand(path) {
|
||||
expanded[path] = !expanded[path];
|
||||
}
|
||||
|
||||
// 모바일 트리 drawer
|
||||
let mobileTreeOpen = $state(false);
|
||||
function openTree() { mobileTreeOpen = true; }
|
||||
function closeTree() { mobileTreeOpen = false; }
|
||||
// 카테고리 선택 시 drawer 자동 닫기 (모바일)
|
||||
function navigateAndClose(path) {
|
||||
navigate(path);
|
||||
mobileTreeOpen = false;
|
||||
}
|
||||
|
||||
// 현재 경로 breadcrumb 분해
|
||||
let crumbs = $derived(activePath ? activePath.split('/') : []);
|
||||
</script>
|
||||
|
||||
<svelte:head><title>자료 학습 — 공부</title></svelte:head>
|
||||
|
||||
<div class="h-full flex flex-col">
|
||||
<!-- 헤더 -->
|
||||
<div class="flex items-center justify-between gap-2 px-4 py-3 border-b border-default bg-surface shrink-0">
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<a href="/study" class="text-dim hover:text-text flex items-center gap-1">
|
||||
<div class="flex items-center justify-between gap-2 px-3 md:px-4 py-2 md:py-3 border-b border-default bg-surface shrink-0">
|
||||
<div class="flex items-center gap-2 text-xs md:text-sm min-w-0">
|
||||
<a href="/study" class="text-dim hover:text-text flex items-center gap-1 shrink-0">
|
||||
<ArrowLeft size={14} /> 공부
|
||||
</a>
|
||||
<span class="text-faint">/</span>
|
||||
<span class="text-text font-medium flex items-center gap-1.5">
|
||||
<span class="text-faint shrink-0">/</span>
|
||||
<span class="text-text font-medium flex items-center gap-1.5 shrink-0">
|
||||
<BookOpen size={14} class="text-accent" /> 자료 학습
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-xs text-dim">
|
||||
총 {totalCount}건 · <span class="text-text">안 본 {totalUnread}건</span>
|
||||
<div class="text-[10px] md:text-xs text-dim shrink-0">
|
||||
총 {totalCount} · <span class="text-text">안 본 {totalUnread}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-h-0 grid grid-cols-1 md:grid-cols-[260px_1fr] gap-0">
|
||||
<!-- 좌측 트리 -->
|
||||
<aside class="border-r border-default overflow-y-auto p-2 hidden md:block">
|
||||
<!-- 모바일 전용: 카테고리 진입 + breadcrumb -->
|
||||
<div class="md:hidden flex items-center gap-2 px-3 py-2 border-b border-default bg-surface shrink-0 overflow-x-auto">
|
||||
<button
|
||||
type="button"
|
||||
onclick={openTree}
|
||||
style="touch-action: manipulation; user-select: none; -webkit-tap-highlight-color: transparent;"
|
||||
class="flex items-center gap-1 px-3 py-1.5 rounded text-xs bg-accent/10 text-accent border border-accent/30 shrink-0"
|
||||
aria-label="카테고리 선택"
|
||||
>
|
||||
<FolderTree size={14} /> 카테고리
|
||||
</button>
|
||||
{#if crumbs.length > 0}
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => navigate(null)}
|
||||
class="text-xs text-dim hover:text-text shrink-0"
|
||||
>전체</button>
|
||||
{#each crumbs as part, i}
|
||||
<span class="text-faint shrink-0">/</span>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => navigate(crumbs.slice(0, i + 1).join('/'))}
|
||||
class="text-xs whitespace-nowrap shrink-0
|
||||
{i === crumbs.length - 1 ? 'text-accent font-medium' : 'text-dim hover:text-text'}"
|
||||
>{part}</button>
|
||||
{/each}
|
||||
{:else}
|
||||
<span class="text-xs text-dim shrink-0">전체 자료</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex-1 min-h-0 grid grid-cols-1 md:grid-cols-[260px_1fr] gap-0 relative">
|
||||
<!-- 좌측 트리 (데스크톱 normal, 모바일 drawer overlay) -->
|
||||
{#if mobileTreeOpen}
|
||||
<button
|
||||
type="button"
|
||||
aria-label="카테고리 닫기"
|
||||
onclick={closeTree}
|
||||
class="md:hidden fixed inset-0 z-40 bg-black/40"
|
||||
></button>
|
||||
{/if}
|
||||
<aside
|
||||
class="border-r border-default overflow-y-auto p-2
|
||||
{mobileTreeOpen ? 'fixed left-0 top-0 bottom-0 w-72 max-w-[85vw] z-50 bg-surface shadow-2xl md:static md:shadow-none md:w-auto md:bg-transparent' : 'hidden md:block'}"
|
||||
>
|
||||
<div class="md:hidden flex items-center justify-between mb-2 px-1">
|
||||
<span class="text-sm font-semibold text-text">카테고리</span>
|
||||
<button
|
||||
type="button"
|
||||
onclick={closeTree}
|
||||
class="p-1 rounded hover:bg-bg text-dim"
|
||||
aria-label="닫기"
|
||||
><X size={16} /></button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => navigateAndClose(null)}
|
||||
style="touch-action: manipulation; user-select: none; -webkit-tap-highlight-color: transparent;"
|
||||
class="w-full flex items-center justify-between gap-2 px-2 py-1.5 rounded text-sm transition-colors
|
||||
{!activePath ? 'bg-accent/15 text-accent' : 'text-text hover:bg-surface'}"
|
||||
>
|
||||
@@ -185,7 +250,8 @@
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => navigate(n.path)}
|
||||
onclick={() => navigateAndClose(n.path)}
|
||||
style="touch-action: manipulation; user-select: none; -webkit-tap-highlight-color: transparent;"
|
||||
class="flex-1 flex items-center justify-between gap-2 px-2 py-1 rounded text-xs transition-colors text-left
|
||||
{isActive ? 'bg-accent/15 text-accent' : isParent ? 'text-text' : 'text-dim hover:bg-surface hover:text-text'}"
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
|
||||
Reference in New Issue
Block a user