feat(browse): extension chip under tree icon + archive refs in hovercard
Two small surface upgrades on file rows:
- Tree icon column now stacks the Lucide glyph on top of a small
uppercase extension chip (PDF, DOCX, YAML, etc.). File type reads
at a glance without expanding the row. Folders and zips skip the
chip — their glyph already carries enough.
- Hovercard on a ZDDC-parseable file gains two clickable references
in the .archive section:
Latest → /<project>/.archive/<tracking>.html
This revision → /<project>/.archive/<tracking>_<rev>.html
Both forms are dispatcher-canonicalised to project-root, so the
link works from any depth. Folders that parse (transmittal folders)
get just the Latest link.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c2423f8873
commit
4497ebdf99
3 changed files with 77 additions and 7 deletions
|
|
@ -361,15 +361,17 @@ body {
|
||||||
|
|
||||||
.tree-name__icon {
|
.tree-name__icon {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
/* Fixed-width column keeps label alignment consistent regardless
|
/* Stacked column — glyph on top, extension chip below for files.
|
||||||
of which symbol the row picks. Height matches one line of label
|
Wider min-width than the 1em glyph itself so common extensions
|
||||||
text so the icon anchors to the title row on two-line layouts. */
|
(pdf/docx/xlsx/json) don't push the label sideways. Height
|
||||||
width: 1.2em;
|
grows with content; flex-start anchors to the title-line. */
|
||||||
height: 1.2em;
|
min-width: 2.2em;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
|
gap: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-name__icon svg {
|
.tree-name__icon svg {
|
||||||
|
|
@ -378,6 +380,19 @@ body {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tree-name__ext {
|
||||||
|
font-size: 0.58rem;
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--text-muted);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
font-weight: 600;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
/* Folder rows get the primary accent so directories stand out from
|
/* Folder rows get the primary accent so directories stand out from
|
||||||
files at a glance — same convention as macOS Finder / GNOME Files. */
|
files at a glance — same convention as macOS Finder / GNOME Files. */
|
||||||
.tree-row[data-isdir="true"] .tree-name__icon,
|
.tree-row[data-isdir="true"] .tree-name__icon,
|
||||||
|
|
@ -951,6 +966,17 @@ body {
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Archive-reference links inside the hovercard pick up the primary
|
||||||
|
accent so they read as clickable, and stay inline with the mono
|
||||||
|
font when they sit inside a mono cell. */
|
||||||
|
.tree-hovercard__val a {
|
||||||
|
color: var(--primary, #2868c8);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.tree-hovercard__val a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
/* Separator stretches across both grid columns. Bleed into the
|
/* Separator stretches across both grid columns. Bleed into the
|
||||||
card's padding so it visually reads as a divider, not a hairline. */
|
card's padding so it visually reads as a divider, not a hairline. */
|
||||||
.tree-hovercard__sep {
|
.tree-hovercard__sep {
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,32 @@
|
||||||
if (parsed.revision) html += kv('Revision', parsed.revision, true);
|
if (parsed.revision) html += kv('Revision', parsed.revision, true);
|
||||||
if (parsed.status) html += kv('Status', parsed.status, true);
|
if (parsed.status) html += kv('Status', parsed.status, true);
|
||||||
if (parsed.title) html += kv('Title', parsed.title);
|
if (parsed.title) html += kv('Title', parsed.title);
|
||||||
|
|
||||||
|
// Archive references — the /<project>/.archive/<tracking>.html
|
||||||
|
// URL is the latest issued version (highest base rev), and
|
||||||
|
// /<project>/.archive/<tracking>_<rev>.html pins the exact
|
||||||
|
// revision the user is currently hovering. The dispatcher
|
||||||
|
// canonicalises both forms to project-root so links work
|
||||||
|
// from any depth.
|
||||||
|
if (parsed.trackingNumber) {
|
||||||
|
var fullPath = tree ? tree.pathFor(node) : '';
|
||||||
|
var rel = fullPath.replace(/^\/+|\/+$/g, '');
|
||||||
|
var firstSeg = rel ? rel.split('/')[0] : '';
|
||||||
|
if (firstSeg) {
|
||||||
|
var encProject = encodeURIComponent(firstSeg);
|
||||||
|
var encTracking = encodeURIComponent(parsed.trackingNumber);
|
||||||
|
var latestUrl = '/' + encProject + '/.archive/' + encTracking + '.html';
|
||||||
|
var latestLbl = '.archive/' + parsed.trackingNumber + '.html';
|
||||||
|
html += kvLink('Latest', latestUrl, latestLbl);
|
||||||
|
if (!node.isDir && parsed.revision) {
|
||||||
|
var encRev = encodeURIComponent(parsed.revision);
|
||||||
|
var inspectUrl = '/' + encProject + '/.archive/' + encTracking + '_' + encRev + '.html';
|
||||||
|
var inspectLbl = '.archive/' + parsed.trackingNumber + '_' + parsed.revision + '.html';
|
||||||
|
html += kvLink('This revision', inspectUrl, inspectLbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
html += '<div class="tree-hovercard__sep"></div>';
|
html += '<div class="tree-hovercard__sep"></div>';
|
||||||
} else if (node.displayName) {
|
} else if (node.displayName) {
|
||||||
// Operator-supplied display name — only useful as info if
|
// Operator-supplied display name — only useful as info if
|
||||||
|
|
@ -136,6 +162,18 @@
|
||||||
+ '">' + escapeHtml(val) + '</span>';
|
+ '">' + escapeHtml(val) + '</span>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// kvLink — value rendered as an <a> the user can click (opens in
|
||||||
|
// a new tab so the hover context isn't lost) or right-click to
|
||||||
|
// copy. Used for the .archive references on ZDDC files.
|
||||||
|
function kvLink(key, href, label) {
|
||||||
|
return '<span class="tree-hovercard__key">' + escapeHtml(key) + '</span>'
|
||||||
|
+ '<span class="tree-hovercard__val tree-hovercard__val--mono">'
|
||||||
|
+ '<a href="' + escapeHtml(href) + '" target="_blank" rel="noopener">'
|
||||||
|
+ escapeHtml(label)
|
||||||
|
+ '</a>'
|
||||||
|
+ '</span>';
|
||||||
|
}
|
||||||
|
|
||||||
function render(node) {
|
function render(node) {
|
||||||
var z = window.zddc;
|
var z = window.zddc;
|
||||||
var parsed = z
|
var parsed = z
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,12 @@
|
||||||
var virtualHint = node.virtual
|
var virtualHint = node.virtual
|
||||||
? '<span class="tree-name__hint">(empty)</span>'
|
? '<span class="tree-name__hint">(empty)</span>'
|
||||||
: '';
|
: '';
|
||||||
|
// Extension chip stacked under the file icon. Files with a
|
||||||
|
// non-empty ext get a small uppercase label; folders / zips
|
||||||
|
// skip it (the chevron + icon glyph carries enough info).
|
||||||
|
var extChip = (!node.isDir && !node.isZip && node.ext)
|
||||||
|
? '<span class="tree-name__ext">' + escapeHtml(String(node.ext)) + '</span>'
|
||||||
|
: '';
|
||||||
return ''
|
return ''
|
||||||
+ '<div class="tree-row ' + (visuallyExpanded ? 'expanded' : '') + selected + virtualCls
|
+ '<div class="tree-row ' + (visuallyExpanded ? 'expanded' : '') + selected + virtualCls
|
||||||
+ '" data-id="' + node.id
|
+ '" data-id="' + node.id
|
||||||
|
|
@ -377,7 +383,7 @@
|
||||||
+ ' style="padding-left:' + indent + 'rem"'
|
+ ' style="padding-left:' + indent + 'rem"'
|
||||||
+ ' role="treeitem" tabindex="-1">'
|
+ ' role="treeitem" tabindex="-1">'
|
||||||
+ '<span class="' + chevronClass + '">' + chevronGlyph + '</span>'
|
+ '<span class="' + chevronClass + '">' + chevronGlyph + '</span>'
|
||||||
+ '<span class="tree-name__icon">' + iconChar + '</span>'
|
+ '<span class="tree-name__icon">' + iconChar + extChip + '</span>'
|
||||||
+ labelHtml(node)
|
+ labelHtml(node)
|
||||||
+ virtualHint
|
+ virtualHint
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue