diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json
index 19c4b99994..b864477107 100644
--- a/.bundlewatch.config.json
+++ b/.bundlewatch.config.json
@@ -26,11 +26,11 @@
},
{
"path": "./dist/css/bootstrap.css",
- "maxSize": "27.75 kB"
+ "maxSize": "28.5 kB"
},
{
"path": "./dist/css/bootstrap.min.css",
- "maxSize": "26.0 kB"
+ "maxSize": "26.5 kB"
},
{
"path": "./dist/js/bootstrap.bundle.js",
diff --git a/js/src/offcanvas.js b/js/src/offcanvas.js
index b5afc0c87b..0ae5dbfdab 100644
--- a/js/src/offcanvas.js
+++ b/js/src/offcanvas.js
@@ -41,6 +41,7 @@ const EVENT_SHOWN = `shown${EVENT_KEY}`
const EVENT_HIDE = `hide${EVENT_KEY}`
const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY}`
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
+const EVENT_RESIZE = `resize${EVENT_KEY}`
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY}`
@@ -263,6 +264,14 @@ EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
}
})
+EventHandler.on(window, EVENT_RESIZE, () => {
+ for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {
+ if (getComputedStyle(element).position !== 'fixed') {
+ Offcanvas.getOrCreateInstance(element).hide()
+ }
+ }
+})
+
enableDismissTrigger(Offcanvas)
/**
diff --git a/js/tests/unit/offcanvas.spec.js b/js/tests/unit/offcanvas.spec.js
index a98a8c13e3..ad0595a866 100644
--- a/js/tests/unit/offcanvas.spec.js
+++ b/js/tests/unit/offcanvas.spec.js
@@ -155,6 +155,28 @@ describe('Offcanvas', () => {
offCanvas.show()
})
})
+
+ it('should call `hide` on resize, if element\'s position is not fixed any more', () => {
+ return new Promise(resolve => {
+ fixtureEl.innerHTML = '
'
+
+ const offCanvasEl = fixtureEl.querySelector('div')
+ const offCanvas = new Offcanvas(offCanvasEl)
+
+ spyOn(offCanvas, 'hide').and.callThrough()
+
+ offCanvasEl.addEventListener('shown.bs.offcanvas', () => {
+ const resizeEvent = createEvent('resize')
+ offCanvasEl.style.removeProperty('position')
+
+ window.dispatchEvent(resizeEvent)
+ expect(offCanvas.hide).toHaveBeenCalled()
+ resolve()
+ })
+
+ offCanvas.show()
+ })
+ })
})
describe('config', () => {
diff --git a/scss/_navbar.scss b/scss/_navbar.scss
index 6db562519c..bd140ae099 100644
--- a/scss/_navbar.scss
+++ b/scss/_navbar.scss
@@ -222,41 +222,31 @@
display: none;
}
- .offcanvas-header {
- display: none;
- }
-
.offcanvas {
- position: inherit;
- bottom: 0;
+ // stylelint-disable declaration-no-important
+ position: static;
z-index: auto;
flex-grow: 1;
- visibility: visible !important; // stylelint-disable-line declaration-no-important
- background-color: transparent;
- border-right: 0;
- border-left: 0;
+ width: auto !important;
+ height: auto !important;
+ visibility: visible !important;
+ background-color: transparent !important;
+ border: 0 !important;
+ transform: none !important;
@include box-shadow(none);
@include transition(none);
- transform: none;
- }
- .offcanvas-top,
- .offcanvas-bottom {
- height: auto;
- border-top: 0;
- border-bottom: 0;
- }
+ // stylelint-enable declaration-no-important
- .offcanvas-body {
- display: flex;
- flex-grow: 0;
- padding: 0;
- overflow-y: visible;
- }
+ .offcanvas-header {
+ display: none;
+ }
- // Reset `background-color` in case `.bg-*` classes are used in offcanvas
- .offcanvas,
- .offcanvas-body {
- background-color: transparent !important; // stylelint-disable-line declaration-no-important
+ .offcanvas-body {
+ display: flex;
+ flex-grow: 0;
+ padding: 0;
+ overflow-y: visible;
+ }
}
}
}
diff --git a/scss/_offcanvas.scss b/scss/_offcanvas.scss
index 5288fa9ce6..e923db2f24 100644
--- a/scss/_offcanvas.scss
+++ b/scss/_offcanvas.scss
@@ -1,27 +1,115 @@
-.offcanvas {
- position: fixed;
- bottom: 0;
- z-index: $zindex-offcanvas;
- display: flex;
- flex-direction: column;
- max-width: 100%;
- color: $offcanvas-color;
- visibility: hidden;
- background-color: $offcanvas-bg-color;
- background-clip: padding-box;
- outline: 0;
- @include box-shadow($offcanvas-box-shadow);
- @include transition(transform $offcanvas-transition-duration ease-in-out);
+// stylelint-disable function-disallowed-list
- &.showing,
- &.show:not(.hiding) {
- transform: none;
+%offcanvas-css-vars {
+ // scss-docs-start offcanvas-css-vars
+ --#{$prefix}offcanvas-width: #{$offcanvas-horizontal-width};
+ --#{$prefix}offcanvas-height: #{$offcanvas-vertical-height};
+ --#{$prefix}offcanvas-padding-x: #{$offcanvas-padding-x};
+ --#{$prefix}offcanvas-padding-y: #{$offcanvas-padding-y};
+ --#{$prefix}offcanvas-color: #{$offcanvas-color};
+ --#{$prefix}offcanvas-bg: #{$offcanvas-bg-color};
+ --#{$prefix}offcanvas-border-width: #{$offcanvas-border-width};
+ --#{$prefix}offcanvas-border-color: #{$offcanvas-border-color};
+ --#{$prefix}offcanvas-box-shadow: #{$offcanvas-box-shadow};
+ // scss-docs-end offcanvas-css-vars
+}
+
+@each $breakpoint in map-keys($grid-breakpoints) {
+ $next: breakpoint-next($breakpoint, $grid-breakpoints);
+ $infix: breakpoint-infix($next, $grid-breakpoints);
+
+ .offcanvas#{$infix} {
+ @extend %offcanvas-css-vars;
}
+}
- &.showing,
- &.hiding,
- &.show {
- visibility: visible;
+@each $breakpoint in map-keys($grid-breakpoints) {
+ $next: breakpoint-next($breakpoint, $grid-breakpoints);
+ $infix: breakpoint-infix($next, $grid-breakpoints);
+
+ .offcanvas#{$infix} {
+ @include media-breakpoint-down($next) {
+ position: fixed;
+ bottom: 0;
+ z-index: $zindex-offcanvas;
+ display: flex;
+ flex-direction: column;
+ max-width: 100%;
+ color: var(--#{$prefix}offcanvas-color);
+ visibility: hidden;
+ background-color: var(--#{$prefix}offcanvas-bg);
+ background-clip: padding-box;
+ outline: 0;
+ @include box-shadow(var(--#{$prefix}offcanvas-box-shadow));
+ @include transition(transform $offcanvas-transition-duration ease-in-out);
+
+ &.showing,
+ &.show:not(.hiding) {
+ transform: none;
+ }
+
+ &.showing,
+ &.hiding,
+ &.show {
+ visibility: visible;
+ }
+
+ &.offcanvas-start {
+ top: 0;
+ left: 0;
+ width: var(--#{$prefix}offcanvas-width);
+ border-right: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateX(-100%);
+ }
+
+ &.offcanvas-end {
+ top: 0;
+ right: 0;
+ width: var(--#{$prefix}offcanvas-width);
+ border-left: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateX(100%);
+ }
+
+ &.offcanvas-top {
+ top: 0;
+ right: 0;
+ left: 0;
+ height: var(--#{$prefix}offcanvas-height);
+ max-height: 100%;
+ border-bottom: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateY(-100%);
+ }
+
+ &.offcanvas-bottom {
+ right: 0;
+ left: 0;
+ height: var(--#{$prefix}offcanvas-height);
+ max-height: 100%;
+ border-top: var(--#{$prefix}offcanvas-border-width) solid var(--#{$prefix}offcanvas-border-color);
+ transform: translateY(100%);
+ }
+ }
+
+ @if not ($infix == "") {
+ @include media-breakpoint-up($next) {
+ --#{$prefix}offcanvas-height: auto;
+ --#{$prefix}offcanvas-border-width: 0;
+ background-color: transparent !important; // stylelint-disable-line declaration-no-important
+
+ .offcanvas-header {
+ display: none;
+ }
+
+ .offcanvas-body {
+ display: flex;
+ flex-grow: 0;
+ padding: 0;
+ overflow-y: visible;
+ // Reset `background-color` in case `.bg-*` classes are used in offcanvas
+ background-color: transparent !important; // stylelint-disable-line declaration-no-important
+ }
+ }
+ }
}
}
@@ -33,13 +121,13 @@
display: flex;
align-items: center;
justify-content: space-between;
- padding: $offcanvas-padding-y $offcanvas-padding-x;
+ padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
.btn-close {
- padding: ($offcanvas-padding-y * .5) ($offcanvas-padding-x * .5);
- margin-top: $offcanvas-padding-y * -.5;
- margin-right: $offcanvas-padding-x * -.5;
- margin-bottom: $offcanvas-padding-y * -.5;
+ padding: calc(var(--#{$prefix}offcanvas-padding-y) * .5) calc(var(--#{$prefix}offcanvas-padding-x) * .5);
+ margin-top: calc(var(--#{$prefix}offcanvas-padding-y) * -.5);
+ margin-right: calc(var(--#{$prefix}offcanvas-padding-x) * -.5);
+ margin-bottom: calc(var(--#{$prefix}offcanvas-padding-y) * -.5);
}
}
@@ -50,41 +138,6 @@
.offcanvas-body {
flex-grow: 1;
- padding: $offcanvas-padding-y $offcanvas-padding-x;
+ padding: var(--#{$prefix}offcanvas-padding-y) var(--#{$prefix}offcanvas-padding-x);
overflow-y: auto;
}
-
-.offcanvas-start {
- top: 0;
- left: 0;
- width: $offcanvas-horizontal-width;
- border-right: $offcanvas-border-width solid $offcanvas-border-color;
- transform: translateX(-100%);
-}
-
-.offcanvas-end {
- top: 0;
- right: 0;
- width: $offcanvas-horizontal-width;
- border-left: $offcanvas-border-width solid $offcanvas-border-color;
- transform: translateX(100%);
-}
-
-.offcanvas-top {
- top: 0;
- right: 0;
- left: 0;
- height: $offcanvas-vertical-height;
- max-height: 100%;
- border-bottom: $offcanvas-border-width solid $offcanvas-border-color;
- transform: translateY(-100%);
-}
-
-.offcanvas-bottom {
- right: 0;
- left: 0;
- height: $offcanvas-vertical-height;
- max-height: 100%;
- border-top: $offcanvas-border-width solid $offcanvas-border-color;
- transform: translateY(100%);
-}
diff --git a/scss/_spinners.scss b/scss/_spinners.scss
index 2fc7d3edc5..ec8473207e 100644
--- a/scss/_spinners.scss
+++ b/scss/_spinners.scss
@@ -29,7 +29,7 @@
--#{$prefix}spinner-animation-name: spinner-border;
// scss-docs-end spinner-border-css-vars
- border: var(--#{$prefix}spinner-border-width) solid currentColor;
+ border: var(--#{$prefix}spinner-border-width) solid currentcolor;
border-right-color: transparent;
}
diff --git a/site/assets/js/application.js b/site/assets/js/application.js
index c14dc57c22..55e8969802 100644
--- a/site/assets/js/application.js
+++ b/site/assets/js/application.js
@@ -10,11 +10,26 @@
* For details, see https://creativecommons.org/licenses/by/3.0/.
*/
-/* global ClipboardJS: false, bootstrap: false */
+/* global bootstrap: false */
(() => {
'use strict'
+ // Scroll the active sidebar link into view
+ const sidenav = document.querySelector('.bd-sidebar')
+ if (sidenav) {
+ const sidenavHeight = sidenav.clientHeight
+ const sidenavActiveLink = document.querySelector('.bd-links-nav .active')
+ const sidenavActiveLinkTop = sidenavActiveLink.offsetTop
+ const sidenavActiveLinkHeight = sidenavActiveLink.clientHeight
+ const viewportTop = sidenavActiveLinkTop
+ const viewportBottom = viewportTop - sidenavHeight + sidenavActiveLinkHeight
+
+ if (sidenav.scrollTop > viewportTop || sidenav.scrollTop < viewportBottom) {
+ sidenav.scrollTop = viewportTop - (sidenavHeight / 2) + (sidenavActiveLinkHeight / 2)
+ }
+ }
+
// Tooltip and popover demos
document.querySelectorAll('.tooltip-demo')
.forEach(tooltip => {
@@ -116,61 +131,4 @@
modalBodyInput.value = recipient
})
}
-
- // Insert copy to clipboard button before .highlight
- const btnTitle = 'Copy to clipboard'
- const btnEdit = 'Edit on StackBlitz'
- const btnHtml = 'Copy
'
- document.querySelectorAll('div.highlight')
- .forEach(element => {
- element.insertAdjacentHTML('beforebegin', btnHtml)
- })
-
- /**
- *
- * @param {string} selector
- * @param {string} title
- */
- function snippetButtonTooltip(selector, title) {
- document.querySelectorAll(selector).forEach(btn => {
- const tooltipBtn = new bootstrap.Tooltip(btn, { title })
-
- btn.addEventListener('mouseleave', () => {
- // Explicitly hide tooltip, since after clicking it remains
- // focused (as it's a button), so tooltip would otherwise
- // remain visible until focus is moved away
- tooltipBtn.hide()
- })
- })
- }
-
- snippetButtonTooltip('.btn-clipboard', btnTitle)
- snippetButtonTooltip('.btn-edit', btnEdit)
-
- const clipboard = new ClipboardJS('.btn-clipboard', {
- target(trigger) {
- return trigger.parentNode.nextElementSibling
- }
- })
-
- clipboard.on('success', event => {
- const tooltipBtn = bootstrap.Tooltip.getInstance(event.trigger)
-
- tooltipBtn.setContent({ '.tooltip-inner': 'Copied!' })
- event.trigger.addEventListener('hidden.bs.tooltip', () => {
- tooltipBtn.setContent({ '.tooltip-inner': btnTitle })
- }, { once: true })
- event.clearSelection()
- })
-
- clipboard.on('error', event => {
- const modifierKey = /mac/i.test(navigator.userAgent) ? '\u2318' : 'Ctrl-'
- const fallbackMsg = `Press ${modifierKey}C to copy`
- const tooltipBtn = bootstrap.Tooltip.getInstance(event.trigger)
-
- tooltipBtn.setContent({ '.tooltip-inner': fallbackMsg })
- event.trigger.addEventListener('hidden.bs.tooltip', () => {
- tooltipBtn.setContent({ '.tooltip-inner': btnTitle })
- }, { once: true })
- })
})()
diff --git a/site/assets/js/code-examples.js b/site/assets/js/code-examples.js
new file mode 100644
index 0000000000..4a61fa09b7
--- /dev/null
+++ b/site/assets/js/code-examples.js
@@ -0,0 +1,88 @@
+// NOTICE!! DO NOT USE ANY OF THIS JAVASCRIPT
+// IT'S ALL JUST JUNK FOR OUR DOCS!
+// ++++++++++++++++++++++++++++++++++++++++++
+
+/*!
+ * JavaScript for Bootstrap's docs (https://getbootstrap.com/)
+ * Copyright 2011-2022 The Bootstrap Authors
+ * Copyright 2011-2022 Twitter, Inc.
+ * Licensed under the Creative Commons Attribution 3.0 Unported License.
+ * For details, see https://creativecommons.org/licenses/by/3.0/.
+ */
+
+/* global ClipboardJS: false, bootstrap: false */
+
+(() => {
+ 'use strict'
+ // Insert copy to clipboard button before .highlight
+ const btnTitle = 'Copy to clipboard'
+ const btnEdit = 'Edit on StackBlitz'
+
+ const btnHtml = [
+ '',
+ '
',
+ ' ',
+ ' ',
+ ' ',
+ '
',
+ '
'
+ ].join('')
+
+ // wrap programmatically code blocks and add copy btn.
+ document.querySelectorAll('.highlight')
+ .forEach(element => {
+ if (!element.closest('.bd-example-snippet')) { // Ignore examples made be shortcode
+ element.insertAdjacentHTML('beforebegin', btnHtml)
+ element.previousElementSibling.append(element)
+ }
+ })
+
+ /**
+ *
+ * @param {string} selector
+ * @param {string} title
+ */
+ function snippetButtonTooltip(selector, title) {
+ document.querySelectorAll(selector).forEach(btn => {
+ bootstrap.Tooltip.getOrCreateInstance(btn, { title })
+ })
+ }
+
+ snippetButtonTooltip('.btn-clipboard', btnTitle)
+ snippetButtonTooltip('.btn-edit', btnEdit)
+
+ const clipboard = new ClipboardJS('.btn-clipboard', {
+ target: trigger => trigger.closest('.bd-code-snippet').querySelector('.highlight')
+ })
+
+ clipboard.on('success', event => {
+ const iconFirstChild = event.trigger.querySelector('.bi').firstChild
+ const tooltipBtn = bootstrap.Tooltip.getInstance(event.trigger)
+ const namespace = 'http://www.w3.org/1999/xlink'
+ const originalXhref = iconFirstChild.getAttributeNS(namespace, 'href')
+ const originalTitle = event.trigger.title
+
+ tooltipBtn.setContent({ '.tooltip-inner': 'Copied!' })
+ event.trigger.addEventListener('hidden.bs.tooltip', () => {
+ tooltipBtn.setContent({ '.tooltip-inner': btnTitle })
+ }, { once: true })
+ event.clearSelection()
+ iconFirstChild.setAttributeNS(namespace, 'href', originalXhref.replace('clipboard', 'check2'))
+
+ setTimeout(() => {
+ iconFirstChild.setAttributeNS(namespace, 'href', originalXhref)
+ event.trigger.title = originalTitle
+ }, 2000)
+ })
+
+ clipboard.on('error', event => {
+ const modifierKey = /mac/i.test(navigator.userAgent) ? '\u2318' : 'Ctrl-'
+ const fallbackMsg = `Press ${modifierKey}C to copy`
+ const tooltipBtn = bootstrap.Tooltip.getInstance(event.trigger)
+
+ tooltipBtn.setContent({ '.tooltip-inner': fallbackMsg })
+ event.trigger.addEventListener('hidden.bs.tooltip', () => {
+ tooltipBtn.setContent({ '.tooltip-inner': btnTitle })
+ }, { once: true })
+ })
+})()
diff --git a/site/assets/js/search.js b/site/assets/js/search.js
index 15197bfd9a..6c90a20872 100644
--- a/site/assets/js/search.js
+++ b/site/assets/js/search.js
@@ -14,12 +14,17 @@
const siteDocsVersion = inputElement.getAttribute('data-bd-docs-version')
document.addEventListener('keydown', event => {
- if (event.ctrlKey && event.key === '/') {
+ if ((((event.ctrlKey || event.metaKey) && event.key === 'k')) || (event.ctrlKey && event.key === '/')) {
event.preventDefault()
inputElement.focus()
}
})
+ if (navigator.platform.includes('Win') || navigator.platform.includes('Linux')) {
+ const searchShortcut = document.querySelector('.bd-search')
+ searchShortcut.setAttribute('data-shortcut', '⌃K')
+ }
+
window.docsearch({
apiKey: '5990ad008512000bba2cf951ccf0332f',
indexName: 'bootstrap',
diff --git a/site/assets/scss/_ads.scss b/site/assets/scss/_ads.scss
index 026d1a17a7..b9369eb19c 100644
--- a/site/assets/scss/_ads.scss
+++ b/site/assets/scss/_ads.scss
@@ -14,7 +14,7 @@
@include font-size(.8125rem);
line-height: 1.4;
text-align: left;
- background-color: rgba(0, 0, 0, .05);
+ background-color: $gray-100;
a {
color: $gray-800;
@@ -22,8 +22,7 @@
}
@include media-breakpoint-up(sm) {
- max-width: 330px;
- @include border-radius(4px);
+ @include border-radius(.5rem);
}
}
diff --git a/site/assets/scss/_algolia.scss b/site/assets/scss/_algolia.scss
index 9c457d2e37..ab22ad9a7e 100644
--- a/site/assets/scss/_algolia.scss
+++ b/site/assets/scss/_algolia.scss
@@ -12,12 +12,15 @@
margin: $dropdown-spacer 0 0;
@include font-size(.875rem);
background-color: $dropdown-bg;
+ background-clip: padding-box;
border: $dropdown-border-width solid $dropdown-border-color;
@include border-radius($dropdown-border-radius);
- @include box-shadow($dropdown-box-shadow);
+ box-shadow: $dropdown-box-shadow;
@include media-breakpoint-up(md) {
- width: 400px;
+ width: 500px;
+ margin-top: .5rem;
+ margin-left: -110px;
}
}
diff --git a/site/assets/scss/_buttons.scss b/site/assets/scss/_buttons.scss
index 93ffa83ed5..13bd6e48a3 100644
--- a/site/assets/scss/_buttons.scss
+++ b/site/assets/scss/_buttons.scss
@@ -8,10 +8,14 @@
--bs-btn-color: var(--bs-white);
--bs-btn-bg: var(--bd-violet);
--bs-btn-border-color: var(--bd-violet);
+ --bs-btn-border-radius: .5rem;
--bs-btn-hover-color: var(--bs-white);
- --bs-btn-hover-bg: #{shade-color($bd-violet, 20%)};
- --bs-btn-hover-border-color: #{shade-color($bd-violet, 20%)};
+ --bs-btn-hover-bg: #{shade-color($bd-violet, 10%)};
+ --bs-btn-hover-border-color: #{shade-color($bd-violet, 10%)};
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
+ --bs-btn-active-color: var(--bs-btn-hover-color);
+ --bs-btn-active-bg: #{shade-color($bd-violet, 20%)};
+ --bs-btn-active-border-color: #{shade-color($bd-violet, 20%)};
}
// scss-docs-end btn-css-vars-example
@@ -23,13 +27,19 @@
--bs-btn-hover-bg: var(--bd-accent);
--bs-btn-hover-border-color: var(--bd-accent);
--bs-btn-focus-shadow-rgb: var(--bd-accent-rgb);
+ --bs-btn-active-color: var(--bs-btn-hover-color);
+ --bs-btn-active-bg: var(--bs-btn-hover-bg);
+ --bs-btn-active-border-color: var(--bs-btn-hover-border-color);
}
.btn-bd-light {
--bs-btn-color: var(--bs-gray-600);
- --bs-btn-border-color: var(--bs-gray-300);
+ --bs-btn-border-color: var(--bs-gray-400);
+ --bs-btn-hover-color: var(--bd-violet);
+ --bs-btn-hover-border-color: var(--bd-violet);
--bs-btn-active-color: var(--bd-violet);
--bs-btn-active-bg: var(--bs-white);
--bs-btn-active-border-color: var(--bd-violet);
+ --bs-btn-focus-border-color: var(--bd-violet);
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
}
diff --git a/site/assets/scss/_callouts.scss b/site/assets/scss/_callouts.scss
index aff91f18b6..4513a7d1d5 100644
--- a/site/assets/scss/_callouts.scss
+++ b/site/assets/scss/_callouts.scss
@@ -6,36 +6,30 @@
padding: 1.25rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
- border: 1px solid $gray-200;
- border-left-width: .25rem;
- @include border-radius();
+ background-color: var(--bd-callout-bg, var(--bs-gray-100));
+ border-left: .25rem solid var(--bd-callout-border, var(--bs-gray-300));
h4 {
margin-bottom: .25rem;
}
- p:last-child {
+ > :last-child {
margin-bottom: 0;
}
- code {
- @include border-radius();
- }
-
+ .bd-callout {
margin-top: -.25rem;
}
+
+ .highlight {
+ background-color: rgba($black, .05);
+ }
}
// Variations
-.bd-callout-info {
- border-left-color: $bd-info;
-}
-
-.bd-callout-warning {
- border-left-color: $bd-warning;
-}
-
-.bd-callout-danger {
- border-left-color: $bd-danger;
+@each $variant in $bd-callout-variants {
+ .bd-callout-#{$variant} {
+ --bd-callout-bg: rgba(var(--bs-#{$variant}-rgb), .075);
+ --bd-callout-border: rgba(var(--bs-#{$variant}-rgb), .5);
+ }
}
diff --git a/site/assets/scss/_clipboard-js.scss b/site/assets/scss/_clipboard-js.scss
index b2b0854dc4..7acf90f0b7 100644
--- a/site/assets/scss/_clipboard-js.scss
+++ b/site/assets/scss/_clipboard-js.scss
@@ -19,26 +19,29 @@
.btn-clipboard,
.btn-edit {
- position: absolute;
- top: .65rem;
- right: .65rem;
- z-index: 10;
display: block;
- padding: .25rem .5rem;
- @include font-size(.65em);
- color: $primary;
- white-space: nowrap;
- background-color: $white;
- border: 1px solid;
- @include border-radius();
+ padding: .5em;
+ line-height: 1;
+ color: $gray-900;
+ background-color: $gray-100;
+ border: 0;
+ @include border-radius(.25rem);
- &:hover,
- &:focus {
- color: $white;
- background-color: $primary;
+ &:hover {
+ color: $primary;
}
}
-.btn-edit {
- right: 3.65rem;
+.btn-clipboard {
+ position: relative;
+ z-index: 2;
+ margin-top: .75rem;
+ margin-right: .75rem;
+}
+
+.highlight-toolbar {
+ .btn-clipboard {
+ margin-top: 0;
+ margin-right: 0;
+ }
}
diff --git a/site/assets/scss/_component-examples.scss b/site/assets/scss/_component-examples.scss
index 330bd43bac..b305f088f9 100644
--- a/site/assets/scss/_component-examples.scss
+++ b/site/assets/scss/_component-examples.scss
@@ -85,21 +85,17 @@
.bd-example {
position: relative;
padding: 1rem;
- margin: 1rem ($bd-gutter-x * -1) 0;
- border: solid $gray-300;
+ margin: 1rem ($bd-gutter-x * -.5) 0;
+ border: solid $border-color;
border-width: 1px 0 0;
@include clearfix();
- @include media-breakpoint-up(sm) {
+ @include media-breakpoint-up(md) {
padding: 1.5rem;
margin-right: 0;
margin-left: 0;
border-width: 1px;
- @include border-top-radius(.25rem);
-
- + .bd-clipboard + .highlight {
- @include border-bottom-radius(.25rem);
- }
+ @include border-top-radius(var(--bs-border-radius));
}
+ p {
@@ -348,12 +344,14 @@
//
.highlight {
- padding: var(--bs-gutter-x) $bd-gutter-x;
+ position: relative;
+ padding: .75rem ($bd-gutter-x * .5);
margin-bottom: 1rem;
background-color: var(--bs-gray-100);
- @include media-breakpoint-up(sm) {
- padding: 1rem 1.5rem;
+ @include media-breakpoint-up(md) {
+ padding: .75rem 1.25rem;
+ @include border-radius(var(--bs-border-radius));
}
pre {
@@ -363,6 +361,11 @@
white-space: pre;
background-color: transparent;
border: 0;
+
+ // Undo tabindex that's automatically added by Hugo
+ &:focus {
+ outline: 0;
+ }
}
pre code {
@@ -372,11 +375,22 @@
}
}
-.bd-content .highlight {
- margin-right: $bd-gutter-x * -1;
- margin-left: $bd-gutter-x * -1;
+.bd-example-snippet {
+ .highlight {
+ @include border-top-radius(0);
+ border: 1px solid $border-color;
+ }
+ .highlight-toolbar {
+ border: solid $border-color;
+ border-width: 0 1px;
+ }
+}
- @include media-breakpoint-up(sm) {
+.bd-content .highlight {
+ margin-right: $bd-gutter-x * -.5;
+ margin-left: $bd-gutter-x * -.5;
+
+ @include media-breakpoint-up(md) {
margin-right: 0;
margin-left: 0;
}
diff --git a/site/assets/scss/_content.scss b/site/assets/scss/_content.scss
index d796c491e0..cd594335a6 100644
--- a/site/assets/scss/_content.scss
+++ b/site/assets/scss/_content.scss
@@ -2,14 +2,13 @@
// Bootstrap docs content theming
//
-// Offset for the sticky header
-@include media-breakpoint-up(md) {
- :root {
- scroll-padding-top: 4rem;
- }
-}
-
.bd-content {
+ // Offset content from fixed navbar when jumping to headings
+ > :target {
+ padding-top: 5rem;
+ margin-top: -5rem;
+ }
+
> h2:not(:first-child) {
margin-top: 3rem;
}
@@ -46,6 +45,10 @@
border-bottom: 2px solid currentcolor;
}
+ tbody:not(:first-child) {
+ border-top: 2px solid currentcolor;
+ }
+
th,
td {
&:first-child {
@@ -59,12 +62,24 @@
// Prevent breaking of code
// stylelint-disable-next-line selector-max-compound-selectors
+ th,
td:first-child > code {
white-space: nowrap;
}
}
}
+.table-options {
+ td:nth-child(2) {
+ min-width: 160px;
+ }
+}
+
+.table-options td:last-child,
+.table-utilities td:last-child {
+ min-width: 280px;
+}
+
.bd-title {
@include font-size(3rem);
}
@@ -77,3 +92,35 @@
.bd-bg-violet {
background-color: $bd-violet;
}
+
+.bi {
+ width: 1em;
+ height: 1em;
+ fill: currentcolor;
+}
+
+.icon-link {
+ display: flex;
+ align-items: center;
+ text-decoration-color: rgba($primary, .5);
+ text-underline-offset: .5rem;
+ backface-visibility: hidden;
+
+ .bi {
+ width: 1.5em;
+ height: 1.5em;
+ transition: .2s ease-in-out transform; // stylelint-disable-line property-disallowed-list
+ }
+
+ &:hover {
+ .bi {
+ transform: translate3d(5px, 0, 0);
+ }
+ }
+}
+
+.border-lg-start {
+ @include media-breakpoint-up(lg) {
+ border-left: $border-width solid $border-color;
+ }
+}
diff --git a/site/assets/scss/_layout.scss b/site/assets/scss/_layout.scss
index f83cf094c9..d0482d9b71 100644
--- a/site/assets/scss/_layout.scss
+++ b/site/assets/scss/_layout.scss
@@ -1,16 +1,14 @@
-.bd-layout {
- padding-right: $bd-gutter-x;
- padding-left: $bd-gutter-x;
+.bd-gutter {
+ --bs-gutter-x: #{$bd-gutter-x};
+}
- @include media-breakpoint-up(md) {
- display: grid;
- grid-template-areas: "sidebar main";
- grid-template-columns: 1fr 3fr;
- gap: $grid-gutter-width;
- }
+.bd-layout {
@include media-breakpoint-up(lg) {
+ display: grid;
+ grid-template-areas: "sidebar main";
grid-template-columns: 1fr 5fr;
+ gap: $grid-gutter-width;
}
}
@@ -21,6 +19,11 @@
.bd-main {
grid-area: main;
+ @include media-breakpoint-down(lg) {
+ max-width: 760px;
+ margin-inline: auto;
+ }
+
@include media-breakpoint-up(md) {
display: grid;
grid-template-areas:
diff --git a/site/assets/scss/_masthead.scss b/site/assets/scss/_masthead.scss
index 2e742e76d1..42ad0f3853 100644
--- a/site/assets/scss/_masthead.scss
+++ b/site/assets/scss/_masthead.scss
@@ -1,38 +1,87 @@
.bd-masthead {
+ --bd-pink-rgb: #{to-rgb($pink)};
padding: 3rem 0;
- background: linear-gradient(165deg, tint-color($bd-purple-light, 85%) 50%, $white 50%);
+ // stylelint-disable
+ background-image: linear-gradient(180deg, rgba(var(--bs-body-bg-rgb), .01), rgba(var(--bs-body-bg-rgb), 1) 85%),
+ radial-gradient(ellipse at top left, rgba(var(--bs-primary-rgb), .5), transparent 50%),
+ radial-gradient(ellipse at top right, rgba(var(--bd-accent-rgb), .5), transparent 50%),
+ radial-gradient(ellipse at center right, rgba(var(--bd-violet-rgb), .5), transparent 50%),
+ radial-gradient(ellipse at center left, rgba(var(--bd-pink-rgb), .5), transparent 50%);
+ // stylelint-enable
h1 {
@include font-size(4rem);
line-height: 1;
}
- p:not(.lead) {
- color: $gray-700;
- }
-
- .btn {
- padding: .8rem 2rem;
- font-weight: 600;
- }
.lead {
- @include font-size(1.5rem);
+ @include font-size(1rem);
font-weight: 400;
color: $gray-700;
}
+
+ .highlight {
+ padding: .5rem 4rem .5rem 1rem;
+ margin-bottom: 0;
+ line-height: 1.25;
+ background-color: rgba(var(--bs-body-color-rgb), .075);
+ @include border-radius(.5rem);
+ }
+ .btn-clipboard {
+ margin-top: .4rem;
+ background-color: transparent;
+ }
+
+ #carbonads { // stylelint-disable-line selector-max-id
+ margin-right: auto;
+ margin-left: auto;
+ }
+
+ @include media-breakpoint-up(md) {
+ .lead {
+ @include font-size(1.5rem);
+ }
+ }
}
-@include media-breakpoint-up(md) {
- .mw-md-75 { max-width: 75%; }
+.masthead-followup {
+ .lead {
+ @include font-size(1rem);
+ }
+
+ .highlight {
+ @include border-radius(.5rem);
+ }
+
+ @include media-breakpoint-up(md) {
+ .lead {
+ @include font-size(1.25rem);
+ }
+ }
+}
+
+.bd-btn-lg {
+ padding: .8rem 2rem;
}
.masthead-followup-icon {
- padding: .75rem;
- background-image: linear-gradient(to bottom right, rgba(255, 255, 255, .2), rgba(255, 255, 255, .01));
- @include border-radius(.75rem);
- box-shadow: 0 .125rem .25rem rgba(0, 0, 0, .1);
+ padding: 1rem;
+ color: rgba(var(--bg-rgb), 1);
+ background-color: rgba(var(--bg-rgb), .1);
+ background-blend-mode: multiple;
+ @include border-radius(1rem);
+ mix-blend-mode: darken;
+
+ svg {
+ filter: drop-shadow(0 1px 1px #fff);
+ }
}
.masthead-followup-svg {
filter: drop-shadow(0 1px 0 rgba(0, 0, 0, .125));
}
+
+.masthead-notice {
+ background-color: var(--bd-accent);
+ box-shadow: inset 0 -1px 1px rgba(var(--bs-body-color-rgb), .15), 0 .25rem 1.5rem rgba(var(--bs-body-bg-rgb), .75);
+}
diff --git a/site/assets/scss/_navbar.scss b/site/assets/scss/_navbar.scss
index 401731ae19..4f9f3f8290 100644
--- a/site/assets/scss/_navbar.scss
+++ b/site/assets/scss/_navbar.scss
@@ -1,44 +1,85 @@
.bd-navbar {
- --bs-gutter-x: $bd-gutter-x;
- --bs-gutter-y: $bd-gutter-x;
-
padding: .75rem 0;
- background-color: $bd-violet;
+ background-color: transparent;
+ background-image: linear-gradient(to bottom, rgba(var(--bd-violet-rgb), 1), rgba(var(--bd-violet-rgb), .95));
+ box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .15), inset 0 -1px 0 rgba(0, 0, 0, .15);
.navbar-toggler {
padding: 0;
+ margin-right: -.5rem;
border: 0;
+
+ &:first-child {
+ margin-left: -.5rem;
+ }
+
+ .bi {
+ width: 1.5rem;
+ height: 1.5rem;
+ }
+
+ &:focus {
+ box-shadow: none;
+ }
}
- .navbar-nav {
- .nav-link {
- padding-right: $spacer * .25;
- padding-left: $spacer * .25;
- color: rgba($white, .85);
+ .navbar-brand {
+ transition: .2s ease-in-out transform; // stylelint-disable-line property-disallowed-list
- &:hover,
- &:focus {
- color: $white;
- }
+ &:hover {
+ transform: rotate(-5deg) scale(1.1);
+ }
+ }
- &.active {
- font-weight: 600;
- color: $white;
- }
+ .navbar-toggler,
+ .nav-link {
+ padding-right: $spacer * .25;
+ padding-left: $spacer * .25;
+ color: rgba($white, .85);
+
+ &:hover,
+ &:focus {
+ color: $white;
+ }
+
+ &.active {
+ font-weight: 600;
+ color: $white;
}
}
.navbar-nav-svg {
- width: 1rem;
- height: 1rem;
+ display: inline-block;
+ vertical-align: -.125rem;
}
- .offcanvas {
- background-color: $bd-violet;
+ .offcanvas-lg {
+ background-color: var(--bd-violet);
border-left: 0;
- @include media-breakpoint-down(md) {
+ @include media-breakpoint-down(lg) {
box-shadow: $box-shadow-lg;
}
}
+
+ .dropdown-toggle {
+ &:focus {
+ outline: 0;
+ }
+ }
+
+ .dropdown-menu {
+ --#{$variable-prefix}dropdown-min-width: 12rem;
+ --#{$variable-prefix}dropdown-link-hover-bg: rgba(var(--bd-violet-rgb), .1);
+ @include rfs(.875rem, --#{$variable-prefix}dropdown-font-size);
+ box-shadow: $dropdown-box-shadow;
+ }
+
+ .dropdown-item.current {
+ font-weight: 600;
+ background-image: escape-svg($dropdown-active-icon);
+ background-repeat: no-repeat;
+ background-position: right $dropdown-item-padding-x top .6rem;
+ background-size: .75rem .75rem;
+ }
}
diff --git a/site/assets/scss/_search.scss b/site/assets/scss/_search.scss
new file mode 100644
index 0000000000..1825337a00
--- /dev/null
+++ b/site/assets/scss/_search.scss
@@ -0,0 +1,62 @@
+.bd-search {
+ position: relative;
+ width: 100%;
+
+ &::after {
+ position: absolute;
+ top: .4rem;
+ right: .4rem;
+ bottom: .4rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-right: .3125rem;
+ padding-left: .3125rem;
+ @include font-size(.75rem);
+ color: rgba($white, .65);
+ // content: "⌘K";
+ content: attr(data-shortcut);
+ background-color: rgba($white, .1);
+ @include border-radius(.125rem);
+ }
+
+ @include media-breakpoint-up(lg) {
+ position: absolute;
+ top: .75rem;
+ left: 50%;
+ width: 200px;
+ margin-left: -100px;
+ }
+
+ @include media-breakpoint-up(xl) {
+ width: 280px;
+ margin-left: -140px;
+ }
+
+ .form-control {
+ padding-right: 2.75rem;
+ color: $white;
+ background-color: rgba($black, .1);
+ border-color: rgba($white, .4);
+ transition-property: background-color, border-color, box-shadow;
+
+ &::placeholder {
+ color: rgba($white, .65);
+ }
+
+ &::-webkit-search-cancel-button {
+ appearance: none;
+ width: 1rem;
+ height: 1rem;
+ cursor: pointer;
+ background: escape-svg($search-clear-icon) no-repeat 0 0;
+ background-size: 100% 100%;
+ }
+
+ &:focus {
+ background-color: rgba($black, .25);
+ border-color: rgba($bd-accent, 1);
+ box-shadow: 0 0 0 .25rem rgba($bd-accent, .4);
+ }
+ }
+}
diff --git a/site/assets/scss/_sidebar.scss b/site/assets/scss/_sidebar.scss
index 452b155ffa..ed76b3ca82 100644
--- a/site/assets/scss/_sidebar.scss
+++ b/site/assets/scss/_sidebar.scss
@@ -1,87 +1,53 @@
.bd-sidebar {
- @include media-breakpoint-down(md) {
- margin: 0 ($bd-gutter-x * -1) 1rem;
- }
-}
-
-.bd-links {
- overflow: auto;
- font-weight: 600;
-
- @include media-breakpoint-up(md) {
+ @include media-breakpoint-up(lg) {
position: sticky;
top: 5rem;
// Override collapse behaviors
// stylelint-disable-next-line declaration-no-important
display: block !important;
- height: subtract(100vh, 7rem);
+ height: subtract(100vh, 6rem);
// Prevent focus styles to be cut off:
padding-left: .25rem;
margin-left: -.25rem;
overflow-y: auto;
}
+}
- > ul {
- @include media-breakpoint-down(md) {
- padding: 1.5rem .75rem;
- background-color: $gray-100;
- border-bottom: 1px solid $gray-200;
- }
+.bd-links-nav {
+ @include media-breakpoint-down(lg) {
+ font-size: .875rem;
}
- a {
- padding: .1875rem .5rem;
- margin-top: .125rem;
- margin-left: 1.25rem;
- color: rgba($black, .65);
- text-decoration: if($link-decoration == none, null, none);
+ @include media-breakpoint-between(xs, lg) {
+ column-count: 2;
+ column-gap: 1.5rem;
- &:hover,
- &:focus {
- color: rgba($black, .85);
- text-decoration: if($link-hover-decoration == underline, none, null);
- background-color: rgba($bd-violet, .1);
- }
- }
-
- .btn {
- // Custom styles (as we don't have a completely neutral button style)
- padding: .25rem .5rem;
- font-weight: 600;
- color: rgba($black, .65);
- background-color: transparent;
- border: 0;
-
- &:hover,
- &:focus {
- color: rgba($black, .85);
- background-color: rgba($bd-violet, .1);
+ .bd-links-group {
+ break-inside: avoid;
}
- &:focus {
- box-shadow: 0 0 0 1px rgba($bd-violet, .7);
+ .bd-links-span-all {
+ column-span: all;
}
-
- // Add chevron if there's a submenu
- &::before {
- width: 1.25em;
- line-height: 0; // Align in the middle
- content: escape-svg($sidebar-collapse-icon);
- @include transition(transform .35s ease);
- transform-origin: .5em 50%;
- }
-
- &[aria-expanded="true"] {
- color: rgba($black, .85);
-
- &::before {
- transform: rotate(90deg);
- }
- }
- }
-
- .active {
- font-weight: 600;
- color: rgba($black, .85);
+ }
+}
+
+.bd-links-link {
+ padding: .1875rem .5rem;
+ margin-top: .125rem;
+ margin-left: 1rem;
+ color: rgba($black, .65);
+ text-decoration: if($link-decoration == none, null, none);
+
+ &:hover,
+ &:focus,
+ &.active {
+ color: rgba($black, .85);
+ text-decoration: if($link-hover-decoration == underline, none, null);
+ background-color: rgba(var(--bd-violet-rgb), .1);
+ }
+
+ &.active {
+ font-weight: 600;
}
}
diff --git a/site/assets/scss/_subnav.scss b/site/assets/scss/_subnav.scss
deleted file mode 100644
index db183ff6a8..0000000000
--- a/site/assets/scss/_subnav.scss
+++ /dev/null
@@ -1,82 +0,0 @@
-.bd-subnavbar {
- --bs-gutter-x: $bd-gutter-x;
- --bs-gutter-y: $bd-gutter-x;
-
- // The position and z-index are needed for the dropdown to stay on top of the content
- position: relative;
- z-index: $zindex-sticky;
- background-color: rgba($white, .95);
- box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .05), inset 0 -1px 0 rgba(0, 0, 0, .15);
-
- .dropdown-menu {
- @include font-size(.875rem);
- box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .05);
- }
-
- .dropdown-item.current {
- font-weight: 600;
- background-image: escape-svg($dropdown-active-icon);
- background-repeat: no-repeat;
- background-position: right $dropdown-item-padding-x top .6rem;
- background-size: .75rem .75rem;
- }
-
- @include media-breakpoint-up(md) {
- position: sticky;
- top: 0;
- }
-}
-
-.bd-search {
- position: relative;
-
- &::after {
- position: absolute;
- top: .4rem;
- right: .4rem;
- bottom: .4rem;
- display: flex;
- align-items: center;
- justify-content: center;
- padding-right: .3125rem;
- padding-left: .3125rem;
- @include font-size(.75rem);
- color: $gray-600;
- content: "Ctrl + /";
- background-color: $gray-100;
- @include border-radius(.125rem);
- }
-
- @include media-breakpoint-down(md) {
- width: 100%;
- }
-
- .form-control {
- padding-right: 3.75rem;
-
- &:focus {
- border-color: $bd-violet;
- box-shadow: 0 0 0 3px rgba($bd-violet, .25);
- }
- }
-}
-
-.bd-sidebar-toggle {
- color: $text-muted;
-
- &:hover,
- &:focus {
- color: $bd-violet;
- }
-
- &:focus {
- box-shadow: 0 0 0 3px rgba($bd-violet, .25);
- }
-
- .bi-collapse { display: none; }
-
- &:not(.collapsed) {
- .bi-expand { display: none; }
- .bi-collapse { display: inline-block; }
- }
-}
diff --git a/site/assets/scss/_syntax.scss b/site/assets/scss/_syntax.scss
index 54f0cdaaa8..662f70dc4d 100644
--- a/site/assets/scss/_syntax.scss
+++ b/site/assets/scss/_syntax.scss
@@ -101,7 +101,7 @@
.language-bash,
.language-sh {
&::before {
- color: #009;
+ color: #777;
content: "$ ";
user-select: none;
}
diff --git a/site/assets/scss/_toc.scss b/site/assets/scss/_toc.scss
index 596945628e..512a11b420 100644
--- a/site/assets/scss/_toc.scss
+++ b/site/assets/scss/_toc.scss
@@ -15,6 +15,7 @@
ul {
padding-left: 0;
+ margin-bottom: 0;
list-style: none;
ul {
@@ -40,3 +41,47 @@
}
}
}
+
+.bd-toc-toggle {
+ display: flex;
+ align-items: center;
+
+ @include media-breakpoint-down(sm) {
+ justify-content: space-between;
+ width: 100%;
+ }
+
+ @include media-breakpoint-down(md) {
+ border: 1px solid $border-color;
+ @include border-radius(.4rem);
+
+ &:hover,
+ &:focus,
+ &:active,
+ &[aria-expanded="true"] {
+ color: var(--bd-violet);
+ background-color: $white;
+ border-color: var(--bd-violet);
+ }
+
+ &:focus,
+ &[aria-expanded="true"] {
+ box-shadow: 0 0 0 3px rgba(var(--bd-violet-rgb), .25);
+ }
+ }
+}
+
+.bd-toc-collapse {
+ @include media-breakpoint-down(md) {
+ nav {
+ padding: 1.25rem;
+ background-color: var(--bs-gray-100);
+ border: 1px solid $border-color;
+ @include border-radius(.25rem);
+ }
+ }
+
+ @include media-breakpoint-up(md) {
+ display: block !important; // stylelint-disable-line declaration-no-important
+ }
+}
diff --git a/site/assets/scss/_variables.scss b/site/assets/scss/_variables.scss
index 0c40b17e9e..8f74f94d0b 100644
--- a/site/assets/scss/_variables.scss
+++ b/site/assets/scss/_variables.scss
@@ -1,17 +1,15 @@
// stylelint-disable scss/dollar-variable-default
// Local docs variables
-$bd-purple: #563d7c;
+$bd-purple: #4c0bce;
$bd-violet: lighten(saturate($bd-purple, 5%), 15%); // stylelint-disable-line function-disallowed-list
$bd-purple-light: lighten(saturate($bd-purple, 5%), 45%); // stylelint-disable-line function-disallowed-list
$bd-accent: #ffe484;
-$bd-info: #5bc0de;
-$bd-warning: #f0ad4e;
-$bd-danger: #d9534f;
$dropdown-active-icon: url("data:image/svg+xml, ");
-$sidebar-collapse-icon: url("data:image/svg+xml, ");
+$search-clear-icon: url("data:image/svg+xml, ");
-$bd-gutter-x: 1.25rem;
+$bd-gutter-x: 3rem;
+$bd-callout-variants: info, warning, danger !default;
:root {
--bd-purple: #{$bd-purple};
@@ -19,4 +17,6 @@ $bd-gutter-x: 1.25rem;
--bd-accent: #{$bd-accent};
--bd-violet-rgb: #{to-rgb($bd-violet)};
--bd-accent-rgb: #{to-rgb($bd-accent)};
+ --bd-pink-rgb: #{to-rgb($pink-500)};
+ --bd-teal-rgb: #{to-rgb($teal-500)};
}
diff --git a/site/assets/scss/docs.scss b/site/assets/scss/docs.scss
index 0029e83af9..f1390e2fae 100644
--- a/site/assets/scss/docs.scss
+++ b/site/assets/scss/docs.scss
@@ -37,7 +37,7 @@ $enable-cssgrid: true; // stylelint-disable-line scss/dollar-variable-default
// Load docs components
@import "variables";
@import "navbar";
-@import "subnav";
+@import "search";
@import "masthead";
@import "ads";
@import "content";
diff --git a/site/content/docs/5.1/components/offcanvas.md b/site/content/docs/5.1/components/offcanvas.md
index 7a8cbc68a7..6ad9b6e893 100644
--- a/site/content/docs/5.1/components/offcanvas.md
+++ b/site/content/docs/5.1/components/offcanvas.md
@@ -137,9 +137,54 @@ When backdrop is set to static, the offcanvas will not close when clicking outsi
{{< /example >}}
+## Responsive
+
+Added in v5.2.0
+
+Responsive offcanvas classes hide content outside the viewport from a specified breakpoint and down. Above that breakpoint, the contents within will behave as usual. For example, `.offcanvas-lg` hides content in an offcanvas below the `lg` breakpoint, but shows the content above the `lg` breakpoint.
+
+
+
Toggle offcanvas
+
+
Resize your browser to show the responsive offcanvas toggle.
+
+
+
+
+
This is content within an .offcanvas-lg
.
+
+
+
+
+```html
+Toggle offcanvas
+
+
+
+
+
This is content within an .offcanvas-lg
.
+
+
+```
+
+Responsive offcanvas classes are available across for each breakpoint.
+
+- `.offcanvas`
+- `.offcanvas-sm`
+- `.offcanvas-md`
+- `.offcanvas-lg`
+- `.offcanvas-xl`
+- `.offcanvas-xxl`
+
## Placement
-There's no default placement for offcanvas components, so you must add one of the modifier classes below;
+There's no default placement for offcanvas components, so you must add one of the modifier classes below.
- `.offcanvas-start` places offcanvas on the left of the viewport (shown above)
- `.offcanvas-end` places offcanvas on the right of the viewport
@@ -194,10 +239,18 @@ Try the top, right, and bottom examples out below.
Since the offcanvas panel is conceptually a modal dialog, be sure to add `aria-labelledby="..."`—referencing the offcanvas title—to `.offcanvas`. Note that you don’t need to add `role="dialog"` since we already add it via JavaScript.
-## Sass
+## CSS
### Variables
+Added in v5.2.0
+
+As part of Bootstrap's evolving CSS variables approach, offcanvas now uses local CSS variables on `.offcanvas` for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too.
+
+{{< scss-docs name="offcanvas-css-vars" file="scss/_offcanvas.scss" >}}
+
+### Sass variables
+
{{< scss-docs name="offcanvas-variables" file="scss/_variables.scss" >}}
## Usage
diff --git a/site/content/docs/5.1/examples/_index.md b/site/content/docs/5.1/examples/_index.md
index 3d5bfab2fb..39102f3646 100644
--- a/site/content/docs/5.1/examples/_index.md
+++ b/site/content/docs/5.1/examples/_index.md
@@ -7,30 +7,39 @@ aliases: "/examples/"
{{< list-examples.inline >}}
{{ range $entry := $.Site.Data.examples -}}
- {{ $entry.category }}
- {{ $entry.description }}
- {{ if eq $entry.category "RTL" -}}
-
-
The RTL feature is still experimental and will probably evolve according to user feedback. Spotted something or have an improvement to suggest? Open an issue , we'd love to get your insights.
-
- {{ end -}}
-
- {{ range $i, $example := $entry.examples -}}
- {{- $len := len $entry.examples -}}
- {{ if (eq $i 0) }}{{ end }}
-
-
-
- {{ $example.name }}
-
-
{{ $example.description }}
+
+
+
{{ $entry.category }}
+
{{ $entry.description }}
+ {{ if eq $entry.category "RTL" -}}
+
+
+ RTL is still experimental and will evolve with feedback. Spotted something or have an improvement to suggest?
+
+
Please open an issue.
- {{ if (eq (add $i 1) $len) }}
{{ end }}
- {{ end -}}
+ {{ end -}}
+
+
+
+ {{ range $i, $example := $entry.examples -}}
+ {{- $len := len $entry.examples -}}
+ {{ if (eq $i 0) }}
{{ end }}
+
+ {{ if (eq (add $i 1) $len) }}
{{ end }}
+ {{ end -}}
+
+
{{ end -}}
{{< /list-examples.inline >}}
diff --git a/site/content/docs/5.1/examples/navbars-offcanvas/index.html b/site/content/docs/5.1/examples/navbars-offcanvas/index.html
new file mode 100644
index 0000000000..47041fa011
--- /dev/null
+++ b/site/content/docs/5.1/examples/navbars-offcanvas/index.html
@@ -0,0 +1,147 @@
+---
+layout: examples
+title: Navbar Template
+extra_css:
+ - "navbar.css"
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Navbar with offcanvas examples
+
This example shows how responsive offcanvas menus work within the navbar. For positioning of navbars, checkout the }}">top and }}">fixed top examples.
+
From the top down, you'll see a dark navbar, light navbar and a responsive navbar—each with offcanvases built in. Resize your browser window to the large breakpoint to see the toggle for the offcanvas.
+
+ }}" role="button">Learn more about offcanvas navbars »
+
+
+
+
+
diff --git a/site/content/docs/5.1/examples/navbars-offcanvas/navbar.css b/site/content/docs/5.1/examples/navbars-offcanvas/navbar.css
new file mode 100644
index 0000000000..70d209409d
--- /dev/null
+++ b/site/content/docs/5.1/examples/navbars-offcanvas/navbar.css
@@ -0,0 +1,7 @@
+body {
+ padding-bottom: 20px;
+}
+
+.navbar {
+ margin-bottom: 20px;
+}
diff --git a/site/content/docs/5.1/utilities/api.md b/site/content/docs/5.1/utilities/api.md
index 16270ad511..86cf329381 100644
--- a/site/content/docs/5.1/utilities/api.md
+++ b/site/content/docs/5.1/utilities/api.md
@@ -11,7 +11,7 @@ Bootstrap utilities are generated with our utility API and can be used to modify
The `$utilities` map contains all our utilities and is later merged with your custom `$utilities` map, if present. The utility map contains a keyed list of utility groups which accept the following options:
-{{< bs-table "table text-start" >}}
+{{< bs-table "table table-utilities" >}}
| Option | Type | Default value | Description |
| --- | --- | --- | --- |
| [`property`](#property) | **Required** | – | Name of the property, this can be a string or an array of strings (e.g., horizontal paddings or margins). |
diff --git a/site/content/docs/5.1/utilities/spacing.md b/site/content/docs/5.1/utilities/spacing.md
index 70fbe76945..1e5f6d32f4 100644
--- a/site/content/docs/5.1/utilities/spacing.md
+++ b/site/content/docs/5.1/utilities/spacing.md
@@ -10,7 +10,9 @@ toc: true
Assign responsive-friendly `margin` or `padding` values to an element or a subset of its sides with shorthand classes. Includes support for individual properties, all properties, and vertical and horizontal properties. Classes are built from a default Sass map ranging from `.25rem` to `3rem`.
-Using the CSS Grid layout module? Consider using [the gap utility](#gap).
+{{< callout >}}
+**Using the CSS Grid layout module?** Consider using [the gap utility](#gap) instead.
+{{< /callout >}}
### Notation
diff --git a/site/data/examples.yml b/site/data/examples.yml
index 6d6419d218..38644ef4a0 100644
--- a/site/data/examples.yml
+++ b/site/data/examples.yml
@@ -63,6 +63,8 @@
examples:
- name: Navbars
description: "Demonstration of all responsive and container options for the navbar."
+ - name: Navbars offcanvas
+ description: "Same as the Navbars example, but with our offcanvas component."
- name: Navbar static
description: "Single navbar example of a static top navbar along with some additional content."
- name: Navbar fixed
diff --git a/site/data/plugins.yml b/site/data/plugins.yml
new file mode 100644
index 0000000000..22cec9877b
--- /dev/null
+++ b/site/data/plugins.yml
@@ -0,0 +1,47 @@
+- name: Alert
+ description: Show and hide alert messages to your users.
+ link: components/alerts/#javascript-behavior
+
+- name: Button
+ description: Programmatically control the active state for buttons.
+ link: components/buttons/#button-plugin
+
+- name: Carousel
+ description: Add slideshows to any page, including support for crossfade.
+ link: components/carousel/
+
+- name: Collapse
+ description: Expand and collapse areas of content, or create accordions.
+ link: components/collapse/
+
+- name: Dropdown
+ description: Create menus of links, actions, forms, and more.
+ link: components/dropdowns/
+
+- name: Modal
+ description: Add flexible and responsive dialogs to your project.
+ link: components/modal/
+
+- name: Offcanvas
+ description: Build and toggle hidden sidebars into any page.
+ link: components/offcanvas/
+
+- name: Popover
+ description: Create custom overlays. Built on Popper.js.
+ link: components/popovers/
+
+- name: Scrollspy
+ description: Automatically update active nav links based on page scroll.
+ link: components/scrollspy/
+
+- name: Tab
+ description: Allow Bootstrap nav components to toggle contents.
+ link: components/navs-tabs/
+
+- name: Toast
+ description: Show and hide notifications to your visitors.
+ link: components/toasts/
+
+- name: Tooltip
+ description: Replace browser tooltips with custom ones. Built on Popper.js.
+ link: components/tooltips/
diff --git a/site/data/sidebar.yml b/site/data/sidebar.yml
index 8aad6027bf..eb03285c5f 100644
--- a/site/data/sidebar.yml
+++ b/site/data/sidebar.yml
@@ -2,6 +2,8 @@
# The logic for the sidebar generation is in "site/layouts/partials/docs-sidebar.html".
- title: Getting started
+ icon: book-half
+ icon_color: indigo
pages:
- title: Introduction
- title: Download
@@ -16,6 +18,8 @@
- title: Contribute
- title: Customize
+ icon: palette2
+ icon_color: pink
pages:
- title: Overview
- title: Sass
@@ -26,6 +30,8 @@
- title: Optimize
- title: Layout
+ icon: grid-fill
+ icon_color: teal
pages:
- title: Breakpoints
- title: Containers
@@ -37,6 +43,8 @@
- title: CSS Grid
- title: Content
+ icon: file-earmark-richtext
+ icon_color: gray
pages:
- title: Reboot
- title: Typography
@@ -45,6 +53,8 @@
- title: Figures
- title: Forms
+ icon: ui-radios
+ icon_color: blue
pages:
- title: Overview
- title: Form control
@@ -57,6 +67,8 @@
- title: Validation
- title: Components
+ icon: menu-button-wide-fill
+ icon_color: cyan
pages:
- title: Accordion
- title: Alerts
@@ -84,6 +96,8 @@
- title: Tooltips
- title: Helpers
+ icon: magic
+ icon_color: orange
pages:
- title: Clearfix
- title: Colored links
@@ -96,6 +110,8 @@
- title: Vertical rule
- title: Utilities
+ icon: braces-asterisk
+ icon_color: red
pages:
- title: API
- title: Background
@@ -116,11 +132,15 @@
- title: Visibility
- title: Extend
+ icon: tools
+ icon_color: blue
pages:
- title: Approach
- title: Icons
- title: About
+ icon: globe2
+ icon_color: indigo
pages:
- title: Overview
- title: Team
diff --git a/site/layouts/_default/baseof.html b/site/layouts/_default/baseof.html
index 713ab2864a..fdf19b31f0 100644
--- a/site/layouts/_default/baseof.html
+++ b/site/layouts/_default/baseof.html
@@ -5,6 +5,7 @@
{{ block "body_override" . }}{{ end }}
{{ partial "skippy" . }}
+ {{ partial "icons" . }}
{{ partial "docs-navbar" . }}
diff --git a/site/layouts/_default/docs.html b/site/layouts/_default/docs.html
index dd063c5dc8..3c61cd3421 100644
--- a/site/layouts/_default/docs.html
+++ b/site/layouts/_default/docs.html
@@ -1,29 +1,45 @@
{{ define "main" }}
- {{ partial "docs-subnav" . }}
-
-
+
-
+
-
View on GitHub
-
{{ .Title | markdownify }}
+
+ View on GitHub
+
+
{{ .Title | markdownify }}
{{ .Page.Params.Description | markdownify }}
{{ partial "ads" . }}
{{ if (eq .Page.Params.toc true) }}
-
-
On this page
- {{ .TableOfContents }}
+
+
+ On this page
+
+
+
On this page
+
+
+ {{ .TableOfContents }}
+
{{ end }}
-
+
{{ if .Page.Params.sections }}
{{ range .Page.Params.sections }}
diff --git a/site/layouts/_default/single.html b/site/layouts/_default/single.html
index 8ba99c7188..ae1a41faa7 100644
--- a/site/layouts/_default/single.html
+++ b/site/layouts/_default/single.html
@@ -1,14 +1,19 @@
{{ define "main" }}
-
+
{{ .Title | markdownify }}
{{ .Page.Params.Description | markdownify }}
{{ if eq .Title "Examples" }}
-
@@ -20,7 +25,7 @@
-
+
{{ .Content }}
{{ if eq .Title "Examples" }}
@@ -30,7 +35,7 @@
{{ partial "icons/droplet-fill.svg" (dict "width" "32" "height" "32") }}
-
Go further with Bootstrap Themes
+
Go further with Bootstrap Themes
Need something more than these examples? Take Bootstrap to the next level with premium themes from the official Bootstrap Themes marketplace . They’re built as their own extended frameworks, rich with new components and plugins, documentation, and powerful build tools.
diff --git a/site/layouts/partials/docs-navbar.html b/site/layouts/partials/docs-navbar.html
index 171a2ad73e..441c2bd56a 100644
--- a/site/layouts/partials/docs-navbar.html
+++ b/site/layouts/partials/docs-navbar.html
@@ -1,74 +1,89 @@
-