]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
v5.2.0 design refresh, plus responsive offcanvas classes (#35736)
authorMark Otto <markd.otto@gmail.com>
Mon, 18 Apr 2022 05:17:50 +0000 (22:17 -0700)
committerGitHub <noreply@github.com>
Mon, 18 Apr 2022 05:17:50 +0000 (22:17 -0700)
* Add responsive offcanvas classes

- Updates navbar-expand classes to de-dupe some styles—these shouldn't interfere now.
- Adds some JS to the offcanvas component to help with responsiveness

Co-Authored-By: GeoSot <geo.sotis@gmail.com>
* Redesign homepage, docs, and examples

Homepage:

- New Bootstrap purple navbar
- Redesigned masthead
- Rewrote and redesigned homepage content
- Replace Copy text with icons like Bootstrap Icons site across all ClipboardJS instances
- Fixed padding issues in site footer
- Match homepage button styles to examples page, use gap instead of tons of responsive margin utils

Docs:

- New navbar, no more subnav. Migrated search and version picker into the main navbar and refreshed the design of it all, including the responsive toggles.
- New sidebar navigation is always expanded, and now features Bootstrap Icons alongside section headings
- Sidebar navigation autoscrolls to active link for better usability
- Subnav and navbar padding issues ironed out
- Enhanced the version picker in anticipation of v5.2: we can now link right to the same page in the previous version.
- Redesign callouts to add more color to our pages
- Collapse table of contents on mobile
- Cleanup and redesign button styles with CSS variables
- Update design for subnav version dropdown
- Update highlight and example to be full-width until md
- Improve the Added In badges
- Turn the ToC into a well on mobile
- Redesign code snippets to better house two action buttons

Examples:

- Redesign Examples page layout
- Add new example for responsive offcanvases in navbars

* Convert offcanvas to CSS vars

* Feat: add resize handler to Offcanvas.js.

If we could use as default the `.offcanvas` class without modifiers, we then, could add a simplified selector
The selector itself, ignores the .offcanvas class as it doesn't have any responsive behavior
The `aria-modal` addon is to protect us, selection backdrop elements

* Separate examples code, Add some selectors, fix stackblitz btn

Co-authored-by: GeoSot <geo.sotis@gmail.com>
51 files changed:
.bundlewatch.config.json
js/src/offcanvas.js
js/tests/unit/offcanvas.spec.js
scss/_navbar.scss
scss/_offcanvas.scss
scss/_spinners.scss
site/assets/js/application.js
site/assets/js/code-examples.js [new file with mode: 0644]
site/assets/js/search.js
site/assets/scss/_ads.scss
site/assets/scss/_algolia.scss
site/assets/scss/_buttons.scss
site/assets/scss/_callouts.scss
site/assets/scss/_clipboard-js.scss
site/assets/scss/_component-examples.scss
site/assets/scss/_content.scss
site/assets/scss/_layout.scss
site/assets/scss/_masthead.scss
site/assets/scss/_navbar.scss
site/assets/scss/_search.scss [new file with mode: 0644]
site/assets/scss/_sidebar.scss
site/assets/scss/_subnav.scss [deleted file]
site/assets/scss/_syntax.scss
site/assets/scss/_toc.scss
site/assets/scss/_variables.scss
site/assets/scss/docs.scss
site/content/docs/5.1/components/offcanvas.md
site/content/docs/5.1/examples/_index.md
site/content/docs/5.1/examples/navbars-offcanvas/index.html [new file with mode: 0644]
site/content/docs/5.1/examples/navbars-offcanvas/navbar.css [new file with mode: 0644]
site/content/docs/5.1/utilities/api.md
site/content/docs/5.1/utilities/spacing.md
site/data/examples.yml
site/data/plugins.yml [new file with mode: 0644]
site/data/sidebar.yml
site/layouts/_default/baseof.html
site/layouts/_default/docs.html
site/layouts/_default/single.html
site/layouts/partials/docs-navbar.html
site/layouts/partials/docs-sidebar.html
site/layouts/partials/docs-subnav.html [deleted file]
site/layouts/partials/docs-versions.html
site/layouts/partials/favicons.html
site/layouts/partials/footer.html
site/layouts/partials/home/masthead-followup.html
site/layouts/partials/home/masthead.html
site/layouts/partials/icons.html [new file with mode: 0644]
site/layouts/partials/scripts.html
site/layouts/shortcodes/example.html
site/static/docs/5.1/assets/img/examples/navbars-offcanvas.png [new file with mode: 0644]
site/static/docs/5.1/assets/img/examples/navbars-offcanvas@2x.png [new file with mode: 0644]

index 19c4b999942904d1f1cbf93a28352a39463d6558..b864477107813203f8bfa1809b3c74815f57b18e 100644 (file)
     },
     {
       "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",
index b5afc0c87b49f3d1773a694092363754180d2c0e..0ae5dbfdab4d8657465e232e1834475384472ed4 100644 (file)
@@ -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)
 
 /**
index a98a8c13e3d091e037a76e457ac969c4b46d553a..ad0595a866808a32376cf0db20908d175d276404 100644 (file)
@@ -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 = '<div class="offcanvas-lg"></div>'
+
+        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', () => {
index 6db562519c62ede560fd9b1eb1007affb205c052..bd140ae09965666dd457021d35f07554e00899b8 100644 (file)
           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;
+          }
         }
       }
     }
index 5288fa9ce68b0834b7d7812c1e56c0f6b82acfc2..e923db2f2481b408c3214df300f695d3b0c6652a 100644 (file)
-.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);
-
-  &.showing,
-  &.show:not(.hiding) {
-    transform: none;
+// stylelint-disable function-disallowed-list
+
+%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;
   }
+}
+
+@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%);
+      }
 
-  &.showing,
-  &.hiding,
-  &.show {
-    visibility: visible;
+      &.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
+        }
+      }
+    }
   }
 }
 
   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);
   }
 }
 
 
 .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%);
-}
index 2fc7d3edc51918eb2f37034c71400db77bc9b1a0..ec8473207eff5c4abc3bc34d4753c9c4c2765602 100644 (file)
@@ -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;
 }
 
index c14dc57c22b56fa672946d63513b73d353ea3dd9..55e8969802c37e464d62ca1be7d478f21d967f78 100644 (file)
  * 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 => {
       modalBodyInput.value = recipient
     })
   }
-
-  // Insert copy to clipboard button before .highlight
-  const btnTitle = 'Copy to clipboard'
-  const btnEdit = 'Edit on StackBlitz'
-  const btnHtml = '<div class="bd-clipboard"><button type="button" class="btn-clipboard">Copy</button></div>'
-  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 (file)
index 0000000..4a61fa0
--- /dev/null
@@ -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 = [
+    '<div class="bd-code-snippet">',
+    '   <div class="bd-clipboard">',
+    '      <button type="button" class="btn-clipboard">',
+    '        <svg class="bi" width="1em" height="1em" fill="currentColor" role="img" aria-label="Copy"><use xlink:href="#clipboard"/></svg>',
+    '      </button>',
+    '   </div>',
+    '</div>'
+  ].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 })
+  })
+})()
index 15197bfd9a5bf602e41f29cddb7bfa3ccbd10623..6c90a208725a2046c2ec4cdb2ac747aad17f6f72 100644 (file)
   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',
index 026d1a17a7a172b17f4965a443eabf5f419f4ece..b9369eb19cfc09a30b7a05d70057c012b632fafb 100644 (file)
@@ -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);
   }
 }
 
index 9c457d2e376529d65060320649207a668accf9b0..ab22ad9a7e18d9f3854f350c15b511bf8cb33237 100644 (file)
   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;
   }
 }
 
index 93ffa83ed57f7a140aa35e88b418f2a2ae0b3af7..13bd6e48a389e626c80b55fe61eec517449b76f2 100644 (file)
@@ -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
 
   --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);
 }
index aff91f18b62877fff40044f3d466c3f77e6bd367..4513a7d1d569c4fd28adb03e2a84f869cfe98948 100644 (file)
@@ -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;
   }
-}
 
-// Variations
-.bd-callout-info {
-  border-left-color: $bd-info;
-}
-
-.bd-callout-warning {
-  border-left-color: $bd-warning;
+  .highlight {
+    background-color: rgba($black, .05);
+  }
 }
 
-.bd-callout-danger {
-  border-left-color: $bd-danger;
+// Variations
+@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);
+  }
 }
index b2b0854dc4155ce233898f2d2e2d0a0d512fb621..7acf90f0b7d014d878a9229cebbc46ba5c7079e2 100644 (file)
 
 .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;
+  }
 }
index 330bd43bac5380e2edde180ac2d5e2b7cb5c4ad2..b305f088f9fce7cf3acd43200010605ee60b21e6 100644 (file)
 .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 {
 //
 
 .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 {
     white-space: pre;
     background-color: transparent;
     border: 0;
+
+    // Undo tabindex that's automatically added by Hugo
+    &:focus {
+      outline: 0;
+    }
   }
 
   pre code {
   }
 }
 
+.bd-example-snippet {
+  .highlight {
+    @include border-top-radius(0);
+    border: 1px solid $border-color;
+  }
+  .highlight-toolbar {
+    border: solid $border-color;
+    border-width: 0 1px;
+  }
+}
+
 .bd-content .highlight {
-  margin-right: $bd-gutter-x * -1;
-  margin-left: $bd-gutter-x * -1;
+  margin-right: $bd-gutter-x * -.5;
+  margin-left: $bd-gutter-x * -.5;
 
-  @include media-breakpoint-up(sm) {
+  @include media-breakpoint-up(md) {
     margin-right: 0;
     margin-left: 0;
   }
index d796c491e01fdd08b656af52af2159adb127062a..cd594335a60574f8365bb82b1ea311202add2fe5 100644 (file)
@@ -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;
   }
-}
 
-.bd-content {
   > h2:not(:first-child) {
     margin-top: 3rem;
   }
       border-bottom: 2px solid currentcolor;
     }
 
+    tbody:not(:first-child) {
+      border-top: 2px solid currentcolor;
+    }
+
     th,
     td {
       &:first-child {
 
     // 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);
 }
 .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;
+  }
+}
index f83cf094c99a965b4d252ce5269f6d49c7be3b3f..d0482d9b71233cb63c26c22f7a1b5f5d56b451cc 100644 (file)
@@ -1,16 +1,14 @@
+.bd-gutter {
+  --bs-gutter-x: #{$bd-gutter-x};
+}
+
 .bd-layout {
-  padding-right: $bd-gutter-x;
-  padding-left: $bd-gutter-x;
 
-  @include media-breakpoint-up(md) {
+  @include media-breakpoint-up(lg) {
     display: grid;
     grid-template-areas: "sidebar main";
-    grid-template-columns: 1fr 3fr;
-    gap: $grid-gutter-width;
-  }
-
-  @include media-breakpoint-up(lg) {
     grid-template-columns: 1fr 5fr;
+    gap: $grid-gutter-width;
   }
 }
 
 .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:
index 2e742e76d16155b7a88a7fccd2fd7ac90b32adde..42ad0f38539627c3ac379c1e3b48b05f3682465e 100644 (file)
@@ -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) {
+  .lead {
+    @include font-size(1rem);
+    font-weight: 400;
     color: $gray-700;
   }
 
-  .btn {
-    padding: .8rem 2rem;
-    font-weight: 600;
+  .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);
+    }
+  }
+}
+
+.masthead-followup {
   .lead {
-    @include font-size(1.5rem);
-    font-weight: 400;
-    color: $gray-700;
+    @include font-size(1rem);
+  }
+
+  .highlight {
+    @include border-radius(.5rem);
+  }
+
+  @include media-breakpoint-up(md) {
+    .lead {
+      @include font-size(1.25rem);
+    }
   }
 }
 
-@include media-breakpoint-up(md) {
-  .mw-md-75 { max-width: 75%; }
+.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);
+}
index 401731ae19eb01ac938b0594b59af0f9681b49ad..4f9f3f829092f71db900638ff70cd62e87edc899 100644 (file)
@@ -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 {
+      transform: rotate(-5deg) scale(1.1);
+    }
+  }
 
-      &:hover,
-      &:focus {
-        color: $white;
-      }
+  .navbar-toggler,
+  .nav-link {
+    padding-right: $spacer * .25;
+    padding-left: $spacer * .25;
+    color: rgba($white, .85);
 
-      &.active {
-        font-weight: 600;
-        color: $white;
-      }
+    &: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 (file)
index 0000000..1825337
--- /dev/null
@@ -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);
+    }
+  }
+}
index 452b155ffa79cfaae63eb7e08e22225286810de1..ed76b3ca823ffd89c28c4b30fed33117fe7fc739 100644 (file)
@@ -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;
-    }
-  }
-
-  a {
-    padding: .1875rem .5rem;
-    margin-top: .125rem;
-    margin-left: 1.25rem;
-    color: rgba($black, .65);
-    text-decoration: if($link-decoration == none, null, none);
-
-    &:hover,
-    &:focus {
-      color: rgba($black, .85);
-      text-decoration: if($link-hover-decoration == underline, none, null);
-      background-color: rgba($bd-violet, .1);
-    }
+.bd-links-nav {
+  @include media-breakpoint-down(lg) {
+    font-size: .875rem;
   }
 
-  .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;
+  @include media-breakpoint-between(xs, lg) {
+    column-count: 2;
+    column-gap: 1.5rem;
 
-    &: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);
-    }
-
-    // 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%;
+    .bd-links-span-all {
+      column-span: all;
     }
+  }
+}
 
-    &[aria-expanded="true"] {
-      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);
 
-      &::before {
-        transform: rotate(90deg);
-      }
-    }
+  &: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 {
+  &.active {
     font-weight: 600;
-    color: rgba($black, .85);
   }
 }
diff --git a/site/assets/scss/_subnav.scss b/site/assets/scss/_subnav.scss
deleted file mode 100644 (file)
index db183ff..0000000
+++ /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; }
-  }
-}
index 54f0cdaaa8d4782511c1cf3dc73b95ed58f83062..662f70dc4d89616a84e6eb9866139025b391d809 100644 (file)
   .language-bash,
   .language-sh {
     &::before {
-      color: #009;
+      color: #777;
       content: "$ ";
       user-select: none;
     }
index 596945628e7c1c7b9c2853b1d1ed2724aac864a2..512a11b42029fd1838dc0d1a7d735367072b1916 100644 (file)
@@ -15,6 +15,7 @@
 
     ul {
       padding-left: 0;
+      margin-bottom: 0;
       list-style: none;
 
       ul {
     }
   }
 }
+
+.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
+  }
+}
index 0c40b17e9e4b3276a9d621154c35270ea0ecd388..8f74f94d0b5390072a1b0138ae789f648590ba21 100644 (file)
@@ -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,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='#292b2c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>");
-$sidebar-collapse-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path fill='none' stroke='rgba(0,0,0,.5)' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M5 14l6-6-6-6'/></svg>");
+$search-clear-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'><path fill='rgba(255,255,255,.75)' d='M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM5.354 4.646a.5.5 0 1 0-.708.708L7.293 8l-2.647 2.646a.5.5 0 0 0 .708.708L8 8.707l2.646 2.647a.5.5 0 0 0 .708-.708L8.707 8l2.647-2.646a.5.5 0 0 0-.708-.708L8 7.293 5.354 4.646z'/></svg>");
 
-$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)};
 }
index 0029e83af96505d040ef29e9e942b980bd4e7af9..f1390e2faece7f562d97fcaf92712a89802e85a2 100644 (file)
@@ -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";
index 7a8cbc68a782edc3f6ecaf608bc2d87e708be368..6ad9b6e893f90fa0e8156c0275900ecb691b828a 100644 (file)
@@ -137,9 +137,54 @@ When backdrop is set to static, the offcanvas will not close when clicking outsi
 </div>
 {{< /example >}}
 
+## Responsive
+
+<small class="d-inline-flex px-2 py-1 fw-semibold text-success bg-success bg-opacity-10 rounded-2">Added in v5.2.0</small>
+
+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.
+
+<div class="bd-example">
+  <button class="btn btn-primary d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasResponsive" aria-controls="offcanvasResponsive">Toggle offcanvas</button>
+
+  <div class="alert alert-info d-none d-lg-block">Resize your browser to show the responsive offcanvas toggle.</div>
+
+  <div class="offcanvas-lg offcanvas-end" tabindex="-1" id="offcanvasResponsive" aria-labelledby="offcanvasResponsiveLabel">
+    <div class="offcanvas-header">
+      <h5 class="offcanvas-title" id="offcanvasResponsiveLabel">Responsive offcanvas</h5>
+      <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
+    </div>
+    <div class="offcanvas-body">
+      <p class="mb-0">This is content within an <code>.offcanvas-lg</code>.</p>
+    </div>
+  </div>
+</div>
+
+```html
+<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasResponsive" aria-controls="offcanvasResponsive">Toggle offcanvas</button>
+
+<div class="offcanvas-lg offcanvas-end" tabindex="-1" id="offcanvasResponsive" aria-labelledby="offcanvasResponsiveLabel">
+  <div class="offcanvas-header">
+    <h5 class="offcanvas-title" id="offcanvasResponsiveLabel">Responsive offcanvas</h5>
+    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
+  </div>
+  <div class="offcanvas-body">
+    <p class="mb-0">This is content within an <code>.offcanvas-lg</code>.</p>
+  </div>
+</div>
+```
+
+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
 
+<small class="d-inline-flex px-2 py-1 fw-semibold text-success bg-success bg-opacity-10 rounded-2">Added in v5.2.0</small>
+
+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
index 3d5bfab2fb464e55bef1d389c06776b5a75857c4..39102f3646a1a2b30e992b5570cd04a44ef2a172 100644 (file)
@@ -7,30 +7,39 @@ aliases: "/examples/"
 
 {{< list-examples.inline >}}
 {{ range $entry := $.Site.Data.examples -}}
-  <h2 id="{{ $entry.category | urlize }}">{{ $entry.category }}</h2>
-  <p>{{ $entry.description }}</p>
-  {{ if eq $entry.category "RTL" -}}
-    <div class="bd-callout bd-callout-warning">
-      <p>The RTL feature is still <strong>experimental</strong> and will probably evolve according to user feedback. Spotted something or have an improvement to suggest? <a href="{{ $.Site.Params.repo }}/issues/new">Open an issue</a>, we'd love to get your insights.</p>
-    </div>
-  {{ end -}}
-
-  {{ range $i, $example := $entry.examples -}}
-    {{- $len := len $entry.examples -}}
-    {{ if (eq $i 0) }}<div class="row">{{ end }}
-      <div class="col-sm-6 col-md-4 col-xl-3 mb-3">
-        <a class="d-block" href="/docs/{{ $.Site.Params.docs_version }}/examples/{{ $example.name | urlize }}/"{{ if in $example.name "RTL" }} hreflang="ar"{{ end }}>
-          <img class="img-thumbnail mb-3" srcset="/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}.png,
-                                                  /docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}@2x.png 2x"
-                                          src="/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}.png"
-                                          alt=""
-                                          width="480" height="300"
-                                          loading="lazy">
-          <h3 class="h5 mb-1">{{ $example.name }}</h3>
-        </a>
-        <p class="text-muted">{{ $example.description }}</p>
+<div class="row g-lg-5 mb-5">
+  <div class="col-lg-3">
+    <h2 id="{{ $entry.category | urlize }}">{{ $entry.category }}</h2>
+    <p>{{ $entry.description }}</p>
+    {{ if eq $entry.category "RTL" -}}
+      <div class="bd-callout bd-callout-warning small">
+        <p>
+          <strong>RTL is still experimental</strong> and will evolve with feedback. Spotted something or have an improvement to suggest?
+        </p>
+        <p><a href="{{ $.Site.Params.repo }}/issues/new">Please open an issue.</a></p>
       </div>
-    {{ if (eq (add $i 1) $len) }}</div>{{ end }}
-  {{ end -}}
+    {{ end -}}
+  </div>
+
+  <div class="col-lg-9">
+    {{ range $i, $example := $entry.examples -}}
+      {{- $len := len $entry.examples -}}
+      {{ if (eq $i 0) }}<div class="row">{{ end }}
+        <div class="col-sm-6 col-md-4 mb-3">
+          <a class="d-block" href="/docs/{{ $.Site.Params.docs_version }}/examples/{{ $example.name | urlize }}/"{{ if in $example.name "RTL" }} hreflang="ar"{{ end }}>
+            <img class="img-thumbnail mb-3" srcset="/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}.png,
+                                                    /docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}@2x.png 2x"
+                                            src="/docs/{{ $.Site.Params.docs_version }}/assets/img/examples/{{ $example.name | urlize }}.png"
+                                            alt=""
+                                            width="480" height="300"
+                                            loading="lazy">
+            <h3 class="h5 mb-1">{{ $example.name }}</h3>
+          </a>
+          <p class="text-muted">{{ $example.description }}</p>
+        </div>
+      {{ if (eq (add $i 1) $len) }}</div>{{ end }}
+    {{ end -}}
+  </div>
+</div>
 {{ 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 (file)
index 0000000..47041fa
--- /dev/null
@@ -0,0 +1,147 @@
+---
+layout: examples
+title: Navbar Template
+extra_css:
+  - "navbar.css"
+---
+
+<main>
+  <nav class="navbar navbar-dark bg-dark" aria-label="Dark offcanvas navbar">
+    <div class="container-fluid">
+      <a class="navbar-brand" href="#">Dark offcanvas navbar</a>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbarDark" aria-controls="offcanvasNavbarDark">
+        <span class="navbar-toggler-icon"></span>
+      </button>
+      <div class="offcanvas offcanvas-end text-white bg-dark" tabindex="-1" id="offcanvasNavbarDark" aria-labelledby="offcanvasNavbarDarkLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="offcanvasNavbarDarkLabel">Offcanvas</h5>
+          <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button>
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
+            <li class="nav-item">
+              <a class="nav-link active" aria-current="page" href="#">Home</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link" href="#">Link</a>
+            </li>
+            <li class="nav-item dropdown">
+              <a class="nav-link dropdown-toggle" href="#" id="offcanvasNavbarDarkDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                Dropdown
+              </a>
+              <ul class="dropdown-menu" aria-labelledby="offcanvasNavbarDarkDropdown">
+                <li><a class="dropdown-item" href="#">Action</a></li>
+                <li><a class="dropdown-item" href="#">Another action</a></li>
+                <li>
+                  <hr class="dropdown-divider">
+                </li>
+                <li><a class="dropdown-item" href="#">Something else here</a></li>
+              </ul>
+            </li>
+          </ul>
+          <form class="d-flex mt-3" role="search">
+            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
+            <button class="btn btn-outline-success" type="submit">Search</button>
+          </form>
+        </div>
+      </div>
+    </div>
+  </nav>
+
+  <nav class="navbar bg-light" aria-label="Light offcanvas navbar">
+    <div class="container-fluid">
+      <a class="navbar-brand" href="#">Light offcanvas navbar</a>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbarLight" aria-controls="offcanvasNavbarLight">
+        <span class="navbar-toggler-icon"></span>
+      </button>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbarLight" aria-labelledby="offcanvasNavbarLightLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="offcanvasNavbarLightLabel">Offcanvas</h5>
+          <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
+            <li class="nav-item">
+              <a class="nav-link active" aria-current="page" href="#">Home</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link" href="#">Link</a>
+            </li>
+            <li class="nav-item dropdown">
+              <a class="nav-link dropdown-toggle" href="#" id="offcanvasNavbarLightDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                Dropdown
+              </a>
+              <ul class="dropdown-menu" aria-labelledby="offcanvasNavbarLightDropdown">
+                <li><a class="dropdown-item" href="#">Action</a></li>
+                <li><a class="dropdown-item" href="#">Another action</a></li>
+                <li>
+                  <hr class="dropdown-divider">
+                </li>
+                <li><a class="dropdown-item" href="#">Something else here</a></li>
+              </ul>
+            </li>
+          </ul>
+          <form class="d-flex mt-3" role="search">
+            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
+            <button class="btn btn-outline-success" type="submit">Search</button>
+          </form>
+        </div>
+      </div>
+    </div>
+  </nav>
+
+  <nav class="navbar navbar-expand-lg navbar-dark bg-dark" aria-label="Offcanvas navbar large">
+    <div class="container-fluid">
+      <a class="navbar-brand" href="#">Responsive offcanvas navbar</a>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar2" aria-controls="offcanvasNavbar2">
+        <span class="navbar-toggler-icon"></span>
+      </button>
+      <div class="offcanvas offcanvas-end text-white bg-dark" tabindex="-1" id="offcanvasNavbar2" aria-labelledby="offcanvasNavbar2Label">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="offcanvasNavbar2Label">Offcanvas</h5>
+          <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button>
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav justify-content-end flex-grow-1 pe-3">
+            <li class="nav-item">
+              <a class="nav-link active" aria-current="page" href="#">Home</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link" href="#">Link</a>
+            </li>
+            <li class="nav-item dropdown">
+              <a class="nav-link dropdown-toggle" href="#" id="offcanvasNavbarLgDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                Dropdown
+              </a>
+              <ul class="dropdown-menu" aria-labelledby="offcanvasNavbarLgDropdown">
+                <li><a class="dropdown-item" href="#">Action</a></li>
+                <li><a class="dropdown-item" href="#">Another action</a></li>
+                <li>
+                  <hr class="dropdown-divider">
+                </li>
+                <li><a class="dropdown-item" href="#">Something else here</a></li>
+              </ul>
+            </li>
+          </ul>
+          <form class="d-flex mt-3 mt-lg-0" role="search">
+            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
+            <button class="btn btn-outline-success" type="submit">Search</button>
+          </form>
+        </div>
+      </div>
+    </div>
+  </nav>
+
+  <div class="container my-5">
+    <div class="bg-light p-5 rounded">
+      <div class="col-sm-8 py-5 mx-auto">
+        <h1 class="display-5 fw-normal">Navbar with offcanvas examples</h1>
+        <p class="fs-5">This example shows how responsive offcanvas menus work within the navbar. For positioning of navbars, checkout the <a href="{{< docsref "/examples/navbar-static" >}}">top</a> and <a href="{{< docsref "/examples/navbar-fixed" >}}">fixed top</a> examples.</p>
+        <p>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.</p>
+        <p>
+          <a class="btn btn-primary" href="{{< docsref "/components/navbar#offcanvas" >}}" role="button">Learn more about offcanvas navbars &raquo;</a>
+        </p>
+    </div>
+    </div>
+  </div>
+</main>
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 (file)
index 0000000..70d2094
--- /dev/null
@@ -0,0 +1,7 @@
+body {
+  padding-bottom: 20px;
+}
+
+.navbar {
+  margin-bottom: 20px;
+}
index 16270ad5112c3d49f5be4337d857ffc79bb4ba28..86cf329381c49aa8dc215d6c561e08d5d6094683 100644 (file)
@@ -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&nbsp;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). |
index 70fbe76945094c94d49225cd8ff11eb8eb15857d..1e5f6d32f4c3780411d31bd25db30e967b9d16c6 100644 (file)
@@ -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
 
index 6d6419d21842e5a48c73ce411e8f7d45369d6a2a..38644ef4a0d4cd91aee6208d3285519275d03807 100644 (file)
@@ -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 (file)
index 0000000..22cec98
--- /dev/null
@@ -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/
index 8aad6027bf0e137507b8de63ad6f3d06ace813d9..eb03285c5f4fd6cddec23179952d9375abb61b8d 100644 (file)
@@ -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
     - title: Vertical rule
 
 - title: Utilities
+  icon: braces-asterisk
+  icon_color: red
   pages:
     - title: API
     - title: Background
     - 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
index 713ab2864ad0ef5b9971ef2ba5f424f959ed32f6..fdf19b31f075a30d1ddf1f353444075efdcea868 100644 (file)
@@ -5,6 +5,7 @@
   </head>
   {{ block "body_override" . }}<body>{{ end }}
     {{ partial "skippy" . }}
+    {{ partial "icons" . }}
 
     {{ partial "docs-navbar" . }}
 
index dd063c5dc8a8cec7f0b8e86da8002d9af2d751ea..3c61cd3421950faf07cec9d88f73b1c012e48059 100644 (file)
@@ -1,29 +1,45 @@
 {{ define "main" }}
-  {{ partial "docs-subnav" . }}
-
-  <div class="container-xxl my-md-4 bd-layout">
+  <div class="container-xxl bd-gutter mt-3 my-md-4 bd-layout">
     <aside class="bd-sidebar">
-      {{ partial "docs-sidebar" . }}
+      <div class="offcanvas-lg offcanvas-start" id="bdSidebar" aria-labelledby="bdSidebarOffcanvasLabel">
+        <div class="offcanvas-header border-bottom">
+          <h5 class="offcanvas-title" id="bdSidebarOffcanvasLabel">Browse docs</h5>
+          <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close" data-bs-target="#bdSidebar"></button>
+        </div>
+
+        <div class="offcanvas-body">
+          {{ partial "docs-sidebar" . }}
+        </div>
+      </div>
     </aside>
 
     <main class="bd-main order-1">
-      <div class="bd-intro ps-lg-4">
+      <div class="bd-intro pt-2 ps-lg-2">
         <div class="d-md-flex flex-md-row-reverse align-items-center justify-content-between">
-          <a class="btn btn-sm btn-bd-light mb-2 mb-md-0" href="{{ .Site.Params.repo }}/blob/main/site/content/{{ .Page.File.Path | replaceRE `\\` "/" }}" title="View and edit this file on GitHub" target="_blank" rel="noopener">View on GitHub</a>
-          <h1 class="bd-title" id="content">{{ .Title | markdownify }}</h1>
+          <a class="btn btn-sm btn-bd-light mb-3 mb-md-0 rounded-2" href="{{ .Site.Params.repo }}/blob/main/site/content/{{ .Page.File.Path | replaceRE `\\` "/" }}" title="View and edit this file on GitHub" target="_blank" rel="noopener">
+            View on GitHub
+          </a>
+          <h1 class="bd-title mb-0" id="content">{{ .Title | markdownify }}</h1>
         </div>
         <p class="bd-lead">{{ .Page.Params.Description | markdownify }}</p>
         {{ partial "ads" . }}
       </div>
 
       {{ if (eq .Page.Params.toc true) }}
-        <div class="bd-toc mt-4 mb-5 my-md-0 ps-xl-3 mb-lg-5 text-muted">
-          <strong class="d-block h6 my-2 pb-2 border-bottom">On this page</strong>
-          {{ .TableOfContents }}
+        <div class="bd-toc mt-3 mb-5 my-lg-0 ps-xl-3 mb-lg-5 text-muted">
+          <button class="btn btn-link link-dark p-md-0 mb-2 mb-md-0 text-decoration-none bd-toc-toggle d-md-none" type="button" data-bs-toggle="collapse" data-bs-target="#tocContents" aria-expanded="false" aria-controls="tocContents">
+            On this page
+            <svg class="bi d-md-none ms-2" aria-hidden="true"><use xlink:href="#chevron-expand"></use></svg>
+          </button>
+          <strong class="d-none d-md-block h6 my-2">On this page</strong>
+          <hr class="d-none d-md-block my-2">
+          <div class="collapse bd-toc-collapse" id="tocContents">
+            {{ .TableOfContents }}
+          </div>
         </div>
       {{ end }}
 
-      <div class="bd-content ps-lg-4">
+      <div class="bd-content ps-lg-2">
         {{ if .Page.Params.sections }}
           <div class="row g-3">
             {{ range .Page.Params.sections }}
index 8ba99c7188afd7d1530f9381ebc2256cace848d8..ae1a41faa76662221806d649c998fbd5aae410d4 100644 (file)
@@ -1,14 +1,19 @@
 {{ define "main" }}
   <header class="py-5 border-bottom">
-    <div class="container pt-md-1 pb-md-4">
+  <div class="container-xxl bd-gutter pt-md-1 pb-md-4">
       <div class="row">
         <div class="col-xl-8">
           <h1 class="bd-title mt-0">{{ .Title | markdownify }}</h1>
           <p class="bd-lead">{{ .Page.Params.Description | markdownify }}</p>
           {{ if eq .Title "Examples" }}
-          <div class="d-flex flex-column flex-sm-row">
-            <a href="{{ .Site.Params.download.dist_examples }}" class="btn btn-lg btn-bd-primary" onclick="ga('send', 'event', 'Examples', 'Hero', 'Download Examples');">Download examples</a>
-            <a href="{{ .Site.Params.download.source }}" class="btn btn-lg btn-outline-secondary mt-3 mt-sm-0 ms-sm-3" onclick="ga('send', 'event', 'Examples', 'Hero', 'Download');">Download source code</a>
+          <div class="d-flex flex-column flex-md-row gap-3">
+            <a href="{{ .Site.Params.download.dist_examples }}" class="btn btn-lg bd-btn-lg btn-bd-primary d-flex align-items-center justify-content-center fw-semibold" onclick="ga('send', 'event', 'Examples', 'Hero', 'Download Examples');">
+              <svg class="bi me-2" aria-hidden="true"><use xlink:href="#box-seam"></use></svg>
+              Download examples
+            </a>
+            <a href="{{ .Site.Params.download.source }}" class="btn btn-lg bd-btn-lg btn-outline-secondary" onclick="ga('send', 'event', 'Examples', 'Hero', 'Download');">
+              Download source code
+            </a>
           </div>
           {{ end }}
         </div>
@@ -20,7 +25,7 @@
   </header>
 
   <main class="bd-content order-1 py-5" id="content">
-    <div class="container">
+    <div class="container-xxl bd-gutter">
       {{ .Content }}
 
       {{ if eq .Title "Examples" }}
@@ -30,7 +35,7 @@
             <div class="masthead-followup-icon d-inline-block mb-2 text-white bg-danger">
               {{ partial "icons/droplet-fill.svg" (dict "width" "32" "height" "32") }}
             </div>
-              <h2 class="display-6 fw-normal">Go further with Bootstrap Themes</h2>
+            <h2 class="display-6 fw-normal">Go further with Bootstrap Themes</h2>
             <p class="col-md-10 col-lg-8 mx-auto lead">
               Need something more than these examples? Take Bootstrap to the next level with premium themes from the <a href="{{ .Site.Params.themes }}">official Bootstrap Themes marketplace</a>. They’re built as their own extended frameworks, rich with new components and plugins, documentation, and powerful build tools.
             </p>
index 171a2ad73e87ab82f1363a56f9a93ea3a6fea373..441c2bd56a240422ff24b886748d91f2b7d98fa2 100644 (file)
@@ -1,74 +1,89 @@
-<header class="navbar navbar-expand-md navbar-dark bd-navbar">
-  <nav class="container-xxl flex-wrap flex-md-nowrap" aria-label="Main navigation">
-    <a class="navbar-brand p-0 me-2" href="/" aria-label="Bootstrap">
+<header class="navbar navbar-expand-lg navbar-dark bd-navbar sticky-top">
+  <nav class="container-xxl bd-gutter flex-wrap flex-lg-nowrap" aria-label="Main navigation">
+    {{- if eq .Layout "docs" }}
+      <button class="navbar-toggler p-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#bdSidebar" aria-controls="bdSidebar" aria-expanded="false" aria-label="Toggle docs navigation">
+        {{ partial "icons/hamburger.svg" (dict "class" "bi" "width" "24" "height" "24") }}
+        <span class="d-none fs-6 pe-1">Browse</span>
+      </button>
+    {{- else }}
+      <div class="d-lg-none" style="width: 2.25rem;"></div>
+    {{- end }}
+
+    <a class="navbar-brand p-0 me-0 me-lg-2" href="/" aria-label="Bootstrap">
       {{ partial "icons/bootstrap-white-fill.svg" (dict "class" "d-block my-1" "width" "40" "height" "32") }}
     </a>
 
-    <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#bdNavbar" aria-controls="bdNavbar" aria-expanded="false" aria-label="Toggle navigation">
-      {{ partial "icons/hamburger.svg" (dict "class" "bi" "width" "32" "height" "32") }}
+    <button class="navbar-toggler d-flex d-lg-none order-3 p-2" type="button" data-bs-toggle="offcanvas" data-bs-target="#bdNavbar" aria-controls="bdNavbar" aria-expanded="false" aria-label="Toggle navigation">
+      <svg class="bi" width="24" height="24" aria-hidden="true"><use xlink:href="#three-dots"></use></svg>
     </button>
 
-    <div class="offcanvas offcanvas-end" tabindex="-1" id="bdNavbar" aria-labelledby="bdNavbarOffcanvasLabel">
-      <div class="offcanvas-header pb-0">
+    <div class="offcanvas-lg offcanvas-end flex-grow-1" id="bdNavbar" aria-labelledby="bdNavbarOffcanvasLabel">
+      <div class="offcanvas-header px-4 pb-0">
         <h5 class="offcanvas-title text-white" id="bdNavbarOffcanvasLabel">Bootstrap</h5>
-        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button>
+        <button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close" data-bs-target="#bdNavbar"></button>
       </div>
 
-      <div class="offcanvas-body pt-0">
-        <hr class="d-md-none text-white-50">
+      <div class="offcanvas-body p-4 pt-0 p-lg-0">
+        <hr class="d-lg-none text-white-50">
         <ul class="navbar-nav flex-row flex-wrap bd-navbar-nav">
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2{{ if .IsHome }} active" aria-current="page{{ end }}" href="/" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Bootstrap');">Home</a>
-          </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2{{ if eq .Page.Layout "docs" }} active" aria-current="true{{ end }}" href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Docs');">Docs</a>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2{{ if eq .Page.Layout "docs" }} active" aria-current="true{{ end }}" href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Docs');">Docs</a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2{{ if eq .Page.Title "Examples" }} active" aria-current="true{{ end }}" href="/docs/{{ .Site.Params.docs_version }}/examples/" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Examples');">Examples</a>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2{{ if eq .Page.Title "Examples" }} active" aria-current="true{{ end }}" href="/docs/{{ .Site.Params.docs_version }}/examples/" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Examples');">Examples</a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="{{ .Site.Params.icons }}" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Icons');" target="_blank" rel="noopener">Icons</a>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="{{ .Site.Params.icons }}" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Icons');" target="_blank" rel="noopener">Icons</a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="{{ .Site.Params.themes }}" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Themes');" target="_blank" rel="noopener">Themes</a>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="{{ .Site.Params.themes }}" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Themes');" target="_blank" rel="noopener">Themes</a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="{{ .Site.Params.blog }}" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Blog');" target="_blank" rel="noopener">Blog</a>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="{{ .Site.Params.blog }}" onclick="ga('send', 'event', 'Navbar', 'Community links', 'Blog');" target="_blank" rel="noopener">Blog</a>
           </li>
         </ul>
 
-        <hr class="d-md-none text-white-50">
+        <hr class="d-lg-none text-white-50">
+
+        {{ if eq .Layout "docs" }}
+        <form class="bd-search" data-shortcut="⌘K">
+          <input type="search" class="form-control" id="search-input" placeholder="Search docs..." aria-label="Search docs for..." autocomplete="off" data-bd-docs-version="{{ .Site.Params.docs_version }}">
+        </form>
+
+        <hr class="d-lg-none text-white-50">
+        {{ end }}
 
         <ul class="navbar-nav flex-row flex-wrap ms-md-auto">
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="{{ .Site.Params.github_org }}" target="_blank" rel="noopener">
-              {{ partial "icons/github.svg" (dict "class" "navbar-nav-svg d-inline-block align-text-top" "width" "36" "height" "36") }}
-              <small class="d-md-none ms-2">GitHub</small>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="{{ .Site.Params.github_org }}" target="_blank" rel="noopener">
+              {{ partial "icons/github.svg" (dict "class" "navbar-nav-svg" "width" "16" "height" "16") }}
+              <small class="d-lg-none ms-2">GitHub</small>
             </a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="https://twitter.com/{{ .Site.Params.twitter }}" target="_blank" rel="noopener">
-              {{ partial "icons/twitter.svg" (dict "class" "navbar-nav-svg d-inline-block align-text-top" "width" "36" "height" "36") }}
-              <small class="d-md-none ms-2">Twitter</small>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="https://twitter.com/{{ .Site.Params.twitter }}" target="_blank" rel="noopener">
+              {{ partial "icons/twitter.svg" (dict "class" "navbar-nav-svg" "width" "16" "height" "16") }}
+              <small class="d-lg-none ms-2">Twitter</small>
             </a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="{{ .Site.Params.slack }}" target="_blank" rel="noopener">
-              {{ partial "icons/slack.svg" (dict "class" "navbar-nav-svg d-inline-block align-text-top" "width" "36" "height" "36") }}
-              <small class="d-md-none ms-2">Slack</small>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="{{ .Site.Params.slack }}" target="_blank" rel="noopener">
+              {{ partial "icons/slack.svg" (dict "class" "navbar-nav-svg" "width" "16" "height" "16") }}
+              <small class="d-lg-none ms-2">Slack</small>
             </a>
           </li>
-          <li class="nav-item col-6 col-md-auto">
-            <a class="nav-link p-2" href="{{ .Site.Params.opencollective }}" target="_blank" rel="noopener">
-              {{ partial "icons/opencollective.svg" (dict "class" "navbar-nav-svg d-inline-block align-text-top" "width" "36" "height" "36") }}
-              <small class="d-md-none ms-2">Open Collective</small>
+          <li class="nav-item col-6 col-lg-auto">
+            <a class="nav-link py-2 px-0 px-lg-2" href="{{ .Site.Params.opencollective }}" target="_blank" rel="noopener">
+              {{ partial "icons/opencollective.svg" (dict "class" "navbar-nav-svg" "width" "16" "height" "16") }}
+              <small class="d-lg-none ms-2">Open Collective</small>
             </a>
           </li>
+          <li class="nav-item py-1 col-12 col-lg-auto">
+            <div class="vr d-none d-lg-flex h-100 mx-lg-2 text-white"></div>
+            <hr class="d-lg-none text-white-50">
+          </li>
+          {{ partial "docs-versions" . }}
         </ul>
-
-        <hr class="d-md-none text-white-50">
-
-        <a class="btn btn-bd-accent d-lg-inline-block my-2 my-md-0 ms-md-3" href="/docs/{{ .Site.Params.docs_version }}/getting-started/download/">Download</a>
       </div>
     </div>
   </nav>
index eec268ceb24adb15360972bbfeb44df572805ac9..3ffe9f4d4cd951e68d998d4ceecc2ef4a54894b6 100644 (file)
@@ -1,8 +1,8 @@
-<nav class="collapse bd-links" id="bd-docs-nav" aria-label="Docs navigation">
+<nav class="bd-links w-100">
   {{- $url := split .Permalink "/" -}}
   {{- $page_slug := index $url (sub (len $url) 2) -}}
 
-  <ul class="list-unstyled mb-0 py-3 pt-md-1">
+  <ul class="bd-links-nav list-unstyled mb-0 pb-3 pb-md-2 pe-lg-2">
   {{- range $group := .Site.Data.sidebar -}}
     {{- $link := $group.title -}}
     {{- $link_slug := $link | urlize -}}
     {{- $is_active_group := eq $.Page.Params.group $group_slug -}}
 
     {{- if $group.pages }}
-      <li class="mb-1">
-        <button class="btn d-inline-flex align-items-center rounded{{ if not $is_active_group }} collapsed{{ end }}" data-bs-toggle="collapse" data-bs-target="#{{ $group_slug }}-collapse" aria-expanded="{{ $is_active_group }}"{{ if $is_active_group }} aria-current="true"{{ end }}>
+      <li class="bd-links-group py-2">
+        <strong class="bd-links-heading d-flex w-100 align-items-center fw-semibold">
+          {{- if $group.icon }}
+            <svg class="bi me-2"{{- if $group.icon_color }} style="color: var(--bs-{{ $group.icon_color }});"{{- end }} aria-hidden="true"><use xlink:href="#{{ $group.icon }}"></use></svg>
+          {{- end }}
           {{ $group.title }}
-        </button>
+        </strong>
 
-        <div class="collapse{{ if $is_active_group }} show{{ end }}" id="{{ $group_slug }}-collapse">
-          <ul class="list-unstyled fw-normal pb-1 small">
-            {{- range $doc := $group.pages -}}
-              {{- $doc_slug := $doc.title | urlize -}}
-              {{- $is_active := and $is_active_group (eq $page_slug $doc_slug) -}}
-              {{- $href := printf "/docs/%s/%s/%s/" $.Site.Params.docs_version $group_slug $doc_slug }}
-              <li><a href="{{ $href }}" class="d-inline-flex align-items-center rounded{{ if $is_active }} active{{ end }}"{{ if $is_active }} aria-current="page"{{ end }}>{{ $doc.title }}</a></li>
-            {{- end }}
-          </ul>
-        </div>
+        <ul class="list-unstyled fw-normal pb-2 small">
+          {{- range $doc := $group.pages -}}
+            {{- $doc_slug := $doc.title | urlize -}}
+            {{- $is_active := and $is_active_group (eq $page_slug $doc_slug) -}}
+            {{- $href := printf "/docs/%s/%s/%s/" $.Site.Params.docs_version $group_slug $doc_slug }}
+            <li><a href="{{ $href }}" class="bd-links-link d-inline-block rounded{{ if $is_active }} active{{ end }}"{{ if $is_active }} aria-current="page"{{ end }}>{{ $doc.title }}</a></li>
+          {{- end }}
+        </ul>
       </li>
     {{- else }}
-      <li class="my-3 mx-4 border-top"></li>
-      <li>
-        <a href="/docs/{{ $.Site.Params.docs_version }}/{{ $group_slug }}/" class="d-inline-flex align-items-center rounded{{ if $is_active_group }} active{{ end }}"{{ if $is_active_group }} aria-current="page"{{ end }}>
+      <li class="bd-links-span-all mt-1 mb-3 mx-4 border-top"></li>
+      <li class="bd-links-span-all">
+        <a href="/docs/{{ $.Site.Params.docs_version }}/{{ $group_slug }}/" class="bd-links-link d-inline-block rounded small {{ if $is_active_group }} active{{ end }}"{{ if $is_active_group }} aria-current="page"{{ end }}>
           {{ $group.title }}
         </a>
       </li>
diff --git a/site/layouts/partials/docs-subnav.html b/site/layouts/partials/docs-subnav.html
deleted file mode 100644 (file)
index 9f2faf3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<nav class="bd-subnavbar py-2" aria-label="Secondary navigation">
-  <div class="container-xxl d-flex align-items-md-center">
-    <form class="bd-search position-relative me-auto">
-      <input type="search" class="form-control" id="search-input" placeholder="Search docs..." aria-label="Search docs for..." autocomplete="off" data-bd-docs-version="{{ .Site.Params.docs_version }}">
-    </form>
-
-    {{ partial "docs-versions" . }}
-
-    <button class="btn bd-sidebar-toggle d-md-none py-0 px-1 ms-3 order-3 collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#bd-docs-nav" aria-controls="bd-docs-nav" aria-expanded="false" aria-label="Toggle docs navigation">
-      {{ partial "icons/expand.svg" (dict "class" "bi bi-expand" "width" "24" "height" "24") }}
-      {{ partial "icons/collapse.svg" (dict "class" "bi bi-collapse" "width" "24" "height" "24") }}
-    </button>
-  </div>
-</nav>
index a38a81823041bab1d9df2077879f7fd32a695e5c..dd234c387beb328a534f40eefaa3b824ead16dc5 100644 (file)
@@ -1,14 +1,30 @@
-<div class="dropdown ms-3">
-  <button class="btn btn-bd-light dropdown-toggle" id="bd-versions" data-bs-toggle="dropdown" aria-expanded="false" data-bs-display="static">
-    <span class="d-none d-lg-inline">Bootstrap</span> v{{ .Site.Params.docs_version }}
-  </button>
+{{- $url := split .Permalink "/" -}}
+{{- $group_slug := index $url (sub (len $url) 3) -}}
+{{- $page_slug := index $url (sub (len $url) 2) -}}
+
+<li class="nav-item dropdown">
+  <a href="#" class="nav-link py-2 px-0 px-lg-2 dropdown-toggle" id="bd-versions" data-bs-toggle="dropdown" aria-expanded="false" data-bs-display="static">
+    <span class="d-lg-none">Bootstrap</span> v{{ .Site.Params.docs_version }}
+  </a>
   <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="bd-versions">
+    <li><h6 class="dropdown-header">v5 releases</h6></li>
     <li><a class="dropdown-item current" aria-current="true" href="/docs/{{ .Site.Params.docs_version }}/">Latest ({{ .Site.Params.docs_version }}.x)</a></li>
+    <li>
+      <a class="dropdown-item" href="https://getbootstrap.com/docs/5.1/{{ $group_slug }}/{{ $page_slug }}/">v5.1.3</a>
+    </li>
+    <li>
+      {{- if eq .Page.Params.added "5.1" }}
+        <div class="dropdown-item disabled">v5.0.2</div>
+      {{- else }}
+        <a class="dropdown-item" href="https://getbootstrap.com/docs/5.0/{{ $group_slug }}/{{ $page_slug }}/">v5.0.2</a>
+      {{- end }}
+    </li>
     <li><hr class="dropdown-divider"></li>
+    <li><h6 class="dropdown-header">Previous releases</h6></li>
     <li><a class="dropdown-item" href="https://getbootstrap.com/docs/4.6/">v4.6.x</a></li>
     <li><a class="dropdown-item" href="https://getbootstrap.com/docs/3.4/">v3.4.1</a></li>
     <li><a class="dropdown-item" href="https://getbootstrap.com/2.3.2/">v2.3.2</a></li>
     <li><hr class="dropdown-divider"></li>
     <li><a class="dropdown-item" href="/docs/versions/">All versions</a></li>
   </ul>
-</div>
+</li>
index 50f6a5bbba159fe8437f1c44afea2c0ebf33b2c7..58bdb8b8b3f9c717bb9fbc9a118689a097956c80 100644 (file)
@@ -3,6 +3,6 @@
 <link rel="icon" href="/docs/{{ .Site.Params.docs_version }}/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
 <link rel="icon" href="/docs/{{ .Site.Params.docs_version }}/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png">
 <link rel="manifest" href="/docs/{{ .Site.Params.docs_version }}/assets/img/favicons/manifest.json">
-<link rel="mask-icon" href="/docs/{{ .Site.Params.docs_version }}/assets/img/favicons/safari-pinned-tab.svg" color="#7952b3">
+<link rel="mask-icon" href="/docs/{{ .Site.Params.docs_version }}/assets/img/favicons/safari-pinned-tab.svg" color="#712cf9">
 <link rel="icon" href="/docs/{{ .Site.Params.docs_version }}/assets/img/favicons/favicon.ico">
-<meta name="theme-color" content="#7952b3">
+<meta name="theme-color" content="#712cf9">
index e3d0f13e41d984be108179e2015d10073a2b8980..2cd5fc2bc33a13d573a9d5dc92ad0d0c59ac0135 100644 (file)
@@ -1,5 +1,5 @@
-<footer class="bd-footer py-5 mt-5 bg-light">
-  <div class="container py-5">
+<footer class="bd-footer py-4 py-md-5 mt-5 bg-light">
+  <div class="container py-4 py-md-5 px-4 px-md-3">
     <div class="row">
       <div class="col-lg-3 mb-3">
         <a class="d-inline-flex align-items-center mb-2 link-dark text-decoration-none" href="/" aria-label="Bootstrap">
@@ -20,6 +20,7 @@
           <li class="mb-2"><a href="/docs/{{ .Site.Params.docs_version }}/examples/">Examples</a></li>
           <li class="mb-2"><a href="{{ .Site.Params.themes }}">Themes</a></li>
           <li class="mb-2"><a href="{{ .Site.Params.blog }}">Blog</a></li>
+          <li class="mb-2"><a href="{{ .Site.Params.swag }}">Swag Store</a></li>
         </ul>
       </div>
       <div class="col-6 col-lg-2 mb-3">
index 48f77f47041ceb61fb066f93079520ca369dbcc9..95f394f5ade098ecd81bd630b9228ff15a6ae56a 100644 (file)
@@ -1,37 +1,39 @@
-<div class="container masthead-followup px-4 px-md-3">
-  <section class="row mb-5 pb-md-4 align-items-center">
-    <div class="col-md-5">
-      <div class="masthead-followup-icon d-inline-block mb-2 text-white bg-success">
-        {{ partial "icons/code.svg" (dict "width" "32" "height" "32") }}
-      </div>
-      <h2 class="display-5 fw-normal">Installation</h2>
-      <p class="lead fw-normal">
-        Install Bootstrap’s source Sass and JavaScript files via npm, Composer, or Meteor.
-      </p>
-      <p>Package managed installs don’t include documentation or our full build scripts. You can also <a href="https://github.com/twbs/bootstrap-npm-starter">use our npm template repo</a> to quickly generate a Bootstrap project via npm.</p>
-      <a class="btn btn-lg btn-outline-primary mb-3" href="/docs/{{ .Site.Params.docs_version }}/getting-started/download/">Read installation docs</a>
-    </div>
-    <div class="col-md-7 ps-md-5">
-      {{ highlight "npm install bootstrap" "sh" "" }}
-      {{ highlight (printf ("gem install bootstrap -v %s") .Site.Params.current_ruby_version) "sh" "" }}
+<div class="container-xxl bd-gutter masthead-followup">
+  <div class="col-lg-7 mx-auto pb-3 mb-3 mb-md-5 text-md-center">
+    <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bd-violet-rgb);">
+      <svg class="bi fs-1"><use xlink:href="#code"></use></svg>
     </div>
-  </section>
+    <h2 class="display-5 mb-3 fw-semibold lh-sm">Get started any way you&nbsp;want</h2>
+    <p class="lead fw-normal">
+      Jump right into building with Bootstrap—use the CDN, install it via package manager, or download the source code.
+    </p>
+    <p class="d-flex justify-content-md-start justify-content-md-center lead fw-normal">
+      <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/download/" class="icon-link fw-semibold justify-content-center ps-md-4">
+        Read installation docs
+        <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+      </a>
+    </p>
+  </div>
 
-  <section class="row mb-5 pb-md-4 align-items-center">
-    <div class="col-md-5">
-      <div class="masthead-followup-icon d-inline-block mb-2 text-white bg-primary">
-        {{ partial "icons/cloud-fill.svg" (dict "width" "32" "height" "32") }}
-      </div>
-      <h2 class="display-5 fw-normal">jsDelivr</h2>
-      <p class="lead fw-normal">
-        When you only need to include Bootstrap’s compiled CSS or JS, you can use <a href="https://www.jsdelivr.com/">jsDelivr</a>.
+  <section class="row g-3 g-md-5 mb-5 pb-5 justify-content-center">
+    <div class="col-lg-6 py-lg-4 pe-lg-5">
+      <svg class="bi mb-2 fs-2 text-muted"><use xlink:href="#box-seam"></use></svg>
+      <h3 class="fw-semibold">Install via package manager</h3>
+      <p class="pe-lg-5">
+        Install Bootstrap’s source Sass and JavaScript files via npm, RubyGems, Composer, or Meteor. Package managed installs don’t include documentation or our full build scripts. You can also <a href="https://github.com/twbs/bootstrap-npm-starter">use our npm template repo</a> to quickly generate a Bootstrap project via npm.
       </p>
+      {{ highlight "npm install bootstrap" "sh" "" }}
+      {{ highlight (printf ("gem install bootstrap -v %s") .Site.Params.current_ruby_version) "sh" "" }}
       <p>
-        See it in action with our simple <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/#starter-template">starter template</a>, or <a href="/docs/{{ .Site.Params.docs_version }}/examples/">browse the examples</a> to jumpstart your next project. You can also choose to include Popper and our JS <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/#separate">separately</a>.
+        <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/download/">Read our installation docs</a> for more info and additional package managers.
       </p>
-      <a class="btn btn-lg btn-outline-primary mb-3" href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/">Explore the docs</a>
     </div>
-    <div class="col-md-7 ps-md-5">
+    <div class="col-lg-6 py-lg-4 ps-lg-5 border-lg-start">
+      <svg class="bi mb-2 fs-2 text-muted"><use xlink:href="#globe2"></use></svg>
+      <h3 class="fw-semibold">Include via CDN</h3>
+      <p class="pe-lg-5">
+        When you only need to include Bootstrap’s compiled CSS or JS, you can use <a href="https://www.jsdelivr.com/package/npm/bootstrap">jsDelivr</a>. See it in action with our simple <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/#starter-template">starter template</a>, or <a href="/docs/{{ .Site.Params.docs_version }}/examples/">browse the examples</a> to jumpstart your next project. You can also choose to include Popper and our JS <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/#separate">separately</a>.
+      </p>
       {{ highlight (printf (`<!-- CSS only -->
 <link href="%s" rel="stylesheet" integrity=%q crossorigin="anonymous">
 `) .Site.Params.cdn.css (.Site.Params.cdn.css_hash | safeHTMLAttr)) "html" "" }}
     </div>
   </section>
 
-  <section class="row mb-5 pb-md-4 align-items-center">
-    <div class="col-md-5">
-      <div class="masthead-followup-icon d-inline-block mb-2 text-white bd-bg-violet">
+  <section class="col-lg-7 mb-5">
+    <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bs-primary-rgb);">
+      <svg class="bi fs-1"><use xlink:href="#palette2"></use></svg>
+    </div>
+    <h2 class="display-5 mb-3 fw-semibold lh-sm">Customize everything with&nbsp;Sass</h2>
+    <p class="lead fw-normal">
+      Bootstrap utilizes Sass for a modular and customizable architecture. Import only the components you need, enable global options like gradients and shadows, and write your own CSS with our variables, maps, functions, and mixins.
+    </p>
+    <p class="d-flex justify-content-start lead fw-normal">
+      <a href="/docs/{{ .Site.Params.docs_version }}/customize/overview/" class="icon-link fw-semibold">
+        Learn more about customizing
+        <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+      </a>
+    </p>
+  </section>
+
+  <section class="row g-md-5 mb-5 pb-md-5">
+    <div class="col-lg-6">
+      <h3>Include all of Bootstrap’s Sass</h3>
+      <p>Import one stylesheet and you're off to the races with every feature of our CSS.</p>
+      {{ highlight (printf `// Variable overrides first
+$primary: #900;
+$enable-shadows: true;
+$variable-prefix: "mo-";
+
+// Then import Bootstrap
+@import "../node_modules/bootstrap/scss/bootstrap";
+`) "scss" "" }}
+      <p>Learn more about our <a href="/docs/{{ .Site.Params.docs_version }}/customize/options/">global Sass options</a>.</p>
+    </div>
+    <div class="col-lg-6">
+      <h3>Include what you need</h3>
+      <p>The easiest way to customize Bootstrap—include only the CSS you need.</p>
+{{ highlight (printf `// Functions first
+@import "../node_modules/bootstrap/scss/functions";
+
+// Variable overrides second
+$primary: #900;
+$enable-shadows: true;
+$variable-prefix: "mo-";
+
+// Required Bootstrap imports
+@import "../node_modules/bootstrap/scss/variables";
+@import "../node_modules/bootstrap/scss/maps";
+@import "../node_modules/bootstrap/scss/mixins";
+@import "../node_modules/bootstrap/scss/root";
+
+// Optional components
+@import "../node_modules/bootstrap/scss/utilities";
+@import "../node_modules/bootstrap/scss/reboot";
+@import "../node_modules/bootstrap/scss/containers";
+@import "../node_modules/bootstrap/scss/grid";
+@import "../node_modules/bootstrap/scss/helpers";
+@import "../node_modules/bootstrap/scss/utilities/api";
+`) "scss" "" }}
+      <p>Learn more about <a href="/docs/{{ .Site.Params.docs_version }}/customize/sass/">using Bootstrap with Sass</a>.</p>
+    </div>
+  </section>
+
+  <section class="row g-md-5 pb-md-5 mb-5 align-items-center">
+    <div class="col-lg-8 mb-5">
+      <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bd-pink-rgb);">
+        <svg class="bi fs-1"><use xlink:href="#braces"></use></svg>
+      </div>
+      <h2 class="display-5 mb-3 fw-semibold lh-sm">Build and extend in real-time with CSS&nbsp;variables</h2>
+      <p class="lead fw-normal">
+        Bootstrap 5 is evolving with each release to better utilize CSS variables for global theme styles, individual components, and even utilities. We provide dozens of variables for colors, font styles, and more at a <code>:root</code> level for use anywhere. On components and utilities, CSS variables are scoped to the relevant class and can easily be modified.
+      </p>
+      <p class="d-flex align-items-start flex-column lead fw-normal mb-0">
+        <a href="/docs/{{ .Site.Params.docs_version }}/customize/css-variables/" class="icon-link fw-semibold mb-3">
+          Learn more about CSS variables
+          <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+        </a>
+      </p>
+    </div>
+    <div class="row gx-md-5">
+      <div class="col-lg-6 mb-3">
+        <h3 class="fw-semibold">Using CSS variables</h3>
+        <p>Use any of our <a href="/docs/{{ .Site.Params.docs_version }}/customize/css-variables/#root-variables">global <code>:root</code> variables</a> to write new styles. CSS variables use the <code>var(--bs-variableName)</code> syntax and can be inherited by children elements.</p>
+        {{ highlight (printf `.component {
+  color: var(--bs-gray-800);
+  background-color: var(--bs-gray-100);
+  border: 1px solid var(--bs-gray-200);
+  border-radius: .25rem;
+}
+
+.component-header {
+  color: var(--bs-purple);
+}`) "scss" "" }}
+      </div>
+      <div class="col-lg-6 mb-3">
+        <h3 class="fw-semibold">Customizing via CSS variables</h3>
+        <p>Override global, component, or utility class variables to customize Bootstrap just how you like. No need to redeclare each rule, just a new variable value.</p>
+        {{ highlight (printf `body {
+  --bs-body-font-family: var(--bs-font-monospace);
+  --bs-body-line-height: 1.4;
+  --bs-body-bg: var(--bs-gray-100);
+}
+
+.table {
+  --bs-table-color: var(--bs-gray-600);
+  --bs-table-bg: var(--bs-gray-100);
+  --bs-table-border-color: transparent;
+}`) "scss" "" }}
+      </div>
+    </div>
+  </section>
+
+  <section class="row g-md-5 pb-md-5 mb-5 align-items-center">
+    <div class="col-lg-6 mb-5 mb-md-0">
+      <div class="masthead-followup-icon d-inline-block mb-3 me-2" style="--bg-rgb: var(--bs-danger-rgb);">
+        <svg class="bi fs-1"><use xlink:href="#menu-button-wide-fill"></use></svg>
+      </div>
+      <svg class="bi me-2 fs-2 text-muted"><use xlink:href="#plus"></use></svg>
+      <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bs-info-rgb);">
+        <svg class="bi fs-1"><use xlink:href="#braces-asterisk"></use></svg>
+      </div>
+      <h2 class="display-5 mb-3 fw-semibold lh-sm">Components, meet the Utility&nbsp;API</h2>
+      <p class="lead fw-normal">
+        New in Bootstrap 5, our utilities are now generated by our <a href="/docs/{{ .Site.Params.docs_version }}/utilities/api/">Utility API</a>. We built it as a feature-packed Sass map that can be quickly and easily customized. It's never been easier to add, remove, or modify any utility classes. Make utilities responsive, add pseudo-class variants, and give them custom names.
+      </p>
+      <p class="d-flex align-items-start flex-column lead fw-normal mb-0">
+        <a href="/docs/{{ .Site.Params.docs_version }}/utilities/api/" class="icon-link fw-semibold mb-3">
+          Learn more about utilities
+          <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+        </a>
+        <a href="/docs/{{ .Site.Params.docs_version }}/examples#snippets" class="icon-link fw-semibold">
+          Explore customized components
+          <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+        </a>
+      </p>
+    </div>
+    <div class="col-lg-6">
+      <div class="p-4 border rounded-3 mb-4">
+        <h6>Quickly customize components</h6>
+        <hr class="mb-4">
+        <ul class="nav nav-pills mb-4" id="pillNav" role="tablist">
+          <li class="nav-item" role="presentation">
+            <button class="nav-link active" id="home-tab" data-bs-toggle="tab" type="button" role="tab" aria-selected="true">Home</button>
+          </li>
+          <li class="nav-item" role="presentation">
+            <button class="nav-link" id="profile-tab" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">Profile</button>
+          </li>
+          <li class="nav-item" role="presentation">
+            <button class="nav-link" id="contact-tab" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">Contact</button>
+          </li>
+        </ul>
+        <ul class="nav nav-pills nav-fill gap-2 p-1 small bg-white border rounded-5 shadow-sm" id="pillNav2" role="tablist">
+          <li class="nav-item" role="presentation">
+            <button class="nav-link active rounded-5" id="home-tab2" data-bs-toggle="tab" type="button" role="tab" aria-selected="true">Home</button>
+          </li>
+          <li class="nav-item" role="presentation">
+            <button class="nav-link rounded-5" id="profile-tab2" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">Profile</button>
+          </li>
+          <li class="nav-item" role="presentation">
+            <button class="nav-link rounded-5" id="contact-tab2" data-bs-toggle="tab" type="button" role="tab" aria-selected="false">Contact</button>
+          </li>
+        </ul>
+      </div>
+  {{ highlight (printf `// Create and extend utilities with the Utility API
+
+@import "bootstrap/scss/bootstrap";
+
+$utilities: map-merge(
+  $utilities,
+  (
+    "cursor": (
+      property: cursor,
+      class: cursor,
+      responsive: true,
+      values: auto pointer grab,
+    )
+  )
+);
+`) "scss" "" }}
+    </div>
+  </section>
+
+  <section class="pb-md-5 mb-5">
+    <div class="col-lg-8 mb-5">
+      <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bs-warning-rgb);">
+        <svg class="bi fs-1"><use xlink:href="#plugin"></use></svg>
+      </div>
+      <h2 class="display-5 mb-3 fw-semibold lh-sm">Powerful JavaScript plugins without&nbsp;jQuery</h2>
+      <p class="lead fw-normal">
+        Easily add toggleable hidden elements, modals and offcanvas menus, popovers and tooltips, and so much more—all without jQuery. JavaScript in Bootstrap is HTML-first, which means adding plugins is as easy as adding <code>data</code> attributes. Need more control? Include individual plugins programmatically.
+      </p>
+      <p class="d-flex justify-content-start lead fw-normal mb-md-0">
+        <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/javascript/" class="icon-link fw-semibold">
+          Learn more about Bootstrap JavaScript
+          <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+        </a>
+      </p>
+    </div>
+    <div class="row gx-md-5">
+      <div class="col-lg-6 mb-3">
+        <h3 class="fw-semibold">Data attribute API</h3>
+        <p>Why write more JavaScript when you can write HTML? Nearly all of Bootstrap's JavaScript plugins feature a first-class data API, allowing you to use JavaScript just by adding <code>data</code> attributes.</p>
+        <div class="p-4 mb-3 border rounded-3">
+          <div class="dropdown">
+            <button class="btn btn-primary dropdown-toggle" type="button" id="dropdown" data-bs-toggle="dropdown" aria-expanded="false">
+              Dropdown
+            </button>
+            <ul class="dropdown-menu" aria-labelledby="dropdown">
+              <li><a class="dropdown-item" href="#">Dropdown item</a></li>
+              <li><a class="dropdown-item" href="#">Dropdown item</a></li>
+              <li><a class="dropdown-item" href="#">Dropdown item</a></li>
+            </ul>
+          </div>
+        </div>
+
+        {{ highlight (printf `<div class="dropdown">
+  <button class="btn btn-primary dropdown-toggle" type="button" id="dropdown" data-bs-toggle="dropdown" aria-expanded="false">
+    Dropdown
+  </button>
+  <ul class="dropdown-menu" aria-labelledby="dropdown">
+    <li><a class="dropdown-item" href="#">Dropdown item</a></li>
+    <li><a class="dropdown-item" href="#">Dropdown item</a></li>
+    <li><a class="dropdown-item" href="#">Dropdown item</a></li>
+  </ul>
+</div>
+`) "html" "" }}
+        <p>Learn more about <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/javascript/#using-bootstrap-as-a-module">our JavaScript as modules</a> and <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/javascript/#programmatic-api">using the programmatic API</a>.</p>
+      </div>
+      <div class="col-lg-6 mb-3">
+        <h3 class="fw-semibold">Comprehensive set of plugins</h3>
+        <p>Bootstrap features a dozen plugins that you can drop into any project. Drop them in all at once, or choose just the ones you need.</p>
+        <hr class="my-4">
+        <div class="row g-3">
+          {{- range $plugin := .Site.Data.plugins -}}
+            {{- $href := printf "/docs/%s/%s" $.Site.Params.docs_version $plugin.link }}
+            <div class="col-sm-6 mb-2">
+              <a class="d-block pe-lg-4 text-decoration-none lh-sm" href="{{ $href }}">
+                <h4 class="mb-0 fs-5 fw-semibold">{{ $plugin.name }}</h4>
+                <small class="text-muted">{{ $plugin.description }}</small>
+              </a>
+            </div>
+          {{- end }}
+        </div>
+      </div>
+    </div>
+
+  </section>
+
+  <section class="row g-3 g-md-5 pb-md-5 mb-5 align-items-center">
+    <div class="col-lg-6">
+      <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bd-teal-rgb);">
         {{ partial "icons/circle-square.svg" (dict "width" "32" "height" "32") }}
       </div>
-      <h2 class="display-5 fw-normal">Bootstrap Icons</h2>
+      <h2 class="display-5 mb-3 fw-semibold lh-sm">Personalize it with Bootstrap&nbsp;Icons</h2>
       <p class="lead fw-normal">
-        For the first time ever, Bootstrap has its own open source SVG icon library, designed to work best with our components and documentation.
+        <a href="{{ .Site.Params.icons }}">Bootstrap Icons</a> is an open source SVG icon library featuring over 1,500 glyphs, with more added every release. They're designed to work in any project, whether you use Bootstrap itself or not. Use them as SVGs or icon fonts—both options give you vector scaling and easy customization via CSS.
       </p>
-      <p>
-        Bootstrap Icons are designed to work best with Bootstrap components, but they’ll work in any project. They’re SVGs, so they scale quickly and easily, can be implemented in several ways, and can be styled with CSS.
+      <p class="d-flex justify-content-start lead fw-normal mb-md-0">
+        <a href="{{ .Site.Params.icons }}" class="icon-link fw-semibold">
+          Get Bootstrap Icons
+          <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+        </a>
       </p>
-      <a href="{{ .Site.Params.icons }}" class="btn btn-lg btn-outline-primary mb-3">Get Bootstrap Icons</a>
     </div>
-    <div class="col-md-7 ps-md-5">
+    <div class="col-lg-6">
         <img class="img-fluid mt-3 mx-auto" srcset="/docs/{{ .Site.Params.docs_version }}/assets/img/bootstrap-icons.png,
                                                     /docs/{{ .Site.Params.docs_version }}/assets/img/bootstrap-icons@2x.png 2x"
                                             src="/docs/{{ .Site.Params.docs_version }}/assets/img/bootstrap-icons.png"
     </div>
   </section>
 
-  <section class="row mb-5 pb-md-4 align-items-center">
-    <div class="col-md-5">
-      <div class="masthead-followup-icon d-inline-block mb-2 text-white bg-danger">
+  <section class="row g-3 g-md-5 pb-md-5 mb-5 align-items-center">
+    <div class="col-lg-6">
+      <div class="masthead-followup-icon d-inline-block mb-3" style="--bg-rgb: var(--bd-violet-rgb);">
         {{ partial "icons/droplet-fill.svg" (dict "width" "32" "height" "32") }}
       </div>
-      <h2 class="display-5 fw-normal">Official Themes</h2>
+      <h2 class="display-5 mb-3 fw-semibold lh-sm">Make it yours with official Bootstrap Themes</h2>
       <p class="lead fw-normal">
-        Take Bootstrap to the next level with premium themes from the <a href="{{ .Site.Params.themes }}">official Bootstrap Themes marketplace</a>.
+        Take Bootstrap to the next level with premium themes from the <a href="{{ .Site.Params.themes }}">official Bootstrap Themes marketplace</a>. Themes are built on Bootstrap as their own extended frameworks, rich with new components and plugins, documentation, and powerful build tools.
       </p>
-      <p>
-        Themes are built on Bootstrap as their own extended frameworks, rich with new components and plugins, documentation, and powerful build tools.
+      <p class="d-flex justify-content-start lead fw-normal mb-md-0">
+        <a href="{{ .Site.Params.themes }}" class="icon-link fw-semibold">
+          Browse Bootstrap Themes
+          <svg class="bi"><use xlink:href="#arrow-right-short"></use></svg>
+        </a>
       </p>
-      <a href="{{ .Site.Params.themes }}" class="btn btn-lg btn-outline-primary mb-3">Browse themes</a>
     </div>
-    <div class="col-md-7 ps-md-5">
+    <div class="col-lg-6">
         <img class="img-fluid mt-3 mx-auto" srcset="/docs/{{ .Site.Params.docs_version }}/assets/img/bootstrap-themes.png,
                                                     /docs/{{ .Site.Params.docs_version }}/assets/img/bootstrap-themes@2x.png 2x"
                                             src="/docs/{{ .Site.Params.docs_version }}/assets/img/bootstrap-themes.png"
index e5661d9b3380df70caaf8cbe1ae3106f4be7559d..63ce0e3b19c86b5db8116a97bcabd86c0d704936 100644 (file)
@@ -1,28 +1,34 @@
 <div class="bd-masthead mb-3" id="content">
-  <div class="container px-4 px-md-3">
-    <div class="row align-items-lg-center">
-      <div class="col-8 mx-auto col-md-4 order-md-2 col-lg-5">
-        {{ partial "icons/homepage-hero.svg" (dict "class" "img-fluid mb-3 mb-md-0" "width" "600" "height" "533") }}
-      </div>
-      <div class="col-md-8 order-md-1 col-lg-7 text-center text-md-start">
-        <h1 class="mb-3">Build fast, responsive sites with Bootstrap</h1>
-        <p class="lead mb-4">
-          Quickly design and customize responsive mobile-first sites with Bootstrap, the world’s most popular front-end open source toolkit, featuring Sass variables and mixins, responsive grid system, extensive prebuilt components, and powerful JavaScript plugins.
-        </p>
-
-        <div class="d-flex flex-column flex-md-row">
-          <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/" class="btn btn-lg btn-bd-primary mb-3 me-md-3" onclick="ga('send', 'event', 'Jumbotron actions', 'Get started', 'Get started');">Get started</a>
-          <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/download/" class="btn btn-lg btn-outline-secondary mb-3" onclick="ga('send', 'event', 'Jumbotron actions', 'Download', 'Download {{ .Site.Params.current_version }}');">Download</a>
+  <div class="container-xxl bd-gutter">
+    <div class="col-md-8 mx-auto text-center">
+      <a class="d-flex flex-column flex-lg-row justify-content-center align-items-center mb-4 text-dark lh-sm text-decoration-none" href="https://blog.getbootstrap.com/2021/08/04/bootstrap-5-1-0/">
+        <strong class="d-sm-inline-block p-2 me-2 mb-2 mb-lg-0 rounded-3 masthead-notice">New in v5.1</strong>
+        <span class="text-muted">CSS Grid, offcanvas navbars, improved utilities, and more!</span>
+      </a>
+      <img src="/docs/{{ .Site.Params.docs_version }}/assets/brand/bootstrap-logo-shadow.png" width="200" height="165" alt="Bootstrap" class="d-block mx-auto mb-3">
+      <h1 class="mb-3 fw-semibold">Build fast, responsive sites with&nbsp;Bootstrap</h1>
+      <p class="lead mb-4">
+        Powerful, extensible, and feature-packed frontend toolkit. Build and customize with Sass, utilize prebuilt grid system and components, and bring projects to life with powerful JavaScript plugins.
+      </p>
+      <div class="d-flex flex-column flex-md-row align-items-md-stretch justify-content-md-center gap-3 mb-4">
+        <div class="d-inline-block v-align-middle fs-5" style="min-width: fit-content;">
+          {{ highlight "npm i bootstrap" "sh" "" }}
         </div>
-        <p class="text-muted mb-0">
-          Currently <strong>v{{ .Site.Params.current_version }}</strong>
-          <span class="px-1">&middot;</span>
-          <a href="https://getbootstrap.com/docs/4.6/getting-started/introduction/" class="link-secondary">v4.6.x docs</a>
-          <span class="px-1">&middot;</span>
-          <a href="/docs/versions/" class="link-secondary">All releases</a>
-        </p>
+        <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/introduction/" class="btn btn-lg bd-btn-lg btn-bd-primary d-flex align-items-center justify-content-center fw-semibold" onclick="ga('send', 'event', 'Jumbotron actions', 'Get started', 'Get started');">
+          <svg class="bi me-2" aria-hidden="true"><use xlink:href="#book-half"></use></svg>
+          Read the docs
+        </a>
       </div>
+      <p class="text-muted mb-0">
+        Currently <strong>v{{ .Site.Params.current_version }}</strong>
+        <span class="px-1">&middot;</span>
+        <a href="/docs/{{ .Site.Params.docs_version }}/getting-started/download/" class="link-secondary">Download</a>
+        <span class="px-1">&middot;</span>
+        <a href="https://getbootstrap.com/docs/4.6/getting-started/introduction/" class="link-secondary text-nowrap">v4.6.x docs</a>
+        <span class="px-1">&middot;</span>
+        <a href="/docs/versions/" class="link-secondary text-nowrap">All releases</a>
+      </p>
+      {{ partial "ads" . }}
     </div>
-    {{ partial "ads" . }}
   </div>
 </div>
diff --git a/site/layouts/partials/icons.html b/site/layouts/partials/icons.html
new file mode 100644 (file)
index 0000000..9841e14
--- /dev/null
@@ -0,0 +1,72 @@
+<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
+  <symbol id="arrow-right-short" viewBox="0 0 16 16">
+    <path fill-rule="evenodd" d="M4 8a.5.5 0 0 1 .5-.5h5.793L8.146 5.354a.5.5 0 1 1 .708-.708l3 3a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708-.708L10.293 8.5H4.5A.5.5 0 0 1 4 8z"/>
+  </symbol>
+  <symbol id="book-half" viewBox="0 0 16 16">
+    <path d="M8.5 2.687c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z"/>
+  </symbol>
+  <symbol id="box-seam" viewBox="0 0 16 16">
+    <path d="M8.186 1.113a.5.5 0 0 0-.372 0L1.846 3.5l2.404.961L10.404 2l-2.218-.887zm3.564 1.426L5.596 5 8 5.961 14.154 3.5l-2.404-.961zm3.25 1.7-6.5 2.6v7.922l6.5-2.6V4.24zM7.5 14.762V6.838L1 4.239v7.923l6.5 2.6zM7.443.184a1.5 1.5 0 0 1 1.114 0l7.129 2.852A.5.5 0 0 1 16 3.5v8.662a1 1 0 0 1-.629.928l-7.185 2.874a.5.5 0 0 1-.372 0L.63 13.09a1 1 0 0 1-.63-.928V3.5a.5.5 0 0 1 .314-.464L7.443.184z"/>
+  </symbol>
+  <symbol id="braces" viewBox="0 0 16 16">
+    <path d="M2.114 8.063V7.9c1.005-.102 1.497-.615 1.497-1.6V4.503c0-1.094.39-1.538 1.354-1.538h.273V2h-.376C3.25 2 2.49 2.759 2.49 4.352v1.524c0 1.094-.376 1.456-1.49 1.456v1.299c1.114 0 1.49.362 1.49 1.456v1.524c0 1.593.759 2.352 2.372 2.352h.376v-.964h-.273c-.964 0-1.354-.444-1.354-1.538V9.663c0-.984-.492-1.497-1.497-1.6zM13.886 7.9v.163c-1.005.103-1.497.616-1.497 1.6v1.798c0 1.094-.39 1.538-1.354 1.538h-.273v.964h.376c1.613 0 2.372-.759 2.372-2.352v-1.524c0-1.094.376-1.456 1.49-1.456V7.332c-1.114 0-1.49-.362-1.49-1.456V4.352C13.51 2.759 12.75 2 11.138 2h-.376v.964h.273c.964 0 1.354.444 1.354 1.538V6.3c0 .984.492 1.497 1.497 1.6z"/>
+  </symbol>
+  <symbol id="braces-asterisk" viewBox="0 0 16 16">
+    <path fill-rule="evenodd" d="M1.114 8.063V7.9c1.005-.102 1.497-.615 1.497-1.6V4.503c0-1.094.39-1.538 1.354-1.538h.273V2h-.376C2.25 2 1.49 2.759 1.49 4.352v1.524c0 1.094-.376 1.456-1.49 1.456v1.299c1.114 0 1.49.362 1.49 1.456v1.524c0 1.593.759 2.352 2.372 2.352h.376v-.964h-.273c-.964 0-1.354-.444-1.354-1.538V9.663c0-.984-.492-1.497-1.497-1.6ZM14.886 7.9v.164c-1.005.103-1.497.616-1.497 1.6v1.798c0 1.094-.39 1.538-1.354 1.538h-.273v.964h.376c1.613 0 2.372-.759 2.372-2.352v-1.524c0-1.094.376-1.456 1.49-1.456v-1.3c-1.114 0-1.49-.362-1.49-1.456V4.352C14.51 2.759 13.75 2 12.138 2h-.376v.964h.273c.964 0 1.354.444 1.354 1.538V6.3c0 .984.492 1.497 1.497 1.6ZM7.5 11.5V9.207l-1.621 1.621-.707-.707L6.792 8.5H4.5v-1h2.293L5.172 5.879l.707-.707L7.5 6.792V4.5h1v2.293l1.621-1.621.707.707L9.208 7.5H11.5v1H9.207l1.621 1.621-.707.707L8.5 9.208V11.5h-1Z"/>
+  </symbol>
+  <symbol id="check2" viewBox="0 0 16 16">
+    <title>Check</title>
+    <path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>
+  </symbol>
+  <symbol id="chevron-expand" viewBox="0 0 16 16">
+    <path fill-rule="evenodd" d="M3.646 9.146a.5.5 0 0 1 .708 0L8 12.793l3.646-3.647a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 0-.708zm0-2.292a.5.5 0 0 0 .708 0L8 3.207l3.646 3.647a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 0 0 0 .708z"/>
+  </symbol>
+  <symbol id="clipboard" viewBox="0 0 16 16">
+    <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
+    <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
+  </symbol>
+  <symbol id="code" viewBox="0 0 16 16">
+    <path d="M5.854 4.854a.5.5 0 1 0-.708-.708l-3.5 3.5a.5.5 0 0 0 0 .708l3.5 3.5a.5.5 0 0 0 .708-.708L2.707 8l3.147-3.146zm4.292 0a.5.5 0 0 1 .708-.708l3.5 3.5a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708-.708L13.293 8l-3.147-3.146z"/>
+  </symbol>
+  <symbol id="file-earmark-richtext" viewBox="0 0 16 16">
+    <path d="M14 4.5V14a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2h5.5L14 4.5zm-3 0A1.5 1.5 0 0 1 9.5 3V1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4.5h-2z"/>
+    <path d="M4.5 12.5A.5.5 0 0 1 5 12h3a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm0-2A.5.5 0 0 1 5 10h6a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm1.639-3.708 1.33.886 1.854-1.855a.25.25 0 0 1 .289-.047l1.888.974V8.5a.5.5 0 0 1-.5.5H5a.5.5 0 0 1-.5-.5V8s1.54-1.274 1.639-1.208zM6.25 6a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5z"/>
+  </symbol>
+  <symbol id="globe2" viewBox="0 0 16 16">
+    <path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855-.143.268-.276.56-.395.872.705.157 1.472.257 2.282.287V1.077zM4.249 3.539c.142-.384.304-.744.481-1.078a6.7 6.7 0 0 1 .597-.933A7.01 7.01 0 0 0 3.051 3.05c.362.184.763.349 1.198.49zM3.509 7.5c.036-1.07.188-2.087.436-3.008a9.124 9.124 0 0 1-1.565-.667A6.964 6.964 0 0 0 1.018 7.5h2.49zm1.4-2.741a12.344 12.344 0 0 0-.4 2.741H7.5V5.091c-.91-.03-1.783-.145-2.591-.332zM8.5 5.09V7.5h2.99a12.342 12.342 0 0 0-.399-2.741c-.808.187-1.681.301-2.591.332zM4.51 8.5c.035.987.176 1.914.399 2.741A13.612 13.612 0 0 1 7.5 10.91V8.5H4.51zm3.99 0v2.409c.91.03 1.783.145 2.591.332.223-.827.364-1.754.4-2.741H8.5zm-3.282 3.696c.12.312.252.604.395.872.552 1.035 1.218 1.65 1.887 1.855V11.91c-.81.03-1.577.13-2.282.287zm.11 2.276a6.696 6.696 0 0 1-.598-.933 8.853 8.853 0 0 1-.481-1.079 8.38 8.38 0 0 0-1.198.49 7.01 7.01 0 0 0 2.276 1.522zm-1.383-2.964A13.36 13.36 0 0 1 3.508 8.5h-2.49a6.963 6.963 0 0 0 1.362 3.675c.47-.258.995-.482 1.565-.667zm6.728 2.964a7.009 7.009 0 0 0 2.275-1.521 8.376 8.376 0 0 0-1.197-.49 8.853 8.853 0 0 1-.481 1.078 6.688 6.688 0 0 1-.597.933zM8.5 11.909v3.014c.67-.204 1.335-.82 1.887-1.855.143-.268.276-.56.395-.872A12.63 12.63 0 0 0 8.5 11.91zm3.555-.401c.57.185 1.095.409 1.565.667A6.963 6.963 0 0 0 14.982 8.5h-2.49a13.36 13.36 0 0 1-.437 3.008zM14.982 7.5a6.963 6.963 0 0 0-1.362-3.675c-.47.258-.995.482-1.565.667.248.92.4 1.938.437 3.008h2.49zM11.27 2.461c.177.334.339.694.482 1.078a8.368 8.368 0 0 0 1.196-.49 7.01 7.01 0 0 0-2.275-1.52c.218.283.418.597.597.932zm-.488 1.343a7.765 7.765 0 0 0-.395-.872C9.835 1.897 9.17 1.282 8.5 1.077V4.09c.81-.03 1.577-.13 2.282-.287z"/>
+  </symbol>
+  <symbol id="grid-fill" viewBox="0 0 16 16">
+    <path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zm8 0A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm-8 8A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm8 0A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3z"/>
+  </symbol>
+  <symbol id="lightning-charge-fill" viewBox="0 0 16 16">
+    <path d="M11.251.068a.5.5 0 0 1 .227.58L9.677 6.5H13a.5.5 0 0 1 .364.843l-8 8.5a.5.5 0 0 1-.842-.49L6.323 9.5H3a.5.5 0 0 1-.364-.843l8-8.5a.5.5 0 0 1 .615-.09z"/>
+  </symbol>
+  <symbol id="list" viewBox="0 0 16 16">
+    <path fill-rule="evenodd" d="M2.5 12a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5z"/>
+  </symbol>
+  <symbol id="magic" viewBox="0 0 16 16">
+    <path d="M9.5 2.672a.5.5 0 1 0 1 0V.843a.5.5 0 0 0-1 0v1.829Zm4.5.035A.5.5 0 0 0 13.293 2L12 3.293a.5.5 0 1 0 .707.707L14 2.707ZM7.293 4A.5.5 0 1 0 8 3.293L6.707 2A.5.5 0 0 0 6 2.707L7.293 4Zm-.621 2.5a.5.5 0 1 0 0-1H4.843a.5.5 0 1 0 0 1h1.829Zm8.485 0a.5.5 0 1 0 0-1h-1.829a.5.5 0 0 0 0 1h1.829ZM13.293 10A.5.5 0 1 0 14 9.293L12.707 8a.5.5 0 1 0-.707.707L13.293 10ZM9.5 11.157a.5.5 0 0 0 1 0V9.328a.5.5 0 0 0-1 0v1.829Zm1.854-5.097a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L8.646 5.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0l1.293-1.293Zm-3 3a.5.5 0 0 0 0-.706l-.708-.708a.5.5 0 0 0-.707 0L.646 13.94a.5.5 0 0 0 0 .707l.708.708a.5.5 0 0 0 .707 0L8.354 9.06Z"/>
+  </symbol>
+  <symbol id="menu-button-wide-fill" viewBox="0 0 16 16">
+    <path d="M1.5 0A1.5 1.5 0 0 0 0 1.5v2A1.5 1.5 0 0 0 1.5 5h13A1.5 1.5 0 0 0 16 3.5v-2A1.5 1.5 0 0 0 14.5 0h-13zm1 2h3a.5.5 0 0 1 0 1h-3a.5.5 0 0 1 0-1zm9.927.427A.25.25 0 0 1 12.604 2h.792a.25.25 0 0 1 .177.427l-.396.396a.25.25 0 0 1-.354 0l-.396-.396zM0 8a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V8zm1 3v2a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2H1zm14-1V8a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1v2h14zM2 8.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0 4a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5z"/>
+  </symbol>
+  <symbol id="palette2" viewBox="0 0 16 16">
+    <path d="M0 .5A.5.5 0 0 1 .5 0h5a.5.5 0 0 1 .5.5v5.277l4.147-4.131a.5.5 0 0 1 .707 0l3.535 3.536a.5.5 0 0 1 0 .708L10.261 10H15.5a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5H3a2.99 2.99 0 0 1-2.121-.879A2.99 2.99 0 0 1 0 13.044m6-.21 7.328-7.3-2.829-2.828L6 7.188v5.647zM4.5 13a1.5 1.5 0 1 0-3 0 1.5 1.5 0 0 0 3 0zM15 15v-4H9.258l-4.015 4H15zM0 .5v12.495V.5z"/>
+    <path d="M0 12.995V13a3.07 3.07 0 0 0 0-.005z"/>
+  </symbol>
+  <symbol id="plugin" viewBox="0 0 16 16">
+    <path fill-rule="evenodd" d="M1 8a7 7 0 1 1 2.898 5.673c-.167-.121-.216-.406-.002-.62l1.8-1.8a3.5 3.5 0 0 0 4.572-.328l1.414-1.415a.5.5 0 0 0 0-.707l-.707-.707 1.559-1.563a.5.5 0 1 0-.708-.706l-1.559 1.562-1.414-1.414 1.56-1.562a.5.5 0 1 0-.707-.706l-1.56 1.56-.707-.706a.5.5 0 0 0-.707 0L5.318 5.975a3.5 3.5 0 0 0-.328 4.571l-1.8 1.8c-.58.58-.62 1.6.121 2.137A8 8 0 1 0 0 8a.5.5 0 0 0 1 0Z"/>
+  </symbol>
+  <symbol id="plus" viewBox="0 0 16 16">
+    <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
+  </symbol>
+  <symbol id="three-dots" viewBox="0 0 16 16">
+    <path d="M3 9.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3zm5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
+  </symbol>
+  <symbol id="tools" viewBox="0 0 16 16">
+    <path d="M1 0 0 1l2.2 3.081a1 1 0 0 0 .815.419h.07a1 1 0 0 1 .708.293l2.675 2.675-2.617 2.654A3.003 3.003 0 0 0 0 13a3 3 0 1 0 5.878-.851l2.654-2.617.968.968-.305.914a1 1 0 0 0 .242 1.023l3.356 3.356a1 1 0 0 0 1.414 0l1.586-1.586a1 1 0 0 0 0-1.414l-3.356-3.356a1 1 0 0 0-1.023-.242L10.5 9.5l-.96-.96 2.68-2.643A3.005 3.005 0 0 0 16 3c0-.269-.035-.53-.102-.777l-2.14 2.141L12 4l-.364-1.757L13.777.102a3 3 0 0 0-3.675 3.68L7.462 6.46 4.793 3.793a1 1 0 0 1-.293-.707v-.071a1 1 0 0 0-.419-.814L1 0zm9.646 10.646a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1-.708.708l-3-3a.5.5 0 0 1 0-.708zM3 11l.471.242.529.026.287.445.445.287.026.529L5 13l-.242.471-.026.529-.445.287-.287.445-.529.026L3 15l-.471-.242L2 14.732l-.287-.445L1.268 14l-.026-.529L1 13l.242-.471.026-.529.445-.287.287-.445.529-.026L3 11z"/>
+  </symbol>
+  <symbol id="ui-radios" viewBox="0 0 16 16">
+    <path d="M7 2.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5v-1zM0 12a3 3 0 1 1 6 0 3 3 0 0 1-6 0zm7-1.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-7a.5.5 0 0 1-.5-.5v-1zm0-5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 8a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zM3 1a3 3 0 1 0 0 6 3 3 0 0 0 0-6zm0 4.5a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3z"/>
+  </symbol>
+</svg>
index 2b70521f5d055aea8943e623670be755fe83723a..5e2e52e90bbbdf671e3181eddd709c6cac0e30b1 100644 (file)
@@ -25,8 +25,7 @@
   // Open in StackBlitz logic
   document.querySelectorAll('.btn-edit').forEach(btn => {
     btn.addEventListener('click', event => {
-      const htmlSnippet = event.target.closest('.bd-edit').previousSibling.innerHTML
-
+      const htmlSnippet = event.target.closest('.bd-code-snippet').querySelector('.bd-example').innerHTML
       StackBlitzSDK.openBootstrapSnippet(htmlSnippet)
     })
   })
index a808c2589afd45b7fbf31c2120ff4088a5cc6669..9dab2f9d1a0f8995304a537ea802a042c93bc9c8 100644 (file)
 {{- $show_markup := .Get "show_markup" | default true -}}
 {{- $input := .Inner -}}
 
-{{- if eq $show_preview true -}}
-<div{{ with $id }} id="{{ . }}"{{ end }} class="bd-example{{ with $class }} {{ . }}{{ end }}">
-  {{- $input -}}
-</div>
-{{- end -}}
-
-{{- if eq $show_markup true -}}
-  <div class="bd-edit">
-    <button type="button" class="btn-edit text-nowrap" title="Try it on StackBlitz">Try it</button>
+<div class="bd-example-snippet bd-code-snippet">
+  {{- if eq $show_preview true -}}
+  <div{{ with $id }} id="{{ . }}"{{ end }} class="bd-example{{ with $class }} {{ . }}{{ end }}">
+    {{- $input -}}
   </div>
-  {{- $content := replaceRE `<svg class="bd-placeholder-img(?:-lg)?(?: *?bd-placeholder-img-lg)? ?(.*?)".*?<\/svg>\n` `<img src="..." class="$1" alt="...">` $input -}}
-  {{- $content = replaceRE ` (class=" *?")` "" $content -}}
-  {{- highlight (trim $content "\n") $lang "" -}}
-{{- end -}}
+  {{- end -}}
+
+  {{- if eq $show_markup true -}}
+    {{- if eq $show_preview true -}}
+      <div class="d-flex align-items-center highlight-toolbar bg-light  ps-3 pe-2 py-1">
+        <small class="font-monospace text-muted text-uppercase">{{- $lang -}}</small>
+        <div class="d-flex ms-auto">
+          <button type="button" class="btn-edit text-nowrap" title="Try it on StackBlitz">
+            <svg class="bi" width="1em" height="1em" fill="currentColor" role="img" aria-label="Copy"><use xlink:href="#lightning-charge-fill"/></svg>
+          </button>
+          <button type="button" class="btn-clipboard" title="Copy to clipboard">
+            <svg class="bi" width="1em" height="1em" fill="currentColor" role="img" aria-label="Copy"><use xlink:href="#clipboard"/></svg>
+          </button>
+        </div>
+      </div>
+    {{- end -}}
+
+    {{- $content := replaceRE `<svg class="bd-placeholder-img(?:-lg)?(?: *?bd-placeholder-img-lg)? ?(.*?)".*?<\/svg>\n` `<img src="..." class="$1" alt="...">` $input -}}
+    {{- $content = replaceRE ` (class=" *?")` "" $content -}}
+    {{- highlight (trim $content "\n") $lang "" -}}
+  {{- end -}}
+</div>
diff --git a/site/static/docs/5.1/assets/img/examples/navbars-offcanvas.png b/site/static/docs/5.1/assets/img/examples/navbars-offcanvas.png
new file mode 100644 (file)
index 0000000..81b000d
Binary files /dev/null and b/site/static/docs/5.1/assets/img/examples/navbars-offcanvas.png differ
diff --git a/site/static/docs/5.1/assets/img/examples/navbars-offcanvas@2x.png b/site/static/docs/5.1/assets/img/examples/navbars-offcanvas@2x.png
new file mode 100644 (file)
index 0000000..af53134
Binary files /dev/null and b/site/static/docs/5.1/assets/img/examples/navbars-offcanvas@2x.png differ