updating bootstrap to v5

This commit is contained in:
Calvin Jhunjhuwala
2025-10-17 16:28:07 -07:00
parent c83fc47941
commit ce49c8b6ba
20 changed files with 371 additions and 621 deletions

View File

@@ -128,22 +128,31 @@ export function Navbar(props) {
});
React.useEffect(() => {
// Turns out jQuery is necessary for firing events on Bootstrap v4
// dropdowns. These events set classes so that the search bar and other
// Bootstrap 5 uses vanilla JavaScript API instead of jQuery
// These events set classes so that the search bar and other
// submenus collapse on mobile when you expand one submenu.
const dds = $("#topnav-pages .dropdown");
const dropdowns = document.querySelectorAll("#topnav-pages .dropdown");
const top_main_nav = document.querySelector("#top-main-nav");
dds.on("show.bs.dropdown", (evt) => {
top_main_nav.classList.add("submenu-expanded");
});
dds.on("hidden.bs.dropdown", (evt) => {
top_main_nav.classList.remove("submenu-expanded");
const handleDropdownShow = () => {
top_main_nav?.classList.add("submenu-expanded");
};
const handleDropdownHidden = () => {
top_main_nav?.classList.remove("submenu-expanded");
};
// Attach Bootstrap 5 dropdown events
dropdowns.forEach((dropdown) => {
dropdown.addEventListener("show.bs.dropdown", handleDropdownShow);
dropdown.addEventListener("hidden.bs.dropdown", handleDropdownHidden);
});
// Close navbar on .dropdown-item click
const toggleNavbar = () => {
const navbarToggler = document.querySelector(".navbar-toggler");
const isNavbarCollapsed =
navbarToggler.getAttribute("aria-expanded") === "true";
navbarToggler?.getAttribute("aria-expanded") === "true";
if (isNavbarCollapsed) {
navbarToggler?.click(); // Simulate click to toggle navbar
}
@@ -156,6 +165,10 @@ export function Navbar(props) {
// Cleanup function to remove event listeners
return () => {
dropdowns.forEach((dropdown) => {
dropdown.removeEventListener("show.bs.dropdown", handleDropdownShow);
dropdown.removeEventListener("hidden.bs.dropdown", handleDropdownHidden);
});
dropdownItems.forEach((item) => {
item.removeEventListener("click", toggleNavbar);
});
@@ -300,7 +313,7 @@ export function NavDropdown(props) {
href="#"
id={toggler_id}
role="button"
data-toggle="dropdown"
data-bs-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
@@ -329,8 +342,8 @@ export function NavControls(props) {
<button
className="navbar-toggler collapsed"
type="button"
data-toggle="collapse"
data-target="#top-main-nav"
data-bs-toggle="collapse"
data-bs-target="#top-main-nav"
aria-controls="navbarHolder"
aria-expanded="false"
aria-label="Toggle navigation"
@@ -422,19 +435,19 @@ export class ThemeToggle extends React.Component {
<div className="nav-item" id="topnav-theme">
<form className="form-inline">
<div
className="custom-control custom-theme-toggle form-inline-item"
className="form-check form-check-inline form-switch custom-theme-toggle"
title=""
data-toggle="tooltip"
data-placement="left"
data-bs-toggle="tooltip"
data-bs-placement="left"
data-original-title="Toggle Dark Mode"
>
<input
type="checkbox"
className="custom-control-input"
className="form-check-input"
id="css-toggle-btn"
onClick={this.user_choose_theme}
/>
<label className="custom-control-label" htmlFor="css-toggle-btn">
<label className="form-check-label" htmlFor="css-toggle-btn">
<span className="d-lg-none">Light/Dark Theme</span>
</label>
</div>

View File

@@ -133,7 +133,7 @@ export default function XrplOverview() {
{translate("Read Technical Docs")}
</Link>{" "}
<a
className="ml-4 video-external-link"
className="ms-4 video-external-link"
target="_blank"
href="https://www.youtube.com/playlist?list=PLJQ55Tj1hIVZtJ_JdTvSum2qMTsedWkNi"
>
@@ -168,7 +168,7 @@ export default function XrplOverview() {
{translate("Read Technical Docs")}
</Link>{" "}
<a
className="ml-4 video-external-link"
className="ms-4 video-external-link"
target="_blank"
href="https://www.youtube.com/playlist?list=PLJQ55Tj1hIVZtJ_JdTvSum2qMTsedWkNi"
>
@@ -287,7 +287,7 @@ export default function XrplOverview() {
</div>
</section>
<section className="container-new py-26">
<div className="d-flex flex-column-reverse col-xl-6 mb-lg-4 pl-0 ">
<div className="d-flex flex-column-reverse col-xl-6 mb-lg-4 ps-0 ">
<h2 className="h4 h2-sm">
{translate(
"Watch the explainer video series to learn more about the XRP Ledger"
@@ -407,7 +407,7 @@ export default function XrplOverview() {
</section>
<section className="container-new py-26">
<div
className="col-md-6 offset-md-3 w-100 pl-0 pr-0 mini-faq"
className="col-md-6 offset-md-3 w-100 ps-0 pe-0 mini-faq"
id="minifaq-accordion"
>
{faqs.map((faq, index) => (
@@ -415,8 +415,8 @@ export default function XrplOverview() {
<a
href={`#heading${index + 1}`}
className="expander collapsed"
data-toggle="collapse"
data-target={`#answer${index + 1}`}
data-bs-toggle="collapse"
data-bs-target={`#answer${index + 1}`}
aria-expanded="false"
aria-controls={`answer${index + 1}`}
>

View File

@@ -850,17 +850,17 @@ export default function Uses() {
</div>
<a
className="btn d-block d-lg-none"
data-toggle="modal"
data-target="#categoryFilterModal"
data-bs-toggle="modal"
data-bs-target="#categoryFilterModal"
>
<span className="mr-3">
<span className="me-3">
<img
src={require("../static/img/uses/usecase-filter.svg")}
alt="Filter button"
/>
</span>
{translate("Filter by Categories")}
<span className="ml-3 total_count category_count">2</span>
<span className="ms-3 total_count category_count">2</span>
</a>
{/* Start company cards */}
<div className="row col-12 m-0 p-0 mt-4 pt-2">

View File

@@ -352,7 +352,7 @@ export default function XrpOverview() {
<span className="d-inline-flex">
<img
id="xrp-mark-overview"
className="mw-100 invertible-img mr-2"
className="mw-100 invertible-img me-2"
src={require("../static/img/logos/xrp-mark.svg")}
alt="XRP Logo Mark"
/>
@@ -494,7 +494,7 @@ export default function XrpOverview() {
href={exch.href}
target="_blank"
>
<span className="longform mr-3">{i+1}</span>
<span className="longform me-3">{i+1}</span>
<img className="mw-100" id={exch.id} alt={exch.alt} />
</a>
</li>

View File

@@ -1384,14 +1384,14 @@ export default function Events() {
</section>
<section className="container-new py-26">
<div className="event-hero card-grid card-grid-2xN">
<div className="pr-2 col">
<div className="pe-2 col">
<img
alt="xrp ledger events hero"
src={require("../static/img/events/xrp-community-night.png")}
className="w-100"
/>
</div>
<div className="pt-5 pr-2 col">
<div className="pt-5 pe-2 col">
<div className="d-flex flex-column-reverse">
<h2 className="mb-8 h4 h2-sm">
{translate("XRP Community Night NYC")}

View File

@@ -618,7 +618,7 @@ const CommunityPage: React.FC = () => {
/>
</div>
<div className="mx-auto text-left col-lg-6 text-md-center hero-title">
<div className="mx-auto text-start col-lg-6 text-md-center hero-title">
<div className="d-flex flex-column-reverse align-items-center sm-align-items-start">
<img
src={require("../static/img/icons/arrow-down.svg")}

View File

@@ -220,7 +220,7 @@ export default function Tokenization() {
{translate("Quick Start")}
</Link>{" "}
<a
className="ml-4 video-external-link btn-none"
className="ms-4 video-external-link btn-none"
target="_blank"
href="https://www.youtube.com/playlist?list=PLJQ55Tj1hIVZtJ_JdTvSum2qMTsedWkNi"
>

561
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -37,7 +37,7 @@
"react-dom": "^19.1.0"
},
"devDependencies": {
"bootstrap": "^4.6.2",
"bootstrap": "^5.3.3",
"htmltojsx": "^0.3.0",
"sass": "1.26.10"
}

View File

@@ -86,8 +86,8 @@ export default function CodeSamples() {
{translate('Help the XRPL community by submitting your own code samples')}
</h6>
</div>
<div className="row pl-4">
<div className=" col-lg-3 pl-4 pl-lg-0 pr-4 contribute dot contribute_1">
<div className="row ps-4">
<div className=" col-lg-3 ps-4 ps-lg-0 pe-4 contribute dot contribute_1">
<span className="dot" />
<h5 className="pb-4 pt-md-5">{translate('Fork and clone')}</h5>
<p className="pb-4">
@@ -98,7 +98,7 @@ export default function CodeSamples() {
{translate('resources.contribute.1.part3', '. Using git, clone the fork to your computer.')}
</p>
</div>
<div className=" col-lg-3 pl-4 pl-lg-0 pr-4 contribute dot contribute_2">
<div className=" col-lg-3 ps-4 ps-lg-0 pe-4 contribute dot contribute_2">
<span className="dot" />
<h5 className="pb-4 pt-md-5">{translate('Add to folder')}</h5>
<p className="pb-4">

View File

@@ -62,8 +62,8 @@ export function CurlButton ({selectedConnection, currentBody}: CurlButtonProps)
return <>
<button
className="btn btn-outline-secondary curl"
data-toggle="modal"
data-target="#wstool-1-curl"
data-bs-toggle="modal"
data-bs-target="#wstool-1-curl"
title={translate("cURL Syntax")}
onClick={() => setShowCurlModal(true)}
>

View File

@@ -62,8 +62,8 @@ export function PermalinkButton ({currentBody, selectedConnection}: PermaLinkBut
return <>
<button
className="btn btn-outline-secondary permalink"
data-toggle="modal"
data-target="#wstool-1-permalink"
data-bs-toggle="modal"
data-bs-target="#wstool-1-permalink"
title={translate("Permalink")}
onClick={() => setShowPermalinkModal(true)}
>

View File

@@ -146,8 +146,8 @@ export default function DevTools() {
<button
className="nav-link active dev-tools-tab"
id="explorers-tab"
data-toggle="tab"
data-target="#explorers"
data-bs-toggle="tab"
data-bs-target="#explorers"
role="tab"
aria-controls="explorers"
aria-selected="true"
@@ -159,8 +159,8 @@ export default function DevTools() {
<button
className="nav-link dev-tools-tab"
id="api-access-tab"
data-toggle="tab"
data-target="#api-access"
data-bs-toggle="tab"
data-bs-target="#api-access"
role="tab"
aria-controls="api-access"
aria-selected="false"
@@ -172,8 +172,8 @@ export default function DevTools() {
<button
className="nav-link dev-tools-tab"
id="other-tab"
data-toggle="tab"
data-target="#other"
data-bs-toggle="tab"
data-bs-target="#other"
role="tab"
aria-controls="other"
aria-selected="false"

View File

@@ -238,7 +238,7 @@ export function WebsocketApiTool() {
className="btn-toolbar justify-content-between pt-4"
role="toolbar"
>
<div className="btn-group mr-3" role="group">
<div className="btn-group me-3" role="group">
<button
className="btn btn-outline-secondary send-request"
onClick={() => sendWebSocketMessage(currentBody)}
@@ -259,8 +259,8 @@ export function WebsocketApiTool() {
connected ? "btn-success" : "btn-outline-secondary"
} ${connectionError ?? "btn-danger"}`}
onClick={openConnectionModal}
data-toggle="modal"
data-target="#wstool-1-connection-settings"
data-bs-toggle="modal"
data-bs-target="#wstool-1-connection-settings"
>
{`${selectedConnection.shortname}${
connected ? ` (${translate('Connected')})` : ` (${translate('Not Connected')})`

View File

@@ -184,7 +184,7 @@ function TestCredentials({selectedFaucet, translate}) {
setBalance,
setSequence,
translate)
} className="btn btn-primary mr-2 mb-2">
} className="btn btn-primary me-2 mb-2">
{`${translate('resources.dev-tools.faucet.cred-btn.part1', 'Generate ')}${selectedFaucet.shortName}${translate('resources.dev-tools.faucet.cred-btn.part2', ' credentials')}`}
</button>
</div>

File diff suppressed because one or more lines are too long

View File

@@ -1,293 +0,0 @@
/**
* bootstrap.js v3.0.0 by @fat and @mdo
* Copyright 2013 Twitter Inc.
* http://www.apache.org/licenses/LICENSE-2.0
*/
if (!jQuery) { throw new Error("Bootstrap requires jQuery") }
/* ========================================================================
* Bootstrap: transition.js v3.0.0
* http://twbs.github.com/bootstrap/javascript.html#transitions
* ========================================================================
* Copyright 2013 Twitter, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ======================================================================== */
+function ($) { "use strict";
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
// ============================================================
function transitionEnd() {
var el = document.createElement('bootstrap')
var transEndEventNames = {
'WebkitTransition' : 'webkitTransitionEnd'
, 'MozTransition' : 'transitionend'
, 'OTransition' : 'oTransitionEnd otransitionend'
, 'transition' : 'transitionend'
}
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] }
}
}
}
// http://blog.alexmaccaw.com/css-transitions
$.fn.emulateTransitionEnd = function (duration) {
var called = false, $el = this
$(this).one($.support.transition.end, function () { called = true })
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
setTimeout(callback, duration)
return this
}
$(function () {
$.support.transition = transitionEnd()
})
}(window.jQuery);
+function ($) { "use strict";
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) {
this.options = options
this.$element = $(element)
this.$backdrop =
this.isShown = null
if (this.options.remote) this.$element.load(this.options.remote)
}
Modal.DEFAULTS = {
backdrop: true
, keyboard: true
, show: true
}
Modal.prototype.toggle = function (_relatedTarget) {
return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
}
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
this.isShown = true
this.escape()
this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(document.body) // don't move modals dom position
}
that.$element.show()
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$element.find('.modal-dialog') // wait for modal to slide in
.one($.support.transition.end, function () {
that.$element.focus().trigger(e)
})
.emulateTransitionEnd(300) :
that.$element.focus().trigger(e)
})
}
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
this.escape()
$(document).off('focusin.bs.modal')
this.$element
.removeClass('in')
.attr('aria-hidden', true)
.off('click.dismiss.modal')
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one($.support.transition.end, $.proxy(this.hideModal, this))
.emulateTransitionEnd(300) :
this.hideModal()
}
Modal.prototype.enforceFocus = function () {
$(document)
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.focus()
}
}, this))
}
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
this.$element.off('keyup.dismiss.bs.modal')
}
}
Modal.prototype.hideModal = function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.removeBackdrop()
that.$element.trigger('hidden.bs.modal')
})
}
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
Modal.prototype.backdrop = function (callback) {
var that = this
var animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.appendTo(document.body)
this.$element.on('click.dismiss.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if (!callback) return
doAnimate ?
this.$backdrop
.one($.support.transition.end, callback)
.emulateTransitionEnd(150) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
$.support.transition && this.$element.hasClass('fade')?
this.$backdrop
.one($.support.transition.end, callback)
.emulateTransitionEnd(150) :
callback()
} else if (callback) {
callback()
}
}
// MODAL PLUGIN DEFINITION
// =======================
var old = $.fn.modal
$.fn.modal = function (option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
}
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT
// =================
$.fn.modal.noConflict = function () {
$.fn.modal = old
return this
}
// MODAL DATA-API
// ==============
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
e.preventDefault()
$target
.modal(option, this)
.one('hide', function () {
$this.is(':visible') && $this.focus()
})
})
// $(document)
// .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
// .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
}(window.jQuery);

File diff suppressed because one or more lines are too long

View File

@@ -15,7 +15,7 @@ body {
}
#topnav-theme .custom-theme-toggle {
.custom-control-label::before {
.form-check-input {
background-color: transparent;
background-position: bottom right;
transform: rotate(-15deg);

View File

@@ -17,9 +17,11 @@ $enable-shadows: true;
$dropdown-box-shadow: 0px 5px 40px $black;
$card-spacer-x: 2rem;
$card-spacer-y: 2rem;
// $card-deck-margin is deprecated in Bootstrap 5 - card-deck no longer exists
// Define custom variable for backward compatibility
$card-deck-margin: 1.25rem;
$card-border-radius: $border-radius-lg;
$card-columns-gap: 2rem;
// $card-columns-gap is deprecated in Bootstrap 5 - use grid system instead
$caret-width: 0.4em;
$input-btn-padding-y: 1rem;