Files
compiler-explorer/docs/Bootstrap5Migration.md
Matt Godbolt 993b8ec7a7 Cleanup post bootstrap 5 (#7608)
Remove some unnecessary functions and clarify docs.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-04-24 18:41:55 -05:00

27 KiB

Bootstrap 5 Migration Plan

This document outlines the step-by-step process for migrating Compiler Explorer from Bootstrap 4 to Bootstrap 5.3.5. The migration will be completed incrementally to allow for testing between steps.

Migration Strategy

We'll break down the migration into smaller, testable chunks rather than making all changes at once. This approach allows for:

  • Easier identification of issues
  • Progressive testing by project maintainers
  • Minimizing disruption to the codebase

Progress tracking will be maintained in this document.

Phases & Current Progress

Phase 1: Dependency Updates and Basic Setup

  • Update package.json with Bootstrap 5.3.5
  • Add @popperjs/core dependency (replacing Popper.js)
  • Update Tom Select theme from bootstrap4 to bootstrap5
  • Update main import statements where Bootstrap is initialized
  • Update webpack configuration if needed for Bootstrap 5 compatibility
  • Verify the application still builds and runs with basic functionality

Notes for Human Testers (Phase 1)

  • At this phase, the application will have console errors related to Bootstrap component initialization
  • Tom Select dropdowns (like compiler picker) may have styling differences with the new bootstrap5 theme
  • Initial page load should still work, but dropdown functionality will be broken
  • Modal dialogs like Settings and Sharing may not function correctly
  • The primary layout and basic display of panes should still function

Phase 2: Global CSS Class Migration

  • Update directional utility classes (ml/mr → ms/me)
    • Search and replace in .pug templates
    • Search and replace in .scss files
    • Search and replace in JavaScript/TypeScript files that generate HTML
  • Update floating utility classes (float-left/right → float-start/end)
  • Update text alignment classes (text-left/right → text-start/end)
  • Update other renamed classes (badge-pill → rounded-pill, etc.)
  • Test and verify styling changes

Notes for Human Testers (Phase 2)

  • Look for proper spacing and margin alignment in the UI
  • Specific components to check:
    • Compiler output area: Check the spacing in compiler.pug (short-compiler-name, compile-info spans)
    • Navbar spacing: The navbar items should maintain proper spacing (ms/me instead of ml/mr)
    • Code editor components: Check the button and icon alignment in codeEditor.pug
    • Tree view components: The tree.pug file had utility class changes
    • Alert messages (widgets/alert.ts): Check that toast messages appear with correct alignment
    • Compiler picker (compiler-picker.ts and compiler-picker-popup.ts): Check dropdown spacing
    • Rounded badge display in menu-policies.pug (now using rounded-pill instead of badge-pill)
  • The float-end class replaces float-right in the index.pug file's copy buttons
  • Any LTR/RTL layout impacts should be especially checked for correct directionality

Phase 3: HTML Attribute Updates

  • Update data attributes across the codebase
    • data-toggle → data-bs-toggle
    • data-target → data-bs-target
    • data-dismiss → data-bs-dismiss
    • data-ride → data-bs-ride (not used in codebase)
    • data-spy → data-bs-spy (not used in codebase)
    • Other data attributes as needed
  • Test components to ensure they function correctly with new attributes

Notes for Human Testers (Phase 3)

  • This phase should restore basic functionality of several Bootstrap components
  • Specific components to check:
    • Dropdowns: All dropdown menus throughout the application should open/close properly
    • Modal dialogs: Settings, Sharing, and other modal dialogs should open/close correctly
    • Tooltips: Hover tooltips (using data-bs-toggle="tooltip") should display properly
    • Popovers: Any popovers used in the UI should function correctly
    • Collapse components: Any collapsible sections should toggle properly
    • Tabs: Any tabbed interfaces should switch between tabs correctly
  • Watch for console errors related to Bootstrap component initialization
  • Some JavaScript component initialization may still be broken until Phase 4 is completed

Phase 4: JavaScript API Compatibility Layer

  • Create a temporary Bootstrap compatibility utility module to abstract component initialization
    • Implement a hybrid approach with bootstrap-utils.ts as a compatibility layer
    • Mark clearly as temporary code to be removed after migration is complete
    • Define methods for each component type (Modal, Dropdown, Toast, etc.)
  • Update component initialization in key files:
    • widgets/alert.ts (modals and toasts)
    • sharing.ts (modals, tooltips, and dropdowns)
    • compiler-picker-popup.ts (modals)
    • load-save.ts (modals)
    • Other files with Bootstrap component initialization:
      • Modal Initialization:
        • widgets/site-templates-widget.ts
        • widgets/runtime-tools.ts
        • widgets/compiler-overrides.ts
        • widgets/timing-info-widget.ts
        • widgets/history-widget.ts
        • widgets/libs-widget.ts
        • main.ts
      • Dropdown Handling:
        • panes/tree.ts
        • panes/compiler.ts
        • panes/editor.ts
      • Popover Handling:
        • main.ts
        • widgets/compiler-version-info.ts
        • panes/executor.ts
        • panes/conformance-view.ts
        • panes/cfg-view.ts
  • Test the compatibility layer with basic components

Notes for Human Testers (Phase 4)

  • This is one of the most critical phases as it involves creating a compatibility layer for the JavaScript API
  • A new utility file will be created for component initialization that abstracts Bootstrap 5's new approach
  • Key differences to watch for:
    • Modal initialization and events: Bootstrap 5 uses a completely different event system
    • Dropdown initialization: Works with data attributes but requires data-bs-toggle instead of data-toggle
    • Toast components: The API has changed significantly
    • Popover/Tooltip initialization: API changes but still support data attributes with proper prefixes
  • Components to thoroughly test:
    • Alert dialogs (widgets/alert.ts): Check all types of alerts (info, warning, error)
    • Sharing functionality (sharing.ts): The share modal should work properly
    • Compiler picker popup (compiler-picker-popup.ts): Should display and function correctly
    • All dropdown menus: Should open and close properly
    • All tooltips and popovers: Should display correctly on hover/click
  • Watch for event handling issues where Bootstrap 4 events no longer exist or are renamed

Phase 5: Component Migration (By Component Type)

Modal Component Migration

  • Update modal implementation in alert.ts
  • Update modal usage in compiler-picker-popup.ts
  • Update modal handling in load-save.ts
  • Update modal event handling in sharing.ts
  • Test modal functionality thoroughly

Dropdown Component Migration

  • Update dropdown handling in sharing.ts
  • Update dropdown usage in compiler.ts, editor.ts, etc.
  • Test dropdown functionality thoroughly

Toast/Alert Component Migration

  • Update toast implementation in alert.ts
  • Update toast styling in explorer.scss
  • Test toast notifications and alerts

Popover/Tooltip Migration

  • Update tooltip initialization in sharing.ts
  • Update popover usage in compiler.ts, executor.ts, editor.ts, etc.
  • Test popover and tooltip functionality thoroughly

Card Component Updates

  • Review card usage and update to Bootstrap 5 standards
  • Replace any card-deck implementations with grid system (Not needed - card-deck not used in codebase)
  • Test card layouts, especially tab navigation within cards

Collapse Component Updates

  • Update any collapse component implementations (Not needed - minimal collapse usage in codebase)
  • Test collapse functionality (limited to navbar hamburger menu on mobile)

Button Group Updates

  • Review button group implementations
  • Update to Bootstrap 5 standards (no changes needed - Bootstrap 5 maintains same button group classes)
  • Test button group functionality in toolbars and dropdown menus

Phase 6: Form System Updates

  • Update form control classes to Bootstrap 5 standards
  • Update input group markup and classes
  • Update checkbox/radio markup to Bootstrap 5 standards
  • Update form validation classes and markup
  • Consider implementing floating labels where appropriate (new in Bootstrap 5) (Not needed for existing form usage)
  • Test form functionality and appearance

Phase 7: Navbar Structure Updates

  • Update navbar structure in templates to match Bootstrap 5 requirements
  • Review custom navbar styling in explorer.scss
  • Test responsive behavior of navbar
  • Ensure mobile menu functionality works correctly
  • Consider implementing offcanvas for mobile navigation (new in Bootstrap 5) (Standard navbar collapse is sufficient for current needs)

Phase 8: SCSS Variables and Theming

  • Review any custom SCSS that extends Bootstrap functionality
  • Update any custom themes to use Bootstrap 5 variables
  • Check z-index variable changes in Bootstrap 5
  • Add navbar container padding fix for proper alignment
  • Test theme switching functionality

Phase 9: Accessibility Improvements

  • Review ARIA attributes in custom component implementations
  • Leverage Bootstrap 5's improved accessibility features
  • Add ARIA labels and live regions for dynamic content
  • Enhance form controls with proper accessibility attributes
  • Test with screen readers and keyboard navigation (left for future work)
  • Ensure color contrast meets accessibility guidelines (left for future work)

Phase 10: Final Testing and Refinement

  • Comprehensive testing across different viewports cursory testing with a few viewports
  • Cross-browser testing (at least; looked in FireFox and we're good)
  • Fix any styling issues or inconsistencies
  • Performance testing (Bootstrap 5 should be more performant) (don't care; site is fine)
  • Ensure no regressions in functionality

Key Learnings From Implementation

These insights were gathered during the migration process and may be helpful for future reference:

  • Data Attributes Still Work Without JavaScript Initialization: Despite some documentation suggesting otherwise, Bootstrap 5 components with data attributes (like tabs) still work without explicit JavaScript initialization. The key is using the correct data-bs-* prefix.
  • Close Button Implementation Completely Changed: Bootstrap 4 used .close class with a &times; entity inside a span, while Bootstrap 5 uses .btn-close class with a background image and no inner content.
  • Tab Navigation Issues: The tab navigation problems were fixed by simply updating data attributes, not by adding JavaScript initialization.
  • jQuery Plugin Methods Removal: jQuery methods like .popover() and .dropdown('toggle') need to be replaced with code that uses the Bootstrap 5 API through a compatibility layer. Always use BootstrapUtils helper methods rather than direct jQuery plugin calls.
  • Grid and Form Class Renaming: Bootstrap 5 renamed several core classes, such as changing .form-row to .row. This can cause subtle template selector issues in code that relies on these class names.
  • Don't Mix Data Attributes and JavaScript Modal Creation: When creating modals via JavaScript (e.g., for dynamically loaded content), don't include data-bs-toggle="modal" on the trigger element unless you also add a matching data-bs-target attribute pointing to a valid modal element.
  • Modal Events Changed Significantly: Bootstrap 5 modal events need to be attached directly to the native DOM element rather than jQuery objects, and the event parameter type is different. For proper typing, import the Modal type from bootstrap and use Modal.Event type.
  • jQuery Event Binding vs Native DOM Events: Bootstrap 5 requires native DOM event binding instead of jQuery's .on() method. Replace $(selector).on('shown.bs.modal', handler) with domElement.addEventListener('shown.bs.modal', handler). This is particularly important for modal events like ' shown.bs.modal'.
  • Tooltip API Changed: The global window.bootstrap.Tooltip reference no longer exists. Import the Tooltip class directly from bootstrap instead.
  • Input Group Structure Simplified: Bootstrap 5 removed the need for .input-group-prepend and .input-group-append wrapper divs. Buttons and other controls can now be direct children of the .input-group container. This simplifies the markup but requires template updates.
  • TomSelect Widget Integration: Bootstrap 5's switch from CSS triangles to SVG background images for dropdowns caused issues with TomSelect. Adding back custom CSS for dropdown arrows was necessary to maintain correct appearance.
  • Btn-block Removed: Bootstrap 5 removed the .btn-block class. Instead, the recommended approach is to wrap buttons in a container with .d-grid and use standard .btn classes. This affects any full-width buttons in the application.
  • Element Selection for Components: When working with Bootstrap 5 components, prefer passing CSS selectors to BootstrapUtils methods rather than jQuery objects, as this provides more consistent behavior.

Fixed Issues & Completed Work

UI Layout & Display Issues

  • Font dropdown styling fixed
  • Templates view proportions fixed (min-width added to columns and modal)
  • Dialog appearance fixed (updated close buttons to use .btn-close)
  • Dropdown positioning fixed (updated to .dropdown-menu-end)
  • TomSelect dropdown arrows fixed (custom CSS implementation)
  • IDE mode border styling improved (temporarily with .list-group-flush)
  • Sponsors window styling fixed (replaced .btn-block with .d-grid approach)
  • The X to close the community/alert notes is harder to see in dark mode than before (fixed: added filter: invert(100%) to make btn-close buttons visible in dark themes)
  • TomSelect dropdowns for compilers are excessively long (both in executor view and normal view) (fixed manually)
  • Default text/placeholder text is too dark, making it hard to read (especially "Compiler options") (fixed manually)
  • Dropdown in the library menu has changed color (fixed: updated .custom-select to .form-select in theme files)
  • Layout has changed slightly in the library menu (decided it looks better now)
  • The "popout" on the TomSelect compiler dropdown is misaligned (fixed: updated styling for TomSelect components)
  • Compiler combobox rounding overlaps left border by 1 pixel (fixed: overrode CSS variables to reset Bootstrap 5's negative margin)
  • Diff view - changing left/right side compiler/window turns combobox to a white background (fixed: removed form-select class to avoid transparent background)
  • The popular arguments dropdown at the right of the options isn't properly aligned (fixed: updated dropdown styling in compiler.pug)
  • Long compiler names wrap instead of widening the dropdown (fixed: improved styling for TomSelect dropdowns)

Navigation & Functional Issues

  • Tab navigation fixed (updated data attributes to data-bs-toggle="tab")
  • Share dialog functionality fixed (proper Bootstrap 5 modal initialization)
  • Sponsors modal error fixed (removed conflicting data attributes)
  • Share dropdown tooltip conflict fixed (moved tooltip to parent element)
  • History view is broken (empty when clicking radio buttons) (fixed: updated modal event binding from jQuery's .on('shown.bs.modal') to native DOM addEventListener('shown.bs.modal'))
  • Conformance view's "add compiler" functionality is broken (fixed: template selector was looking for .form-row which changed to .row in Bootstrap 5)
  • Need to check for more instances of old Bootstrap v4 code patterns (fixed: replaced dropdown('toggle') in main.ts with BootstrapUtils.getDropdownInstance() and .toggle())
  • Runtime tools window is broken - doesn't save settings anymore (fixed: updated modal hide event handling with setElementEventHandler)
  • Emulation functionality is broken due to modal issues (fixed: replaced direct .modal() calls with BootstrapUtils.showModal)

Code Structure Improvements

  • Custom classes in runtime tools selection (.custom-runtimetool) and overrides selection (.custom-override) - removed as they were superfluous
  • .form-row still used in theme files (dark-theme.scss, one-dark-theme.scss, pink-theme.scss) - replaced with standard .row
  • Border directional properties in explorer.scss updated for better RTL support - added border-inline-start and border radius logical properties with appropriate fallbacks for older browsers
  • Input group structures verified - all instances of the deprecated .input-group-prepend and .input-group-append have already been updated to use Bootstrap 5's simplified approach
  • Toast header close button styling verified - explorer.scss already uses .btn-close consistently for toast components
  • Event handlers verified - history-widget.ts and sharing.ts are correctly using native DOM addEventListener methods with the appropriate Bootstrap 5 event names

Future Work

Phase 11: Documentation Update

  • Update any documentation that references Bootstrap components
  • Document custom component implementations
  • Note any deprecated features or changes in functionality

Phase 12: Optional jQuery Removal and Cleanup

  • Create a plan for jQuery removal (if desired) (tracked in issue #7600)
  • Identify non-Bootstrap jQuery usage that would need refactoring (tracked in issue #7600)
  • Remove the temporary bootstrap-utils.ts compatibility layer (Decision: Keep this utility for the foreseeable future as it provides valuable functionality for jQuery-Bootstrap 5 integration)
    • Replace all uses with direct Bootstrap 5 API calls (Not necessary - updated documentation to indicate direct API usage when possible)
    • Document the native Bootstrap 5 API for future reference (Added documentation in the utilities themselves)
  • Investigate and fix modal accessibility warnings (tracked in issue #7602)
    • Address the warning: "Blocked aria-hidden on an element because its descendant retained focus" (part of issue #7602)
    • Update modal template markup to leverage Bootstrap 5.3's built-in support for the inert attribute (part of issue #7602)
    • Ensure proper focus management in modals for improved accessibility (part of issue #7602)

Additional Pending Issues

  • Check Sentry for additional errors on the live site
  • Investigate the "focus" selected check boxes in the settings view. They're very light when focused, in particular in pink theme. I couldn't work out how to fix this, but it seemed minor. (tracked in issue #7603)
  • The "pop out" div that's attached to the compiler picker doesn't work on the conformance view: this was broken before. Essentially the z-order means it's drawn behind the lower conformance compilers and z-index can't fix it. Needs a rethink of how this is done. (tracked in issue #7604)
  • File tracking issues for anything on this list we don't complete. (completed - all issues have been tracked)

Custom Component Implementations Reference

This section provides documentation for the custom Bootstrap component implementations developed during the migration.

BootstrapUtils (bootstrap-utils.ts)

The bootstrap-utils.ts file serves as a temporary compatibility layer between jQuery-based Bootstrap 4 code and the new Bootstrap 5 JavaScript API. It provides methods for initializing and controlling various Bootstrap components.

Modal Component

Methods:

  • showModal(selector): Displays a modal using a CSS selector or jQuery object
  • hideModal(selector): Hides a modal using a CSS selector or jQuery object
  • setModalHiddenHandler(selector, handler): Sets a handler for the 'hidden.bs.modal' event
  • setModalShownHandler(selector, handler): Sets a handler for the 'shown.bs.modal' event
  • getModalInstance(selector): Gets the Bootstrap Modal instance for a given element

Key Changes from Bootstrap 4:

  • Modal events like 'shown.bs.modal' now need native DOM event listeners
  • Modal objects are obtained using bootstrap.Modal.getInstance() or new bootstrap.Modal()
  • jQuery's .modal('show') is replaced with modalInstance.show()

Dropdown Component

Methods:

  • getDropdownInstance(selector): Gets the Bootstrap Dropdown instance for a given element
  • initializeAllDropdowns(): Initializes all dropdowns on the page

Key Changes from Bootstrap 4:

  • Dropdown toggling with jQuery's .dropdown('toggle') is replaced with dropdownInstance.toggle()
  • Data attributes changed from data-toggle="dropdown" to data-bs-toggle="dropdown"

Tooltip Component

Methods:

  • createTooltip(element, options): Creates a tooltip instance on an element
  • initializeAllTooltips(selector, options): Initializes all tooltips matching a selector

Key Changes from Bootstrap 4:

  • Tooltips must be explicitly initialized with new bootstrap.Tooltip()
  • Global tooltip access changed from $.fn.tooltip to direct import from bootstrap
  • Data attribute changed from data-toggle="tooltip" to data-bs-toggle="tooltip"

Popover Component

Methods:

  • createPopover(element, options): Creates a popover instance on an element
  • initializeAllPopovers(selector, options): Initializes all popovers matching a selector

Key Changes from Bootstrap 4:

  • Popovers must be explicitly initialized with new bootstrap.Popover()
  • Data attribute changed from data-toggle="popover" to data-bs-toggle="popover"

Tab Component

Methods:

  • activateTab(selector): Activates a specific tab

Key Changes from Bootstrap 4:

  • Tab activation changed from $(selector).tab('show') to tabInstance.show()
  • Data attribute changed from data-toggle="tab" to data-bs-toggle="tab"

Toast Component

Methods:

  • createToast(element, options): Creates a toast instance on an element
  • showToast(selector): Shows a toast using a CSS selector or jQuery object

Key Changes from Bootstrap 4:

  • Toasts must be explicitly initialized with new bootstrap.Toast()
  • Toast show/hide methods are direct methods on the toast instance

Event Handling

Key Changes:

  • jQuery event methods (.on(), .off(), etc.) should be replaced with native DOM methods
  • Event registration for Bootstrap components now requires direct DOM element access
  • Event types include the bs prefix (e.g., shown.bs.modal)

CSS Class Changes

Several Bootstrap CSS classes were renamed in version 5:

  • Directional classes: ml-*ms-*, mr-*me-*, etc.
  • Floating classes: float-leftfloat-start, float-rightfloat-end
  • Text alignment: text-lefttext-start, text-righttext-end
  • Form classes: custom-selectform-select, form-rowrow
  • Close button: .close.btn-close (with completely different HTML structure)
  • Dropdown alignment: .dropdown-menu-right.dropdown-menu-end
  • Full-width buttons: .btn-block → Container with .d-grid

Special Integration Notes

TomSelect Integration:

  • Bootstrap 5 changed dropdown indicators from CSS triangles to SVG backgrounds
  • Custom CSS was needed in explorer.scss to fix dropdown arrow appearance
  • The bootstrap5 theme for TomSelect needed additional styling fixes

Modal Focus Management:

  • Bootstrap 5 has stricter focus management in modals
  • Focus must be properly handled when modals are shown/hidden
  • The inert attribute is now supported for better accessibility

Deprecated Features

The following Bootstrap 4 features were deprecated or removed in Bootstrap 5:

  1. jQuery Dependency: Bootstrap 5 no longer requires jQuery
  2. jQuery Plugin Methods: Methods like .modal('show') no longer exist
  3. Global Bootstrap Access: No more $.fn.modal or similar
  4. Card Decks: Replaced by grid system
  5. Form Row: .form-row replaced by standard .row
  6. Input Group Prepend/Append: Wrappers removed, children can be direct
  7. Button Block: .btn-block removed in favor of .d-grid
  8. Close Class: .close replaced by .btn-close with different HTML structure

Final Testing Checklist

Before considering the Bootstrap 5 migration complete, a comprehensive UI testing checklist was created and used to verify functionality. This checklist has been completed with all tests passing. The tests cover all major UI components that could be affected by the Bootstrap migration.

The checklist included:

  • Modal dialogs (Settings, Share, Load/Save, etc.)
  • Dropdown components (navigation, compiler options, TomSelect)
  • Toast/Alert components
  • Popovers and tooltips
  • Card, button group, and form components
  • Specialized views (Conformance, Tree, Visualization)
  • Responsive behavior

A permanent version of this UI testing checklist has been created as a separate document and can be used for testing future UI changes or upgrades: UI Testing Checklist

Notes for Implementation

  1. Make minimal changes in each step to allow for easier testing and troubleshooting
  2. Test thoroughly after each phase before moving to the next
  3. Document issues encountered during migration for future reference
  4. Focus on accessibility to ensure the site remains accessible throughout changes
  5. Maintain browser compatibility with all currently supported browsers
  6. Consider performance implications of the changes
  7. NEVER mark any issue as fixed in this document until you have explicit confirmation from the reviewer that the issue is completely resolved
  8. NEVER commit changes until you have explicit confirmation that the fix works correctly

Technical References