collin/anvil · 76f9fe52
ui: svg folder and file icons in the tree view
Collin Richards · 2026-06-10 08:12 UTC · 76f9fe529616fae8231551d4bdc13c12aea7e1a1 · parent b056637e · browse files
modifiedcrates/anvil-web/src/ui.rs+14 −2
| ⋯ 102 unchanged lines | |||
| 103 | 103 | .box .row a.fc-msg { flex:1; margin-left:24px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; text-align:left; color:var(--muted); font-size:13px; } | |
| 104 | 104 | .box .row a.fc-msg:hover { color:var(--accent); } | |
| 105 | 105 | .box .row .fc-time { margin-left:16px; white-space:nowrap; color:var(--muted); font-size:13px; } | |
| 106 | - | .icon { width:16px; color:var(--muted); } | |
| 106 | + | .icon { width:16px; flex:none; display:inline-flex; align-items:center; justify-content:center; color:var(--muted); } | |
| 107 | + | .icon.dir { color:#54aeff; } | |
| 107 | 108 | table.code { border-collapse:collapse; width:100%; font:12px/1.45 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; } | |
| 108 | 109 | table.code td { padding:0 10px; vertical-align:top; white-space:pre; } | |
| 109 | 110 | table.code td.ln { text-align:right; color:var(--muted); user-select:none; width:1%; border-right:1px solid var(--border); background:var(--code-bg); } | |
| ⋯ 76 unchanged lines | |||
| 186 | 187 | ||
| 187 | 188 | /// Clipboard icon for the clone "copy" button. | |
| 188 | 189 | const CLIPBOARD_SVG: &str = r#"<svg viewBox="0 0 16 16" width="15" height="15" fill="currentColor" aria-hidden="true"><path d="M10 1.5H6a.5.5 0 0 0-.5.5v1H4A1.5 1.5 0 0 0 2.5 4.5v9A1.5 1.5 0 0 0 4 15h8a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 12 3h-1.5V2a.5.5 0 0 0-.5-.5zm-3.5 1h3v1h-3v-1zM4 4.5h8v9H4v-9z"/></svg>"#; | |
| 190 | + | ||
| 191 | + | /// Filled folder icon for directory entries in the tree view. | |
| 192 | + | const FOLDER_SVG: &str = r#"<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"/></svg>"#; | |
| 193 | + | ||
| 194 | + | /// Outline file icon for blob entries in the tree view. | |
| 195 | + | const FILE_SVG: &str = r#"<svg viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"/></svg>"#; | |
| 196 | + | ||
| 189 | 197 | /// Delegated handlers for the clone widget: protocol toggle + copy-to-clipboard. | |
| 190 | 198 | /// Registered once on `document`, so it survives htmx body swaps. | |
| 191 | 199 | const CLONE_JS: &str = r#" | |
| ⋯ 876 unchanged lines | |||
| 1068 | 1076 | @let kind = if e.is_dir { "tree" } else { "blob" }; | |
| 1069 | 1077 | div.row { | |
| 1070 | 1078 | a.entry href=(format!("/{owner}/{repo}/{kind}/{rev}/{child}")) { | |
| 1071 | - | span.icon { (if e.is_dir { "[ ]" } else { "·" }) } | |
| 1079 | + | @if e.is_dir { | |
| 1080 | + | span.icon.dir { (PreEscaped(FOLDER_SVG)) } | |
| 1081 | + | } @else { | |
| 1082 | + | span.icon { (PreEscaped(FILE_SVG)) } | |
| 1083 | + | } | |
| 1072 | 1084 | (e.name) @if e.is_dir { "/" } | |
| 1073 | 1085 | } | |
| 1074 | 1086 | @if let Some(c) = latest.get(&e.name) { | |
| ⋯ 491 unchanged lines | |||