]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
v6: Form cleanup & new `--radius-*` tokens/classes (#42356)
authorMark Otto <markd.otto@gmail.com>
Fri, 1 May 2026 02:32:41 +0000 (19:32 -0700)
committerGitHub <noreply@github.com>
Fri, 1 May 2026 02:32:41 +0000 (19:32 -0700)
* New border-radius tokens, --radius-*; update nav-overflow to work in more situations; fix disabled chip inputs; fix sizing of OTP and chip by removing it lol; fix vertical pills with new radius tokens

* Finish off improving radius scale

* fixes after rebase

* format

51 files changed:
js/src/nav-overflow.js
scss/_accordion.scss
scss/_alert.scss
scss/_badge.scss
scss/_breadcrumb.scss
scss/_card.scss
scss/_chip.scss
scss/_config.scss
scss/_datepicker.scss
scss/_dialog.scss
scss/_drawer.scss
scss/_list-group.scss
scss/_menu.scss
scss/_nav-overflow.scss
scss/_nav.scss
scss/_navbar.scss
scss/_popover.scss
scss/_progress.scss
scss/_root.scss
scss/_toasts.scss
scss/_tooltip.scss
scss/_utilities.scss
scss/buttons/_button.scss
scss/buttons/_close.scss
scss/content/_images.scss
scss/content/_reboot.scss
scss/forms/_chip-input.scss
scss/forms/_form-control.scss
scss/forms/_form-field.scss
scss/forms/_otp-input.scss
scss/forms/_strength.scss
scss/mixins/_border-radius.scss
scss/tests/modules/_configuration.test.scss
scss/tests/modules/_root-tokens-bootstrap.test.scss
site/src/components/shortcodes/ButtonPlayground.astro
site/src/content/docs/components/nav.mdx
site/src/content/docs/components/tab.mdx
site/src/content/docs/forms/chip-input.mdx
site/src/content/docs/forms/input-group.mdx
site/src/content/docs/forms/otp-input.mdx
site/src/content/docs/guides/migration.mdx
site/src/content/docs/utilities/border-radius.mdx
site/src/layouts/DocsLayout.astro
site/src/scss/_ads.scss
site/src/scss/_badge.scss
site/src/scss/_callouts.scss
site/src/scss/_component-examples.scss
site/src/scss/_details.scss
site/src/scss/_search.scss
site/src/scss/_syntax.scss
site/src/scss/_toc.scss

index a443c2007b932b35b6d5f7603fb591c5c60df417..a6fa1d103642b884dc04baf342691a710d9ce6db 100644 (file)
@@ -242,20 +242,25 @@ class NavOverflow extends BaseComponent {
 
     const overflowWidth = overflowItem?.offsetWidth || 0
 
+    // Keep items are always visible; subtract their widths so the threshold
+    // reflects actual available space for non-keep items.
+    const keepWidth = this._items
+      .filter(item => item.classList.contains(CLASS_NAME_KEEP))
+      .reduce((sum, item) => sum + item.offsetWidth, 0)
+
     let usedWidth = 0
     const itemsToOverflow = []
-    const overflowThreshold = navWidth - overflowWidth - 10 // 10px buffer
+    const overflowThreshold = navWidth - overflowWidth - keepWidth - 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
       }
 
+      usedWidth += item.offsetWidth
+
       if (usedWidth > overflowThreshold) {
         itemsToOverflow.push(item)
       }
index a1cce3fd7694d428cdffe43713567c1dda99eb01..b95606603d015caf2adcd2458beed4eeb055ebc0 100644 (file)
@@ -19,7 +19,7 @@ $accordion-tokens: defaults(
     --accordion-transition: var(--accordion-transition-property) var(--accordion-timing),
     --accordion-border-color: var(--border-color),
     --accordion-border-width: var(--border-width),
-    --accordion-border-radius: var(--accordion-radius, var(--border-radius-lg)),
+    --accordion-border-radius: var(--accordion-radius, var(--radius-7)),
     --accordion-btn-color: var(--fg-2),
     --accordion-btn-bg: var(--bg-body),
     --accordion-btn-icon-width: 1rem,
index 1094ee18f36bade0d39ce7260986a83eadd2d239..10077c8b98aa449a246eee3509a827093d67e116 100644 (file)
@@ -16,7 +16,7 @@ $alert-tokens: defaults(
     --alert-color: var(--theme-fg, inherit),
     --alert-border-color: var(--theme-border, var(--border-color)),
     --alert-border: var(--border-width) solid var(--alert-border-color),
-    --alert-border-radius: var(--border-radius),
+    --alert-border-radius: var(--radius-5),
     --alert-link-color: inherit,
     --hr-border-color: var(--theme-border, var(--border-color)),
   ),
index b57ed0464246d172a4d2346f76d6e58a144cb039..7fdb38d88503f94f60554d44c84f27e6238301c1 100644 (file)
@@ -16,7 +16,7 @@ $badge-tokens: defaults(
     --badge-bg: var(--bg-2),
     --badge-border-width: var(--border-width),
     --badge-border-color: transparent,
-    --badge-border-radius: var(--border-radius-lg),
+    --badge-border-radius: var(--radius-7),
   ),
   $badge-tokens
 );
index 1f49d6b020e8833c7df54e58a8ecb24f56fd1b29..499d352310abed2624f08f351e8593677b0721e6 100644 (file)
@@ -12,7 +12,7 @@ $breadcrumb-tokens: defaults(
     --breadcrumb-margin-bottom: 1rem,
     --breadcrumb-font-size: inherit,
     --breadcrumb-bg: transparent,
-    --breadcrumb-border-radius: var(--border-radius),
+    --breadcrumb-border-radius: var(--radius-5),
     --breadcrumb-divider-color: var(--fg-4),
     --breadcrumb-link-padding-x: .75rem,
     --breadcrumb-link-padding-y: .25rem,
@@ -20,7 +20,7 @@ $breadcrumb-tokens: defaults(
     --breadcrumb-link-hover-color: var(--fg-2),
     --breadcrumb-link-hover-bg: var(--bg-1),
     --breadcrumb-link-active-color: var(--fg-1),
-    --breadcrumb-link-border-radius: var(--border-radius-lg),
+    --breadcrumb-link-border-radius: var(--radius-7),
   ),
   $breadcrumb-tokens
 );
index 406696168d04ec4aa2e331c5886f434ed764a3c3..97aa9c9bbb75492f71cf71bd0bc824f2d92bbea9 100644 (file)
@@ -16,9 +16,9 @@ $card-tokens: defaults(
     --card-subtitle-color: inherit,
     --card-border-width: var(--border-width),
     --card-border-color: var(--border-color-translucent),
-    --card-border-radius: var(--border-radius-lg),
+    --card-border-radius: var(--radius-7),
     --card-box-shadow: none,
-    --card-inner-border-radius: calc(var(--border-radius-lg) - var(--border-width)),
+    --card-inner-border-radius: calc(var(--radius-7) - var(--border-width)),
     --card-cap-padding-y: var(--spacer-3),
     --card-cap-padding-x: var(--spacer),
     --card-cap-bg: var(--bg-1),
index 2b354b92f054798664063deec32f60b59103baf2..9f618ba1a2cf14812cdc84224514acab958194f6 100644 (file)
@@ -13,7 +13,7 @@ $chip-tokens: defaults(
     --chip-height: 1.75rem,
     --chip-padding-x: .625rem,
     --chip-gap: .3125rem,
-    --chip-border-radius: var(--border-radius-pill),
+    --chip-border-radius: var(--radius-pill),
     --chip-img-size: 1.25rem,
     --chip-icon-size: 1rem,
     --chip-dismiss-size: 1rem,
index 81c0f17bb9c85ab3d0b8b62c1a2c9afaf4766943..cdab5f393d56c4ef91cdb9a2ec725ecb95b51c8c 100644 (file)
@@ -69,17 +69,31 @@ $negative-spacers: (
 
 $sizes: (
   1: $spacer,
-  2: calc($spacer * 2),
-  3: calc($spacer * 3),
-  4: calc($spacer * 4),
-  5: calc($spacer * 5),
-  6: calc($spacer * 6),
-  7: calc($spacer * 7),
-  8: calc($spacer * 8),
-  9: calc($spacer * 9),
-  10: calc($spacer * 10),
-  11: calc($spacer * 11),
-  12: calc($spacer * 12),
+  2: $spacer * 2,
+  3: $spacer * 3,
+  4: $spacer * 4,
+  5: $spacer * 5,
+  6: $spacer * 6,
+  7: $spacer * 7,
+  8: $spacer * 8,
+  9: $spacer * 9,
+  10: $spacer * 10,
+  11: $spacer * 11,
+  12: $spacer * 12,
+) !default;
+
+$radius: .5rem !default;
+$radii: (
+  0: 0,
+  1: $radius * .25,
+  2: $radius * .375,
+  3: $radius * .5,
+  4: $radius * .75,
+  5: $radius,
+  6: $radius * 1.25,
+  7: $radius * 1.5,
+  8: $radius * 2,
+  9: $radius * 3,
 ) !default;
 
 // Breakpoints
index 7849495514207aa946398ecaf90a92a00526baf2..ae8c9adec6644c3f86644d1e99a0c287ac23ca17 100644 (file)
@@ -17,7 +17,7 @@ $datepicker-tokens: defaults(
     --datepicker-color: var(--fg-body),
     --datepicker-border-color: var(--border-color-translucent),
     --datepicker-border-width: var(--border-width),
-    --datepicker-border-radius: var(--border-radius-lg),
+    --datepicker-border-radius: var(--radius-7),
     --datepicker-box-shadow: var(--box-shadow),
     --datepicker-font-size: var(--font-size-sm),
     --datepicker-min-width: 280px,
@@ -107,7 +107,7 @@ $datepicker-tokens: defaults(
     cursor: pointer;
     background-color: transparent;
     border: 0;
-    @include border-radius(var(--border-radius));
+    @include border-radius(var(--radius-5));
 
     &::before {
       position: absolute;
@@ -191,7 +191,7 @@ $datepicker-tokens: defaults(
     // cursor: pointer;
     background-color: transparent;
     border: 0;
-    @include border-radius(var(--border-radius));
+    @include border-radius(var(--radius-5));
 
     &:disabled {
       color: var(--datepicker-day-disabled-color);
@@ -240,7 +240,7 @@ $datepicker-tokens: defaults(
     cursor: pointer;
     background-color: transparent;
     border: 0;
-    @include border-radius(var(--border-radius));
+    @include border-radius(var(--radius-5));
 
     &:disabled {
       color: var(--datepicker-day-disabled-color);
@@ -338,7 +338,7 @@ $datepicker-tokens: defaults(
     cursor: pointer;
     background-color: transparent;
     border: 0;
-    border-radius: var(--border-radius);
+    border-radius: var(--radius-5);
 
     &:hover {
       background-color: var(--datepicker-day-hover-bg);
@@ -370,17 +370,17 @@ $datepicker-tokens: defaults(
   }
 
   [data-vc-date-hover="first"] [data-vc-date-btn] {
-    border-start-start-radius: var(--border-radius);
-    border-end-start-radius: var(--border-radius);
+    border-start-start-radius: var(--radius-5);
+    border-end-start-radius: var(--radius-5);
   }
 
   [data-vc-date-hover="last"] [data-vc-date-btn] {
-    border-start-end-radius: var(--border-radius);
-    border-end-end-radius: var(--border-radius);
+    border-start-end-radius: var(--radius-5);
+    border-end-end-radius: var(--radius-5);
   }
 
   [data-vc-date-hover="first-and-last"] [data-vc-date-btn] {
-    border-radius: var(--border-radius);
+    border-radius: var(--radius-5);
   }
 
   [data-vc-date-selected="middle"] [data-vc-date-btn] {
@@ -396,20 +396,20 @@ $datepicker-tokens: defaults(
   }
 
   [data-vc-date-selected="first"] [data-vc-date-btn] {
-    border-top-left-radius: var(--border-radius);
+    border-top-left-radius: var(--radius-5);
     border-top-right-radius: 0;
     border-bottom-right-radius: 0;
-    border-bottom-left-radius: var(--border-radius);
+    border-bottom-left-radius: var(--radius-5);
   }
 
   [data-vc-date-selected="last"] [data-vc-date-btn] {
     border-top-left-radius: 0;
-    border-top-right-radius: var(--border-radius);
-    border-bottom-right-radius: var(--border-radius);
+    border-top-right-radius: var(--radius-5);
+    border-bottom-right-radius: var(--radius-5);
     border-bottom-left-radius: 0;
   }
 
   [data-vc-date-selected="first-and-last"] [data-vc-date-btn] {
-    border-radius: var(--border-radius);
+    border-radius: var(--radius-5);
   }
 }
index b67288c94aad7c77f0561d410873ec692db4c4e1..a9b268362920490b3626465fcf147d5c28e49cbc 100644 (file)
@@ -26,7 +26,7 @@ $dialog-tokens: defaults(
     --dialog-bg: var(--bg-body),
     --dialog-border-color: var(--border-color-translucent),
     --dialog-border-width: var(--border-width),
-    --dialog-border-radius: var(--border-radius-lg),
+    --dialog-border-radius: var(--radius-7),
     --dialog-box-shadow: var(--box-shadow-lg),
     --dialog-transition-duration: .3s,
     --dialog-transition-timing: cubic-bezier(.22, 1, .36, 1),
index 4fc813b4125eaa8b00f8457cd3d60312e47894f3..7c9edeac837e27838482da32148782358675e2c6 100644 (file)
@@ -24,7 +24,7 @@ $drawer-tokens: defaults(
     --drawer-bg: var(--bg-body),
     --drawer-border-width: var(--border-width),
     --drawer-border-color: var(--border-color-translucent),
-    --drawer-border-radius: var(--border-radius-lg),
+    --drawer-border-radius: var(--radius-7),
     --drawer-box-shadow: var(--box-shadow-lg),
     --drawer-transition-duration: .3s,
     --drawer-transition-timing: cubic-bezier(.22, 1, .36, 1),
index 8052ccfb2e0e6410a642355225e09d465078f1ec..52b0e4b424ce848f39b5f758fb7418c61b33898a 100644 (file)
@@ -15,7 +15,7 @@ $list-group-tokens: defaults(
     --list-group-bg: var(--bg-body),
     --list-group-border-color: var(--border-color),
     --list-group-border-width: var(--border-width),
-    --list-group-border-radius: var(--border-radius),
+    --list-group-border-radius: var(--radius-5),
     --list-group-item-padding-x: var(--spacer),
     --list-group-item-padding-y: var(--spacer-2),
     --list-group-action-color: var(--fg-2),
index ed12970911a552ca59c90dc771ea9691180313b2..b988cd716f25f5496f0d48d024ffd7c2b74891cc 100644 (file)
@@ -21,7 +21,7 @@ $menu-tokens: defaults(
     --menu-color: var(--fg-body),
     --menu-bg: var(--bg-body),
     // --menu-border-color: var(--border-color-translucent),
-    // --menu-border-radius: var(--border-radius-lg),
+    // --menu-border-radius: var(--radius-7),
     // --menu-border-width: var(--border-width),
     --menu-box-shadow: var(--box-shadow),
     // --menu-max-height: none,
@@ -37,7 +37,7 @@ $menu-tokens: defaults(
     --menu-item-gap: .5rem,
     --menu-item-padding-x: .75rem,
     --menu-item-padding-y: .25rem,
-    --menu-item-border-radius: var(--border-radius),
+    --menu-item-border-radius: var(--radius-5),
     --menu-icon-size: 1rem,
     --menu-image-size: 1.5rem,
     --menu-description-font-size: var(--font-size-xs),
@@ -76,7 +76,7 @@ $menu-tokens: defaults(
     background-color: var(--menu-bg);
     background-clip: padding-box;
     border: var(--menu-border-width, var(--border-width)) solid var(--menu-border-color, var(--border-color-translucent));
-    @include border-radius(var(--menu-border-radius, var(--border-radius-lg)));
+    @include border-radius(var(--menu-border-radius, var(--radius-7)));
     @include box-shadow(var(--menu-box-shadow));
     opacity: 0;
     transform: scale(.95);
@@ -206,7 +206,7 @@ $menu-tokens: defaults(
     width: var(--menu-image-size);
     height: var(--menu-image-size);
     object-fit: cover;
-    @include border-radius(var(--border-radius-sm));
+    @include border-radius(var(--radius-5));
   }
 
   .menu-item-content {
index 28b34c5e0899e9898e86e08c312124a6c31a44f8..0b810a351e168358acea72c8e29b67ad984d0da2 100644 (file)
@@ -9,6 +9,18 @@
     min-width: 0; // Allow flex child to shrink below content width
   }
 
+  // Pills use inline-flex by default; override so the nav fills its container
+  // and the ResizeObserver can detect width changes.
+  .nav-pills.nav-overflow {
+    display: flex;
+  }
+
+  // Inside a navbar the nav is a flex child that sizes to content by default;
+  // grow it so it fills remaining space and shrinks with the container.
+  .navbar-nav.nav-overflow {
+    flex: 1 1 0;
+  }
+
   // Container item for overflow
   .nav-overflow-item {
     flex-shrink: 0;
index 8958d20202f3501ea28c6ed3dce79fe4b08552d6..7ea73d6f59bb7f99a58f5c1dda08726f3b825cd2 100644 (file)
@@ -41,7 +41,7 @@ $nav-tabs-tokens: defaults(
   (
     --nav-tabs-border-width: var(--border-width),
     --nav-tabs-border-color: var(--border-color),
-    --nav-tabs-border-radius: var(--border-radius),
+    --nav-tabs-border-radius: var(--radius-5),
     --nav-tabs-link-hover-border-color: var(--border-subtle),
     --nav-tabs-link-active-color: var(--fg-color),
     --nav-tabs-link-active-bg: var(--bg-body),
@@ -59,8 +59,10 @@ $nav-pills-tokens: defaults(
   (
     --nav-pills-bg: var(--bg-1),
     --nav-pills-padding: .25rem,
+    --nav-pills-border-radius: var(--radius-9),
     --nav-pills-link-active-color: var(--primary-contrast),
     --nav-pills-link-active-bg: var(--primary-bg),
+    --nav-pills-link-border-radius: var(--radius-9),
   ),
   $nav-pills-tokens
 );
@@ -114,7 +116,7 @@ $nav-underline-tokens: defaults(
     white-space: nowrap;
     background: none;
     border: var(--nav-link-border-width) solid transparent;
-    @include border-radius(var(--border-radius));
+    @include border-radius(var(--radius-5));
     @include transition(var(--nav-link-transition));
 
     &:hover,
@@ -192,10 +194,10 @@ $nav-underline-tokens: defaults(
     display: inline-flex;
     padding: var(--nav-pills-padding);
     background-color: var(--nav-pills-bg);
-    @include border-radius(var(--border-radius-pill));
+    @include border-radius(var(--nav-pills-border-radius));
 
     .nav-link {
-      @include border-radius(var(--border-radius-pill));
+      @include border-radius(var(--nav-pills-link-border-radius));
     }
 
     .nav-link.active,
@@ -205,6 +207,16 @@ $nav-underline-tokens: defaults(
     }
   }
 
+  .nav-pills-vertical {
+    flex-direction: column;
+    align-items: stretch;
+
+    .nav-item,
+    .nav-link {
+      width: 100%;
+    }
+  }
+
   //
   // Underline
   //
index 7dc0012c4ba57d9d3f499ffcd83b22d897adbb59..7c30a57a20e85c14be0462dea721fd984f1bb43d 100644 (file)
@@ -38,7 +38,7 @@ $navbar-tokens: defaults(
     --navbar-toggler-padding-x: .75rem,
     --navbar-toggler-font-size: var(--font-size-lg),
     --navbar-toggler-border-color: color-mix(in oklch, var(--fg-body) 15%, transparent),
-    --navbar-toggler-border-radius: var(--border-radius),
+    --navbar-toggler-border-radius: var(--radius-5),
     --navbar-toggler-transition: box-shadow .15s ease-in-out,
   ),
   $navbar-tokens
index c3b6334e3a8d7cfbecf19e6074265908c1692409..9377f5f03ec2c75a40382fdf99a1ce184563d741 100644 (file)
@@ -17,8 +17,8 @@ $popover-tokens: defaults(
     --popover-bg: var(--bg-body),
     --popover-border-width: var(--border-width),
     --popover-border-color: var(--border-color-translucent),
-    --popover-border-radius: var(--border-radius-lg),
-    --popover-inner-border-radius: calc(var(--border-radius-lg) - var(--border-width)),
+    --popover-border-radius: var(--radius-7),
+    --popover-inner-border-radius: calc(var(--radius-7) - var(--border-width)),
     --popover-box-shadow: var(--box-shadow),
     --popover-header-padding-x: var(--spacer),
     --popover-header-padding-y: var(--spacer-3),
index 7e905fad5db0810b9d480142861f4c20532fc385..4d042e23bd9ca663f3b73171eb764a172e6c894d 100644 (file)
@@ -15,7 +15,7 @@ $progress-tokens: defaults(
     --progress-height: 1rem,
     --progress-font-size: var(--font-size-sm),
     --progress-bg: var(--bg-2),
-    --progress-border-radius: var(--border-radius),
+    --progress-border-radius: var(--radius-5),
     --progress-box-shadow: var(--box-shadow-inset),
     --progress-bar-color: var(--white),
     --progress-bar-bg: var(--primary-bg),
index 4abe148b66b833b71c3991ed2d1c5424743dfda4..1eca05d7a2f56262d475aa087f44d6ec590823e7 100644 (file)
@@ -54,16 +54,6 @@ $root-tokens: defaults(
     --border-color-translucent: color-mix(in oklch, var(--fg-body) 15%, transparent),
     // scss-docs-end root-border-var
 
-    // scss-docs-start root-border-radius-var
-    --border-radius: .5rem,
-    --border-radius-xs: .375rem,
-    --border-radius-sm: .5rem,
-    --border-radius-lg: .75rem,
-    --border-radius-xl: 1rem,
-    --border-radius-2xl: 2rem,
-    --border-radius-pill: 50rem,
-    // scss-docs-end root-border-radius-var
-
     // scss-docs-start root-box-shadow-variables
     --box-shadow: 0 .5rem 1rem rgb(0 0 0 / 15%),
     --box-shadow-sm: 0 .125rem .25rem rgb(0 0 0 / 7.5%),
@@ -96,28 +86,28 @@ $root-tokens: defaults(
     --btn-input-padding-x: .75rem,
     --btn-input-font-size: var(--font-size-base),
     --btn-input-line-height: var(--line-height-base),
-    --btn-input-border-radius: var(--border-radius),
+    --btn-input-border-radius: var(--radius-5),
 
     --btn-input-xs-min-height: 1.5rem,
     --btn-input-xs-padding-y: .125rem,
     --btn-input-xs-padding-x: .5rem,
     --btn-input-xs-font-size: var(--font-size-xs),
     --btn-input-xs-line-height: 1.125,
-    --btn-input-xs-border-radius: var(--border-radius-xs),
+    --btn-input-xs-border-radius: var(--radius-5),
 
     --btn-input-sm-min-height: 2rem,
     --btn-input-sm-padding-y: .25rem,
     --btn-input-sm-padding-x: .625rem,
     --btn-input-sm-font-size: var(--font-size-sm),
     --btn-input-sm-line-height: var(--line-height-sm),
-    --btn-input-sm-border-radius: var(--border-radius-sm),
+    --btn-input-sm-border-radius: var(--radius-5),
 
     --btn-input-lg-min-height: 2.75rem,
     --btn-input-lg-padding-y: .5rem,
     --btn-input-lg-padding-x: 1rem,
     --btn-input-lg-font-size: var(--font-size-md),
     --btn-input-lg-line-height: var(--line-height-md),
-    --btn-input-lg-border-radius: var(--border-radius-lg),
+    --btn-input-lg-border-radius: var(--radius-7),
     // scss-docs-end root-form-variables
   ),
   $root-tokens
@@ -163,9 +153,20 @@ $root-tokens: defaults(
 }
 
 // Generate spacer tokens
+// scss-docs-start root-spacer-loop
 @each $key, $value in $spacers {
   $root-tokens: map.set($root-tokens, --spacer-#{$key}, $value);
 }
+// scss-docs-end root-spacer-loop
+
+// Generate radius tokens
+// scss-docs-start root-radius-loop
+@each $key, $value in $radii {
+  $root-tokens: map.set($root-tokens, --radius-#{$key}, $value);
+}
+// stylelint-disable-next-line scss/dollar-variable-default
+$root-tokens: map.set($root-tokens, --radius-pill, 50rem);
+// scss-docs-end root-radius-loop
 
 :root {
   @include tokens($root-tokens);
index 97aba6950d774e5689c1e595fe0bf07525a29430..6b6359ea526798bdd15a1a62f70fbc68de358777 100644 (file)
@@ -47,7 +47,7 @@ $toast-tokens: defaults(
     background-clip: padding-box;
     border: var(--toast-border-width) solid var(--theme-border, var(--toast-border-color));
     box-shadow: var(--toast-box-shadow);
-    @include border-radius(var(--toast-border-radius, var(--border-radius-lg)));
+    @include border-radius(var(--toast-border-radius, var(--radius-7)));
 
     &.showing {
       opacity: 0;
index 6a88e44e4e79d9d0bbe8b2f86254c67aeaf3a47c..ccbb6bb0bdbd308280601475e4f95a4352cd9b05 100644 (file)
@@ -17,7 +17,7 @@ $tooltip-tokens: defaults(
     --tooltip-font-size: var(--font-size-sm),
     --tooltip-color: var(--bg-body),
     --tooltip-bg: var(--fg-body),
-    --tooltip-border-radius: var(--border-radius),
+    --tooltip-border-radius: var(--radius-5),
     --tooltip-opacity: .95,
     --tooltip-arrow-width: .8rem,
     --tooltip-arrow-height: .4rem,
index 2779b25daf5a5ca98633a5048e8dccc02a05f12b..5b6adb4bbd3bb4d5e05e0dd1ef757cb1929297d7 100644 (file)
@@ -872,76 +872,61 @@ $utilities: map.merge(
     "border-radius": (
       property: border-radius,
       class: rounded,
-      values: (
-        null: var(--border-radius),
-        0: 0,
-        1: var(--border-radius-sm),
-        2: var(--border-radius),
-        3: var(--border-radius-lg),
-        4: var(--border-radius-xl),
-        5: var(--border-radius-2xl),
-        circle: 50%,
-        pill: var(--border-radius-pill)
+      values: map.merge(
+        $radii,
+        (
+          null: map.get($radii, 5),
+          circle: 50%,
+          pill: var(--radius-pill)
+        )
       )
     ),
     "rounded-top": (
       property: border-start-start-radius border-start-end-radius,
       class: rounded-top,
-      values: (
-        null: var(--border-radius),
-        0: 0,
-        1: var(--border-radius-sm),
-        2: var(--border-radius),
-        3: var(--border-radius-lg),
-        4: var(--border-radius-xl),
-        5: var(--border-radius-2xl),
-        circle: 50%,
-        pill: var(--border-radius-pill)
+      values: map.merge(
+        $radii,
+        (
+          null: map.get($radii, 5),
+          circle: 50%,
+          pill: var(--radius-pill)
+        )
       )
     ),
     "rounded-end": (
       property: border-end-end-radius border-end-start-radius,
       class: rounded-end,
-      values: (
-        null: var(--border-radius),
-        0: 0,
-        1: var(--border-radius-sm),
-        2: var(--border-radius),
-        3: var(--border-radius-lg),
-        4: var(--border-radius-xl),
-        5: var(--border-radius-2xl),
-        circle: 50%,
-        pill: var(--border-radius-pill)
+      values: map.merge(
+        $radii,
+        (
+          null: map.get($radii, 5),
+          circle: 50%,
+          pill: var(--radius-pill)
+        )
       )
     ),
     "rounded-bottom": (
       property: border-end-end-radius border-end-start-radius,
       class: rounded-bottom,
-      values: (
-        null: var(--border-radius),
-        0: 0,
-        1: var(--border-radius-sm),
-        2: var(--border-radius),
-        3: var(--border-radius-lg),
-        4: var(--border-radius-xl),
-        5: var(--border-radius-2xl),
-        circle: 50%,
-        pill: var(--border-radius-pill)
+      values: map.merge(
+        $radii,
+        (
+          null: map.get($radii, 5),
+          circle: 50%,
+          pill: var(--radius-pill)
+        )
       )
     ),
     "rounded-start": (
       property: border-start-start-radius border-start-end-radius,
       class: rounded-start,
-      values: (
-        null: var(--border-radius),
-        0: 0,
-        1: var(--border-radius-sm),
-        2: var(--border-radius),
-        3: var(--border-radius-lg),
-        4: var(--border-radius-xl),
-        5: var(--border-radius-2xl),
-        circle: 50%,
-        pill: var(--border-radius-pill)
+      values: map.merge(
+        $radii,
+        (
+          null: map.get($radii, 5),
+          circle: 50%,
+          pill: var(--radius-pill)
+        )
       )
     ),
     // scss-docs-end utils-border-radius
index 3653ffaafbc9b493beebf12b461e68fd36947f70..a778c09a7dd79dba84880e76a832721fde155201 100644 (file)
@@ -27,7 +27,7 @@ $button-tokens: defaults(
     --btn-white-space: nowrap,
     --btn-border-width: var(--border-width),
     --btn-border-color: transparent,
-    --btn-border-radius: var(--border-radius),
+    --btn-border-radius: var(--radius-5),
     --btn-hover-border-color: transparent,
     --btn-disabled-opacity: .65,
     --btn-transition-timing: .15s ease-in-out,
index f1fc957d0be1b8fd8f77bc02f7d2e8b87e07858a..98c653eba0a69647231efc25752b2e1c9fe73471 100644 (file)
@@ -35,7 +35,7 @@ $btn-close-tokens: defaults(
     color: var(--btn-close-color);
     background: transparent; // for button elements
     border: 0; // for button elements
-    @include border-radius(var(--border-radius-sm));
+    @include border-radius(var(--radius-5));
     opacity: var(--btn-close-opacity);
 
     > svg {
index efad765dde2cb2782743634e06b611e50edc255a..c1f17212dc0fd32bd33f3ca00dcaaff382ea0bce 100644 (file)
@@ -14,7 +14,7 @@ $thumbnail-tokens: defaults(
     --thumbnail-bg: var(--bg-body),
     --thumbnail-border-width: var(--border-width),
     --thumbnail-border-color: var(--border-color),
-    --thumbnail-border-radius: var(--border-radius),
+    --thumbnail-border-radius: var(--radius-5),
     --thumbnail-box-shadow: var(--box-shadow-sm),
   ),
   $thumbnail-tokens
index 806e7b02e19504a28d41ac6c218197f175e18335..7feb7b1cf2c5fe8900a2bf290e72ad66dd41ed76 100644 (file)
@@ -17,7 +17,7 @@ $reboot-kbd-tokens: defaults(
     --kbd-font-size: var(--font-size-xs),
     --kbd-color: var(--bg-body),
     --kbd-bg: var(--fg-2),
-    --kbd-border-radius: var(--border-radius-sm),
+    --kbd-border-radius: var(--radius-5),
   ),
   $reboot-kbd-tokens
 );
index edfbff244047de83dfdb2fe36c53c12145442831..7236c0d0bdf17387c3a359e5fb98c36f31cc9717 100644 (file)
@@ -17,7 +17,7 @@ $chip-input-tokens: defaults(
     --control-bg: var(--btn-input-bg),
     --control-border-width: var(--border-width),
     --control-border-color: var(--border-color),
-    --control-border-radius: var(--border-radius),
+    --control-border-radius: var(--radius-5),
   ),
   $chip-input-tokens
 );
@@ -56,58 +56,14 @@ $chip-input-tokens: defaults(
     // Disabled state
     &.disabled,
     &:has(.form-ghost:disabled) {
+      cursor: not-allowed;
       background-color: var(--bg-2);
       opacity: 1;
 
       > .chip {
+        pointer-events: none;
         opacity: var(--control-disabled-opacity);
-
-        .chip-dismiss {
-          pointer-events: none;
-        }
-      }
-
-      > .form-ghost {
-        cursor: not-allowed;
       }
     }
   }
-
-  // Theme cascade: .chip-input.theme-* passes theme to child chips
-  // Chips inherit theme variables from parent
-  // @each $color-name, $theme-props in $theme-map {
-  //   .chip-input.theme-#{$color-name} > .chip {
-  //     // Subtle default state
-  //     --chip-color: var(--theme-fg);
-  //     --chip-bg: var(--theme-bg-subtle);
-
-  //     // Selected/active solid state
-  //     --chip-selected-color: var(--theme-contrast);
-  //     --chip-selected-bg: var(--theme-bg);
-  //     --chip-selected-border-color: var(--theme-bg);
-  //   }
-  // }
-
-  // // Sizing variants
-  // .chip-input-sm {
-  //   --control-min-height: #{$control-min-height-sm};
-  //   --control-padding-y: #{$control-padding-y-sm};
-  //   --control-padding-x: #{$control-padding-x-sm};
-  //   --control-font-size: #{$control-font-size-sm};
-  //   --control-line-height: #{$control-line-height-sm};
-  //   --control-border-radius: #{$control-border-radius-sm};
-  //   --chip-input-gap: .25rem;
-  //   --chip-input-chip-font-size: .8125em;
-  // }
-
-  // .chip-input-lg {
-  //   --control-min-height: #{$control-min-height-lg};
-  //   --control-padding-y: #{$control-padding-y-lg};
-  //   --control-padding-x: #{$control-padding-x-lg};
-  //   --control-font-size: #{$control-font-size-lg};
-  //   --control-line-height: #{$control-line-height-lg};
-  //   --control-border-radius: #{$control-border-radius-lg};
-  //   --chip-input-gap: .5rem;
-  //   --chip-input-chip-font-size: .9375em;
-  // }
 }
index 6c501426a19199b5fc4eb8676440e19484f3e518..9ae6ab9bf8625ec64805732995db00d5af60ab47 100644 (file)
@@ -21,7 +21,7 @@ $form-control-tokens: defaults(
     --control-bg: var(--btn-input-bg),
     --control-border-width: var(--border-width),
     --control-border-color: var(--border-color),
-    --control-border-radius: var(--border-radius),
+    --control-border-radius: var(--radius-5),
     --control-box-shadow: var(--box-shadow-inset),
     --control-action-bg: var(--bg-1),
     --control-action-hover-bg: var(--bg-2),
@@ -239,12 +239,12 @@ $form-control-sizes: defaults(
 
     &::-moz-color-swatch {
       border: 0 !important; // stylelint-disable-line declaration-no-important
-      @include border-radius(var(--border-radius-sm));
+      @include border-radius(var(--radius-5));
     }
 
     &::-webkit-color-swatch {
       border: 0 !important; // stylelint-disable-line declaration-no-important
-      @include border-radius(var(--border-radius-sm));
+      @include border-radius(var(--radius-5));
     }
   }
 
index 68cc79e9eb11f94ba7e14c78aa127678ff463cbb..3f58835f513a5f2c4af16b29bdaf2e71189feb57 100644 (file)
@@ -46,7 +46,7 @@
     padding: calc(var(--spacer) * .75);
     cursor: pointer;
     border: var(--border-width) solid transparent;
-    @include border-radius(var(--border-radius-lg));
+    @include border-radius(var(--radius-7));
 
     &:hover {
       background-color: var(--bg-1);
index 25a12f73a71e4e6441eae666435111c4a3b6f0c8..2e42960619ecc88e4efcdac8f694af577ae6fab5 100644 (file)
@@ -1,8 +1,6 @@
 @use "../functions" as *;
-@use "../mixins/border-radius" as *;
 @use "../mixins/tokens" as *;
 
-// stylelint-disable custom-property-no-missing-var-function
 $otp-tokens: () !default;
 
 // scss-docs-start otp-tokens
@@ -16,7 +14,6 @@ $otp-tokens: defaults(
   $otp-tokens
 );
 // scss-docs-end otp-tokens
-// stylelint-enable custom-property-no-missing-var-function
 
 // scss-docs-start otp-sizes
 $otp-sizes: () !default;
@@ -42,7 +39,6 @@ $otp-sizes: defaults(
       font-weight: 500;
       line-height: 1;
       text-align: center;
-      @include border-radius(var(--otp-border-radius, var(--btn-input-border-radius)));
 
       // Remove default number spinners
       &::-webkit-outer-spin-button,
@@ -80,12 +76,4 @@ $otp-sizes: defaults(
     color: var(--fg-4);
     user-select: none;
   }
-
-  @each $size, $_ in $otp-sizes {
-    .otp-#{$size} {
-      --otp-size: var(--btn-input-#{$size}-min-height);
-      --otp-font-size: var(--btn-input-#{$size}-font-size);
-      --otp-border-radius: var(--btn-input-#{$size}-border-radius);
-    }
-  }
 }
index 61b2f14821773bbe408b3fd4d636cc93258e7d8a..a414023425c93bd4fd195970a8f8a8505d4a4a28 100644 (file)
@@ -14,7 +14,7 @@ $strength-tokens: defaults(
     --strength-height: .375rem,
     --strength-gap: .25rem,
     --strength-margin-top: .25rem,
-    --strength-border-radius: var(--border-radius-pill),
+    --strength-border-radius: var(--radius-pill),
     --strength-bg: var(--bg-2),
     --strength-color: var(--bg-2),
     --strength-weak-color: var(--danger-bg),
index 69de12ff0353a22ce2af0a7c278c416dbb794337..6dd7e6175dc1260c6069d6db2c5a213544084e6e 100644 (file)
@@ -20,7 +20,7 @@
 }
 
 // scss-docs-start border-radius-mixins
-@mixin border-radius($radius: var(--border-radius), $fallback-border-radius: false) {
+@mixin border-radius($radius: var(--radius-5), $fallback-border-radius: false) {
   @if $enable-rounded {
     border-radius: valid-radius($radius);
   }
   }
 }
 
-@mixin border-top-radius($radius: var(--border-radius)) {
+@mixin border-top-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-start-start-radius: valid-radius($radius);
     border-start-end-radius: valid-radius($radius);
   }
 }
 
-@mixin border-end-radius($radius: var(--border-radius)) {
+@mixin border-end-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-start-end-radius: valid-radius($radius);
     border-end-end-radius: valid-radius($radius);
   }
 }
 
-@mixin border-bottom-radius($radius: var(--border-radius)) {
+@mixin border-bottom-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-end-start-radius: valid-radius($radius);
     border-end-end-radius: valid-radius($radius);
   }
 }
 
-@mixin border-start-radius($radius: var(--border-radius)) {
+@mixin border-start-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-start-start-radius: valid-radius($radius);
     border-end-start-radius: valid-radius($radius);
   }
 }
 
-@mixin border-top-start-radius($radius: var(--border-radius)) {
+@mixin border-top-start-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-start-start-radius: valid-radius($radius);
   }
 }
 
-@mixin border-top-end-radius($radius: var(--border-radius)) {
+@mixin border-top-end-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-start-end-radius: valid-radius($radius);
   }
 }
 
-@mixin border-bottom-end-radius($radius: var(--border-radius)) {
+@mixin border-bottom-end-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-end-end-radius: valid-radius($radius);
   }
 }
 
-@mixin border-bottom-start-radius($radius: var(--border-radius)) {
+@mixin border-bottom-start-radius($radius: var(--radius-5)) {
   @if $enable-rounded {
     border-end-start-radius: valid-radius($radius);
   }
index 94c3bd5231a67f088dc64607e154a8ddf49361cb..1fc7b974c7d164e1c9acaec18ff860354aa81dd7 100644 (file)
@@ -10,7 +10,7 @@
     --alert-color: var(--theme-fg, inherit),
     --alert-border-color: var(--theme-border, var(--border-color)),
     --alert-border: var(--border-width) solid var(--alert-border-color),
-    --alert-border-radius: var(--border-radius),
+    --alert-border-radius: var(--radius-2),
     --alert-link-color: #0a58ca,
     --hr-border-color: var(--theme-border, var(--border-color)),
   )
@@ -52,7 +52,7 @@ $true-terminal-output: false;
             padding-y: 1rem;
             padding-x: 1rem;
             // stylelint-disable-next-line property-disallowed-list
-            border-radius: var(--border-radius);
+            border-radius: var(--radius-2);
           }
         }
       }
index 45a8186780768a50d71369eae8a5befaf12a4e74..ed3523c9d4fb423fe56d7505ad11bdd6aa1dfaee 100644 (file)
@@ -19,7 +19,7 @@
   // Customize menu tokens
   $menu-tokens: (
     --menu-bg: var(--bg-2),
-    --menu-item-border-radius: var(--border-radius-xl),
+    --menu-item-border-radius: var(--radius-4),
     --menu-padding-x: 1rem,
     --menu-padding-y: 1rem,
   )
index 212db94df92559a5bf80e7f0021d65df2e2e2896..87e7e2192894c92291cf654fa2b00aaf3586adc0 100644 (file)
@@ -135,14 +135,14 @@ const rounded = ['default', 'pill', 'square']
   class="d-flex flex-wrap align-items-start gap-2"
   code={`<button type="button" class="btn-solid theme-primary btn-sm" data-button-type="text">Button</button>
 <button type="button" class="btn-solid theme-primary" data-button-type="left-icon">
-  <svg class="bi me-1" width="16" height="16" aria-hidden="true">
+  <svg class="bi" width="16" height="16" aria-hidden="true">
     <use href="#arrow-left" />
   </svg>
   Left icon
 </button>
 <button type="button" class="btn-solid theme-primary btn-sm" data-button-type="right-icon">
   Right icon
-  <svg class="bi ms-1" width="16" height="16" aria-hidden="true">
+  <svg class="bi" width="16" height="16" aria-hidden="true">
     <use href="#arrow-right" />
   </svg>
 </button>
index c50cdae0b35e28b3ab6a9370de1773f39cee4af4..24d3159468a3ad4f62be41a499277e54c5317000 100644 (file)
@@ -48,7 +48,7 @@ Where appropriate, you can also use `<button>` elements instead of `<a>` element
 <Example code={`<nav class="nav">
     <a class="nav-link active" aria-current="page" href="#">Active</a>
     <a class="nav-link" href="#">Link</a>
-    <button class="nav-link" data-bs-toggle="menu" href="#" role="button" aria-expanded="false">Menu</button>
+    <button class="nav-link" data-bs-toggle="menu" href="#" role="button" aria-expanded="false">Menu</button><!-- [!code highlight] -->
     <div class="menu">
       <a class="menu-item" href="#">Action</a>
       <a class="menu-item" href="#">Another action</a>
@@ -70,7 +70,7 @@ Change the style of `.nav`s component with modifiers and utilities. Mix and matc
 
 Takes the basic nav from above and adds the `.nav-tabs` class to generate a tabbed interface.
 
-<Example code={`<ul class="nav nav-tabs">
+<Example code={`<ul class="nav nav-tabs"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -89,7 +89,24 @@ Takes the basic nav from above and adds the `.nav-tabs` class to generate a tabb
 
 Take that same HTML, but use `.nav-pills` instead for a more themed appearance.
 
-<Example code={`<ul class="nav nav-pills">
+<Example code={`<ul class="nav nav-pills"><!-- [!code highlight] -->
+    <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="#">Link</a>
+    </li>
+    <li class="nav-item">
+      <a class="nav-link disabled" aria-disabled="true">Disabled</a>
+    </li>
+  </ul>`} />
+
+Pill navigation can also go vertical with an additional modifier class, `.nav-pills-vertical`.
+
+<Example code={`<ul class="nav nav-pills nav-pills-vertical"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -108,7 +125,7 @@ Take that same HTML, but use `.nav-pills` instead for a more themed appearance.
 
 Take that same HTML, but use `.nav-underline` instead:
 
-<Example code={`<ul class="nav nav-underline">
+<Example code={`<ul class="nav nav-underline"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -131,7 +148,7 @@ Change the alignment of your nav with [flexbox utilities]([[docsref:/utilities/f
 
 Centered with `.justify-content-center`:
 
-<Example code={`<ul class="nav justify-content-center">
+<Example code={`<ul class="nav justify-content-center"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -148,7 +165,7 @@ Centered with `.justify-content-center`:
 
 Right-aligned with `.justify-content-end`:
 
-<Example code={`<ul class="nav justify-content-end">
+<Example code={`<ul class="nav justify-content-end"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -167,7 +184,7 @@ Right-aligned with `.justify-content-end`:
 
 Stack your navigation by changing the flex item direction with the `.flex-column` utility. Need to stack them on some viewports but not others? Use the responsive versions (e.g., `.sm:flex-column`).
 
-<Example code={`<ul class="nav flex-column">
+<Example code={`<ul class="nav flex-column"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -195,7 +212,7 @@ As always, vertical navigation is possible without `<ul>`s, too.
 
 Force your `.nav`’s contents to extend the full available width with one of two modifier classes. To proportionately fill all available space with your `.nav-item`s, use `.nav-fill`. Notice that all horizontal space is occupied, but not every nav item has the same width.
 
-<Example code={`<ul class="nav nav-pills nav-fill">
+<Example code={`<ul class="nav nav-pills nav-fill"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
@@ -221,7 +238,7 @@ When using a `<nav>`-based navigation, you can safely omit `.nav-item` as only `
 
 For equal-width elements, use `.nav-justified`. All horizontal space will be occupied by nav links, but unlike the `.nav-fill` above, every nav item will be the same width.
 
-<Example code={`<ul class="nav nav-pills nav-justified">
+<Example code={`<ul class="nav nav-pills nav-justified"><!-- [!code highlight] -->
     <li class="nav-item">
       <a class="nav-link active" aria-current="page" href="#">Active</a>
     </li>
index 1a47dbfc3c42f5c93cd19b7fa05e98ea610c4839..b4a6ffe2b9373f6e1a40a52f41a3ba140ccffa6a 100644 (file)
@@ -104,8 +104,8 @@ The tabs plugin also works with pills.
 
 And with vertical pills. Ideally, for vertical tabs, you should also add `aria-orientation="vertical"` to the tab list container.
 
-<Example class="vstack gap-3" code={`<div class="d-flex align-items-start">
-  <div class="nav flex-column nav-pills me-3" id="v-pills-tab" role="tablist" aria-orientation="vertical">
+<Example code={`<div class="d-flex align-items-start">
+  <div class="nav nav-pills nav-pills-vertical me-4" id="v-pills-tab" role="tablist" aria-orientation="vertical">
     <button class="nav-link active" id="v-pills-home-tab" data-bs-toggle="tab" data-bs-target="#v-pills-home" type="button" role="tab" aria-controls="v-pills-home" aria-selected="true">Home</button>
     <button class="nav-link" id="v-pills-profile-tab" data-bs-toggle="tab" data-bs-target="#v-pills-profile" type="button" role="tab" aria-controls="v-pills-profile" aria-selected="false">Profile</button>
     <button class="nav-link" id="v-pills-disabled-tab" data-bs-toggle="tab" data-bs-target="#v-pills-disabled" type="button" role="tab" aria-controls="v-pills-disabled" aria-selected="false" disabled>Disabled</button>
index f76c480962a2af903d4be7fa40dec05024c977de..c14e9b905c822005adc1cb93c9b196880e847da5 100644 (file)
@@ -117,7 +117,7 @@ Start with just the ghost input—chips are created as users type.
 
 Use a form label for better accessibility.
 
-<Example code={`<div class="mb-3">
+<Example code={`<div class="form-field">
     <label class="form-label" for="skillsInputLabel">Skills</label>
     <div class="chip-input theme-primary" data-bs-chip-input>
       <span class="chip">
@@ -131,40 +131,6 @@ Use a form label for better accessibility.
     <div class="form-text">Press Enter or comma to add a skill.</div>
   </div>`} />
 
-## Sizing
-
-Use `.chip-input-sm` or `.chip-input-lg` for different sizes.
-
-<Example class="vstack gap-3" code={`<div class="chip-input chip-input-sm theme-primary" data-bs-chip-input>
-    <span class="chip">
-      Small
-      <button type="button" class="chip-dismiss" aria-label="Remove">
-        <svg 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"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>
-      </button>
-    </span>
-    <input type="text" class="form-ghost" placeholder="Small...">
-  </div>
-
-  <div class="chip-input theme-primary" data-bs-chip-input>
-    <span class="chip">
-      Default
-      <button type="button" class="chip-dismiss" aria-label="Remove">
-        <svg 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"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>
-      </button>
-    </span>
-    <input type="text" class="form-ghost" placeholder="Default...">
-  </div>
-
-  <div class="chip-input chip-input-lg theme-primary" data-bs-chip-input>
-    <span class="chip">
-      Large
-      <button type="button" class="chip-dismiss" aria-label="Remove">
-        <svg 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"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>
-      </button>
-    </span>
-    <input type="text" class="form-ghost" placeholder="Large...">
-  </div>`} />
-
 ## Disabled
 
 Disable the ghost input to prevent adding new chips. Existing chips become non-interactive.
index dc3b67fb4103da8b3855d0e57a46c30edd1e78a5..94899beb282535c653dfbc810d68d48e6ab0d17c 100644 (file)
@@ -145,6 +145,12 @@ Place any checkbox or radio within an input group’s addon instead of text.
 While multiple `<input>`s are supported visually, validation styles are only available for input groups with a single `<input>`.
 
 <Example class="vstack gap-3" code={`<div class="input-group">
+    <input type="text" aria-label="First name" class="form-control">
+    <input type="text" aria-label="Middle name" class="form-control">
+    <input type="text" aria-label="Last name" class="form-control">
+  </div>
+
+  <div class="input-group">
     <span class="input-group-text">First and last name</span>
     <input type="text" aria-label="First name" class="form-control">
     <input type="text" aria-label="Last name" class="form-control">
index 49903b407f2ba77fe1451cb8f9c74563ad1eb3db..9cd103758e3a5f4c4f2ed861c5a9cbacfcae81b1 100644 (file)
@@ -8,7 +8,7 @@ js: required
 
 ## Overview
 
-OTP (One-Time Password) inputs are a common pattern for two-factor authentication, verification codes, and PIN entry. Bootstraps OTP input component provides:
+OTP (One-Time Password) inputs are a common pattern for two-factor authentication, verification codes, and PIN entry. Bootstrap's OTP input component provides:
 
 - **Auto-advance**: Focus moves to the next input after entering a digit
 - **Backspace navigation**: Pressing backspace in an empty field moves to the previous field
@@ -33,7 +33,7 @@ Wrap your inputs in a container with `.otp` and add `data-bs-otp` to enable the
 
 ## Connected inputs
 
-Add `.input-group` to visually connect the inputs into a single cohesive field, leveraging Bootstraps [input group]([[docsref:/forms/input-group]]) styles. We override the `width` to prevent stretching the inputs.
+Add `.input-group` to visually connect the inputs into a single cohesive field, leveraging Bootstrap's [input group]([[docsref:/forms/input-group]]) styles. We override the `width` to prevent stretching the inputs.
 
 <Example code={`<div class="otp input-group" data-bs-otp>
     <input type="text" class="form-control" aria-label="Digit 1">
@@ -85,37 +85,6 @@ You can also use separators with connected inputs by wrapping each group in a ne
     </div>
   </div>`} />
 
-## Sizing
-
-Use `.otp-sm` or `.otp-lg` for different sizes. Don’t use the input group size classes on the `.otp` container as we override specific CSS variables for sizing.
-
-<Example class="vstack align-items-start gap-3" code={`<div class="otp input-group otp-sm" data-bs-otp>
-    <input type="text" class="form-control" aria-label="Digit 1">
-    <input type="text" class="form-control" aria-label="Digit 2">
-    <input type="text" class="form-control" aria-label="Digit 3">
-    <input type="text" class="form-control" aria-label="Digit 4">
-    <input type="text" class="form-control" aria-label="Digit 5">
-    <input type="text" class="form-control" aria-label="Digit 6">
-  </div>
-
-  <div class="otp input-group" data-bs-otp>
-    <input type="text" class="form-control" aria-label="Digit 1">
-    <input type="text" class="form-control" aria-label="Digit 2">
-    <input type="text" class="form-control" aria-label="Digit 3">
-    <input type="text" class="form-control" aria-label="Digit 4">
-    <input type="text" class="form-control" aria-label="Digit 5">
-    <input type="text" class="form-control" aria-label="Digit 6">
-  </div>
-
-  <div class="otp input-group otp-lg" data-bs-otp>
-    <input type="text" class="form-control" aria-label="Digit 1">
-    <input type="text" class="form-control" aria-label="Digit 2">
-    <input type="text" class="form-control" aria-label="Digit 3">
-    <input type="text" class="form-control" aria-label="Digit 4">
-    <input type="text" class="form-control" aria-label="Digit 5">
-    <input type="text" class="form-control" aria-label="Digit 6">
-  </div>`} />
-
 ## Disabled
 
 Add the `disabled` attribute to each input to prevent interaction.
@@ -239,7 +208,7 @@ otpInput.clear()
 <BsTable>
 | Event | Description |
 | --- | --- |
-| `complete.bs.otp` | Fired when all inputs are filled. The events `value` property contains the complete code. |
+| `complete.bs.otp` | Fired when all inputs are filled. The event's `value` property contains the complete code. |
 | `input.bs.otp` | Fired on each input change. Includes `value` (current combined value) and `index` (changed input index). |
 </BsTable>
 
index ade4f48637e9eabbcb7ed613e36450bc291ee7a7..1007b97b77a6b1c0328d1671978f272e8e7169c8 100644 (file)
@@ -319,20 +319,42 @@ Bootstrap 6 is a major release with many breaking changes to modernize our codeb
 | — | — | `.fs-6xl` | `clamp(3.75rem, …, 5rem)` |
 </BsTable>
 
-- **Border radius scale updated.** The underlying CSS custom property values have increased, and the utility mapping has shifted:
+- **Border radius tokens replaced with a numeric scale.** The named `$border-radius-*` Sass variables and `--border-radius-*` CSS custom properties (`-xs`, `-sm`, default, `-lg`, `-xl`, `-2xl`) have been removed in favor of a numeric `$radii` Sass map (keyed `0`–`9`) that generates `--radius-0` through `--radius-9` tokens, plus `--radius-pill`. The scale is driven by a single `$radius: .5rem` base, so all steps move together when the base changes. To migrate any custom Sass or CSS that referenced the old tokens directly:
 
 <BsTable>
-| Utility class | v5 variable | v5 value | v6 variable | v6 value |
-|---|---|---|---|---|
-| `.rounded` | `$border-radius` | `0.375rem` | `--border-radius` | `0.5rem` |
-| `.rounded-0` | — | `0` | — | `0` |
-| `.rounded-1` | `$border-radius-sm` | `0.25rem` | `--border-radius-sm` | `0.5rem` |
-| `.rounded-2` | `$border-radius` | `0.375rem` | `--border-radius` | `0.5rem` |
-| `.rounded-3` | `$border-radius-lg` | `0.5rem` | `--border-radius-lg` | `0.75rem` |
-| `.rounded-4` | `$border-radius-xl` | `1rem` | `--border-radius-xl` | `1rem` |
-| `.rounded-5` | `$border-radius-xxl` | `2rem` | `--border-radius-2xl` | `2rem` |
+| v5 variable | v5 value | v6 token | v6 value |
+|---|---|---|---|
+| `$border-radius-xs` / `--border-radius-xs` | `0.25rem` | `--radius-3` | `0.25rem` |
+| `$border-radius-sm` / `--border-radius-sm` | `0.25rem` | `--radius-3` | `0.25rem` |
+| `$border-radius` / `--border-radius` | `0.375rem` | `--radius-4` | `0.375rem` |
+| `$border-radius-lg` / `--border-radius-lg` | `0.5rem` | `--radius-5` | `0.5rem` |
+| `$border-radius-xl` / `--border-radius-xl` | `1rem` | `--radius-8` | `1rem` |
+| `$border-radius-xxl` / `--border-radius-2xl` | `2rem` | — (closest: `--radius-9` `1.5rem`) |
+| `$border-radius-pill` / `--border-radius-pill` | `50rem` | `--radius-pill` | `50rem` |
 </BsTable>
 
+- **Border radius utilities expanded and remapped.** `.rounded-*` is now generated from the `$radii` map, so the scale spans `.rounded-0` through `.rounded-9` (previously `.rounded-0` through `.rounded-5`). The default `.rounded` still resolves to `0.5rem`, but the numbered classes now map to different values than v5:
+
+<BsTable>
+| Utility class | v5 value | v6 value | v6 token |
+|---|---|---|---|
+| `.rounded` | `0.375rem` | `0.5rem` | `var(--radius-5)` |
+| `.rounded-0` | `0` | `0` | `var(--radius-0)` |
+| `.rounded-1` | `0.25rem` | `0.125rem` | `var(--radius-1)` |
+| `.rounded-2` | `0.375rem` | `0.1875rem` | `var(--radius-2)` |
+| `.rounded-3` | `0.5rem` | `0.25rem` | `var(--radius-3)` |
+| `.rounded-4` | `1rem` | `0.375rem` | `var(--radius-4)` |
+| `.rounded-5` | `2rem` | `0.5rem` | `var(--radius-5)` |
+| `.rounded-6` | — | `0.625rem` | `var(--radius-6)` |
+| `.rounded-7` | — | `0.75rem` | `var(--radius-7)` |
+| `.rounded-8` | — | `1rem` | `var(--radius-8)` |
+| `.rounded-9` | — | `1.5rem` | `var(--radius-9)` |
+| `.rounded-circle` | `50%` | `50%` | — |
+| `.rounded-pill` | `50rem` | `50rem` | `var(--radius-pill)` |
+</BsTable>
+
+  To preserve v5 visual roundness, shift class numbers up the scale (e.g. `.rounded-1` &rarr; `.rounded-3`, `.rounded-2` &rarr; `.rounded-4`, `.rounded-3` &rarr; `.rounded-5`, `.rounded-4` &rarr; `.rounded-8`, `.rounded-5` &rarr; `.rounded-9`). The `.rounded-{top,end,bottom,start}-*` directional variants follow the same scale.
+
 - **Font weight additions.** Added `.fw-medium` (`500`) and `.fw-semibold` (`600`) utilities. v5 only had `lighter`, `light` (`300`), `normal` (`400`), `bold` (`700`), and `bolder`.
 - **Negative margins limited.** Negative spacers are reduced to only `-1` (`-0.25rem`) and `-2` (`-0.5rem`), and only applied to `margin-inline-start` (`.ms-n1`, `.ms-n2`) and `margin-inline-end` (`.me--1`, `.me--2`). The v5 full negative margin utilities across all sides have been removed.
 - **Spacing and border utilities now use CSS logical properties.** `margin-top` &rarr; `margin-block-start`, `margin-right` &rarr; `margin-inline-end`, `padding-left` &rarr; `padding-inline-start`, `border-right` &rarr; `border-inline-end`, etc. Class names (`.mt-*`, `.me-*`, `.ps-*`, `.border-end`) remain the same, but the underlying CSS properties are now logical, improving RTL and writing-mode support.
index a983fabbf6174f7faae54ce4c02b6449dcf4aa11..bbcb41098ab753cd4115df0f3465932ff1007089 100644 (file)
@@ -46,7 +46,9 @@ Use the scaling classes for larger or smaller rounded corners. Sizes range from
 
 ### Variables
 
-<ScssDocs name="root-border-radius-var" file="scss/_root.scss" />
+Radius tokens are generated from the `$spacers` map in `scss/_root.scss`. [Learn how to use the root tokens.]([[docsref:/utilities/api#using-root-tokens]])
+
+<ScssDocs name="root-spacer-loop" file="scss/_root.scss" />
 
 ### Sass maps
 
index ffdde814be73f5cf0751821a7e178ca457f18d2e..be15cc43cd0f7357e04c3817631ce4e4cb628bf3 100644 (file)
@@ -173,11 +173,14 @@ if (currentPageIndex < allPages.length - 1) {
 
         <slot />
 
-        <nav class="bd-links-nav py-5 mt-5 border-top">
-          <div class="d-flex flex-column md:flex-row justify-content-stretch gap-3 md:gap-5">
+        <nav class="bd-links-nav py-9 mt-9 border-top">
+          <div class="d-flex flex-column md:flex-row justify-content-stretch gap-3 md:gap-5 lh-1">
             {
               prevPage && (
-                <a href={prevPage.url} class="d-block p-3 text-decoration-none border rounded-3 flex-grow-1">
+                <a
+                  href={prevPage.url}
+                  class="d-flex flex-column gap-2 p-5 text-decoration-none border rounded-5 flex-grow-1"
+                >
                   <div class="fg-3">← Previous</div>
                   <div class="fs-5 fw-semibold">{prevPage.title}</div>
                   <div class="fg-3">{prevPage.groupTitle}</div>
@@ -186,7 +189,10 @@ if (currentPageIndex < allPages.length - 1) {
             }
             {
               nextPage && (
-                <a href={nextPage.url} class="d-block p-3 text-decoration-none text-end border rounded-3 flex-grow-1">
+                <a
+                  href={nextPage.url}
+                  class="d-flex flex-column gap-2 p-5 text-decoration-none text-end border rounded-5 flex-grow-1"
+                >
                   <div class="fg-3">Next →</div>
                   <div class="fs-5 fw-semibold">{nextPage.title}</div>
                   <div class="fg-3">{nextPage.groupTitle}</div>
index cfbfcb8c1e8a761086cb16e89ab54451311b3d03..009dd25d671f536c904a8ec2f62c073fc58ebdf0 100644 (file)
@@ -11,7 +11,7 @@
     padding: 1rem !important;
     background-color: var(--bs-bg-1) !important;
     border: 0 !important;
-    @include border-radius(var(--bs-border-radius-lg) !important);
+    @include border-radius(var(--radius-7) !important);
   }
   // #carbon-responsive a,
   // .carbon-description {
@@ -20,7 +20,7 @@
   .carbon-img {
     position: relative;
     overflow: hidden;
-    @include border-radius(var(--bs-border-radius));
+    @include border-radius(var(--radius-5));
 
     &::after {
       position: absolute;
@@ -28,7 +28,7 @@
       display: block;
       content: "";
       border: 1px solid var(--bs-border-color-translucent);
-      @include border-radius(var(--bs-border-radius));
+      @include border-radius(var(--radius-5));
     }
   }
 }
index 5fe5b80c5ffbe40f50e5d6fe7f8b23ccb5b01f0c..422c8f9716fcfea5a46f69fe20b2d467af9db0a5 100644 (file)
@@ -14,7 +14,7 @@
     line-height: 1.25rem;
     color: var(--bs-theme-fg, var(--bs-fg-2));
     background-color: var(--bs-theme-bg-subtle, var(--bs-gray-100));
-    @include border-radius(var(--bs-border-radius));
+    @include border-radius(var(--radius-5));
   }
 
   .bd-meta-tooltip {
index dd380ce2509b19748704cc550d2963aa195fcabd..97dedd7a95ddf665438f04487feb5f9c8d5e63f1 100644 (file)
@@ -18,7 +18,7 @@
     background-color: var(--bd-callout-bg, var(--bs-gray-100));
     border: 1px solid var(--bd-callout-border, var(--bs-border-color));
     border-inline-start: .25rem solid var(--bd-callout-border, var(--bs-gray-300));
-    @include border-radius(var(--bs-border-radius));
+    @include border-radius(var(--radius-5));
 
     h4 {
       margin-bottom: .25rem;
index 346b2f53d08f72c03ecdae775056373913dc0f29..6f8aaa1e8a893d375aad5d50aedd8c0b8d914234 100644 (file)
@@ -8,12 +8,12 @@
 @layer custom {
   .bd-code-snippet {
     --bd-example-padding: 1.25rem;
-    --bd-example-inner-radius: calc(var(--bs-border-radius) - 1px);
+    --bd-example-inner-radius: calc(var(--radius-5) - 1px);
 
     margin: 0;
     background-color: var(--bd-pre-bg);
     border: 1px solid var(--bs-border-color);
-    @include border-radius(var(--bs-border-radius));
+    @include border-radius(var(--radius-5));
 
     .bd-example {
       &:first-child {
@@ -40,7 +40,7 @@
     border-bottom: 1px solid var(--bs-border-color);
 
     &:first-child {
-      @include border-top-radius(calc(var(--bs-border-radius) - 1px));
+      @include border-top-radius(calc(var(--radius-5) - 1px));
     }
 
     &:not(:first-child) {
@@ -68,7 +68,7 @@
       min-height: 120px;
       padding: var(--bs-spacer);
       background-color: var(--bs-bg-1);
-      @include border-radius(var(--bs-border-radius));
+      @include border-radius(var(--radius-5));
     }
 
     > .menu.position-static {
       color: var(--bs-fg-3);
       background-color: var(--bs-bg-1);
       border: var(--bs-border-width) solid var(--bs-border-color);
-      @include border-radius(var(--bs-border-radius));
+      @include border-radius(var(--radius-5));
     }
   }
 
     resize: horizontal;
     background-color: var(--bs-bg-body);
     border: 1px dashed var(--bs-border-color);
-    @include border-radius(var(--bs-border-radius));
+    @include border-radius(var(--radius-5));
   }
 
   //
index 347285e255fb0fd3e25833098e9d64e2b1a90749..3556cda9137b1262cbbd70d04ebe469f3948327d 100644 (file)
@@ -7,7 +7,7 @@
     line-height: var(--bs-line-height-sm);
     color: var(--bs-fg-3);
     background-color: var(--bs-bg-1);
-    @include border-radius(var(--bs-border-radius-lg));
+    @include border-radius(var(--radius-7));
 
     &:hover,
     &[open] {
index cdafbeea0e6b0dd7397ff3951d5987cf1d2dddd3..a5d0d6cbeaa5ff37a8f312b031e0144698650bda 100644 (file)
@@ -43,7 +43,7 @@
   cursor: pointer;
   background-color: transparent;
   border: 0;
-  @include border-radius(var(--bs-border-radius));
+  @include border-radius(var(--bs-radius-6));
   @include transition(color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out);
 
   &:hover {
   color: var(--bs-fg-3, var(--bs-secondary-color));
   background-color: var(--bs-bg-body);
   border: var(--bs-border-width) solid var(--bs-border-color);
-  @include border-radius(var(--bs-border-radius-sm));
+  @include border-radius(var(--bs-radius-4));
 }
 
 // Search dialog shell
   --dialog-padding: .75rem;
   --dialog-header-padding: .75rem;
   --dialog-footer-padding: .5rem .75rem;
-  --dialog-border-radius: var(--border-radius-xl);
+  --dialog-border-radius: var(--bs-radius-8);
 
   align-self: flex-start;
   width: 640px;
@@ -225,7 +225,7 @@ bd-search-results:not(:focus-within) .bd-search-result:first-child > .bd-search-
   column-gap: .5rem;
   padding: .75rem;
   text-decoration: none;
-  @include border-radius(var(--bs-border-radius-lg));
+  @include border-radius(var(--bs-radius-6));
 
   &:hover {
     background-color: var(--bs-bg-1);
@@ -321,7 +321,7 @@ bd-search-results:not(:focus-within) .bd-search-result:first-child > .bd-search-
   cursor: pointer;
   background-color: transparent;
   border: 0;
-  @include border-radius(var(--bs-border-radius-sm));
+  @include border-radius(var(--bs-radius-3));
   @include transition(color .15s ease-in-out, background-color .15s ease-in-out);
 
   &:hover {
@@ -370,7 +370,7 @@ bd-search-results:not(:focus-within) .bd-search-result:first-child > .bd-search-
   .placeholder {
     display: block;
     height: .65rem;
-    @include border-radius(var(--bs-border-radius-sm));
+    @include border-radius(var(--bs-radius-3));
   }
 
   .placeholder.col-4 {
index 239bf4a1d284cd5877716c1fcfda764d7c30ec63..4900b5449e342fb2b9c2a7ecb23ff637b3fdb5f7 100644 (file)
@@ -17,7 +17,7 @@
   font-size: 13px;
   line-height: 20px;
   background-color: var(--bd-pre-bg) !important; // stylelint-disable-line declaration-no-important
-  @include border-radius(calc(var(--bs-border-radius) - 1px));
+  @include border-radius(calc(var(--radius-5) - 1px));
 
   > code {
     display: flex;
@@ -83,7 +83,7 @@
   color: var(--bs-fg-3);
   background: transparent;
   border: 0;
-  @include border-radius(var(--bs-border-radius-sm));
+  @include border-radius(var(--radius-5));
   @include transition(color .15s ease-in-out, background-color .15s ease-in-out);
 
   &:hover {
index 87b624d82c3cead4e4e48a2cb1ea801351690ed9..849721dc50c8430c94127a26e7be90e01bf742c5 100644 (file)
@@ -1,4 +1,5 @@
 @use "../../../scss/layout/breakpoints" as *;
+@use "../../../scss/mixins/border-radius" as *;
 
 @layer custom {
   .bd-toc {
       --bs-nav-link-hover-bg: transparent;
       --bs-nav-link-active-bg: transparent;
       --bs-nav-link-active-color: var(--bs-fg-body);
-      --bs-border-radius: 0;
 
-      .nav .nav-link{
+      .nav .nav-link {
         padding-inline-start: 1.75rem;
       }
     }
 
     .nav-link {
       border-inline-start: .125rem solid transparent;
+      @include border-radius(0);
 
       &.active {
         font-weight: 500;