- viewport meta on layout.tmpl + login.tmpl (iOS won't render legibly without) - two breakpoints: tablet (≤768px), phone (≤480px) - chip strips: horizontal-scroll with sticky labels instead of wrapping - tables → card lists: classify + bulk render as stacked cards on mobile - forms: single column on phone; min 44px touch targets on buttons - dashboard: cards already 1-col, polish for narrow widths; grid jumps to 2 columns at ≥1280px with stale card spanning both - /graph: SVG scrolls inside .graph-canvas (max-width 100vw, max-height 75vh, overflow auto); "fit to screen" toggle flips natural vs viewport - TestLayoutHasViewportMeta verifies every chrome-bearing route ships the meta tag - CLAUDE.md "Out of scope" drops mobile/Otto-PWA exclusion (head approved on m/mAi#1861); replaced with native-PWA-install line for Phase 3j - design.md adds §"Mobile responsiveness" with breakpoint + principle notes
54 lines
2.3 KiB
Cheetah
54 lines
2.3 KiB
Cheetah
{{define "content"}}
|
|
<h1>Graph <small class="muted">{{.Matched}} / {{.Total}} items</small></h1>
|
|
|
|
<section class="tagbar" id="graph-filterbar">
|
|
<form id="graph-filter" class="search"
|
|
hx-get="/graph"
|
|
hx-target="main"
|
|
hx-select="main"
|
|
hx-swap="outerHTML"
|
|
hx-trigger="change from:select, change from:input[type=checkbox], keyup changed delay:200ms from:input[name=q]"
|
|
hx-push-url="true">
|
|
<input type="search" name="q" value="{{.Filter.Q}}" placeholder="search…" autocomplete="off">
|
|
<label>tag
|
|
<select name="tag" multiple size="3">
|
|
{{$sel := .Filter.Tags}}
|
|
{{range .AllTags}}<option value="{{.}}" {{if contains $sel .}}selected{{end}}>{{.}}</option>{{end}}
|
|
</select>
|
|
</label>
|
|
<label>mgmt
|
|
<select name="mgmt" multiple size="4">
|
|
{{$selM := .Filter.Management}}
|
|
<option value="mai" {{if contains $selM "mai"}}selected{{end}}>mai</option>
|
|
<option value="self" {{if contains $selM "self"}}selected{{end}}>self</option>
|
|
<option value="external" {{if contains $selM "external"}}selected{{end}}>external</option>
|
|
<option value="unmanaged"{{if contains $selM "unmanaged"}}selected{{end}}>unmanaged</option>
|
|
</select>
|
|
</label>
|
|
<label class="checkbox">
|
|
<input type="checkbox" name="isolate" value="1" {{if .Isolate}}checked{{end}}>
|
|
isolate (hide non-matches)
|
|
</label>
|
|
{{if .Filter.Active}}<a class="clear" href="/graph">clear filters</a>{{end}}
|
|
<a class="download" href="/graph?download=svg">download SVG</a>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="graph-canvas" id="graph-canvas">
|
|
<p class="graph-controls muted">
|
|
<button type="button" class="fit-screen" onclick="document.getElementById('graph-canvas').classList.toggle('fit')">fit to screen</button>
|
|
<small>scroll / pinch to zoom on touch</small>
|
|
</p>
|
|
{{template "graph-svg" .P}}
|
|
</section>
|
|
|
|
<section class="graph-legend muted">
|
|
<span class="legend-key key-mai">mai</span>
|
|
<span class="legend-key key-self">self</span>
|
|
<span class="legend-key key-external">external</span>
|
|
<span class="legend-key key-mixed">mixed</span>
|
|
<span class="legend-key key-unmanaged">unmanaged</span>
|
|
· status opacity: active 1.0 · done 0.6 · archived 0.3
|
|
</section>
|
|
{{end}}
|