]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Massive update
authorMark Otto <markdotto@gmail.com>
Fri, 23 Jan 2026 16:17:13 +0000 (08:17 -0800)
committerMark Otto <markdotto@gmail.com>
Tue, 27 Jan 2026 21:23:51 +0000 (13:23 -0800)
31 files changed:
js/src/dropdown.js
js/src/nav-overflow.js [new file with mode: 0644]
scss/_nav-overflow.scss [new file with mode: 0644]
scss/_nav.scss
scss/_navbar.scss
scss/_offcanvas.scss
scss/bootstrap.scss
site/data/sidebar.yml
site/src/assets/examples/album-rtl/index.astro
site/src/assets/examples/album/index.astro
site/src/assets/examples/carousel-rtl/index.astro
site/src/assets/examples/carousel/index.astro
site/src/assets/examples/cheatsheet-rtl/index.astro
site/src/assets/examples/cheatsheet/index.astro
site/src/assets/examples/navbar-bottom/index.astro
site/src/assets/examples/navbar-fixed/index.astro
site/src/assets/examples/navbar-static/index.astro
site/src/assets/examples/navbars-offcanvas/index.astro
site/src/assets/examples/navbars/index.astro
site/src/assets/examples/offcanvas-navbar/index.astro
site/src/assets/examples/product/index.astro
site/src/assets/examples/sticky-footer-navbar/index.astro
site/src/components/header/Navigation.astro
site/src/components/shortcodes/NavbarPlacementPlayground.astro [new file with mode: 0644]
site/src/components/shortcodes/ResizableExample.astro [new file with mode: 0644]
site/src/content/docs/components/dropdown.mdx
site/src/content/docs/components/nav-overflow.mdx [new file with mode: 0644]
site/src/content/docs/components/navbar.mdx
site/src/content/docs/components/offcanvas.mdx
site/src/scss/_component-examples.scss
site/src/types/auto-import.d.ts

index 86955dd597385d91109da146f3874e641d31bd88..5bd5323aaa2902f5a2219dc87614476693ea7d7e 100644 (file)
@@ -102,6 +102,7 @@ const Default = {
   floatingConfig: null,
   placement: DEFAULT_PLACEMENT,
   reference: 'toggle',
+  strategy: 'absolute',
   // Submenu options
   submenuTrigger: 'both', // 'click', 'hover', or 'both'
   submenuDelay: SUBMENU_CLOSE_DELAY
@@ -115,6 +116,7 @@ const DefaultType = {
   floatingConfig: '(null|object|function)',
   placement: 'string',
   reference: '(string|element|object)',
+  strategy: 'string',
   submenuTrigger: 'string',
   submenuDelay: 'number'
 }
@@ -326,7 +328,8 @@ class Dropdown extends BaseComponent {
       referenceElement,
       this._menu,
       floatingConfig.placement,
-      floatingConfig.middleware
+      floatingConfig.middleware,
+      floatingConfig.strategy
     )
   }
 
