Bugfix Issue 1796 Dead Bootstrap45 Modal Classes - sebiboga/testlink-upgraded GitHub Wiki
Bugfix — Issue #1796: three modernized screens carried dead Bootstrap 4/5 modal classes (modal-xl, modal-dialog-centered) so their dialogs were 600px and top-aligned
Issue — #1796 (label bug, opened
2026-10-02T19:33:45Z — the NEWEST open issue without a work-type label at the time of this run)
Screens — gui/templates/documentation/documentation.html,
gui/templates/requirements/reqTcAssign.html,
gui/templates/requirements/reqTcBulkAssign.html
Component — Bootstrap modal geometry (no PHP, no BFF endpoint, no data)
Fix commits — 904b0d88f (fix) + ed647bf89 (code-review follow-ups), branch fix/issue-1796
Status — fixed, verified error-free, regression suite 15/15 PASS
This is the cosmetic residue of #1683,
which fixed the functional half of the same Bootstrap-3-vs-4/5 family on
reqTreeReorder.html and then asked for a repo-wide grep. That grep is what produced this
issue — and this page closes it for good.
Three dialogs opened at the wrong size and never moved away from the top of the viewport.
| Screen | Dialog | Wanted (BS4/5 classes used) | Got (BS3 reality) |
|---|---|---|---|
documentation.html |
View (PDF/attachment preview) | 1140px (modal-xl), centred |
600px, margin-top:30px
|
reqTcAssign.html |
confirm (unlink requirement, …) | centred (modal-dialog-centered) |
520px, margin-top:30px
|
reqTcBulkAssign.html |
confirm (bulk unlink, …) | centred | 520px, margin-top:30px
|
The View dialog was the visible offender: a PDF preview squeezed into 600px and pinned
to the top. On a short window it was worse than "wrong look" — at 780x437 the dialog ran
from top:30 to bottom:451.6 in a 437px viewport, i.e. 15px of the dialog was below the
fold.
Nothing was broken functionally: the dialogs open, close, are dismissible, are localised. Bootstrap 3 ignores unknown class names with no console warning, no Event Viewer row and no HTTP signal, which is precisely why this survived review.
-
http://localhost:8082/index.php→ sign inadmin/admin http://localhost:8082/gui/templates/documentation/documentation.html- click View on any PDF card (e.g. User Manual →
testlink_user_manual.pdf) - read
#pdfModal .modal-content— 600px wide, 30px from the top
For the confirm dialogs (the fresh test database ships no test cases to drive the click
path, so the screen's own helper is used — confirmThen() at reqTcAssign.html:256,
the function every destructive action on that screen calls):
// run in the page console of reqTcAssign.html / reqTcBulkAssign.html
confirmThen('Unlink requirement', 'Remove <b>REQ-1</b> from this test case?', 'OK', function(){});
const m=document.querySelector('#confirmModal'),c=document.querySelector('#confirmModal .modal-content'),
mr=m.getBoundingClientRect(),cr=c.getBoundingClientRect();
console.log({cls:c.parentElement.className,w:cr.width,
vGap:[cr.top-mr.top,mr.bottom-cr.bottom]}); // -> [30, 694] pre-fixThe Dashio bundle is Bootstrap 3.4.1 (gui/templates/dashio/lib/bootstrap/js/bootstrap.min.js:2).
Its entire dialog vocabulary is:
| Class | Width | Where |
|---|---|---|
.modal-dialog |
600px @≥768px, margin:30px auto
|
bootstrap.css:5980 |
.modal-sm |
300px | bootstrap.css:6059 |
.modal-lg |
900px | bootstrap.css:6064 |
.modal-xl |
does not exist | — |
.modal-dialog-centered |
does not exist | — |
The three screens were authored against the BS4/5 names, so both modal-xl and
modal-dialog-centered matched no rule at all and the element degraded to the bare BS3
defaults. Verified by scanning every rule of every loaded stylesheet at runtime — no rule
matches either token.
The 25 other modal-sm / modal-lg usages across the modernized screens are real BS3
classes and were deliberately left untouched.
The dead tokens are removed and the intent is re-expressed in BS3-legal, per-screen scoped
rules (each modernized screen owns a page-level <style> block — documentation.html:10,
reqTcAssign.html:10, reqTcBulkAssign.html:10):
/* documentation.html */
#pdfModal .modal-body { height: 80vh; max-height: calc(100vh - 130px); }
#pdfModal .modal-dialog { display:flex; align-items:center; justify-content:center;
min-height:calc(100% - 20px); width:auto; margin:10px auto; }
#pdfModal .modal-content{ width: 1140px; max-width: calc(100% - 20px); }
/* reqTcAssign.html + reqTcBulkAssign.html */
#confirmModal .modal-dialog { display:flex; align-items:center; justify-content:center;
min-height:calc(100% - 20px); width:auto; margin:10px auto; }
#confirmModal .modal-content{ width: 520px; max-width: calc(100% - 20px); }<!-- before -->
<div class="modal-dialog modal-xl modal-dialog-centered">
<div class="modal-dialog modal-dialog-centered" style="max-width:520px;">
<!-- after -->
<div class="modal-dialog">Four things were measured the hard way and are worth writing down, because each one silently defeats the obvious implementation:
-
The width belongs on
.modal-content, not on.modal-dialog. Once the dialog isdisplay:flex,.modal-contentis a flex item, and a flex item with no width shrinks to its content — the first attempt measured 302px, not 1140px. -
margin:10px autoon awidth:autoblock resolves tomargin:10px 0(auto side margins only act on an over-constrained box). The horizontal gutter therefore comes from the content'smax-width:calc(100% - 20px), not from the dialog's margin. Without it the dialog went full-bleed (765px content in a 765px dialog at a 780px window). -
justify-content:centeris required, not optional. BS3 keeps the container at 600px and centres it withmargin:auto; the visible 520px.modal-contentthen sat at the container's left edge — measuredleft 420 / right 500, an 80px asymmetry. -
The
min-heightand the margin must agree (10px + (100% − 20px) + 10px = 100%). With BS3'smargin-top:30pxstill in force the dialog ended up 10px taller than the viewport and the flex centring pushed the top down:vGap [382, 342].
Overflow safety: .modal-dialog keeps height:auto, so the flex line grows with the
content — a dialog taller than the viewport is never clipped at the top, and
.modal-open .modal { overflow-y:auto } (bootstrap.css:5976) keeps the scroll reachable.
The #pdfModal .modal-body max-height cap is what guarantees centring has slack on short
screens (80vh of a 437px viewport = 350px, which already exceeded the min-height box).
-
Upgrade the bundle to Bootstrap 4/5 — every modal, dropdown, DataTable and
$(el).modal()call site on ~30 modernized screens is Bootstrap 3 API. Not a 3-line fix. -
Add
.modal-xl/.modal-dialog-centeredshims to the shared Dashio CSS — one file would fix three screens, but it re-introduces the exact dead names that #1683's grep hunts for, leaving the next reader (and the next grep) worse off. Screen-local rules are self-documenting. -
JS positioning on
show.bs.modal— more code, no benefit, fights the CSS.
Measured in headless Chrome at four viewport sizes; the console was clean and the Event
Viewer (events) gained no Error/Warning rows (events = 1 row, the
audit_login_succeeded INFO row).
| # | Case | Before | After |
|---|---|---|---|
| 1 |
documentation.html View, 1440x900 |
w=600, vGap [30,78]
|
w=1140, hGap [143,143], vGap [54,54]
|
| 2 |
documentation.html View, 1024x600 |
600px |
w=989 = min(1140, window-20), centred |
| 3 |
documentation.html View, 780x437 |
600px, overflows 15px |
w=745, vGap [29,29], overflow=false
|
| 4 |
documentation.html View → × → reopen |
— | embed cleared by hidden.bs.modal, reopens centred |
| 5 |
reqTcAssign.html confirm, 1440x900 |
vGap [30,694]
|
w=520, hGap [460,460], vGap [362,362]
|
| 6 |
reqTcBulkAssign.html confirm, 1440x900 |
vGap [30,694]
|
w=520, hGap [460,460], vGap [362,362]
|
| 7 | confirm dialogs, 500x420 | hard 520px (overflows a 500px window) |
w=480, vGap [122,122], no overflow |
| 8 | Cancel / OK / × on both confirm dialogs | — | all three dismiss; the OK callback fires exactly once |
| 9 | i18n | — | unchanged; no bundle touched (git diff --name-only = 3 HTML files) |
| 10 | grep -rn 'modal-dialog-centered|modal-xl|new BSS.Modal|data-bs-dismiss' gui/templates/*/*.html |
3 hits | 0 hits |
| 11 | grep -c 'modal-dialog modal-sm|modal-dialog modal-lg' |
25 | 25 (legit BS3 classes, untouched) |
Regression suite: tmp/TLU_Test_Cases.md → Regression — Issue #1796 (R1796-1 … R1796-15),
15/15 PASS.

Modernized screens run on Bootstrap 3.4.1. For a dialog:
- size it with
.modal-sm/.modal-lg, or — when you need something wider — an explicitwidth+max-width:calc(100% - 20px)on.modal-content; - Bootstrap 3 has no vertical-centring utility — use
display:flex; align-items:center; justify-content:center; min-height:calc(100% - 20px); width:auto; margin:10px autoon.modal-dialogand keep the width on.modal-content; - drive it with
$(el).modal('show'|'hide')and close it with<button class="close" data-dismiss="modal">×</button>.
A grep -rn 'modal-xl\|modal-dialog-centered\|new BSS.Modal\|data-bs-dismiss\|btn-close'
over gui/templates/*/*.html must stay empty — that is the check this issue came from.