Skip to content

Migrate to Bootstrap 5.3#93

Draft
malberts wants to merge 7 commits into
masterfrom
bs5-migration
Draft

Migrate to Bootstrap 5.3#93
malberts wants to merge 7 commits into
masterfrom
bs5-migration

Conversation

@malberts
Copy link
Copy Markdown
Collaborator

@malberts malberts commented May 22, 2026

Scope discipline

This PR is the BS4→BS5 framework lift only.

Not in scope:

Verification

Tested with MW 1.43.8, mediawiki/bootstrap ^6.0 (Bootstrap framework 5.3.x), Chameleon at master HEAD (128fe31) and Medik at master HEAD (f7ca0ac). Two candidate wikis stood up side-by-side: Chameleon-default and Medik-default. Skin:Chameleon and Skin:Medik are only installed on their respective stack (useskin=<other-BS-skin> falls back to the wiki's default), so each was exercised on the stack that actually loads it. MW-core skins (vector-2022, vector, monobook, timeless) were exercised via ?useskin=.

A single wikitext test page, BCTestMatrix, exercises every BC component across every documented attribute / colour / size / placement value (modals in five colours and three sizes, popovers in four placements and three trigger modes, eight alert colours plus dismissible variants, three-pane accordion, three-image carousel, the full button / badge / card / jumbotron matrix). Each interactive component was driven via Playwright with real user-input events (real mouseenter for tooltips, click toggles for collapse / modal / popover), and assertions cover both the visible state (.modal.show, .popover.show with BS5-shaped .popover-header / .popover-body, .btn-close-style dismissals) and the framework-level z-indices (modal 1055 / backdrop 1050 / popover 1070).

Per-skin matrix of JS-driven components

Badge, Button, and Jumbotron have no JS and aren't listed; their rendering is covered by the screenshots below.

Skin Modal Popover Tooltip Alert Card Accordion Carousel
chameleon
medik ⚠ collapsible
vector-2022
vector (legacy)
monobook
timeless

The ⚠ on the Medik / Card cell is the collapsible variant only; static cards render correctly. See Known issues below.

Rendered output per skin

The same BCTestMatrix wikitext rendered under each skin (full-page screenshots):

chameleon medik vector-2022 vector (legacy) monobook timeless
BCTestMatrix-chameleon BCTestMatrix-medik BCTestMatrix-vector-2022 BCTestMatrix-vector BCTestMatrix-monobook BCTestMatrix-timeless

Test page wikitext: BCTestMatrix.txt

Side-by-side baseline comparison against the BS4 5.x release showed only expected BS4→BS5 stylistic evolution: BS5's .btn-close SVG icon vs BS4's × character; softer pastel BS5 alert palette; jumbotron utility-class composition (p-5 mb-4 bg-body-tertiary rounded-3) replacing the dropped .jumbotron. No functional or layout regressions outside the Skin:Medik card-collapsible defect noted below.

Known issues

Skin:Medik card-collapsible doesn't re-collapse. The body opens on the first click but stays open on subsequent clicks. Root cause: BS5's JS ends up loaded twice on the page — once via skins.medik.js (Medik is a BS-based skin and bundles the framework directly), and once via BC's ext.bootstrap.scripts. Both copies bind a click delegation to [data-bs-toggle="collapse"], so each click fires the toggle handler twice. Modal / popover / tooltip / accordion / carousel / alert-dismiss all survive the double-init because BS5's _isTransitioning short-circuit absorbs the duplicate event; Collapse on a .fade-classed body re-shows itself. The fix is BC-side: #70 ("Remove hard dependency on Extension:Bootstrap") already tracks making BC detect when BS is already loaded by the environment and skip its own load.

`mediawiki/bootstrap` ^6.0 ships Bootstrap framework 5.3.x; the prior
^5.0 ships BS4. Adds a `dev-master` branch alias to 6.x-dev so the
v6 development line is explicit.

Wires the new `ext.bootstrapComponents.modal.js` init script onto the
`modal.fix` module. The init script (added in a follow-up commit)
calls `bootstrap.Modal.getOrCreateInstance` on every `.modal`, replacing
the implicit jQuery `[data-toggle="modal"]` lifecycle that BS4 ran
automatically and BS5 no longer does.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@malberts malberts force-pushed the bs5-migration branch 4 times, most recently from 808af8f to 552e618 Compare May 22, 2026 10:43
@malberts
Copy link
Copy Markdown
Collaborator Author

malberts commented May 22, 2026

color="default"

Historical chain:

  • Bootstrap 3 shipped a neutral-grey button colour called default (.btn-default, .badge-default, etc.). BootstrapComponents was originally built against BS3 and exposed default as a valid value for color on Modal, Popover, Button, and Badge.
  • Bootstrap 4 dropped the default colour family. The BS4 migration guide recommends replacing btn-default with btn-secondary; the same recommendation applied to alerts and badges.
  • Bootstrap 5 kept BS4's recommendation and went further on badges, dropping the whole badge-<color> family in favour of text-bg-<color> utilities.
  • BC 4.x and 5.x effectively shipped color="default" as a no-op at the framework-rule level. The PHP emitters continued to accept the value and emit btn-default / badge-default, but the BS4 framework had no rule for those classes, and BC carried only one partial fix — link-colour rules for a.btn-default in button.fix.css, which only overrode MediaWiki's anchor colour and didn't define background, border, padding, or anything else. Net BC 5.x rendering of color="default":
    • Modal / Popover trigger buttons (<button class="btn btn-default">): browser-default <button> styling + BS4's .btn base. Cross-browser-inconsistent.
    • Button component (<a class="btn btn-default">): dark-text padded link (the link-colour fix mattering here), no background, no border.
    • Badge (<span class="badge badge-default">): transparent label with .badge padding only.
    • Alert (<div class="alert alert-default">): transparent box with .alert padding + transparent default border. Effectively invisible.
  • BC 6.0 (this PR) ships the same effectively-unstyled rendering for color="default" under BS5. The *-default class is a no-op there too — BS5 has no rule for it either. The link-colour fix in button.fix.css is preserved so the Button component renders the same dark-padded-text shape it did under BS4.

Why this PR doesn't translate default

We investigated mapping defaultsecondary (or light) at the PHP layer so existing wikitext using the legacy value would render with proper BS5 styling under 6.0. Decided against it because:

  • The "back-compat being preserved" was an effectively-unstyled rendering. Mapping to secondary (or anything) would have been an improvement — a behaviour change layered on top of the framework lift, not a lift change itself.
  • Mixing "lift to BS5 framework" with "improve previously-broken rendering" muddies the PR's character. Without the translation, this PR is purely a framework lift: same PHP-level semantics as BC 5.x, just compiled against BS5 instead of BS4.

Options if we decide to act later

  1. Keep as-is. color="default" remains a documented attribute value that renders as effectively-unstyled.
  2. Drop default from the attribute manager's allowed-value list. Documented behaviour change for 6.0: color="default" becomes invalid and falls back to the per-component default (primary for Button/Badge, info for Popover, no colour class for Modal).
  3. Map to a visually meaningful BS5 class in the PHP layer. Sub-choice on the target: secondary (BS4 upstream recommendation, mid-grey filled) vs light (closer to BS3's actual visual character, light filled) vs outline-secondary (subtle outlined). Apply consistently to Modal / Popover / Button / Badge / Alert.
  4. Ship full BC-owned CSS for *-default. Define .btn-default, .badge-default, .alert-default etc. in BC's fix CSS so the class becomes meaningful again. Half-measure — recreating BS3 styling from scratch (filled + outline variants, full state matrix) ends up as an approximation, and we'd be defining classes no framework owns (conflicting with consumer CSS).

@malberts malberts force-pushed the bs5-migration branch 6 times, most recently from 2f66741 to 157397b Compare May 22, 2026 10:57
@malberts
Copy link
Copy Markdown
Collaborator Author

malberts commented May 22, 2026

Jumbotron contained-heading sizing

Historical chain:

  • Bootstrap 4 styled .jumbotron h1 and .jumbotron .h1 directly via descendant selectors — contained headings auto-enlarged (2.5rem normal, 6rem ≥576px) without authors touching their markup.
  • Bootstrap 5 dropped _jumbotron.scss entirely; the only utility-class composition the BS5 docs recommend has the heading class set explicitly (e.g. display-5 fw-bold).
  • This PR's Jumbotron emitter wraps user wikitext as a single blob inside the BS5 utility-class container (p-5 mb-4 bg-body-tertiary rounded-3); no descendant heading rules ship and no heading element is owned by the emitter. Existing wikitext like <bootstrap_jumbotron>== Headline ==\nBody\n</bootstrap_jumbotron> renders with a normal-sized heading post-upgrade, where it would have rendered with a BS4-enlarged one on 5.x.

Options if we decide to act later

  1. Accept the size regression. Existing wikitext keeps working but headings inside a jumbotron lose their auto-enlargement. Docs (docs/components/jumbotron.md) note that authors should apply display-* / fs-* utility classes themselves and point at the BS5 example.
  2. Recreate the descendant rules in BC-owned CSS. Add a bsc-jumbotron class to the outer wrapper in Jumbotron.php and ship modules/ext.bootstrapComponents.jumbotron.fix.css with descendant selectors that reproduce BS4's sizing (font-size: 2.5rem normal, 6rem on ≥576px). No API change. Mirrors how BC's other *.fix.css modules paper over framework transitions; goes against BS5's "utility classes only" philosophy.
  3. Restructure the component to emit the heading itself. Add a heading (or title) attribute. Jumbotron::placeMe() builds the DOM as
    <div class="p-5 mb-4 bg-body-tertiary rounded-3">
        <h1 class="display-5 fw-bold">{heading}</h1>
        {body content}
    </div>
    so the <h1> is BC-owned and the utility classes are applied directly on it — matches the BS5 example exactly. Documented behaviour change: existing wikitext that used == Title == inside the tag won't auto-enlarge until authors migrate to heading="Title".

@malberts malberts force-pushed the bs5-migration branch 5 times, most recently from 78f1284 to 72241a6 Compare May 22, 2026 14:47
@malberts
Copy link
Copy Markdown
Collaborator Author

Accordion uses BS3-vestigial markup, not BS5 native primitives

Historical chain:

  • Bootstrap 3 shipped panels as the accordion building block: a .panel-group wrapper around .panel children with .panel-heading + .panel-body, wired together by data-parent.
  • Bootstrap 4 dropped panels and the .panel-group class entirely. The BS4 idiomatic accordion was a stack of .card children inside a <div class="accordion"> wrapper, where the framework's .accordion > .card rules collapsed inter-card borders into a single combined outline (see Bootstrap-baseline repo: resources/bootstrap/scss/_card.scss:266-286).
  • Bootstrap 5 dropped the wrapper-around-cards pattern as well and introduced dedicated primitives: .accordion, .accordion-item, .accordion-header, .accordion-button, .accordion-collapse, .accordion-body. The BS5 .accordion no longer touches .card at all (_accordion.scss operates on .accordion-item).
  • BC has always emitted <div class="panel-group bsc_accordion"> wrapping .card children with .card-header / .card-body / .collapse, wired by data-bs-parent. Under BS4 the in-line comment in Accordion.php says the author deliberately avoided the framework's .accordion class because its border-collapse behaviour wasn't the look they wanted, and used a BS3-vestigial panel-group (no-op under BS4+) plus their own bsc_accordion class for radii trimming.
  • BC 6.0 (this PR) ships the same markup. panel-group is still a no-op under BS5; .card is still styled; bsc_accordion still strips the joining radii. The data-attribute prefix rename (data-parentdata-bs-parent, data-toggledata-bs-toggle) is the only thing this PR touched in the accordion code path, and that lives in Card.php rather than Accordion.php. The in-line "Extension:Bootstrap cuts the border-bottom of every card" comment is now stale (the BS5 framework no longer has that rule).

Current behaviour under BS5

Functionally working: clicking a header expands the pane, expanding one pane collapses siblings via data-bs-parent, ARIA attributes are honoured. Verified across all six skins as part of this PR's matrix.

Visually: a stack of independently-bordered .card blocks with rounded outer corners and squared inter-card corners (bsc_accordion providing the latter). Not the BS5 native accordion look (single-piece outline, larger touch-target headers with chevron indicator, padded .accordion-body).

Why this PR doesn't restructure

The work would be a rewrite of Accordion.php and Card.php (when the card is being used as an accordion pane) to emit .accordion-item / .accordion-button / .accordion-header / .accordion-collapse / .accordion-body markup, plus updates to the JSONScript fixtures under tests/phpunit/Integration/JSONScript/TestCases/. That's a structural change of the component, not a framework lift, and would land alongside the other v6 follow-ups under discussion.

Options if we decide to act later

  1. Keep as-is. Markup stays BS3-vestigial; BC's accordion.fix.css carries the visual treatment forward indefinitely. Slightly off-pattern from the rest of the BS5 ecosystem but works.
  2. Port to BS5 native primitives. Restructure Accordion.php + Card.php to emit .accordion-item / .accordion-button / .accordion-header / .accordion-collapse / .accordion-body. Touches both component classes, the JSONScript fixtures, and the documented HTML output. Aligns BC with the BS5 framework idiom and gets the larger touch targets + chevron indicator "for free" from the framework.
  3. Ship BC-owned CSS that mimics the BS5 accordion look on top of the current card structure. Keep the markup but extend accordion.fix.css to recreate the single-piece outline, larger header targets, and chevron indicator. Avoids the structural rewrite; recreates BS5-owned CSS in BC, which becomes a maintenance liability against future BS5.x framework changes.

malberts and others added 5 commits May 24, 2026 13:01
BootstrapComponents' JS modules wired Popover and Tooltip via jQuery's
top-level `$( '...' ).popover()` / `.tooltip()` calls. Bootstrap 5
dropped its jQuery dependency entirely, so the per-component init that
BC owns has to switch to vanilla DOM + `bootstrap.X.getOrCreateInstance`
calls. Switch all four init modules accordingly:

* targets the BS5 `data-bs-toggle` attribute set by the PHP emitters,
* calls the relevant `bootstrap.Modal|Popover|Tooltip|Carousel`
  constructor on every matching element after DOMContentLoaded.

Popover and Tooltip are opt-in in BS5 (no framework-side delegation)
so their init scripts are required. Modal and Carousel aren't strictly
required — BS5 still auto-binds modal trigger clicks and carousel
`data-bs-ride` via its data-api — but the explicit loops mirror
Popover/Tooltip's shape and ensure programmatic
`bootstrap.Modal.getOrCreateInstance(el).show()` works without first
racing the data-api init.

`ext.bootstrapComponents.modal.js` is new and wired onto `modal.fix`
in the previous commit. The other three replace the jQuery
`$(...).popover()` / `$(...).tooltip()` / `$(...).carousel()`
top-level calls.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bootstrap 5 namespaced all its data-attribute hooks with a `bs-` prefix
(`data-bs-toggle`, `data-bs-target`, etc.) to stop conflicting with
authoring code. Update every BC component that emits these attributes
plus `ModalBuilder` and its trigger-matching regexes:

* `Components/Modal.php` — `data-toggle`/`data-target` on the trigger
  button.
* `Components/Popover.php` — `data-toggle`, `data-content`,
  `data-placement`, `data-trigger`.
* `Components/Tooltip.php` — `data-toggle`, `data-placement`.
* `Components/Carousel.php` — `data-ride`, `data-slide`,
  `data-slide-to`, `data-target` on indicators.
* `Components/Card.php` — `data-toggle`/`data-target` on collapsible
  card heads, `data-parent` on accordion children.
* `Components/Collapse.php` — `data-toggle` on the toggle button.
* `Components/Alert.php` — `data-dismiss` on the close button.
* `ModalBuilder.php` — `data-toggle`/`data-target`/`data-dismiss` in
  the emitted markup, plus the `preg_match` regexes that test for
  a user-supplied trigger pointing at the modal.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bootstrap 5 dropped several BS3/BS4 class names that BC's PHP emitters
were hard-coding. Update the affected sites to BS5 equivalents:

* `Components/Badge.php` — `badge-pill` -> `rounded-pill`, and the
  `badge-<color>` family -> the BS5 `text-bg-<color>` utilities that
  set background AND a contrasting foreground.
* `Components/Alert.php` — close button switches from BS4's
  `class="close"` + `<span aria-hidden>&times;</span>` shape to BS5's
  self-styled `class="btn-close"` (no inner span; the X is drawn by
  the class via a background SVG).
* `Components/Jumbotron.php` — `.jumbotron` was removed in BS5;
  recreate the same look with utility classes per the BS5 example.
* `ModalBuilder.php` — same close-button shape change as Alert,
  and switch the footer dismiss button from BS4's removed
  `btn-default` to `btn-secondary` (BS5 default colour).
* `Components/Modal.php` — whitespace-only realign of the array
  literal to keep keys consistent with the renamed `data-bs-*` entries.

`color="default"` on Modal / Popover / Button / Badge is deliberately
left as-is. BS5 (and BS4) have no rule for `*-default`, so it renders
effectively-unstyled; back-compat for existing wikitext is preserved by
accepting the value, not by translating it. See the migration guide for
the decision and the recommended user-side replacements.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bootstrap 5's carousel indicator example uses `<div class="carousel-indicators">`
holding `<button>` elements rather than the BS3-era `<ol>/<li>` shape. The
button form is what Bootstrap's JS wires keyboard focus and `aria-current`
on. The old markup still renders visually under BS5 CSS but doesn't pick
up the accessibility behaviour.

Switch the wrapper to `<div>`, the indicator elements to `<button>`, and add
`aria-current="true"` on the initially-active indicator + `aria-label` on each.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The PHP emitters now produce `data-bs-*` attributes, BS5 class names
(`rounded-pill`, `text-bg-<color>`, `btn-close`, the utility-class
jumbotron set, `btn-secondary` modal footer dismiss), and BS5
`<button>` carousel indicators. Update the expected strings in:

* `Components/*Test.php` — data-attribute renames, badge class
  renames, close-button shape, jumbotron utility classes, carousel
  `<ol>/<li>` -> `<div>/<button>` markup, modal footer dismiss
  button colour, `default` -> `secondary` colour mapping.
* `ImageModalTest.php`, `ImageModalTriggerTest.php`,
  `ModalBuilderTest.php` — same renames inside the modal markup
  these tests exercise via `ModalBuilder`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* `docs/release-notes.md` — write a focused 6.0.0 entry covering the
  actual BS5-lift changes (Bootstrap-extension bump, attribute renames,
  JS modules, class-name updates, carousel indicator markup,
  `color="default"` back-compat note). The MediaWiki (1.43) and PHP
  (8.1) floors are unchanged from 5.x and not listed under "Breaking
  changes". The bug-fix entries that already shipped in 5.2.3 / 5.2.4
  are not re-listed under 6.0 since 6.0 inherits them from the 5.x
  line.
* `docs/migration-guide.md` — new file. Step-by-step upgrade guide
  for wiki admins moving from BC 5.x (Bootstrap 4) to BC 6.0 (BS5).
  Explicitly notes that the MW and PHP floors are unchanged; the only
  new requirement is `mediawiki/bootstrap` ^6.0.
* `docs/components.md` — note the jumbotron now emits utility classes
  instead of the removed `.jumbotron` class.
* `docs/components/*.md` — update Bootstrap-version text references
  (`4.1` -> `5.3` doc URLs, "default" colour notes).
* `docs/known-issues.md` — replace the pre-5.2.4 modal-backdrop
  workaround sections (which told users to add `.modal-backdrop {
  display: none }` to their wiki CSS) with a single entry describing
  the current shipped behaviour: the workaround CSS now rides along
  with the extension and is applied automatically on Vector and
  Vector 2022 (the only two skins where the page-container traps
  the modal under its backdrop on MW 1.43+). Point at #91 for the
  root-cause tracking. Refresh the navbar-overlaps-modal section
  opener so it no longer leans on the removed backdrop-troubleshooting
  context.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant