fix(ui): 모바일 가로 오버플로 제거 (min-w-0/minmax/flex-wrap/break)
flex/grid 자식이 truncate·긴 텍스트를 품으면서 min-w-0 부재 → 좁은 화면서 줄지 못해 페이지 좌우 스크롤·글자 화면 벗어남(대시보드 최근활동 타임라인이 대표 사례). - dashboard: 타임라인 grid 1fr→minmax(0,1fr)+셀 min-w-0 / 도메인라벨·고정항목 flex-1 min-w-0(+break-words) - inbox: 리스트 제목 min-w-0 - ask: 검색바 flex-wrap + 입력 min-w-0 + select min-w-0 max-w - library: 트리노드·브레드크럼 min-w-0/truncate/flex-wrap - events: 메타행 min-w-0 + project_tag break-all - memos: 본문/code/링크 overflow-wrap:anywhere + table 가로스크롤 가드 감사 11p→수정 6p, 페이지별 적대 재스캔으로 잔존 antipattern까지 제거. 데스크탑 무회귀·토큰/이모지 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -329,13 +329,13 @@
|
||||
<div class="flex flex-col">
|
||||
{#each summary.recent_documents as doc, i (doc.id)}
|
||||
<a href="/documents/{doc.id}"
|
||||
class="grid grid-cols-[auto_14px_1fr] gap-x-3 py-2.5 {i > 0 ? 'border-t border-default' : ''} group">
|
||||
class="grid grid-cols-[auto_14px_minmax(0,1fr)] gap-x-3 py-2.5 {i > 0 ? 'border-t border-default' : ''} group">
|
||||
<div class="text-[10px] text-faint text-right pt-1 whitespace-nowrap tabular-nums w-14">{formatTime(doc.created_at)}</div>
|
||||
<div class="flex flex-col items-center">
|
||||
<span class="w-2 h-2 rounded-full mt-1.5 shrink-0 {domainBgClass(doc.ai_domain)}"></span>
|
||||
{#if i < summary.recent_documents.length - 1}<span class="flex-1 w-px bg-default mt-1"></span>{/if}
|
||||
</div>
|
||||
<div class="pb-1">
|
||||
<div class="pb-1 min-w-0">
|
||||
<div class="text-[10px] font-bold uppercase tracking-wide text-dim mb-0.5">{domainLabel(doc.ai_domain)}</div>
|
||||
<div class="text-[13px] text-text leading-snug group-hover:text-accent transition-colors truncate">{doc.title || '제목 없음'}</div>
|
||||
</div>
|
||||
@@ -382,7 +382,7 @@
|
||||
{#each domainDist.slice(0, 6) as d (d.name)}
|
||||
<a href="/documents?domain={encodeURIComponent(d.name)}" class="flex items-center gap-2 text-xs hover:text-accent transition-colors group">
|
||||
<span class="w-2.5 h-2.5 rounded-sm shrink-0 {domainBgClass(d.name)}"></span>
|
||||
<span class="flex-1 text-text truncate group-hover:text-accent">{domainLabel(d.name)}</span>
|
||||
<span class="flex-1 min-w-0 text-text truncate group-hover:text-accent">{domainLabel(d.name)}</span>
|
||||
<span class="font-semibold text-dim tabular-nums">{d.count.toLocaleString()}</span>
|
||||
</a>
|
||||
{/each}
|
||||
@@ -410,7 +410,7 @@
|
||||
{#each pinnedMemos as memo (memo.id)}
|
||||
<a href="/memos" class="flex items-start gap-2.5 px-3 py-2.5 rounded-lg bg-bg hover:bg-surface-hover transition-colors">
|
||||
<span class="text-[9px] font-bold rounded px-1.5 py-0.5 uppercase tracking-wide shrink-0 mt-0.5 text-accent-hover bg-accent/10">메모</span>
|
||||
<span class="text-xs text-text leading-snug flex-1">{pinTitle(memo)}</span>
|
||||
<span class="text-xs text-text leading-snug flex-1 min-w-0 break-words">{pinTitle(memo)}</span>
|
||||
<Pin size={11} class="text-faint shrink-0 mt-0.5" />
|
||||
</a>
|
||||
{/each}
|
||||
|
||||
@@ -204,8 +204,8 @@
|
||||
<div class="h-full overflow-auto">
|
||||
<!-- 상단 검색바 (sticky) -->
|
||||
<div class="sticky top-0 z-10 bg-bg/80 backdrop-blur border-b border-default px-4 py-3">
|
||||
<div class="flex items-center gap-2 max-w-[1680px] mx-auto">
|
||||
<div class="relative flex-1">
|
||||
<div class="flex flex-wrap items-center gap-2 max-w-[1680px] mx-auto">
|
||||
<div class="relative flex-1 min-w-0">
|
||||
<Search
|
||||
size={14}
|
||||
class="absolute left-3 top-1/2 -translate-y-1/2 text-dim pointer-events-none"
|
||||
@@ -234,7 +234,7 @@
|
||||
<select
|
||||
bind:value={selectedBackend}
|
||||
title="Backend 선택 — silent fallback 0 정책 (선택한 backend 만 시도, 실패 시 503)."
|
||||
class="py-2 px-2 bg-surface border border-default rounded-lg text-text text-xs focus:border-accent outline-none"
|
||||
class="py-2 px-2 bg-surface border border-default rounded-lg text-text text-xs focus:border-accent outline-none min-w-0 max-w-[42vw] truncate"
|
||||
>
|
||||
<option value="auto">Auto (router)</option>
|
||||
<option value="mac-mini-default">Mac mini (default)</option>
|
||||
|
||||
@@ -278,13 +278,13 @@
|
||||
<li>
|
||||
<Card class="flex items-start gap-3 p-3 {KIND_COLOR[item.kind]}">
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 text-xs text-slate-500">
|
||||
<div class="flex min-w-0 items-center gap-2 text-xs text-slate-500">
|
||||
<span>{KIND_LABEL[item.kind]}</span>
|
||||
<span class="rounded px-1.5 py-0.5 text-[10px] {STATUS_COLOR[item.status]}">
|
||||
{STATUS_LABEL[item.status]}
|
||||
</span>
|
||||
{#if item.project_tag}
|
||||
<span class="text-slate-400">#{item.project_tag}</span>
|
||||
<span class="min-w-0 break-all text-slate-400">#{item.project_tag}</span>
|
||||
{/if}
|
||||
</div>
|
||||
<a href="/events/{item.id}" class="mt-1 block break-words text-sm font-medium hover:underline">
|
||||
|
||||
@@ -355,7 +355,7 @@
|
||||
<span class="text-faint"><FormatIcon format={doc.file_format} size={14} /></span>
|
||||
<a
|
||||
href="/documents/{doc.id}"
|
||||
class="text-sm font-medium text-text hover:text-accent truncate"
|
||||
class="text-sm font-medium text-text hover:text-accent truncate min-w-0"
|
||||
>
|
||||
{doc.title || '제목 없음'}
|
||||
</a>
|
||||
|
||||
@@ -438,7 +438,7 @@
|
||||
|
||||
<div class="p-4 lg:p-6">
|
||||
<!-- breadcrumb -->
|
||||
<div class="flex items-center gap-2 text-sm mb-4 text-dim">
|
||||
<div class="flex flex-wrap items-center gap-2 text-sm mb-4 text-dim">
|
||||
<a href="/documents" class="hover:text-text">문서</a>
|
||||
<span class="text-faint">/</span>
|
||||
<span class="text-text">자료실</span>
|
||||
@@ -448,7 +448,7 @@
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => navigate(activePath.split('/').slice(0, i + 1).join('/'))}
|
||||
class="hover:text-text"
|
||||
class="hover:text-text min-w-0 truncate max-w-[40vw]"
|
||||
>
|
||||
{segment}
|
||||
</button>
|
||||
@@ -532,14 +532,14 @@
|
||||
|
||||
<button
|
||||
onclick={() => navigate(n.path)}
|
||||
class="flex-1 flex items-center justify-between px-2 py-1.5 rounded-md text-sm transition-colors
|
||||
class="flex-1 min-w-0 flex items-center justify-between px-2 py-1.5 rounded-md text-sm transition-colors
|
||||
{isActive
|
||||
? 'bg-accent/15 text-accent'
|
||||
: isParent
|
||||
? 'text-text'
|
||||
: 'text-dim hover:bg-surface-hover hover:text-text'}"
|
||||
>
|
||||
<span class="truncate">{n.name}</span>
|
||||
<span class="truncate min-w-0">{n.name}</span>
|
||||
<span class="text-xs text-dim shrink-0 ml-2">{n.count}</span>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -656,12 +656,14 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.memo-content { overflow-wrap: anywhere; word-break: break-word; }
|
||||
.memo-content :global(p) { margin: 0.2em 0; }
|
||||
.memo-content :global(ul), .memo-content :global(ol) { margin: 0.2em 0; padding-left: 1.5em; }
|
||||
.memo-content :global(li) { margin: 0.1em 0; }
|
||||
.memo-content :global(code) { background: var(--bg); padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.85em; }
|
||||
.memo-content :global(code) { background: var(--bg); padding: 0.1em 0.3em; border-radius: 3px; font-size: 0.85em; overflow-wrap: anywhere; word-break: break-word; }
|
||||
.memo-content :global(pre) { background: var(--bg); padding: 0.75em; border-radius: 6px; overflow-x: auto; margin: 0.5em 0; }
|
||||
.memo-content :global(a) { color: var(--accent); }
|
||||
.memo-content :global(table) { display: block; overflow-x: auto; max-width: 100%; }
|
||||
.memo-content :global(a) { color: var(--accent); overflow-wrap: anywhere; word-break: break-word; }
|
||||
.memo-content :global(blockquote) { border-left: 3px solid var(--border-default); padding-left: 0.75em; color: var(--text-dim); margin: 0.5em 0; }
|
||||
.memo-content :global(.memo-checkbox) {
|
||||
cursor: pointer;
|
||||
|
||||
Reference in New Issue
Block a user