fix: structure calendar/Gantt hover cards into title and field grid
- Regroup Redmine's "<strong>Label</strong>: value<br>" tooltip lines on first hover into a title block and a label/value grid (theme.js). - Style the issue link as a kicker, the subject as title-small, and the labels as a muted column next to aligned values. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6c271ffffe
commit
906153014b
@@ -133,6 +133,40 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Calendar/Gantt hover cards: Redmine renders "<a>Tracker #id</a>: subject<br><br>" followed by
|
||||||
|
// "<strong>Label</strong>: value<br>" lines. Regroup them on first hover into a title and a
|
||||||
|
// label/value grid (nodes are moved, not re-parsed, so links and avatars stay intact).
|
||||||
|
function structureTip(tip) {
|
||||||
|
var lines = [[]];
|
||||||
|
Array.prototype.slice.call(tip.childNodes).forEach(function (node) {
|
||||||
|
if (node.nodeName === 'BR') lines.push([]);
|
||||||
|
else if (node.nodeType !== 3 || node.nodeValue.trim()) lines[lines.length - 1].push(node);
|
||||||
|
});
|
||||||
|
var title = document.createElement('span');
|
||||||
|
var fields = document.createElement('span');
|
||||||
|
title.className = 'nm-tip__title';
|
||||||
|
fields.className = 'nm-tip__fields';
|
||||||
|
lines.filter(function (line) { return line.length; }).forEach(function (line, i) {
|
||||||
|
var head = line[0];
|
||||||
|
var value = document.createElement('span');
|
||||||
|
line.slice(1).forEach(function (node) { value.appendChild(node); });
|
||||||
|
if (value.firstChild && value.firstChild.nodeType === 3) {
|
||||||
|
value.firstChild.nodeValue = value.firstChild.nodeValue.replace(/^\s*:\s*/, '');
|
||||||
|
}
|
||||||
|
var target = i > 0 && head.nodeName === 'STRONG' ? fields : title;
|
||||||
|
target.appendChild(head);
|
||||||
|
target.appendChild(value);
|
||||||
|
});
|
||||||
|
tip.replaceChildren(title, fields);
|
||||||
|
tip.classList.add('nm-tip');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('mouseover', function (event) {
|
||||||
|
var tip = event.target.closest && event.target.closest('div.tooltip');
|
||||||
|
tip = tip && tip.querySelector(':scope > span.tip:not(.nm-tip)');
|
||||||
|
if (tip) structureTip(tip);
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
var menu = document.querySelector('#account .dropdown-content .dropdown-divider');
|
var menu = document.querySelector('#account .dropdown-content .dropdown-divider');
|
||||||
if (menu) menu.insertAdjacentHTML('afterend', pickerHtml() + '<div class="dropdown-divider"></div>');
|
if (menu) menu.insertAdjacentHTML('afterend', pickerHtml() + '<div class="dropdown-divider"></div>');
|
||||||
|
|||||||
@@ -373,6 +373,41 @@ div.tooltip:hover span.tip {
|
|||||||
}
|
}
|
||||||
div.tooltip span.tip strong { color: var(--md-sys-color-on-surface); font-weight: 500; }
|
div.tooltip span.tip strong { color: var(--md-sys-color-on-surface); font-weight: 500; }
|
||||||
div.tooltip span.tip .avatar { vertical-align: middle; }
|
div.tooltip span.tip .avatar { vertical-align: middle; }
|
||||||
|
/* Structured by theme.js (structureTip): title block, then a label/value grid. */
|
||||||
|
div.tooltip span.nm-tip .nm-tip__title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
margin-block-end: 12px;
|
||||||
|
}
|
||||||
|
div.tooltip span.nm-tip .nm-tip__title > a {
|
||||||
|
font: var(--md-sys-typescale-label-medium);
|
||||||
|
letter-spacing: var(--md-sys-typescale-label-medium-tracking);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
div.tooltip span.nm-tip .nm-tip__title > span {
|
||||||
|
color: var(--md-sys-color-on-surface);
|
||||||
|
font: var(--md-sys-typescale-title-small);
|
||||||
|
letter-spacing: var(--md-sys-typescale-title-small-tracking);
|
||||||
|
}
|
||||||
|
div.tooltip span.nm-tip .nm-tip__fields {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
gap: 4px 16px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
div.tooltip span.nm-tip .nm-tip__fields > strong {
|
||||||
|
color: var(--md-sys-color-on-surface-variant);
|
||||||
|
font: var(--md-sys-typescale-label-medium);
|
||||||
|
letter-spacing: var(--md-sys-typescale-label-medium-tracking);
|
||||||
|
}
|
||||||
|
div.tooltip span.nm-tip .nm-tip__fields > span {
|
||||||
|
color: var(--md-sys-color-on-surface);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
min-inline-size: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/***** jQuery UI: dialogs, date picker, menus *****/
|
/***** jQuery UI: dialogs, date picker, menus *****/
|
||||||
.ui-widget, .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: var(--md-ref-typeface-plain); }
|
.ui-widget, .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: var(--md-ref-typeface-plain); }
|
||||||
|
|||||||
Reference in New Issue
Block a user