@@ -434,7 +437,8 @@ class Dropdown extends BaseComponent {
   _getFloatingConfig(placement, middleware) {
     const defaultConfig = {
       placement,
-      middleware
+      middleware,
+      strategy: this._config.strategy
     }
 
     return {
@@ -451,7 +455,7 @@ class Dropdown extends BaseComponent {
   }
 
   // Shared helper for positioning any floating element
-  async _applyFloatingPosition(reference, floating, placement, middleware) {
+  async _applyFloatingPosition(reference, floating, placement, middleware, strategy = 'absolute') {
     if (!floating.isConnected) {
       return null
     }
@@ -459,7 +463,7 @@ class Dropdown extends BaseComponent {
     const { x, y, placement: finalPlacement } = await computePosition(
       reference,
       floating,
-      { placement, middleware }
+      { placement, middleware, strategy }
     )
 
     if (!floating.isConnected) {
@@ -467,7 +471,7 @@ class Dropdown extends BaseComponent {
     }
 
     Object.assign(floating.style, {
-      position: 'absolute',
+      position: strategy,
       left: `${x}px`,
       top: `${y}px`,
       margin: '0'
diff --git a/js/src/nav-overflow.js b/js/src/nav-overflow.js
new file mode 100644 (file)
index 0000000..c723371
--- /dev/null
@@ -0,0 +1,290 @@
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap nav-overflow.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+import BaseComponent from './base-component.js'
+import EventHandler from './dom/event-handler.js'
+import SelectorEngine from './dom/selector-engine.js'
+import Dropdown from './dropdown.js'
+
+/**
+ * Constants
+ */
+
+const NAME = 'navoverflow'
+const DATA_KEY = 'bs.navoverflow'
+const EVENT_KEY = `.${DATA_KEY}`
+
+const EVENT_UPDATE = `update${EVENT_KEY}`
+const EVENT_OVERFLOW = `overflow${EVENT_KEY}`
+
+const CLASS_NAME_OVERFLOW = 'nav-overflow'
+const CLASS_NAME_OVERFLOW_MENU = 'nav-overflow-menu'
+const CLASS_NAME_HIDDEN = 'd-none'
+
+const SELECTOR_NAV_ITEM = '.nav-item'
+const SELECTOR_NAV_LINK = '.nav-link'
+const SELECTOR_OVERFLOW_TOGGLE = '.nav-overflow-toggle'
+const SELECTOR_OVERFLOW_MENU = '.nav-overflow-menu'
+const CLASS_NAME_KEEP = 'nav-overflow-keep'
+
+const Default = {
+  moreText: 'More',
+  moreIcon: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" 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 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3m5 0a1.5 1.5 0 1 1 0-3 1.5 1.5 0 0 1 0 3"/></svg>',
+  threshold: 0 // Minimum items to keep visible before showing overflow
+}
+
+const DefaultType = {
+  moreText: 'string',
+  moreIcon: 'string',
+  threshold: 'number'
+}
+
+/**
+ * Class definition
+ */
+
+class NavOverflow extends BaseComponent {
+  constructor(element, config) {
+    super(element, config)
+
+    this._items = []
+    this._overflowItems = []
+    this._overflowMenu = null
+    this._overflowToggle = null
+    this._resizeObserver = null
+    this._isInitialized = false
+
+    this._init()
+  }
+
+  // Getters
+  static get Default() {
+    return Default
+  }
+
+  static get DefaultType() {
+    return DefaultType
+  }
+
+  static get NAME() {
+    return NAME
+  }
+
+  // Public
+  update() {
+    this._calculateOverflow()
+    EventHandler.trigger(this._element, EVENT_UPDATE)
+  }
+
+  dispose() {
+    if (this._resizeObserver) {
+      this._resizeObserver.disconnect()
+    }
+
+    // Move items back to original positions
+    this._restoreItems()
+
+    // Remove overflow menu
+    if (this._overflowToggle && this._overflowToggle.parentElement) {
+      this._overflowToggle.parentElement.remove()
+    }
+
+    super.dispose()
+  }
+
+  // Private
+  _init() {
+    // Add overflow class to nav
+    this._element.classList.add(CLASS_NAME_OVERFLOW)
+
+    // Get all nav items
+    this._items = [...SelectorEngine.find(SELECTOR_NAV_ITEM, this._element)]
+
+    // Store original order data
+    for (const [index, item] of this._items.entries()) {
+      item.dataset.bsNavOrder = index
+    }
+
+    // Create overflow dropdown if it doesn't exist
+    this._createOverflowMenu()
+
+    // Setup resize observer
+    this._setupResizeObserver()
+
+    // Initial calculation
+    this._calculateOverflow()
+
+    this._isInitialized = true
+  }
+
+  _createOverflowMenu() {
+    // Check if overflow menu already exists
+    this._overflowToggle = SelectorEngine.findOne(SELECTOR_OVERFLOW_TOGGLE, this._element)
+
+    if (this._overflowToggle) {
+      this._overflowMenu = SelectorEngine.findOne(SELECTOR_OVERFLOW_MENU, this._element)
+      return
+    }
+
+    // Create the overflow dropdown item
+    const overflowItem = document.createElement('li')
+    overflowItem.className = 'nav-item nav-overflow-item dropdown'
+    overflowItem.innerHTML = `
+      <button class="nav-link nav-overflow-toggle dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
+        <span class="nav-overflow-icon">${this._config.moreIcon}</span>
+        <span class="nav-overflow-text">${this._config.moreText}</span>
+      </button>
+      <ul class="${CLASS_NAME_OVERFLOW_MENU} dropdown-menu dropdown-menu-end"></ul>
+    `
+
+    this._element.append(overflowItem)
+    this._overflowToggle = overflowItem.querySelector(SELECTOR_OVERFLOW_TOGGLE)
+    this._overflowMenu = overflowItem.querySelector(SELECTOR_OVERFLOW_MENU)
+
+    // Initialize dropdown with fixed strategy to escape overflow containers
+    Dropdown.getOrCreateInstance(this._overflowToggle, {
+      strategy: 'fixed'
+    })
+  }
+
+  _setupResizeObserver() {
+    if (typeof ResizeObserver === 'undefined') {
+      // Fallback for older browsers
+      EventHandler.on(window, 'resize', () => this._calculateOverflow())
+      return
+    }
+
+    this._resizeObserver = new ResizeObserver(() => {
+      this._calculateOverflow()
+    })
+
+    this._resizeObserver.observe(this._element)
+  }
+
+  _calculateOverflow() {
+    // First, restore all items to measure properly
+    this._restoreItems()
+
+    const navWidth = this._element.offsetWidth
+    const overflowItem = this._overflowToggle?.closest('.nav-item')
+    const overflowWidth = overflowItem?.offsetWidth || 0
+
+    let usedWidth = 0
+    const itemsToOverflow = []
+    const overflowThreshold = navWidth - overflowWidth - 10 // 10px buffer
+
+    // Calculate which items need to overflow (skip items with keep class)
+    for (const item of this._items) {
+      const itemWidth = item.offsetWidth
+      usedWidth += itemWidth
+
+      // Never overflow items with the keep class
+      if (item.classList.contains(CLASS_NAME_KEEP)) {
+        continue
+      }
+
+      if (usedWidth > overflowThreshold) {
+        itemsToOverflow.push(item)
+      }
+    }
+
+    // Check if we need threshold minimum visible
+    const visibleCount = this._items.length - itemsToOverflow.length
+    if (visibleCount < this._config.threshold && this._items.length > this._config.threshold) {
+      // Add more items to overflow until we reach threshold (but not keep items)
+      const toMove = this._items.slice(this._config.threshold).filter(item => !item.classList.contains(CLASS_NAME_KEEP))
+      itemsToOverflow.length = 0
+      itemsToOverflow.push(...toMove)
+    }
+
+    // Move items to overflow menu
+    this._moveToOverflow(itemsToOverflow)
+
+    // Show/hide overflow toggle
+    if (overflowItem) {
+      if (itemsToOverflow.length > 0) {
+        overflowItem.classList.remove(CLASS_NAME_HIDDEN)
+      } else {
+        overflowItem.classList.add(CLASS_NAME_HIDDEN)
+      }
+    }
+
+    // Trigger overflow event if items changed
+    if (itemsToOverflow.length > 0) {
+      EventHandler.trigger(this._element, EVENT_OVERFLOW, {
+        overflowCount: itemsToOverflow.length,
+        visibleCount: this._items.length - itemsToOverflow.length
+      })
+    }
+  }
+
+  _moveToOverflow(items) {
+    if (!this._overflowMenu) {
+      return
+    }
+
+    // Clear existing overflow items
+    this._overflowMenu.innerHTML = ''
+    this._overflowItems = []
+
+    for (const item of items) {
+      // Clone the nav link as a dropdown item
+      const link = SelectorEngine.findOne(SELECTOR_NAV_LINK, item)
+      if (!link) {
+        continue
+      }
+
+      const dropdownItem = document.createElement('li')
+      const clonedLink = link.cloneNode(true)
+      clonedLink.className = 'dropdown-item'
+
+      // Preserve active state
+      if (link.classList.contains('active')) {
+        clonedLink.classList.add('active')
+      }
+
+      // Preserve disabled state
+      if (link.classList.contains('disabled') || link.hasAttribute('disabled')) {
+        clonedLink.classList.add('disabled')
+      }
+
+      dropdownItem.append(clonedLink)
+      this._overflowMenu.append(dropdownItem)
+
+      // Hide original item
+      item.classList.add(CLASS_NAME_HIDDEN)
+      item.dataset.bsNavOverflow = 'true'
+
+      this._overflowItems.push(item)
+    }
+  }
+
+  _restoreItems() {
+    for (const item of this._items) {
+      item.classList.remove(CLASS_NAME_HIDDEN)
+      delete item.dataset.bsNavOverflow
+    }
+
+    if (this._overflowMenu) {
+      this._overflowMenu.innerHTML = ''
+    }
+
+    this._overflowItems = []
+  }
+}
+
+/**
+ * Data API implementation
+ */
+
+EventHandler.on(document, 'DOMContentLoaded', () => {
+  for (const element of SelectorEngine.find('[data-bs-toggle="nav-overflow"]')) {
+    NavOverflow.getOrCreateInstance(element)
+  }
+})
+
+export default NavOverflow
diff --git a/scss/_nav-overflow.scss b/scss/_nav-overflow.scss
new file mode 100644 (file)
index 0000000..862c6f2
--- /dev/null
@@ -0,0 +1,29 @@
+// Nav Overflow (Priority+ Pattern)
+//
+// A responsive navigation pattern that automatically moves items
+// to an overflow dropdown when space is limited.
+
+@use "config" as *;
+@use "variables" as *;
+
+@layer components {
+  .nav-overflow {
+    flex-wrap: nowrap;
+  }
+
+  // Container item for overflow
+  .nav-overflow-item {
+    flex-shrink: 0;
+    margin-inline-start: auto;
+  }
+
+  // Hide items that have been moved to overflow
+  .nav-overflow [data-bs-nav-overflow="true"] {
+    display: none;
+  }
+
+  // Preserve items that should never overflow
+  .nav-overflow-keep {
+    flex-shrink: 0;
+  }
+}
index 773c21dcd436f763dd9c7624f32d28bf1587662e..733c8ce9ad71b65f5bae0fa7ac0fadc6c9315233 100644 (file)
@@ -10,8 +10,8 @@ $nav-gap:                           .125rem !default;
 $nav-link-gap:                      .5rem !default;
 $nav-link-align:                    center !default;
 $nav-link-justify:                  center !default;
-$nav-link-padding-y:                .5rem !default;
-$nav-link-padding-x:                1rem !default;
+$nav-link-padding-y:                .375rem !default;
+$nav-link-padding-x:                .75rem !default;
 $nav-link-color:                    var(--fg-2) !default;
 $nav-link-hover-color:              var(--fg-1) !default;
 $nav-link-hover-bg:                 var(--bg-1) !default;
@@ -80,6 +80,7 @@ $nav-underline-link-active-color:   var(--fg-color) !default;
     font-weight: var(--nav-link-font-weight);
     color: var(--nav-link-color);
     text-decoration: none;
+    white-space: nowrap;
     background: none;
     border: 0;
     @include border-radius(var(--border-radius));
index 80f53720d85af770d882b33554b0f64c08b331b6..2a21fc77ed9589fb25759d2fdab791de786c9997 100644 (file)
 @use "mixins/transition" as *;
 
 // scss-docs-start navbar-variables
-$navbar-padding-y:                  $spacer * .5 !default;
+$navbar-padding-y:                  $spacer * .25 !default;
 $navbar-padding-x:                  null !default;
 
 $navbar-nav-link-padding-x:         .75rem !default;
 
 $navbar-brand-font-size:            $font-size-lg !default;
-// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
-// mdo-do: fix this
-// $nav-link-height:                   $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;
-// $navbar-brand-height:               $navbar-brand-font-size * $line-height-base !default;
 $navbar-brand-height:               1.5rem !default;
-// $navbar-brand-padding-y:            ($nav-link-height - $navbar-brand-height) * .5 !default;
 $navbar-brand-padding-y:            $navbar-brand-height * .5 !default;
 $navbar-brand-margin-end:           1rem !default;
 
-$navbar-toggler-padding-y:          .25rem !default;
-$navbar-toggler-padding-x:          .75rem !default;
+$navbar-toggler-padding-y:          .375rem !default;
+$navbar-toggler-padding-x:          .375rem !default;
 $navbar-toggler-font-size:          $font-size-lg !default;
 $navbar-toggler-border-radius:      var(--border-radius) !default;
 $navbar-toggler-transition:         box-shadow .15s ease-in-out !default;
@@ -36,8 +31,6 @@ $navbar-light-color:                var(--fg-2) !default;
 $navbar-light-hover-color:          var(--fg-1) !default;
 $navbar-light-active-color:         var(--fg) !default;
 $navbar-light-disabled-color:       var(--fg-3) !default;
-$navbar-light-icon-color:           color-mix(in oklch, var(--body-color) 75%, transparent) !default;
-$navbar-light-toggler-icon-bg:      url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-light-icon-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
 $navbar-light-toggler-border-color: color-mix(in oklch, var(--fg-body) 15%, transparent) !default;
 $navbar-light-brand-color:          $navbar-light-active-color !default;
 $navbar-light-brand-hover-color:    $navbar-light-active-color !default;
@@ -48,14 +41,13 @@ $navbar-dark-color:                 rgba($white, .55) !default;
 $navbar-dark-hover-color:           rgba($white, .75) !default;
 $navbar-dark-active-color:          $white !default;
 $navbar-dark-disabled-color:        rgba($white, .25) !default;
-$navbar-dark-icon-color:            $navbar-dark-color !default;
-$navbar-dark-toggler-icon-bg:       url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke='#{$navbar-dark-icon-color}' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg>") !default;
 $navbar-dark-toggler-border-color:  rgba($white, .1) !default;
 $navbar-dark-brand-color:           $navbar-dark-active-color !default;
 $navbar-dark-brand-hover-color:     $navbar-dark-active-color !default;
 // scss-docs-end navbar-dark-variables
 
 @layer components {
+  // Base navbar
   .navbar {
     // scss-docs-start navbar-css-vars
     // stylelint-disable-next-line scss/at-function-named-arguments
@@ -74,7 +66,6 @@ $navbar-dark-brand-hover-color:     $navbar-dark-active-color !default;
     --navbar-toggler-padding-y: #{$navbar-toggler-padding-y};
     --navbar-toggler-padding-x: #{$navbar-toggler-padding-x};
     --navbar-toggler-font-size: #{$navbar-toggler-font-size};
-    --navbar-toggler-icon-bg: #{escape-svg($navbar-light-toggler-icon-bg)};
     --navbar-toggler-border-color: #{$navbar-light-toggler-border-color};
     --navbar-toggler-border-radius: #{$navbar-toggler-border-radius};
     --navbar-toggler-transition: #{$navbar-toggler-transition};
@@ -82,15 +73,14 @@ $navbar-dark-brand-hover-color:     $navbar-dark-active-color !default;
 
     position: relative;
     display: flex;
-    flex-wrap: wrap; // allow us to do the line break for collapsing content
+    flex-wrap: wrap;
     align-items: center;
-    justify-content: space-between; // space out brand from logo
+    justify-content: space-between;
     padding: var(--navbar-padding-y) var(--navbar-padding-x);
+    container-type: inline-size; // Enable container queries for responsive behavior
     @include gradient-bg();
 
-    // Because flex properties aren't inherited, we need to redeclare these first
-    // few properties so that content nested within behave properly.
-    // The `flex-wrap` property is inherited to simplify the expanded navbars
+    // Container properties for nested containers
     %container-flex-properties {
       display: flex;
       flex-wrap: inherit;
@@ -133,81 +123,70 @@ $navbar-dark-brand-hover-color:     $navbar-dark-active-color !default;
 
   // Navbar nav
   //
-  // Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
+  // Navigation within navbars. Sets all nav-link CSS variables needed for
+  // proper styling. Can be used standalone or with `.nav` base class.
 
   .navbar-nav {
     // scss-docs-start navbar-nav-css-vars
-    // --nav-link-padding-x: 0;
-    // @mdo-do: fix this, navbar shouldn't need to reuse nav link variables mb? or we need to bring them in…
-    // --nav-link-padding-y: #{$nav-link-padding-y};
-    // @include rfs($nav-link-font-size, --nav-link-font-size);
-    // --nav-link-font-weight: #{$nav-link-font-weight};
+    // Set all nav-link variables for self-contained styling
+    --nav-gap: .25rem;
+    --nav-link-gap: .5rem;
+    --nav-link-padding-x: .5rem;
+    --nav-link-padding-y: .5rem;
     --nav-link-color: var(--navbar-color);
     --nav-link-hover-color: var(--navbar-hover-color);
+    --nav-link-hover-bg: transparent;
+    --nav-link-active-color: var(--navbar-active-color);
+    --nav-link-active-bg: transparent;
     --nav-link-disabled-color: var(--navbar-disabled-color);
     // scss-docs-end navbar-nav-css-vars
 
     display: flex;
-    flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
+    flex-direction: column;
+    gap: var(--nav-gap);
     padding-inline-start: 0;
     margin-bottom: 0;
     list-style: none;
 
     .nav-link {
+      white-space: nowrap;
+
       &.active,
       &.show {
         color: var(--navbar-active-color);
       }
     }
-
-    // .dropdown-menu {
-    //   position: static;
-    // }
   }
 
 
   // Navbar text
   //
-  //
+  // For adding text or inline elements to the navbar
 
   .navbar-text {
-    // @mdo-do: fix this too
-    // padding-top: $nav-link-padding-y;
-    // padding-bottom: $nav-link-padding-y;
+    padding-top: var(--navbar-brand-padding-y);
+    padding-bottom: var(--navbar-brand-padding-y);
     color: var(--navbar-color);
 
     a,
     a:hover,
-    a:focus  {
+    a:focus {
       color: var(--navbar-active-color);
     }
   }
 
 
-  // Responsive navbar
+  // Navbar toggler
   //
-  // Custom styles for responsive collapsing and toggling of navbar contents.
-  // Powered by the collapse Bootstrap JavaScript plugin.
-
-  // When collapsed, prevent the toggleable navbar contents from appearing in
-  // the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
-  // on the `.navbar` parent.
-  .navbar-collapse {
-    flex-grow: 1;
-    flex-basis: 100%;
-    // For always expanded or extra full navbars, ensure content aligns itself
-    // properly vertically. Can be easily overridden with flex utilities.
-    align-items: center;
-  }
-
   // Button for toggling the navbar when in its collapsed state
+
   .navbar-toggler {
     padding: var(--navbar-toggler-padding-y) var(--navbar-toggler-padding-x);
     font-size: var(--navbar-toggler-font-size);
     line-height: 1;
     color: var(--navbar-color);
-    background-color: transparent; // remove default button style
-    border: var(--border-width) solid var(--navbar-toggler-border-color); // remove default button style
+    background-color: transparent;
+    border: var(--border-width) solid var(--navbar-toggler-border-color);
     @include border-radius(var(--navbar-toggler-border-radius));
     @include transition(var(--navbar-toggler-transition));
 
@@ -221,101 +200,99 @@ $navbar-dark-brand-hover-color:     $navbar-dark-active-color !default;
     }
   }
 
-  // Keep as a separate element so folks can easily override it with another icon
-  // or image file as needed.
+  // Navbar toggler icon (inline SVG)
   .navbar-toggler-icon {
     display: inline-block;
-    width: 1.5em;
-    height: 1.5em;
-    vertical-align: middle;
-    background-image: var(--navbar-toggler-icon-bg);
-    background-repeat: no-repeat;
-    background-position: center;
-    background-size: 100%;
+    width: 1em;
+    height: 1em;
+    color: var(--navbar-color);
+    vertical-align: -.125em;
   }
 
-  .navbar-nav-scroll {
-    max-height: var(--scroll-height, 75vh);
-    overflow-y: auto;
-  }
 
   // scss-docs-start navbar-expand-loop
   // Generate series of `.navbar-expand-*` responsive classes for configuring
-  // where your navbar collapses.
+  // where your navbar collapses and expands. Uses container queries so the
+  // navbar responds to its own width, not the viewport width.
+
+  // Mixin for expanded state styles (applied to descendants)
+  @mixin navbar-expanded {
+    // Style the inner container since we can't style .navbar itself with container queries
+    > .container,
+    > .container-fluid,
+    %navbar-expand-container {
+      flex-wrap: nowrap;
+      justify-content: flex-start;
+    }
+
+    .navbar-nav {
+      --nav-link-padding-x: var(--navbar-nav-link-padding-x);
+      flex-direction: row;
+    }
+
+    .navbar-toggler {
+      display: none !important; // stylelint-disable-line declaration-no-important
+    }
+
+    .offcanvas {
+      // stylelint-disable declaration-no-important
+      position: static;
+      z-index: auto;
+      flex-grow: 1;
+      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);
+      // stylelint-enable declaration-no-important
+
+      .offcanvas-header {
+        display: none;
+      }
+
+      .offcanvas-body {
+        display: flex;
+        flex-grow: 0;
+        align-items: center;
+        padding: 0;
+        overflow-y: visible;
+      }
+    }
+  }
+
+  // Always expanded (no responsive behavior)
   .navbar-expand {
-    @each $breakpoint in map.keys($grid-breakpoints) {
-      $next: breakpoint-next($breakpoint, $grid-breakpoints);
-      $infix: breakpoint-infix($next, $grid-breakpoints);
-
-      // stylelint-disable-next-line scss/selector-no-union-class-name
-      &#{$infix} {
-        @include media-breakpoint-up($next) {
-          flex-wrap: nowrap;
-          justify-content: flex-start;
-
-          .navbar-nav {
-            --nav-link-padding-x: var(--navbar-nav-link-padding-x);
-            flex-direction: row;
-
-            // .dropdown-menu {
-            //   position: absolute;
-            // }
-
-            // .nav-link {
-            //   padding-inline: var(--navbar-nav-link-padding-x);
-            // }
-          }
-
-          .navbar-nav-scroll {
-            overflow: visible;
-          }
-
-          .navbar-collapse {
-            display: flex !important; // stylelint-disable-line declaration-no-important
-            flex-basis: auto;
-          }
-
-          .navbar-toggler {
-            display: none !important; // stylelint-disable-line declaration-no-important
-          }
-
-          .offcanvas {
-            // stylelint-disable declaration-no-important
-            position: static;
-            z-index: auto;
-            flex-grow: 1;
-            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);
-            // stylelint-enable declaration-no-important
-
-            .offcanvas-header {
-              display: none;
-            }
-
-            .offcanvas-body {
-              display: flex;
-              flex-grow: 0;
-              padding: 0;
-              overflow-y: visible;
-            }
-          }
+    @include navbar-expanded();
+
+    // Also set on navbar itself for non-responsive case
+    flex-wrap: nowrap;
+    justify-content: flex-start;
+  }
+
+  // Responsive navbar expand classes using container queries
+  @each $breakpoint in map.keys($grid-breakpoints) {
+    $next: breakpoint-next($breakpoint, $grid-breakpoints);
+    $infix: breakpoint-infix($next, $grid-breakpoints);
+    $min-width: breakpoint-min($next, $grid-breakpoints);
+
+    @if $next and $min-width {
+      .navbar-expand#{$infix} {
+        @container (min-width: #{$min-width}) {
+          @include navbar-expanded();
         }
       }
     }
   }
   // scss-docs-end navbar-expand-loop
 
+
   // Navbar themes
   //
-  // Styles for switching between navbars with light or dark background.
+  // Style for dark navbar backgrounds. Use data-bs-theme="dark" for modern approach.
 
-  .navbar-dark,
   .navbar[data-bs-theme="dark"] {
     // scss-docs-start navbar-dark-css-vars
     --navbar-color: #{$navbar-dark-color};
@@ -325,15 +302,6 @@ $navbar-dark-brand-hover-color:     $navbar-dark-active-color !default;
     --navbar-brand-color: #{$navbar-dark-brand-color};
     --navbar-brand-hover-color: #{$navbar-dark-brand-hover-color};
     --navbar-toggler-border-color: #{$navbar-dark-toggler-border-color};
-    --navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
     // scss-docs-end navbar-dark-css-vars
   }
-
-  @if $enable-dark-mode {
-    @include color-mode(dark) {
-      .navbar-toggler-icon {
-        --navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
-      }
-    }
-  }
 }
index 8dfbb55d8cccf465b26e1851066d6cd2b62c414f..8d6ad0dcb52225903f62e0fd941abac40d122720 100644 (file)
@@ -6,6 +6,22 @@
 @use "mixins/backdrop" as *;
 @use "layout/breakpoints" as *;
 
+// scss-docs-start offcanvas-variables
+$offcanvas-padding-y:               $spacer !default;
+$offcanvas-padding-x:               $spacer !default;
+$offcanvas-horizontal-width:        400px !default;
+$offcanvas-vertical-height:         30vh !default;
+$offcanvas-transition-duration:     .3s !default;
+$offcanvas-border-color:            var(--border-color-translucent) !default;
+$offcanvas-border-width:            var(--border-width) !default;
+$offcanvas-title-line-height:       $line-height-base !default;
+$offcanvas-bg-color:                var(--bg-body) !default;
+$offcanvas-color:                   var(--fg-body) !default;
+$offcanvas-box-shadow:              var(--box-shadow-lg) !default;
+$offcanvas-backdrop-bg:             $black !default;
+$offcanvas-backdrop-opacity:        .5 !default;
+// scss-docs-end offcanvas-variables
+
 %offcanvas-css-vars {
   // scss-docs-start offcanvas-css-vars
   --offcanvas-zindex: #{$zindex-offcanvas};
@@ -24,6 +40,7 @@
 }
 
 @layer components {
+  // Apply CSS vars to all offcanvas responsive variants
   @each $breakpoint in map.keys($grid-breakpoints) {
     $next: breakpoint-next($breakpoint, $grid-breakpoints);
     $infix: breakpoint-infix($next, $grid-breakpoints);
@@ -33,6 +50,7 @@
     }
   }
 
+  // Responsive offcanvas styles
   @each $breakpoint in map.keys($grid-breakpoints) {
     $next: breakpoint-next($breakpoint, $grid-breakpoints);
     $infix: breakpoint-infix($next, $grid-breakpoints);
@@ -53,6 +71,7 @@
         @include box-shadow(var(--offcanvas-box-shadow));
         @include transition(var(--offcanvas-transition));
 
+        // Placement: Start (left in LTR, right in RTL)
         &.offcanvas-start {
           inset-block: 0;
           inset-inline-start: 0;
@@ -65,6 +84,7 @@
           }
         }
 
+        // Placement: End (right in LTR, left in RTL)
         &.offcanvas-end {
           inset-block: 0;
           inset-inline-end: 0;
@@ -77,6 +97,7 @@
           }
         }
 
+        // Placement: Top
         &.offcanvas-top {
           inset: 0 0 auto;
           height: var(--offcanvas-height);
           transform: translateY(-100%);
         }
 
+        // Placement: Bottom
         &.offcanvas-bottom {
           inset: auto 0 0;
           height: var(--offcanvas-height);
           transform: translateY(100%);
         }
 
+        // Fullscreen variant - covers entire viewport
+        &.offcanvas-fullscreen {
+          inset: 0;
+          width: 100%;
+          max-width: none;
+          height: 100%;
+          max-height: none;
+          border: 0;
+          transform: translateY(100%);
+        }
+
+        // Show/hide states
         &.showing,
         &.show:not(.hiding) {
           transform: none;
         }
       }
 
+      // Above breakpoint - show content inline (for responsive offcanvas)
       @if not ($infix == "") {
         @include media-breakpoint-up($next) {
           --offcanvas-height: auto;
             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
           }
         }
     }
   }
 
+  // Backdrop overlay
   .offcanvas-backdrop {
     @include overlay-backdrop($zindex-offcanvas-backdrop, $offcanvas-backdrop-bg, $offcanvas-backdrop-opacity);
   }
 
+  // Header with close button
   .offcanvas-header {
     display: flex;
     align-items: center;
 
     .btn-close {
       padding: calc(var(--offcanvas-padding-y) * .5) calc(var(--offcanvas-padding-x) * .5);
-      // Split properties to avoid invalid calc() function if value is 0
       margin-inline-start: auto;
       margin-inline-end: calc(-.5 * var(--offcanvas-padding-x));
       margin-top: calc(-.5 * var(--offcanvas-padding-y));
     }
   }
 
+  // Title
   .offcanvas-title {
     margin-bottom: 0;
     line-height: var(--offcanvas-title-line-height);
   }
 
+  // Scrollable body
   .offcanvas-body {
     flex-grow: 1;
     padding: var(--offcanvas-padding-y) var(--offcanvas-padding-x);
     overflow-y: auto;
   }
+
+  // Optional footer
+  .offcanvas-footer {
+    display: flex;
+    flex-shrink: 0;
+    flex-wrap: wrap;
+    gap: .5rem;
+    align-items: center;
+    justify-content: flex-end;
+    padding: var(--offcanvas-padding-y) var(--offcanvas-padding-x);
+    border-block-start: var(--offcanvas-border-width) solid var(--offcanvas-border-color);
+  }
 }
index 441b6609b286dd4c2657a094b65ce5ec1c06693f..89f91122057f0c9e72fd999b4b3ea2a3ed391c6a 100644 (file)
@@ -24,6 +24,7 @@
 @forward "dropdown";
 @forward "list-group";
 @forward "nav";
+@forward "nav-overflow";
 @forward "navbar";
 @forward "offcanvas";
 @forward "pagination";
index 1adbb4c977ede454e6a613848d70b2e0e292bf3d..f25eb46b9b8d7261c93f6fb930f7c2174ca698c2 100644 (file)
@@ -99,8 +99,9 @@
     - title: Dialog
     - title: Dropdown
     - title: List group
-    - title: Navbar
     - title: Navs & tabs
+    - title: Nav overflow
+    - title: Navbar
     - title: Offcanvas
     - title: Pagination
     - title: Placeholder
index a5e224a00b80318281c57d2cb0b6f75ac8d1cf59..1c4662867f3e08eabe47e0777dd37efc3a4f6119 100644 (file)
@@ -32,7 +32,7 @@ export const direction = 'rtl'
         <strong>الألبوم</strong>
       </a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="تبديل التنقل">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
     </div>
   </div>
index 204062c52a9723d1f243e7c2566fe83fc764c1d1..fe40f677fe3b03b03893618196eb5d3c575191d7 100644 (file)
@@ -31,7 +31,7 @@ import Placeholder from "@shortcodes/Placeholder.astro"
         <strong>Album</strong>
       </a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
     </div>
   </div>
index 6a981e49423c9fcf226fbe2ca0d837aff206ce42..6cdbfa973d807df4a3f67420307ce4f44cd6da0b 100644 (file)
@@ -10,7 +10,7 @@ import Placeholder from "@shortcodes/Placeholder.astro"
     <div class="container-fluid">
       <a class="navbar-brand" href="#">شرائح العرض</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="تبديل التنقل">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="collapse navbar-collapse" id="navbarCollapse">
         <ul class="navbar-nav me-auto mb-2 mb-md-0">
index 2ca4339be0288903b133e273109312bcde999222..5f6b5b259e9c741a43ed21c092788bf03f6d0b57 100644 (file)
@@ -9,7 +9,7 @@ import Placeholder from "@shortcodes/Placeholder.astro"
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Carousel</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="collapse navbar-collapse" id="navbarCollapse">
         <ul class="navbar-nav me-auto mb-2 mb-md-0">
index 2c0909adfd5eac555447bed0dc1835e7adf0c57b..f503aa19451ba68ef018f53c42c1dc2e3886ca09 100644 (file)
@@ -1186,7 +1186,7 @@ import Placeholder from "@shortcodes/Placeholder.astro"
               <img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy" style="filter: invert(1) grayscale(100%) brightness(200%);">
             </a>
             <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="تبديل التنقل">
-              <span class="navbar-toggler-icon"></span>
+              <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
             </button>
             <div class="collapse navbar-collapse" id="navbarSupportedContent">
               <ul class="navbar-nav me-auto mb-2 mb-lg-0">
@@ -1225,7 +1225,7 @@ import Placeholder from "@shortcodes/Placeholder.astro"
               <img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy">
             </a>
             <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent2" aria-controls="navbarSupportedContent2" aria-expanded="false" aria-label="تبديل التنقل">
-              <span class="navbar-toggler-icon"></span>
+              <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
             </button>
             <div class="collapse navbar-collapse" id="navbarSupportedContent2">
               <ul class="navbar-nav me-auto mb-2 mb-lg-0">
index 01d0af1b8ee4f4810f5c020f3952d9caab5b94c5..1adf0095a66ec832850e87b473264b84cb2327a2 100644 (file)
@@ -1182,7 +1182,7 @@ export const body_class = 'bg-body-tertiary'
                 <img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy" style="filter: invert(1) grayscale(100%) brightness(200%);">
               </a>
               <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
-                <span class="navbar-toggler-icon"></span>
+                <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
               </button>
               <div class="collapse navbar-collapse" id="navbarSupportedContent">
                 <ul class="navbar-nav me-auto mb-2 mb-lg-0">
@@ -1221,7 +1221,7 @@ export const body_class = 'bg-body-tertiary'
                 <img src="${getVersionedDocsPath('/assets/brand/bootstrap-logo-white.svg')}" width="38" height="30" class="d-inline-block align-top" alt="Bootstrap" loading="lazy">
               </a>
               <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent2" aria-controls="navbarSupportedContent2" aria-expanded="false" aria-label="Toggle navigation">
-                <span class="navbar-toggler-icon"></span>
+                <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
               </button>
               <div class="collapse navbar-collapse" id="navbarSupportedContent2">
                 <ul class="navbar-nav me-auto mb-2 mb-lg-0">
index 35aa348c69b25e68670fb28d1b255f647331c46a..fefb9521621f7bec5102e9bac230075605f2c3dd 100644 (file)
@@ -15,7 +15,7 @@ export const title = 'Bottom navbar example'
   <div class="container-fluid">
     <a class="navbar-brand" href="#">Bottom navbar</a>
     <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
     <div class="collapse navbar-collapse" id="navbarCollapse">
       <ul class="navbar-nav">
index 3524255c2f5fc929effb64c5defdd5f6e382c498..dc66eb4eeb1ba603d163d0bea0b89f54e1b68e3c 100644 (file)
@@ -9,7 +9,7 @@ export const extra_css = ['navbar-fixed.css']
   <div class="container-fluid">
     <a class="navbar-brand" href="#">Fixed navbar</a>
     <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
     <div class="collapse navbar-collapse" id="navbarCollapse">
       <ul class="navbar-nav me-auto mb-2 mb-md-0">
index 600b313ec5c1e0e882b9386ff593125c353d55bd..c6dad132a8810fcbdbaa31f530fbd5fe73c006b8 100644 (file)
@@ -9,7 +9,7 @@ export const extra_css = ['navbar-static.css']
   <div class="container-fluid">
     <a class="navbar-brand" href="#">Top navbar</a>
     <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
     <div class="collapse navbar-collapse" id="navbarCollapse">
       <ul class="navbar-nav me-auto mb-2 mb-md-0">
index ec6b03f76d9284d7e8b749240681c1ad43fa60b4..0c067e8aa2bcb17da418af22112110e5f8bb8d4e 100644 (file)
@@ -10,7 +10,7 @@ export const extra_css = ['navbars-offcanvas.css']
     <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" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasNavbarDark" aria-labelledby="offcanvasNavbarDarkLabel">
         <div class="offcanvas-header">
@@ -52,7 +52,7 @@ export const extra_css = ['navbars-offcanvas.css']
     <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" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbarLight" aria-labelledby="offcanvasNavbarLightLabel">
         <div class="offcanvas-header">
@@ -94,7 +94,7 @@ export const extra_css = ['navbars-offcanvas.css']
     <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" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasNavbar2" aria-labelledby="offcanvasNavbar2Label">
         <div class="offcanvas-header">
index 43c73f87ca3f40f7c42602fbb12fead5983cf355..ba3132e2f2b280958e9a3c6351ab6ca0c8cd3425 100644 (file)
@@ -10,7 +10,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Never expand</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample01" aria-controls="navbarsExample01" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample01">
@@ -44,7 +44,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Always expand</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample02" aria-controls="navbarsExample02" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample02">
@@ -67,7 +67,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Expand at sm</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample03" aria-controls="navbarsExample03" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample03">
@@ -101,7 +101,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Expand at md</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample04" aria-controls="navbarsExample04" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample04">
@@ -135,7 +135,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Expand at lg</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample05" aria-controls="navbarsExample05" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample05">
@@ -169,7 +169,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Expand at xl</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample06" aria-controls="navbarsExample06" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample06">
@@ -203,7 +203,7 @@ export const extra_css = ['navbars.css']
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Expand at 2xl</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample2xl" aria-controls="navbarsExample2xl" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample2xl">
@@ -237,7 +237,7 @@ export const extra_css = ['navbars.css']
     <div class="container">
       <a class="navbar-brand" href="#">Container</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample07" aria-controls="navbarsExample07" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample07">
@@ -271,7 +271,7 @@ export const extra_css = ['navbars.css']
     <div class="container-xl">
       <a class="navbar-brand" href="#">Container XL</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample07XL" aria-controls="navbarsExample07XL" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse" id="navbarsExample07XL">
@@ -308,7 +308,7 @@ export const extra_css = ['navbars.css']
   <nav class="navbar navbar-expand-lg navbar-dark bg-dark" aria-label="Tenth navbar example">
     <div class="container-fluid">
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample08" aria-controls="navbarsExample08" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
 
       <div class="collapse navbar-collapse justify-content-md-center" id="navbarsExample08">
@@ -340,7 +340,7 @@ export const extra_css = ['navbars.css']
       <div class="container-fluid">
         <a class="navbar-brand" href="#">Navbar</a>
         <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample09" aria-controls="navbarsExample09" aria-expanded="false" aria-label="Toggle navigation">
-          <span class="navbar-toggler-icon"></span>
+          <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
         </button>
 
         <div class="collapse navbar-collapse" id="navbarsExample09">
@@ -373,7 +373,7 @@ export const extra_css = ['navbars.css']
     <nav class="navbar navbar-expand-lg bg-body-tertiary rounded" aria-label="Twelfth navbar example">
       <div class="container-fluid">
         <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample10" aria-controls="navbarsExample10" aria-expanded="false" aria-label="Toggle navigation">
-          <span class="navbar-toggler-icon"></span>
+          <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
         </button>
 
         <div class="collapse navbar-collapse justify-content-md-center" id="navbarsExample10">
@@ -403,7 +403,7 @@ export const extra_css = ['navbars.css']
     <nav class="navbar navbar-expand-lg bg-body-tertiary rounded" aria-label="Thirteenth navbar example">
       <div class="container-fluid">
         <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarsExample11" aria-controls="navbarsExample11" aria-expanded="false" aria-label="Toggle navigation">
-          <span class="navbar-toggler-icon"></span>
+          <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
         </button>
 
         <div class="collapse navbar-collapse d-lg-flex" id="navbarsExample11">
index ac94ca882af69587c2099dd155c74c5fd32bdfad..9c8b2a8cf9923083120f8a090a75112efe020162 100644 (file)
@@ -13,7 +13,7 @@ import Placeholder from "@shortcodes/Placeholder.astro"
   <div class="container-fluid">
     <a class="navbar-brand" href="#">Offcanvas navbar</a>
     <button class="navbar-toggler p-0 border-0" type="button" id="navbarSideCollapse" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
 
     <div class="navbar-collapse offcanvas-collapse" id="navbarsExampleDefault">
index 8fbf4a0c33bb5dde2776ef2d278a80031ba602f0..f6344a79001a6ac566abd251f3df4ab5378f87ea 100644 (file)
@@ -23,7 +23,7 @@ export const extra_css = ['product.css']
       Aperture
     </a>
     <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvas" aria-controls="offcanvas" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
     <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvas" aria-labelledby="offcanvasLabel">
       <div class="offcanvas-header">
index 9b9b5ebb98939e4abce38296cff88bd162c5d8c0..afcc81c31e160ab9b6c00d3d0a02d31083a9a9c9 100644 (file)
@@ -13,7 +13,7 @@ export const body_class = 'd-flex flex-column h-100'
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Fixed navbar</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="collapse navbar-collapse" id="navbarCollapse">
         <ul class="navbar-nav me-auto mb-2 mb-md-0">
index 056d58d9b298075827cee5227c679104ff2b9032..841f0a30422e2233f7c01a98348671652baa292d 100644 (file)
@@ -23,6 +23,7 @@ const { addedIn, layout, title } = Astro.props
 
 <header class="navbar navbar-expand-lg bg-body bd-navbar border-bottom sticky-top bd-sticky-navbar">
   <nav class="container-2xl bd-gutter flex-wrap flex-lg-nowrap" aria-label="Main navigation">
+    {/* Docs sidebar toggle - only shown on docs pages */}
     {
       layout === 'docs' && (
         <div class="bd-navbar-toggle">
@@ -42,10 +43,12 @@ const { addedIn, layout, title } = Astro.props
     }
     {layout !== 'docs' && <div class="d-lg-none" style="width: 4.25rem;" />}
 
+    {/* Brand */}
     <a class="navbar-brand p-0 me-0 me-lg-2" href="/" aria-label="Bootstrap" style="color: var(--bs-indigo-500);">
       <BootstrapWhiteFillIcon class="d-block my-1" height={32} width={40} />
     </a>
 
+    {/* Search and main nav toggle */}
     <div class="d-flex">
       <div class="bd-search" id="docsearch" data-bd-docs-version={getConfig().docs_version}></div>
 
@@ -61,6 +64,7 @@ const { addedIn, layout, title } = Astro.props
       </button>
     </div>
 
+    {/* Main navigation - offcanvas on mobile, inline on desktop */}
     <div
       class="offcanvas-lg offcanvas-end flex-grow-1"
       tabindex="-1"
@@ -108,6 +112,7 @@ const { addedIn, layout, title } = Astro.props
             <OpenCollectiveIcon class="navbar-nav-svg" height={16} width={16} />
             <small class="d-lg-none ms-2">Open Collective</small>
           </LinkItem>
+
           <li class="nav-item py-2 py-lg-1 col-12 col-lg-auto">
             <div class="vr d-none d-lg-flex mx-lg-2 my-auto"></div>
             <hr class="d-lg-none my-2" />
diff --git a/site/src/components/shortcodes/NavbarPlacementPlayground.astro b/site/src/components/shortcodes/NavbarPlacementPlayground.astro
new file mode 100644 (file)
index 0000000..3f633e6
--- /dev/null
@@ -0,0 +1,142 @@
+---
+import Example from '@components/shortcodes/Example.astro'
+
+const placements = [
+  { value: '', label: 'Default (static)' },
+  { value: 'fixed-top', label: 'Fixed top' },
+  { value: 'fixed-bottom', label: 'Fixed bottom' },
+  { value: 'sticky-top', label: 'Sticky top' },
+  { value: 'sticky-bottom', label: 'Sticky bottom' }
+]
+---
+
+<div class="bg-1 p-3 fs-sm rounded-3">
+  <div class="vstack gap-1">
+    <label class="form-label fw-semibold mb-0">Placement</label>
+    <div class="dropdown">
+      <button
+        type="button"
+        class="btn btn-outline theme-secondary dropdown-toggle"
+        id="navbar-placement-dropdown"
+        data-bs-toggle="dropdown"
+        aria-expanded="false"
+        data-placement=""
+      >
+        <span>Default (static)</span>
+        <svg class="bi ms-1" width="16" height="16" aria-hidden="true">
+          <use href="#chevron-expand" />
+        </svg>
+      </button>
+      <ul class="dropdown-menu" aria-labelledby="navbar-placement-dropdown">
+        {placements.map((p) => (
+          <li>
+            <a
+              class:list={['dropdown-item', { 'active': p.value === '' }]}
+              href="#"
+              data-placement={p.value}
+            >
+              {p.label}
+            </a>
+          </li>
+        ))}
+      </ul>
+    </div>
+  </div>
+</div>
+
+<Example
+  code={`<nav class="navbar bg-1">
+  <div class="container-fluid">
+    <a class="navbar-brand" href="#">Default</a>
+  </div>
+</nav>`}
+  id="navbar-placement-preview"
+/>
+
+<script>
+  const placementDropdownButton = document.querySelector('#navbar-placement-dropdown') as HTMLButtonElement
+  const placementDropdownItems = document.querySelectorAll('#navbar-placement-dropdown + .dropdown-menu .dropdown-item')
+  const previewContainer = document.querySelector('#navbar-placement-preview') as HTMLElement
+  const previewNavbar = previewContainer?.querySelector('.navbar') as HTMLElement
+  const codeSnippet = previewContainer?.closest('.bd-example-snippet')?.querySelector('.highlight code') as HTMLElement
+
+  const placementClasses = ['fixed-top', 'fixed-bottom', 'sticky-top', 'sticky-bottom']
+
+  const placementLabels: Record<string, string> = {
+    '': 'Default',
+    'fixed-top': 'Fixed top',
+    'fixed-bottom': 'Fixed bottom',
+    'sticky-top': 'Sticky top',
+    'sticky-bottom': 'Sticky bottom'
+  }
+
+  function updatePlacement(placement: string) {
+    if (!previewNavbar || !placementDropdownButton) return
+
+    // Update dropdown button text
+    const labelSpan = placementDropdownButton.querySelector('span')
+    if (labelSpan) {
+      labelSpan.textContent = placementLabels[placement] ? `${placementLabels[placement]}${placement ? '' : ' (static)'}` : 'Default (static)'
+    }
+    placementDropdownButton.dataset.placement = placement
+
+    // Update active state in dropdown
+    placementDropdownItems.forEach(item => {
+      const itemPlacement = (item as HTMLElement).dataset.placement
+      item.classList.toggle('active', itemPlacement === placement)
+    })
+
+    // Remove all placement classes
+    placementClasses.forEach(cls => {
+      previewNavbar.classList.remove(cls)
+    })
+
+    // Add new placement class if not default
+    if (placement) {
+      previewNavbar.classList.add(placement)
+    }
+
+    // Update the brand text to show current placement
+    const brand = previewNavbar.querySelector('.navbar-brand')
+    if (brand) {
+      brand.textContent = placementLabels[placement] || 'Default'
+    }
+
+    // Update code snippet
+    updateCodeSnippet(placement)
+  }
+
+  function updateCodeSnippet(placement: string) {
+    if (!codeSnippet) return
+
+    const placementClass = placement ? ` ${placement}` : ''
+    const label = placementLabels[placement] || 'Default'
+
+    const htmlCode = `<nav class="navbar${placementClass} bg-body-tertiary">
+  <div class="container-fluid">
+    <a class="navbar-brand" href="#">${label}</a>
+  </div>
+</nav>`
+
+    codeSnippet.className = 'language-html'
+    codeSnippet.textContent = htmlCode
+
+    if (typeof window !== 'undefined' && (window as any).Prism) {
+      (window as any).Prism.highlightElement(codeSnippet)
+    }
+  }
+
+  // Initialize dropdown
+  if (placementDropdownButton) {
+    const placementDropdown = bootstrap.Dropdown.getOrCreateInstance(placementDropdownButton)
+
+    placementDropdownItems.forEach(item => {
+      item.addEventListener('click', (e) => {
+        e.preventDefault()
+        const placement = (item as HTMLElement).dataset.placement || ''
+        updatePlacement(placement)
+        placementDropdown.hide()
+      })
+    })
+  }
+</script>
diff --git a/site/src/components/shortcodes/ResizableExample.astro b/site/src/components/shortcodes/ResizableExample.astro
new file mode 100644 (file)
index 0000000..9fed55d
--- /dev/null
@@ -0,0 +1,69 @@
+---
+import { replacePlaceholdersInHtml } from '@libs/placeholder'
+import Code from '@components/shortcodes/Code.astro'
+
+interface Props {
+  /**
+   * The example code.
+   */
+  code: string | string[]
+  /**
+   * The CSS class(es) to be added to the resizable container.
+   */
+  class?: string
+  /**
+   * Alias for class prop.
+   */
+  className?: string
+  /**
+   * Initial width of the resizable container.
+   * @default '100%'
+   */
+  initialWidth?: string
+  /**
+   * Minimum width of the resizable container.
+   * @default '200px'
+   */
+  minWidth?: string
+  /**
+   * Whether to show the code markup below.
+   * @default true
+   */
+  showMarkup?: boolean
+}
+
+const {
+  code,
+  class: classFromClass,
+  className,
+  initialWidth = '100%',
+  minWidth = '200px',
+  showMarkup = true
+} = Astro.props
+
+// Support both class and className props
+const containerClass = className || classFromClass
+
+let markup = Array.isArray(code) ? code.join('\n') : code
+markup = replacePlaceholdersInHtml(markup)
+
+const simplifiedMarkup = markup
+  .replace(
+    /<svg.*class="bd-placeholder-img(?:-lg)?(?: *?bd-placeholder-img-lg)? ?(.*?)".*?<\/svg>/g,
+    (match, classes) => `<img src="..."${classes ? ` class="${classes}"` : ''} alt="...">`
+  )
+---
+
+<div class="bd-example-snippet bd-code-snippet">
+  <div class="bd-example bd-example-resizable p-2">
+    <div
+      class:list={['bd-resizable-container', containerClass]}
+      style={`width: ${initialWidth}; min-width: ${minWidth};`}
+    >
+      <Fragment set:html={markup} />
+    </div>
+  </div>
+  {showMarkup && (
+    <Code code={simplifiedMarkup} lang="html" nestedInExample={true} />
+  )}
+</div>
index 4a6ad8e55b129f7490c49470e6f3f81b7f718e60..d2d26925f09d30770d9ea7d06319c0b70edbaf64 100644 (file)
@@ -105,7 +105,7 @@ And putting it to use in a navbar:
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar</a>
       <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDarkDropdown" aria-controls="navbarNavDarkDropdown" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
       <div class="collapse navbar-collapse" id="navbarNavDarkDropdown">
         <ul class="navbar-nav">
@@ -587,6 +587,7 @@ The dropdown plugin requires the following JavaScript files if you're building B
 | `floatingConfig` | null, object, function | `null` | To change Bootstrap's default Floating UI config, see [Floating UI's configuration](https://floating-ui.com/docs/computePosition). When a function is used to create the Floating UI configuration, it's called with an object that contains the Bootstrap's default Floating UI configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Floating UI. |
 | `placement` | string | `'bottom-start'` | Placement of the dropdown menu. Physical placements: `'top'`, `'bottom'`, `'left'`, `'right'`. Logical placements (RTL-aware): `'start'`, `'end'`. All support alignment modifiers: `-start`, `-end`. Supports responsive prefixes like `'bottom-start md:end'`. |
 | `reference` | string, element, object | `'toggle'` | Reference element of the dropdown menu. Accepts the values of `'toggle'`, `'parent'`, an HTMLElement reference or an object providing `getBoundingClientRect`. For more information refer to Floating UI's [virtual elements docs](https://floating-ui.com/docs/virtual-elements). |
+| `strategy` | string | `'absolute'` | Positioning strategy for the dropdown. Use `'absolute'` for default positioning, or `'fixed'` to escape containers with `overflow: hidden`. For more information refer to Floating UI's [strategy docs](https://floating-ui.com/docs/computePosition#strategy). |
 | `submenuTrigger` | string | `'both'` | How submenus are triggered. Use `'click'` for click only, `'hover'` for hover only, or `'both'` for both click and hover activation. |
 | `submenuDelay` | number | `100` | Delay in milliseconds before closing a submenu when the mouse leaves. Provides a grace period for diagonal mouse movement toward the submenu. |
 </BsTable>
diff --git a/site/src/content/docs/components/nav-overflow.mdx b/site/src/content/docs/components/nav-overflow.mdx
new file mode 100644 (file)
index 0000000..75838c3
--- /dev/null
@@ -0,0 +1,297 @@
+---
+title: Nav overflow
+description: Automatically collapse navigation items into a "More" dropdown when space is limited using the Priority+ pattern.
+toc: true
+---
+
+## How it works
+
+The nav overflow component (also known as the "Priority+" pattern) automatically detects when navigation items don't fit within their container and moves them into a dropdown menu. This provides a responsive navigation experience without requiring different markup for different screen sizes.
+
+Here's what you need to know before getting started:
+
+- Add `data-bs-toggle="nav-overflow"` to any `.nav` element to enable automatic overflow detection.
+- **Responds to container size**, not viewport size. The component uses a ResizeObserver to monitor its own width, so it works perfectly in embedded contexts, documentation examples, and responsive containers.
+- Overflow items are cloned into a "More" dropdown menu while the originals are hidden.
+- Works with all nav styles: default, pills, tabs, and underline.
+- Active and disabled states are preserved in the overflow menu.
+
+<Callout name="info-prefersreducedmotion" />
+
+## Examples
+
+Add `data-bs-toggle="nav-overflow"` to your nav element. When items don't fit, they'll automatically move to a "More" dropdown. Drag the right edge of the container below to see how nav items automatically move to the "More" dropdown as space becomes limited.
+
+<ResizableExample code={`<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+    <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="#">Dashboard</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Products</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Services</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Analytics</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Reports</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Settings</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Help</a>
+    </li>
+  </ul>`} />
+
+### With tabs
+
+The overflow pattern works seamlessly with tabbed navigation:
+
+<ResizableExample code={`<ul class="nav nav-tabs" data-bs-toggle="nav-overflow">
+    <li class="nav-item">
+      <a class="nav-link active" aria-current="page" href="#">Overview</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Details</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">History</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Activity</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Comments</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Attachments</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Related</a>
+    </li>
+  </ul>`} />
+
+### With underline
+
+<ResizableExample code={`<ul class="nav nav-underline" data-bs-toggle="nav-overflow">
+    <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="#">Features</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Pricing</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">FAQs</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">About</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Contact</a>
+    </li>
+  </ul>`} />
+
+### Keep items visible
+
+Use the `.nav-overflow-keep` class on items that should never be moved to the overflow menu. These items will remain visible regardless of available space—useful for high-priority items like "Home" or action buttons.
+
+<ResizableExample code={`<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+    <li class="nav-item nav-overflow-keep">
+      <a class="nav-link active" aria-current="page" href="#">Home</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Products</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Services</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">About</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Blog</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Careers</a>
+    </li>
+    <li class="nav-item nav-overflow-keep">
+      <a class="nav-link" href="#">Contact</a>
+    </li>
+  </ul>`} />
+
+### With disabled items
+
+Disabled states are preserved when items move to the overflow menu:
+
+<ResizableExample code={`<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+    <li class="nav-item">
+      <a class="nav-link active" aria-current="page" href="#">Active</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Link</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Another link</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">More content</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link" href="#">Even more</a>
+    </li>
+  </ul>`} />
+
+### In a navbar
+
+The nav overflow pattern can also be used within a [navbar]([[docsref:/components/navbar]]) for horizontal navigation that adapts to available space:
+
+<ResizableExample code={`<nav class="navbar navbar-expand bg-body-tertiary">
+    <div class="container-fluid">
+      <a class="navbar-brand" href="#">Brand</a>
+      <ul class="navbar-nav" data-bs-toggle="nav-overflow">
+        <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="#">Features</a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" href="#">Pricing</a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" href="#">About</a>
+        </li>
+        <li class="nav-item">
+          <a class="nav-link" href="#">Contact</a>
+        </li>
+      </ul>
+    </div>
+  </nav>`} />
+
+## Customizing the toggle
+
+### Custom text
+
+Use the `moreText` option to customize the text shown in the overflow toggle button:
+
+```js
+const nav = document.querySelector('.nav')
+new bootstrap.NavOverflow(nav, {
+  moreText: 'See all'
+})
+```
+
+### Custom icon
+
+Provide a custom icon via the `moreIcon` option:
+
+```js
+const nav = document.querySelector('.nav')
+new bootstrap.NavOverflow(nav, {
+  moreIcon: '<i class="bi bi-three-dots"></i>',
+  moreText: '' // Hide text, show only icon
+})
+```
+
+### Minimum visible items
+
+Use the `threshold` option to ensure a minimum number of items remain visible before the overflow kicks in:
+
+```js
+const nav = document.querySelector('.nav')
+new bootstrap.NavOverflow(nav, {
+  threshold: 3 // Always keep at least 3 items visible
+})
+```
+
+## Usage
+
+### Via data attributes
+
+Add `data-bs-toggle="nav-overflow"` to any `.nav` element to automatically enable the overflow behavior.
+
+```html
+<ul class="nav nav-pills" data-bs-toggle="nav-overflow">
+  <li class="nav-item"><a class="nav-link" href="#">Link 1</a></li>
+  <li class="nav-item"><a class="nav-link" href="#">Link 2</a></li>
+  <li class="nav-item"><a class="nav-link" href="#">Link 3</a></li>
+  <!-- More items... -->
+</ul>
+```
+
+### Via JavaScript
+
+Initialize the nav overflow component manually:
+
+```js
+const navElement = document.querySelector('.nav')
+const navOverflow = new bootstrap.NavOverflow(navElement, {
+  moreText: 'More',
+  threshold: 2
+})
+```
+
+### Options
+
+<JsDataAttributes />
+
+<BsTable>
+| Name | Type | Default | Description |
+| --- | --- | --- | --- |
+| `moreText` | string | `'More'` | Text label for the overflow toggle button. |
+| `moreIcon` | string | `'<svg>...</svg>'` | SVG or HTML icon for the overflow toggle button. |
+| `threshold` | number | `0` | Minimum number of items to keep visible before showing overflow. |
+</BsTable>
+
+### Methods
+
+<Callout name="danger-async-methods" type="danger" />
+
+You can create a nav overflow instance with the constructor:
+
+```js
+const navOverflow = new bootstrap.NavOverflow('#myNav', {
+  threshold: 2
+})
+```
+
+<BsTable>
+| Method | Description |
+| --- | --- |
+| `dispose` | Destroys the nav overflow instance and restores items to their original positions. |
+| `getInstance` | *Static* method to get the nav overflow instance associated with a DOM element. |
+| `getOrCreateInstance` | *Static* method to get the nav overflow instance or create a new one if not initialized. |
+| `update` | Manually recalculates which items should overflow. Called automatically on resize. |
+</BsTable>
+
+### Events
+
+Bootstrap's nav overflow component exposes events for hooking into overflow functionality.
+
+<BsTable>
+| Event type | Description |
+| --- | --- |
+| `update.bs.navoverflow` | Fired when the overflow calculation is updated (on resize or manual update). |
+| `overflow.bs.navoverflow` | Fired when items are moved to the overflow menu. Event includes `overflowCount` and `visibleCount` properties. |
+</BsTable>
+
+```js
+const myNav = document.getElementById('myNav')
+
+myNav.addEventListener('overflow.bs.navoverflow', event => {
+  console.log(`${event.overflowCount} items moved to overflow`)
+  console.log(`${event.visibleCount} items still visible`)
+})
+```
index 3d4b01f82a9aec07dc700cd8420599a1847905e9..f61d5ab48784d73905ba25482e7a5b92ae630e2e 100644 (file)
@@ -1,6 +1,6 @@
 ---
 title: Navbar
-description: Documentation and examples for Bootstrap’s powerful, responsive navigation header, the navbar. Includes support for branding, navigation, and more, including support for our collapse plugin.
+description: Documentation and examples for Bootstrap's powerful, responsive navigation header. The navbar includes support for branding, navigation, and more with built-in offcanvas for mobile.
 toc: true
 ---
 
@@ -8,12 +8,12 @@ import { getConfig } from '@libs/config'
 
 ## How it works
 
-Heres what you need to know before getting started with the navbar:
+Here's what you need to know before getting started with the navbar:
 
-- Navbars require a wrapping `.navbar` with `.navbar-expand{-sm|-md|-lg|-xl|-2xl}` for responsive collapsing and [color scheme](#color-schemes) classes.
+- Navbars require a wrapping `.navbar` with `.navbar-expand-lg{-sm|-md|-lg|-xl|-2xl}` for responsive collapsing and [color scheme](#color-schemes) classes.
 - Navbars and their contents are fluid by default. Change the [container](#containers) to limit their horizontal width in different ways.
 - Use our [margin]([[docsref:/utilities/margin]]), [padding]([[docsref:/utilities/padding]]), and [flex]([[docsref:/utilities/flex]]) utility classes for controlling spacing and alignment within navbars.
-- Navbars are responsive by default, but you can easily modify them to change that. Responsive behavior depends on our Collapse JavaScript plugin.
+- Navbars are responsive by default using our **offcanvas component**. On mobile, navigation links slide in from the side as a drawer.
 - Ensure accessibility by using a `<nav>` element or, if using a more generic element such as a `<div>`, add a `role="navigation"` to every navbar to explicitly identify it as a landmark region for users of assistive technologies.
 - Indicate the current item by using `aria-current="page"` for the current page or `aria-current="true"` for the current item in a set.
 
@@ -25,47 +25,53 @@ Navbars come with built-in support for a handful of sub-components. Choose from
 
 - `.navbar-brand` for your company, product, or project name.
 - `.navbar-nav` for a full-height and lightweight navigation (including support for dropdowns).
-- `.navbar-toggler` for use with our collapse plugin and other [navigation toggling](#responsive-behaviors) behaviors.
+- `.navbar-toggler` for use with our offcanvas plugin and other [navigation toggling](#responsive-behaviors) behaviors.
 - Flex and spacing utilities for any form controls and actions.
 - `.navbar-text` for adding vertically centered strings of text.
-- `.collapse.navbar-collapse` for grouping and hiding navbar contents by a parent breakpoint.
-- Add an optional `.navbar-nav-scroll` to set a `max-height` and [scroll expanded navbar content](#scrolling).
 
-Here’s an example of all the sub-components included in a responsive light-themed navbar that automatically collapses at the `lg` (large) breakpoint.
+Here's an example of all the sub-components included in a responsive light-themed navbar that automatically shows an offcanvas drawer at the `lg` (large) breakpoint.
 
-<Example code={`<nav class="navbar navbar-expand-lg">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarOffcanvas" aria-controls="navbarOffcanvas" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarSupportedContent">
-        <ul class="nav navbar-nav me-auto mb-2 mb-lg-0">
-          <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="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-              Dropdown
-            </a>
-            <ul class="dropdown-menu">
-              <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>
-          <li class="nav-item">
-            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
-          </li>
-        </ul>
-        <form class="d-flex" role="search">
-          <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
-          <button class="btn btn-subtle theme-primary" type="submit">Search</button>
-        </form>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarOffcanvas" aria-labelledby="navbarOffcanvasLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarOffcanvasLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body mb-2 mb-md-0">
+          <ul class="nav nav-pills me-auto">
+            <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="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                Dropdown
+              </a>
+              <ul class="dropdown-menu">
+                <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>
+            <li class="nav-item">
+              <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+            </li>
+          </ul>
+          <form class="d-flex" role="search">
+            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+            <button class="btn btn-icon btn-solid theme-secondary" type="submit">
+              <svg class="bi" width="16" height="16"><use href="#search" /></svg>
+            </button>
+          </form>
+        </div>
       </div>
     </div>
   </nav>`} />
@@ -81,14 +87,14 @@ The `.navbar-brand` can be applied to most elements, but an anchor works best, a
 Add your text within an element with the `.navbar-brand` class.
 
 <Example code={`<!-- As a link -->
-  <nav class="navbar bg-body-tertiary">
+  <nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar</a>
     </div>
   </nav>
 
   <!-- As a heading -->
-  <nav class="navbar bg-body-tertiary">
+  <nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
       <span class="navbar-brand mb-0 h1">Navbar</span>
     </div>
@@ -98,7 +104,7 @@ Add your text within an element with the `.navbar-brand` class.
 
 You can replace the text within the `.navbar-brand` with an `<img>`.
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <div class="container">
       <a class="navbar-brand" href="#">
         <img src="/docs/${getConfig().docs_version}/assets/brand/bootstrap-logo.svg" alt="Bootstrap" width="30" height="24">
@@ -110,7 +116,7 @@ You can replace the text within the `.navbar-brand` with an `<img>`.
 
 You can also make use of some additional utilities to add an image and text at the same time. Note the addition of `.d-inline-block` and `.align-text-top` on the `<img>`.
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">
         <img src="/docs/${getConfig().docs_version}/assets/brand/bootstrap-logo.svg" alt="Logo" width="30" height="24" class="d-inline-block align-text-top">
@@ -127,45 +133,57 @@ Add the `.active` class on `.nav-link` to indicate the current page.
 
 Please note that you should also add the `aria-current` attribute on the active `.nav-link`.
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-sm bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarNav">
-        <ul class="navbar-nav">
-          <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="#">Features</a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link" href="#">Pricing</a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
-          </li>
-        </ul>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarNav" aria-labelledby="navbarNavLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarNavLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav">
+            <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="#">Features</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link" href="#">Pricing</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+            </li>
+          </ul>
+        </div>
       </div>
     </div>
   </nav>`} />
 
 And because we use classes for our navs, you can avoid the list-based approach entirely if you like.
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-sm bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
-        <div class="navbar-nav">
-          <a class="nav-link active" aria-current="page" href="#">Home</a>
-          <a class="nav-link" href="#">Features</a>
-          <a class="nav-link" href="#">Pricing</a>
-          <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarNavAltMarkup" aria-labelledby="navbarNavAltMarkupLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarNavAltMarkupLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <div class="nav nav-pills navbar-nav">
+            <a class="nav-link active" aria-current="page" href="#">Home</a>
+            <a class="nav-link" href="#">Features</a>
+            <a class="nav-link" href="#">Pricing</a>
+            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+          </div>
         </div>
       </div>
     </div>
@@ -173,34 +191,40 @@ And because we use classes for our navs, you can avoid the list-based approach e
 
 You can also use dropdowns in your navbar. Dropdown menus require a wrapping element for positioning, so be sure to use separate and nested elements for `.nav-item` and `.nav-link` as shown below.
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-lg bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarNavDropdown">
-        <ul class="navbar-nav">
-          <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="#">Features</a>
-          </li>
-          <li class="nav-item">
-            <a class="nav-link" href="#">Pricing</a>
-          </li>
-          <li class="nav-item dropdown">
-            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-              Dropdown link
-            </a>
-            <ul class="dropdown-menu">
-              <li><a class="dropdown-item" href="#">Action</a></li>
-              <li><a class="dropdown-item" href="#">Another action</a></li>
-              <li><a class="dropdown-item" href="#">Something else here</a></li>
-            </ul>
-          </li>
-        </ul>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarNavDropdown" aria-labelledby="navbarNavDropdownLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarNavDropdownLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav">
+            <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="#">Features</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link" href="#">Pricing</a>
+            </li>
+            <li class="nav-item dropdown">
+              <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
+                Dropdown link
+              </a>
+              <ul class="dropdown-menu">
+                <li><a class="dropdown-item" href="#">Action</a></li>
+                <li><a class="dropdown-item" href="#">Another action</a></li>
+                <li><a class="dropdown-item" href="#">Something else here</a></li>
+              </ul>
+            </li>
+          </ul>
+        </div>
       </div>
     </div>
   </nav>`} />
@@ -209,7 +233,7 @@ You can also use dropdowns in your navbar. Dropdown menus require a wrapping ele
 
 Place various form controls and components within a navbar:
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
       <form class="d-flex" role="search">
         <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
@@ -220,7 +244,7 @@ Place various form controls and components within a navbar:
 
 Immediate child elements of `.navbar` use flex layout and will default to `justify-content: space-between`. Use additional [flex utilities]([[docsref:/utilities/flex]]) as needed to adjust this behavior.
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand">Navbar</a>
       <form class="d-flex" role="search">
@@ -232,7 +256,7 @@ Immediate child elements of `.navbar` use flex layout and will default to `justi
 
 Input groups work, too. If your navbar is an entire form, or mostly a form, you can use the `<form>` element as the container and save some HTML.
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <form class="container-fluid">
       <div class="input-group">
         <span class="input-group-text" id="basic-addon1">@</span>
@@ -243,7 +267,7 @@ Input groups work, too. If your navbar is an entire form, or mostly a form, you
 
 Various buttons are supported as part of these navbar forms, too. This is also a great reminder that vertical alignment utilities can be used to align different sized elements.
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <form class="container-fluid justify-content-start">
       <button class="btn btn-outline-success me-2" type="button">Main button</button>
       <button class="btn btn-sm btn-outline-secondary" type="button">Smaller button</button>
@@ -254,7 +278,7 @@ Various buttons are supported as part of these navbar forms, too. This is also a
 
 Navbars may contain bits of text with the help of `.navbar-text`. This class adjusts vertical alignment and horizontal spacing for strings of text.
 
-<Example code={`<nav class="navbar bg-body-tertiary">
+<Example code={`<nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
       <span class="navbar-text">
         Navbar text with an inline element
@@ -264,14 +288,55 @@ Navbars may contain bits of text with the help of `.navbar-text`. This class adj
 
 Mix and match with other components and utilities as needed.
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
     <div class="container-fluid">
       <a class="navbar-brand" href="#">Navbar w/ text</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarText">
-        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarText" aria-labelledby="navbarTextLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarTextLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav me-auto mb-2 mb-md-0">
+            <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="#">Features</a>
+            </li>
+            <li class="nav-item">
+              <a class="nav-link" href="#">Pricing</a>
+            </li>
+          </ul>
+          <span class="navbar-text">
+            Navbar text with an inline element
+          </span>
+        </div>
+      </div>
+    </div>
+  </nav>`} />
+
+## Color schemes
+
+Navbar themes are easier than ever thanks to Bootstrap's combination of Sass and CSS variables. The default is our "light navbar" for use with light background colors, but you can also apply `data-bs-theme="dark"` to the `.navbar` parent for dark background colors. Then, customize with `.bg-*` and additional utilities.
+
+<ResizableExample className="d-flex flex-column gap-2" showMarkup={false} code={`
+<nav class="navbar navbar-expand-md bg-body border-bottom border-body" data-bs-theme="dark">
+  <div class="container-fluid">
+    <a class="navbar-brand" href="#">Navbar</a>
+    <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
+    </button>
+    <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarColor01" aria-labelledby="navbarColor01Label">
+      <div class="offcanvas-header">
+        <h5 class="offcanvas-title" id="navbarColor01Label">Menu</h5>
+        <CloseButton dismiss="offcanvas" />
+      </div>
+      <div class="offcanvas-body">
+        <ul class="navbar-nav me-auto mb-2 mb-md-0">
           <li class="nav-item">
             <a class="nav-link active" aria-current="page" href="#">Home</a>
           </li>
@@ -281,109 +346,92 @@ Mix and match with other components and utilities as needed.
           <li class="nav-item">
             <a class="nav-link" href="#">Pricing</a>
           </li>
+          <li class="nav-item">
+            <a class="nav-link" href="#">About</a>
+          </li>
         </ul>
-        <span class="navbar-text">
-          Navbar text with an inline element
-        </span>
+        <form class="d-flex" role="search">
+          <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+          <button class="btn btn-outline theme-secondary" type="submit">Search</button>
+        </form>
       </div>
     </div>
-  </nav>`} />
-
-## Color schemes
-
-Navbar themes are easier than ever thanks to Bootstrap’s combination of Sass and CSS variables. The default is our “light navbar” for use with light background colors, but you can also apply `data-bs-theme="dark"` to the `.navbar` parent for dark background colors. Then, customize with `.bg-*` and additional utilities.
-
-<Example showMarkup={false} code={`
-<nav class="navbar navbar-expand-lg bg-dark border-bottom border-body" data-bs-theme="dark">
-  <div class="container-fluid">
-    <a class="navbar-brand" href="#">Navbar</a>
-    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor01" aria-controls="navbarColor01" aria-expanded="false" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
-    </button>
-    <div class="collapse navbar-collapse" id="navbarColor01">
-      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-        <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="#">Features</a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="#">Pricing</a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="#">About</a>
-        </li>
-      </ul>
-      <form class="d-flex" role="search">
-        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
-        <button class="btn btn-outline-light" type="submit">Search</button>
-      </form>
-    </div>
   </div>
 </nav>
 
-<nav class="navbar navbar-expand-lg bg-primary" data-bs-theme="dark">
+<nav class="navbar navbar-expand-md bg-primary" data-bs-theme="dark">
   <div class="container-fluid">
     <a class="navbar-brand" href="#">Navbar</a>
-    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor02" aria-controls="navbarColor02" aria-expanded="false" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+    <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarColor02" aria-controls="navbarColor02" aria-expanded="false" aria-label="Toggle navigation">
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
-    <div class="collapse navbar-collapse" id="navbarColor02">
-      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-        <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="#">Features</a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="#">Pricing</a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="#">About</a>
-        </li>
-      </ul>
-      <form class="d-flex" role="search">
-        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
-        <button class="btn btn-outline-light" type="submit">Search</button>
-      </form>
+    <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarColor02" aria-labelledby="navbarColor02Label">
+      <div class="offcanvas-header">
+        <h5 class="offcanvas-title" id="navbarColor02Label">Menu</h5>
+        <CloseButton dismiss="offcanvas" />
+      </div>
+      <div class="offcanvas-body">
+        <ul class="navbar-nav me-auto mb-2 mb-md-0">
+          <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="#">Features</a>
+          </li>
+          <li class="nav-item">
+            <a class="nav-link" href="#">Pricing</a>
+          </li>
+          <li class="nav-item">
+            <a class="nav-link" href="#">About</a>
+          </li>
+        </ul>
+        <form class="d-flex" role="search">
+          <input class="form-control me-2" data-bs-theme="light" type="search" placeholder="Search" aria-label="Search"/>
+          <button class="btn btn-solid theme-inverse" type="submit">Search</button>
+        </form>
+      </div>
     </div>
   </div>
 </nav>
 
-<nav class="navbar navbar-expand-lg" style="background-color: #e3f2fd;" data-bs-theme="light">
+<nav class="navbar navbar-expand-md bg-1" data-bs-theme="light">
   <div class="container-fluid">
     <a class="navbar-brand" href="#">Navbar</a>
-    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
-      <span class="navbar-toggler-icon"></span>
+    <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarColor03" aria-controls="navbarColor03" aria-expanded="false" aria-label="Toggle navigation">
+      <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
     </button>
-    <div class="collapse navbar-collapse" id="navbarColor03">
-      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-        <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="#">Features</a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="#">Pricing</a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="#">About</a>
-        </li>
-      </ul>
-      <form class="d-flex" role="search">
-        <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
-        <button class="btn btn-outline-primary" type="submit">Search</button>
-      </form>
+    <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarColor03" aria-labelledby="navbarColor03Label">
+      <div class="offcanvas-header">
+        <h5 class="offcanvas-title" id="navbarColor03Label">Menu</h5>
+        <CloseButton dismiss="offcanvas" />
+      </div>
+      <div class="offcanvas-body">
+        <ul class="navbar-nav me-auto mb-2 mb-md-0">
+          <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="#">Features</a>
+          </li>
+          <li class="nav-item">
+            <a class="nav-link" href="#">Pricing</a>
+          </li>
+          <li class="nav-item">
+            <a class="nav-link" href="#">About</a>
+          </li>
+        </ul>
+        <form class="d-flex" role="search">
+          <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
+          <button class="btn btn-outline-primary" type="submit">Search</button>
+        </form>
+      </div>
     </div>
   </div>
 </nav>
 `} />
 
 ```html
-<nav class="navbar bg-dark border-bottom border-body" data-bs-theme="dark">
+<nav class="navbar bg-body border-bottom border-body" data-bs-theme="dark">
   <!-- Navbar content -->
 </nav>
 
@@ -398,10 +446,10 @@ Navbar themes are easier than ever thanks to Bootstrap’s combination of Sass a
 
 ## Containers
 
-Although its not required, you can wrap a navbar in a `.container` to center it on a page–though note that an inner container is still required. Or you can add a container inside the `.navbar` to only center the contents of a [fixed or static top navbar](#placement).
+Although it's not required, you can wrap a navbar in a `.container` to center it on a page–though note that an inner container is still required. Or you can add a container inside the `.navbar` to only center the contents of a [fixed or static top navbar](#placement).
 
 <Example code={`<div class="container">
-    <nav class="navbar navbar-expand-lg bg-body-tertiary">
+    <nav class="navbar navbar-expand-lg bg-1 fg-2">
       <div class="container-fluid">
         <a class="navbar-brand" href="#">Navbar</a>
       </div>
@@ -410,7 +458,7 @@ Although it’s not required, you can wrap a navbar in a `.container` to center
 
 Use any of the responsive containers to change how wide the content in your navbar is presented.
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<Example code={`<nav class="navbar navbar-expand-lg bg-1 fg-2">
     <div class="container-md">
       <a class="navbar-brand" href="#">Navbar</a>
     </div>
@@ -420,237 +468,129 @@ Use any of the responsive containers to change how wide the content in your navb
 
 Use our [position utilities]([[docsref:/utilities/position]]) to place navbars in non-static positions. Choose from fixed to the top, fixed to the bottom, stickied to the top (scrolls with the page until it reaches the top, then stays there), or stickied to the bottom (scrolls with the page until it reaches the bottom, then stays there).
 
-Fixed navbars use `position: fixed`, meaning they’re pulled from the normal flow of the DOM and may require custom CSS (e.g., `padding-top` on the `<body>`) to prevent overlap with other elements.
-
-<Example code={`<nav class="navbar bg-body-tertiary">
-    <div class="container-fluid">
-      <a class="navbar-brand" href="#">Default</a>
-    </div>
-  </nav>`} />
+Fixed navbars use `position: fixed`, meaning they're pulled from the normal flow of the DOM and may require custom CSS (e.g., `padding-top` on the `<body>`) to prevent overlap with other elements.
 
-<Example code={`<nav class="navbar fixed-top bg-body-tertiary">
-    <div class="container-fluid">
-      <a class="navbar-brand" href="#">Fixed top</a>
-    </div>
-  </nav>`} />
-
-<Example code={`<nav class="navbar fixed-bottom bg-body-tertiary">
-    <div class="container-fluid">
-      <a class="navbar-brand" href="#">Fixed bottom</a>
-    </div>
-  </nav>`} />
-
-<Example code={`<nav class="navbar sticky-top bg-body-tertiary">
-    <div class="container-fluid">
-      <a class="navbar-brand" href="#">Sticky top</a>
-    </div>
-  </nav>`} />
+<NavbarPlacementPlayground />
 
-<Example code={`<nav class="navbar sticky-bottom bg-body-tertiary">
-    <div class="container-fluid">
-      <a class="navbar-brand" href="#">Sticky bottom</a>
-    </div>
-  </nav>`} />
+## Responsive behaviors
 
-## Scrolling
+Navbars can use `.navbar-toggler`, and `.navbar-expand-lg{-sm|-md|-lg|-xl|-2xl}` classes to determine when their content appears in an offcanvas drawer or inline. In combination with other utilities, you can easily choose when to show or hide particular elements.
 
-Add `.navbar-nav-scroll` to a `.navbar-nav` (or other navbar sub-component) to enable vertical scrolling within the toggleable contents of a collapsed navbar. By default, scrolling kicks in at `75vh` (or 75% of the viewport height), but you can override that with the local CSS custom property `--bs-navbar-height` or custom styles. At larger viewports when the navbar is expanded, content will appear as it does in a default navbar.
+For navbars that never collapse, add the `.navbar-expand-lg` class on the navbar. For navbars that always show the offcanvas drawer, don't add any `.navbar-expand-lg` class.
 
-Please note that this behavior comes with a potential drawback of `overflow`—when setting `overflow-y: auto` (required to scroll the content here), `overflow-x` is the equivalent of `auto`, which will crop some horizontal content.
+### Offcanvas drawer
 
-Here’s an example navbar using `.navbar-nav-scroll` with `style="--bs-scroll-height: 100px;"`, with some extra margin utilities for optimum spacing.
+By default, navbars use the [offcanvas component]([[docsref:/components/offcanvas]]) for their responsive behavior. This provides a modern drawer-style menu that slides in from any side of the screen.
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
-    <div class="container-fluid">
-      <a class="navbar-brand" href="#">Navbar scroll</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarScroll" aria-controls="navbarScroll" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
-      </button>
-      <div class="collapse navbar-collapse" id="navbarScroll">
-        <ul class="navbar-nav me-auto my-2 my-lg-0 navbar-nav-scroll" style="--bs-scroll-height: 100px;">
-          <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="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-              Link
-            </a>
-            <ul class="dropdown-menu">
-              <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>
-          <li class="nav-item">
-            <a class="nav-link disabled" aria-disabled="true">Link</a>
-          </li>
-        </ul>
-        <form class="d-flex" 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>
-  </nav>`} />
+#### Drawer placement
 
-## Responsive behaviors
+You can customize which side the drawer appears from using offcanvas placement classes:
 
-Navbars can use `.navbar-toggler`, `.navbar-collapse`, and `.navbar-expand{-sm|-md|-lg|-xl|-2xl}` classes to determine when their content collapses behind a button. In combination with other utilities, you can easily choose when to show or hide particular elements.
+- `.offcanvas-start` - slides in from the left (or right in RTL)
+- `.offcanvas-end` - slides in from the right (or left in RTL)
+- `.offcanvas-top` - slides in from the top
+- `.offcanvas-bottom` - slides in from the bottom
 
-For navbars that never collapse, add the `.navbar-expand` class on the navbar. For navbars that always collapse, don’t add any `.navbar-expand` class.
+These examples omit the `.navbar-expand-lg-*` class to always show the drawer behavior. Click the toggler to see the drawer slide in from different directions.
 
-### Toggler
-
-Navbar togglers are left-aligned by default, but should they follow a sibling element like a `.navbar-brand`, they’ll automatically be aligned to the far right. Reversing your markup will reverse the placement of the toggler. Below are examples of different toggle styles.
-
-With no `.navbar-brand` shown at the smallest breakpoint:
-
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
     <div class="container-fluid">
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <a class="navbar-brand" href="#">Left Drawer</a>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarLeftDrawer" aria-controls="navbarLeftDrawer" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarTogglerDemo01">
-        <a class="navbar-brand" href="#">Hidden brand</a>
-        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-          <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">
-            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
-          </li>
-        </ul>
-        <form class="d-flex" 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 class="offcanvas offcanvas-start" tabindex="-1" id="navbarLeftDrawer" aria-labelledby="navbarLeftDrawerLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarLeftDrawerLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav me-auto mb-2 mb-md-0">
+            <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"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
+          </ul>
+        </div>
       </div>
     </div>
   </nav>`} />
 
-With a brand name shown on the left and toggler on the right:
-
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
     <div class="container-fluid">
-      <a class="navbar-brand" href="#">Navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <a class="navbar-brand" href="#">Top Drawer</a>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTopDrawer" aria-controls="navbarTopDrawer" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="collapse navbar-collapse" id="navbarTogglerDemo02">
-        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-          <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">
-            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
-          </li>
-        </ul>
-        <form class="d-flex" 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 class="offcanvas offcanvas-top" tabindex="-1" id="navbarTopDrawer" aria-labelledby="navbarTopDrawerLabel">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarTopDrawerLabel">Menu</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <ul class="navbar-nav me-auto mb-2 mb-md-0">
+            <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"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
+          </ul>
+        </div>
       </div>
     </div>
   </nav>`} />
 
-With a toggler on the left and brand name on the right:
+### Toggler
 
-<Example code={`<nav class="navbar navbar-expand-lg bg-body-tertiary">
-    <div class="container-fluid">
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
-      </button>
-      <a class="navbar-brand" href="#">Navbar</a>
-      <div class="collapse navbar-collapse" id="navbarTogglerDemo03">
-        <ul class="navbar-nav me-auto mb-2 mb-lg-0">
-          <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">
-            <a class="nav-link disabled" aria-disabled="true">Disabled</a>
-          </li>
-        </ul>
-        <form class="d-flex" 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>
-  </nav>`} />
+Navbar togglers are left-aligned by default, but should they follow a sibling element like a `.navbar-brand`, they'll automatically be aligned to the far right. Reversing your markup will reverse the placement of the toggler.
 
-### External content
+These examples omit the `.navbar-expand-lg-*` class to always show the collapsed state with the toggler visible. Click the toggler to open the offcanvas drawer.
 
-Sometimes you want to use the collapse plugin to trigger a container element for content that structurally sits outside of the `.navbar` . Because our plugin works on the `id` and `data-bs-target` matching, that’s easily done!
+With no `.navbar-brand` shown (hidden inside the drawer):
 
-<Example code={`<div class="collapse" id="navbarToggleExternalContent" data-bs-theme="dark">
-    <div class="bg-dark p-4">
-      <h5 class="text-body-emphasis h4">Collapsed content</h5>
-      <span class="text-body-secondary">Toggleable via the navbar brand.</span>
-    </div>
-  </div>
-  <nav class="navbar navbar-dark bg-dark">
+<ResizableExample code={`<nav class="navbar navbar-expand-md bg-1 fg-2">
     <div class="container-fluid">
-      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarTogglerDemo01" aria-labelledby="navbarTogglerDemo01Label">
+        <div class="offcanvas-header">
+          <h5 class="offcanvas-title" id="navbarTogglerDemo01Label">Hidden brand</h5>
+          <CloseButton dismiss="offcanvas" />
+        </div>
+        <div class="offcanvas-body">
+          <a class="navbar-brand" href="#">Hidden brand</a>
+          <ul class="navbar-nav me-auto mb-2 mb-md-0">
+            <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"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
+          </ul>
+          <form class="d-flex" 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>`} />
 
-When you do this, we recommend including additional JavaScript to move the focus programmatically to the container when it is opened. Otherwise, keyboard users and users of assistive technologies will likely have a hard time finding the newly revealed content - particularly if the container that was opened comes *before* the toggler in the document’s structure. We also recommend making sure that the toggler has the `aria-controls` attribute, pointing to the `id` of the content container. In theory, this allows assistive technology users to jump directly from the toggler to the container it controls–but support for this is currently quite patchy.
-
-### Offcanvas
-
-Transform your expanding and collapsing navbar into an offcanvas drawer with the [offcanvas component]([[docsref:/components/offcanvas]]). We extend both the offcanvas default styles and use our `.navbar-expand-*` classes to create a dynamic and flexible navigation sidebar.
-
-In the example below, to create an offcanvas navbar that is always collapsed across all breakpoints, omit the `.navbar-expand-*` class entirely.
+With a brand name shown on the left and toggler on the right:
 
-<Example code={`<nav class="navbar bg-body-tertiary fixed-top">
+<ResizableExample code={`<nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
-      <a class="navbar-brand" href="#">Offcanvas navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar" aria-controls="offcanvasNavbar" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <a class="navbar-brand" href="#">Navbar</a>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTogglerDemo02" aria-controls="navbarTogglerDemo02" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasNavbar" aria-labelledby="offcanvasNavbarLabel">
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarTogglerDemo02" aria-labelledby="navbarTogglerDemo02Label">
         <div class="offcanvas-header">
-          <h5 class="offcanvas-title" id="offcanvasNavbarLabel">Offcanvas</h5>
+          <h5 class="offcanvas-title" id="navbarTogglerDemo02Label">Menu</h5>
           <CloseButton dismiss="offcanvas" />
         </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="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                Dropdown
-              </a>
-              <ul class="dropdown-menu">
-                <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 class="navbar-nav me-auto mb-2">
+            <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"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
           </ul>
-          <form class="d-flex mt-3" role="search">
+          <form class="d-flex" 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>
@@ -659,64 +599,57 @@ In the example below, to create an offcanvas navbar that is always collapsed acr
     </div>
   </nav>`} />
 
-To create an offcanvas navbar that expands into a normal navbar at a specific breakpoint like `lg`, use `.navbar-expand-lg`.
-
-```html
-<nav class="navbar navbar-expand-lg bg-body-tertiary fixed-top">
-  <a class="navbar-brand" href="#">Offcanvas navbar</a>
-  <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarOffcanvasLg" aria-controls="navbarOffcanvasLg" aria-label="Toggle navigation">
-    <span class="navbar-toggler-icon"></span>
-  </button>
-  <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarOffcanvasLg" aria-labelledby="navbarOffcanvasLgLabel">
-    ...
-  </div>
-</nav>
-```
-
-When using offcanvas in a dark navbar, be aware that you may need to have a dark background on the offcanvas content to avoid the text becoming illegible. In the example below, we add `.navbar-dark` and `.bg-dark` to the `.navbar`, `.text-bg-dark` to the `.offcanvas`, `.dropdown-menu-dark` to `.dropdown-menu`, and `.btn-close-white` to `.btn-close` for proper styling with a dark offcanvas.
+With a toggler on the left and brand name on the right:
 
-<Example code={`<nav class="navbar navbar-dark bg-dark fixed-top">
+<ResizableExample code={`<nav class="navbar bg-1 fg-2">
     <div class="container-fluid">
-      <a class="navbar-brand" href="#">Offcanvas dark navbar</a>
-      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasDarkNavbar" aria-controls="offcanvasDarkNavbar" aria-label="Toggle navigation">
-        <span class="navbar-toggler-icon"></span>
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarTogglerDemo03" aria-controls="navbarTogglerDemo03" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
       </button>
-      <div class="offcanvas offcanvas-end text-bg-dark" tabindex="-1" id="offcanvasDarkNavbar" aria-labelledby="offcanvasDarkNavbarLabel">
+      <a class="navbar-brand" href="#">Navbar</a>
+      <div class="offcanvas offcanvas-end" tabindex="-1" id="navbarTogglerDemo03" aria-labelledby="navbarTogglerDemo03Label">
         <div class="offcanvas-header">
-          <h5 class="offcanvas-title" id="offcanvasDarkNavbarLabel">Dark offcanvas</h5>
+          <h5 class="offcanvas-title" id="navbarTogglerDemo03Label">Menu</h5>
           <CloseButton dismiss="offcanvas" />
         </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="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
-                Dropdown
-              </a>
-              <ul class="dropdown-menu dropdown-menu-dark">
-                <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 class="navbar-nav me-auto mb-2">
+            <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"><a class="nav-link disabled" aria-disabled="true">Disabled</a></li>
           </ul>
-          <form class="d-flex mt-3" role="search">
+          <form class="d-flex" role="search">
             <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search"/>
-            <button class="btn btn-success" type="submit">Search</button>
+            <button class="btn btn-outline-success" type="submit">Search</button>
           </form>
         </div>
       </div>
     </div>
   </nav>`} />
 
+### External content
+
+Sometimes you want to use the offcanvas plugin to trigger a container element for content that structurally sits outside of the `.navbar`. Because our plugin works on the `id` and `data-bs-target` matching, that's easily done!
+
+<ResizableExample code={`<div class="offcanvas offcanvas-top" tabindex="-1" id="navbarToggleExternalContent" data-bs-theme="dark" aria-labelledby="navbarToggleExternalContentLabel">
+    <div class="offcanvas-header">
+      <h5 class="offcanvas-title" id="navbarToggleExternalContentLabel">Collapsed content</h5>
+      <CloseButton dismiss="offcanvas" />
+    </div>
+    <div class="offcanvas-body">
+      <span class="text-body-secondary">Toggleable via the navbar toggler.</span>
+    </div>
+  </div>
+  <nav class="navbar bg-body" data-bs-theme="dark">
+    <div class="container-fluid">
+      <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#navbarToggleExternalContent" aria-controls="navbarToggleExternalContent" aria-expanded="false" aria-label="Toggle navigation">
+        <svg class="navbar-toggler-icon" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M2 3.5h12M2 8h12M2 12.5h12"/></svg>
+      </button>
+    </div>
+  </nav>`} />
+
+When you do this, we recommend including additional JavaScript to move the focus programmatically to the container when it is opened. Otherwise, keyboard users and users of assistive technologies will likely have a hard time finding the newly revealed content - particularly if the container that was opened comes *before* the toggler in the document's structure. We also recommend making sure that the toggler has the `aria-controls` attribute, pointing to the `id` of the content container. In theory, this allows assistive technology users to jump directly from the toggler to the container it controls–but support for this is currently quite patchy.
+
 ## CSS
 
 ### Variables
@@ -729,7 +662,7 @@ Some additional CSS variables are also present on `.navbar-nav`:
 
 <ScssDocs name="navbar-nav-css-vars" file="scss/_navbar.scss" />
 
-Customization through CSS variables can be seen on the `.navbar-dark` class where we override specific values without adding duplicate CSS selectors.
+Customization through CSS variables can be seen on navbars with `data-bs-theme="dark"` where we override specific values without adding duplicate CSS selectors.
 
 <ScssDocs name="navbar-dark-css-vars" file="scss/_navbar.scss" />
 
index 92e8b1f609dc927ce79161b620d488965588ef05..fd01ef2adf3ad374d72af90e7c3239084d85c4be 100644 (file)
@@ -166,14 +166,15 @@ To make a responsive offcanvas, replace the `.offcanvas` base class with a respo
 
 ## Placement
 
-Theres 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
 - `.offcanvas-top` places offcanvas on the top of the viewport
 - `.offcanvas-bottom` places offcanvas on the bottom of the viewport
+- `.offcanvas-fullscreen` covers the entire viewport
 
-Try the top, right, and bottom examples out below.
+Try the top, right, bottom, and fullscreen examples out below.
 
 <Example code={`<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasTop" aria-controls="offcanvasTop">Toggle top offcanvas</button>
 
@@ -211,6 +212,36 @@ Try the top, right, and bottom examples out below.
     </div>
   </div>`} />
 
+<Example code={`<button class="btn btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasFullscreen" aria-controls="offcanvasFullscreen">Toggle fullscreen offcanvas</button>
+
+  <div class="offcanvas offcanvas-fullscreen" tabindex="-1" id="offcanvasFullscreen" aria-labelledby="offcanvasFullscreenLabel">
+    <div class="offcanvas-header">
+      <h5 class="offcanvas-title" id="offcanvasFullscreenLabel">Fullscreen offcanvas</h5>
+      <CloseButton dismiss="offcanvas" />
+    </div>
+    <div class="offcanvas-body">
+      <p>This offcanvas covers the entire viewport, useful for full-page menus or modal-like experiences.</p>
+    </div>
+  </div>`} />
+
+## Footer
+
+Add an optional `.offcanvas-footer` for action buttons or other content at the bottom of the offcanvas.
+
+<Example class="bd-example-offcanvas p-0 bg-body-tertiary overflow-hidden" code={`<div class="offcanvas offcanvas-start show" tabindex="-1" id="offcanvasFooter" aria-labelledby="offcanvasFooterLabel">
+    <div class="offcanvas-header">
+      <h5 class="offcanvas-title" id="offcanvasFooterLabel">Offcanvas with footer</h5>
+      <CloseButton dismiss="offcanvas" />
+    </div>
+    <div class="offcanvas-body">
+      <p>Content for the offcanvas goes here. The footer will stick to the bottom.</p>
+    </div>
+    <div class="offcanvas-footer">
+      <button type="button" class="btn btn-secondary" data-bs-dismiss="offcanvas">Close</button>
+      <button type="button" class="btn btn-primary">Save changes</button>
+    </div>
+  </div>`} />
+
 ## Accessibility
 
 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.
index 36931f00b23804e453a07ebb2514a15401da7c96..51b7ff8ed2e04b48813b429b61676dd0aeb160d6 100644 (file)
     }
   }
 
+  //
+  // Resizable examples
+  //
+
+  .bd-example-resizable {
+    position: relative;
+  }
+
+  .bd-resizable-container {
+    max-width: 100%;
+    padding: 1rem;
+    overflow: hidden;
+    resize: horizontal;
+    background-color: var(--bs-bg-body);
+    border: 1px dashed var(--bs-border-color);
+    @include border-radius(var(--bs-border-radius));
+  }
+
   //
   // Code snippets
   //
index 858b11dc9d12b7512df6eed856f92e311589e6a6..7530544649ba7ef30145f47aaed73402e6fc62ad 100644 (file)
@@ -20,7 +20,9 @@ export declare global {
   export const Example: typeof import('@shortcodes/Example.astro').default
   export const JsDismiss: typeof import('@shortcodes/JsDismiss.astro').default
   export const JsDocs: typeof import('@shortcodes/JsDocs.astro').default
+  export const NavbarPlacementPlayground: typeof import('@shortcodes/NavbarPlacementPlayground.astro').default
   export const Placeholder: typeof import('@shortcodes/Placeholder.astro').default
+  export const ResizableExample: typeof import('@shortcodes/ResizableExample.astro').default
   export const ScssDocs: typeof import('@shortcodes/ScssDocs.astro').default
   export const StepperPlayground: typeof import('@shortcodes/StepperPlayground.astro').default
   export const Swatch: typeof import('@shortcodes/Swatch.astro').default