diff --git a/bemo/static/bootstrap-components.css b/bemo/static/bootstrap-components.css new file mode 100644 index 00000000..5ddf8d95 --- /dev/null +++ b/bemo/static/bootstrap-components.css @@ -0,0 +1,78 @@ +/* Additional styles for Bootstrap components that need JS */ + +/* Navbar toggler icon */ +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%23333333' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"); + background-repeat: no-repeat; + background-position: center; + background-size: 100%; +} + +/* Navbar collapse - only hide on small screens */ +@media (max-width: 991.98px) { + .navbar-collapse { + display: none; + } + + .navbar-collapse.show { + display: block !important; + } +} + +@media (min-width: 992px) { + .navbar-collapse { + display: flex !important; + flex-basis: auto; + } +} + +/* Dropdown menu positioning */ +.dropdown-menu { + display: none; + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0,0,0,.15); + border-radius: 0.25rem; +} + +.dropdown-menu.show { + display: block !important; +} + +.dropdown-menu-end { + right: 0; + left: auto; +} + +/* Alert dismissible */ +.alert-dismissible { + padding-right: 3rem; +} + +.alert-dismissible .btn-close { + position: absolute; + top: 0; + right: 0; + z-index: 2; + padding: 0.75rem 1rem; +} + +/* Hidden class for JavaScript-controlled visibility */ +.hidden { + display: none !important; +} diff --git a/bemo/static/bootstrap-icons-minimal.css b/bemo/static/bootstrap-icons-minimal.css new file mode 100644 index 00000000..16914824 --- /dev/null +++ b/bemo/static/bootstrap-icons-minimal.css @@ -0,0 +1,18 @@ +/* Minimal Bootstrap Icons replacement using Unicode/Emoji */ +.bi::before { + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + -webkit-font-smoothing: antialiased; +} + +.bi-trophy-fill::before { content: "🏆"; } +.bi-star-fill::before { content: "⭐"; } +.bi-code-square::before { content: "💻"; } +.bi-person-circle::before { content: "👤"; } +.bi-credit-card::before { content: "💳"; } +.bi-gear-fill::before { content: "⚙️"; } +.bi-moon-fill::before { content: "🌙"; } +.bi-box-arrow-right::before { content: "➡️"; } +.bi-box-arrow-in-right::before { content: "🔑"; } diff --git a/bemo/static/bootstrap-minimal.js b/bemo/static/bootstrap-minimal.js new file mode 100644 index 00000000..478f0e84 --- /dev/null +++ b/bemo/static/bootstrap-minimal.js @@ -0,0 +1,52 @@ +// Minimal Bootstrap JS replacement for dropdowns and collapsible navbar +document.addEventListener('DOMContentLoaded', function() { + // Handle navbar toggle + const navbarToggler = document.querySelector('.navbar-toggler'); + const navbarCollapse = document.querySelector('.navbar-collapse'); + + if (navbarToggler && navbarCollapse) { + navbarToggler.addEventListener('click', function() { + const isExpanded = navbarCollapse.classList.contains('show'); + navbarCollapse.classList.toggle('show'); + // Update ARIA attribute for accessibility + this.setAttribute('aria-expanded', !isExpanded); + }); + } + + // Handle dropdown toggles + const dropdownToggles = document.querySelectorAll('[data-bs-toggle="dropdown"]'); + dropdownToggles.forEach(function(toggle) { + toggle.addEventListener('click', function(e) { + e.preventDefault(); + const menu = this.nextElementSibling; + // Check if next element is a dropdown menu + if (menu && menu.classList.contains('dropdown-menu')) { + // Close other dropdowns + document.querySelectorAll('.dropdown-menu.show').forEach(function(m) { + if (m !== menu) m.classList.remove('show'); + }); + menu.classList.toggle('show'); + } + }); + }); + + // Close dropdowns when clicking outside + document.addEventListener('click', function(e) { + if (!e.target.closest('[data-bs-toggle="dropdown"]')) { + document.querySelectorAll('.dropdown-menu.show').forEach(function(menu) { + menu.classList.remove('show'); + }); + } + }); + + // Handle alert dismissals + const alertCloses = document.querySelectorAll('[data-bs-dismiss="alert"]'); + alertCloses.forEach(function(btn) { + btn.addEventListener('click', function() { + const alert = this.closest('.alert'); + if (alert) { + alert.classList.add('hidden'); + } + }); + }); +}); diff --git a/bemo/templates/layout.html b/bemo/templates/layout.html index 82e4d543..a5e37ace 100644 --- a/bemo/templates/layout.html +++ b/bemo/templates/layout.html @@ -6,11 +6,11 @@ Bemo 🐄 {{title}} - - - - - + + + + +