diff --git a/services/web/frontend/js/bootstrap-3.ts b/services/web/frontend/js/bootstrap-3.ts index 61d2b98421..68d04baafe 100644 --- a/services/web/frontend/js/bootstrap-3.ts +++ b/services/web/frontend/js/bootstrap-3.ts @@ -1,6 +1,6 @@ import 'bootstrap' import './features/contact-form' -import './features/bookmarkable-tab' +import './features/bookmarkable-tab/index' $('[data-ol-lang-selector-tooltip]').tooltip({ trigger: 'hover' }) $('[data-toggle="tooltip"]').tooltip() diff --git a/services/web/frontend/js/bootstrap-5.ts b/services/web/frontend/js/bootstrap-5.ts index 3b4282f29f..a4132ec789 100644 --- a/services/web/frontend/js/bootstrap-5.ts +++ b/services/web/frontend/js/bootstrap-5.ts @@ -1 +1,2 @@ import 'bootstrap-5' +import './features/bookmarkable-tab/index-bs5' diff --git a/services/web/frontend/js/features/bookmarkable-tab/index-bs5.ts b/services/web/frontend/js/features/bookmarkable-tab/index-bs5.ts new file mode 100644 index 0000000000..51f43925a6 --- /dev/null +++ b/services/web/frontend/js/features/bookmarkable-tab/index-bs5.ts @@ -0,0 +1,30 @@ +import { Tab } from 'bootstrap-5' + +function bookmarkableTab(tabEl: HTMLElement) { + tabEl.addEventListener('click', () => { + window.location.hash = tabEl.getAttribute('href') as string + }) +} + +function handleHashChange() { + const hash = window.location.hash + if (!hash) return + + // Find the bookmarkable tab that links to the hash + const tabEl = document.querySelector( + `[data-ol-bookmarkable-tab][href="${hash}"]` + ) + + if (!tabEl) return + + // Select the tab via Bootstrap 5 + const tab = new Tab(tabEl) + tab.show() +} + +document + .querySelectorAll('[data-ol-bookmarkable-tab]') + .forEach(tabEl => bookmarkableTab(tabEl as HTMLElement)) + +window.addEventListener('hashchange', handleHashChange) +handleHashChange() diff --git a/services/web/frontend/stylesheets/bootstrap-5/abstracts/mixins.scss b/services/web/frontend/stylesheets/bootstrap-5/abstracts/mixins.scss index 5459581931..3a56cd202a 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/abstracts/mixins.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/abstracts/mixins.scss @@ -97,6 +97,6 @@ } } -@mixin focus-style() { +@mixin box-shadow-button-input { box-shadow: 0 0 0 2px var(--blue-30); } diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/all.scss b/services/web/frontend/stylesheets/bootstrap-5/components/all.scss index b00806c5ca..75b20bd3ca 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/components/all.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/components/all.scss @@ -17,3 +17,4 @@ @import 'navbar'; @import 'styled-text'; @import 'table'; +@import 'tabs'; diff --git a/services/web/frontend/stylesheets/bootstrap-5/components/tabs.scss b/services/web/frontend/stylesheets/bootstrap-5/components/tabs.scss new file mode 100644 index 0000000000..c0a39f59d9 --- /dev/null +++ b/services/web/frontend/stylesheets/bootstrap-5/components/tabs.scss @@ -0,0 +1,83 @@ +.ol-tabs { + --border-width-base: 3px; + + .nav-tabs-container { + overflow-x: auto; + display: flex; + flex-direction: column; + + @include media-breakpoint-down(md) { + display: block; + } + + .nav-tabs { + display: inline-flex; + gap: var(--spacing-04); + margin: 0 auto; + padding: 0; + border-bottom: var(--border-width-base) solid var(--neutral-20); + text-align: center; + border-top: 2px solid transparent; // so that top focus border is visible + min-width: max-content; // This is for horizontal scrolling + + li { + display: inline-block; + float: none; + margin-bottom: calc(var(--border-width-base) * -0.6); + + &:last-child { + margin-right: 0; + } + + a { + border: 0; + border-radius: 0; + color: var(--neutral-70); + margin-right: unset; + padding: var(--spacing-04); + line-height: var(--line-height-03); + + &:focus, + &:hover { + border: 0; + } + + &:focus, + &:focus-visible { + background-color: unset; + outline: 0; + } + + &:hover { + background-color: var(--neutral-10); + } + + &:focus-visible { + @include box-shadow-button-input; + } + } + } + + li > a.active { + background-color: transparent !important; + border: 0 !important; + border-bottom: 3px solid var(--green-50) !important; + color: var(--neutral-90) !important; + + &:hover { + border-bottom: 3px solid var(--green-50) !important; + } + } + } + } + + .tab-content { + margin-top: var(--spacing-11); + } +} + +// Scroll the page up a bit to allow tab links to be shown when navigating to +// a bookmarked tab hash +[data-ol-bookmarkable-tabset] .tab-pane { + scroll-margin-top: 120px; +} diff --git a/services/web/frontend/stylesheets/bootstrap-5/pages/website-redesign.scss b/services/web/frontend/stylesheets/bootstrap-5/pages/website-redesign.scss index 6f2f6b584d..813c5410a6 100644 --- a/services/web/frontend/stylesheets/bootstrap-5/pages/website-redesign.scss +++ b/services/web/frontend/stylesheets/bootstrap-5/pages/website-redesign.scss @@ -13,7 +13,7 @@ } &:focus-visible { - @include focus-style; + @include box-shadow-button-input; } // TODO: remove visited?