]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
redo buttons
authorMark Otto <markdotto@gmail.com>
Wed, 24 Sep 2025 05:34:34 +0000 (22:34 -0700)
committerMark Otto <markdotto@gmail.com>
Wed, 1 Oct 2025 03:48:49 +0000 (20:48 -0700)
scss/buttons/_button.scss
site/src/content/docs/components/buttons.mdx
site/src/scss/_component-examples.scss

index 15b2c7d8da7ed7e09654a2288f9322286a778ad3..c7a5aba2a159e0a0242802c96530cbfa2797ac98 100644 (file)
@@ -1,6 +1,10 @@
 @use "sass:color";
+@use "sass:list";
+@use "sass:map";
+@use "sass:meta";
 @use "../colors" as *;
 @use "../config" as *;
+@use "../theme" as *;
 @use "../variables" as *;
 @use "../theme" as *;
 @use "../functions" as *;
 @use "../mixins/transition" as *;
 @use "button-variables" as *;
 
-// Button variants
-//
-// Easily pump out default styles, as well as :hover, :focus, :active,
-// and disabled options for all buttons
+// scss-docs-start btn-variants
+$button-variants: (
+  "solid": (
+    "base": (
+      "bg": "bg",
+      "color": "contrast",
+      "border-color": "bg"
+    ),
+    "hover": (
+      "bg": "bg",
+      "border-color": "bg",
+      "color": "contrast"
+    ),
+    "active": (
+      "bg": "bg",
+      "border-color": "bg",
+      "color": "contrast"
+    )
+  ),
+  "outline": (
+    "base": (
+      "bg": "transparent",
+      "color": "text",
+      "border-color": "border"
+    ),
+    "hover": (
+      "bg": "bg",
+      "color": "contrast",
+      "border-color": "bg"
+    ),
+    "active": (
+      "bg": "bg",
+      "color": "contrast",
+      "border-color": "bg"
+    )
+  ),
+  "subtle": (
+    "base": (
+      "bg": "bg-subtle",
+      "color": "text",
+      "border-color": "transparent"
+    ),
+    "hover": (
+      "bg": ("bg-muted", "bg-subtle"),
+      "color": "text"
+    ),
+    "active": (
+      "bg": "bg-subtle",
+      "color": "text"
+    )
+  ),
+  "text": (
+    "base": (
+      "color": "text",
+      "bg": "transparent",
+      "border-color": "transparent"
+    ),
+    "hover": (
+      "color": "text",
+      "bg": "bg-subtle"
+    ),
+    "active": (
+      "color": "text",
+      "bg": "bg-subtle"
+    )
+  )
+) !default;
+// scss-docs-end btn-variants
+
+
+// Helper function to get nested map values using dot notation
+@function get-nested-value($map, $keys) {
+  $value: $map;
+  @each $key in $keys {
+    @if type-of($value) == "map" {
+      $value: map-get($value, $key);
+    } @else {
+      @return null;
+    }
+  }
+  @return $value;
+}
 
+// Helper function to split dot notation string into list
+@function split-keys($key) {
+  $keys: ();
+  $parts: str-slice($key, 1);
+  @each $part in $parts {
+    $keys: append($keys, $part);
+  }
+  @return $keys;
+}
+
+// Main button style generator mixin
 // scss-docs-start btn-variant-mixin
+<<<<<<< HEAD
 // @mixin button-variant(
 //   $background,
 //   $border,
 //   --#{$prefix}gradient: none;
 // }
 // scss-docs-end btn-outline-variant-mixin
+=======
+@mixin button-variant($color, $variant) {
+  $variant-styles: map.get($button-variants, $variant);
+
+  @if $variant-styles {
+    // Base properties
+    @each $property, $value in map.get($variant-styles, "base") {
+      @if $value == "transparent" {
+        --#{$prefix}btn-#{$property}: transparent;
+      } @else {
+        --#{$prefix}btn-#{$property}: var(--#{$prefix}#{$color}-#{$value});
+      }
+    }
+
+    // Hover state
+    &:hover {
+      @each $property, $value in map.get($variant-styles, "hover") {
+        @if $value == "transparent" {
+          --#{$prefix}btn-hover-#{$property}: transparent;
+        } @else if meta.type-of($value) == "list" {
+          $first-value: list.nth($value, 1);
+          $second-value: list.nth($value, 2);
+          --#{$prefix}btn-hover-#{$property}: color-mix(in oklch, var(--#{$prefix}#{$color}-#{$first-value}) 50%, var(--#{$prefix}#{$color}-#{$second-value}));
+        } @else if $value == "bg-subtle" {
+          --#{$prefix}btn-hover-#{$property}: var(--#{$prefix}#{$color}-#{$value});
+        } @else {
+          --#{$prefix}btn-hover-#{$property}: oklch(from var(--#{$prefix}#{$color}-#{$value}) calc(l * .95) calc(c * 1.1) h);
+        }
+      }
+    }
+
+    &:focus-visible {
+      outline-color: var(--#{$prefix}#{$color}-focus-ring);
+    }
+
+    // Active state
+    &:active,
+    &.active {
+      @each $property, $value in map.get($variant-styles, "active") {
+        @if $value == "transparent" {
+          --#{$prefix}btn-active-#{$property}: transparent;
+        } @else if $value == "bg-subtle" {
+          --#{$prefix}btn-active-#{$property}: var(--#{$prefix}#{$color}-#{$value});
+        } @else {
+          --#{$prefix}btn-active-#{$property}: oklch(from var(--#{$prefix}#{$color}-#{$value}) calc(l * .9) calc(c * 1.15) h);
+        }
+      }
+    }
+  }
+}
+// scss-docs-end btn-variant-mixin
+
+// Generate all button variants
+@each $color, $_ in $new-theme-colors {
+  @each $variant, $_ in $button-variants {
+    .btn-#{$color}-#{$variant} {
+      @include button-variant($color, $variant);
+    }
+  }
+}
+>>>>>>> f87a3a593 (redo buttons)
 
 // scss-docs-start btn-size-mixin
 @mixin button-size($padding-y, $padding-x, $font-size, $border-radius) {
     }
 
     &:focus-visible {
-      color: var(--#{$prefix}btn-hover-color);
-      @include gradient-bg(var(--#{$prefix}btn-hover-bg));
-      border-color: var(--#{$prefix}btn-hover-border-color);
       @include focus-ring(true);
       --#{$prefix}focus-ring-offset: 1px;
     }
 
     .btn-check:focus-visible + & {
-      border-color: var(--#{$prefix}btn-hover-border-color);
       @include focus-ring(true);
     }
 
   //
 
   // scss-docs-start btn-variant-loops
+<<<<<<< HEAD
   // @each $color, $value in $new-theme-colors {
   //   .btn-#{$color} {
   //     @if $color == "light" {
   //     @include button-outline-variant($value);
   //   }
   // }
+=======
+  @each $color, $value in $theme-colors {
+    .btn-#{$color} {
+      @include button-variant($color, "solid");
+    }
+  }
+
+  @each $color, $value in $theme-colors {
+    .btn-outline-#{$color} {
+      @include button-variant($color, "outline");
+    }
+  }
+>>>>>>> f87a3a593 (redo buttons)
   // scss-docs-end btn-variant-loops
 
 
index e6bbd3b5ba42484af708b268b64b29f240491697..62f88ed24634ea41782141f2213ffcba354431cb 100644 (file)
@@ -22,7 +22,7 @@ When using `.btn` without a modifier, be sure to add some explicit `:focus-visib
 
 Bootstrap includes several button variants, each serving its own semantic purpose, with a few extras thrown in for more control.
 
-<Example code={[...getData('theme-colors').map((themeColor) => `<button type="button" class="btn btn-${themeColor.name}">${themeColor.title}</button>`), `
+<Example class="bd-example-buttons" code={[...getData('theme-colors').map((themeColor) => `<button type="button" class="btn btn-${themeColor.name}-solid justify-self-start">${themeColor.title}</button> <button type="button" class="btn btn-${themeColor.name}-outline justify-self-start">${themeColor.title}</button> <button type="button" class="btn btn-${themeColor.name}-subtle justify-self-start">${themeColor.title}</button> <button type="button" class="btn btn-${themeColor.name}-text justify-self-start">${themeColor.title}</button>`), `
 <button type="button" class="btn btn-link">Link</button>`]} />
 
 <Callout name="warning-color-assistive-technologies" />
@@ -276,15 +276,23 @@ Here’s an example of building a custom `.btn-*` modifier class as we do for th
 
 ### Sass variables
 
-<ScssDocs name="btn-variables" file="scss/_variables.scss" />
+<ScssDocs name="btn-variables" file="scss/buttons/_button-variables.scss" />
+
+### Sass map
+
+Button variants—including all their states—are defined in the `$button-variants` Sass map. This map identifies which theme color tokens to use for each variant's state.
+
+For example, a solid button uses the same `bg` token for its background and border colors because we want it to have a seamless look.
+
+<ScssDocs name="btn-variants" file="scss/buttons/_button.scss" />
 
 ### Sass mixins
 
 There are three mixins for buttons: button and button outline variant mixins (both based on `$theme-colors`), plus a button size mixin.
 
-{/*<ScssDocs name="btn-variant-mixin" file="scss/mixins/_buttons.scss" />
+<ScssDocs name="btn-variant-mixin" file="scss/buttons/_button.scss" />
 
-<ScssDocs name="btn-outline-variant-mixin" file="scss/mixins/_buttons.scss" />
+{/*<ScssDocs name="btn-outline-variant-mixin" file="scss/mixins/_buttons.scss" />
 
 <ScssDocs name="btn-size-mixin" file="scss/mixins/_buttons.scss" />*/}
 
index 6f023647a1ac2cb949f848f24a21cffcd53de0bb..fd41efa511daf792b23f7e3226c343ac62f7ee86 100644 (file)
     border: 1px solid color-mix(in srgb, var(--bd-violet) 30%, transparent);
   }
 
+  .bd-example-buttons {
+    display: grid;
+    grid-template-columns: repeat(4, 1fr);
+    gap: .5rem;
+    justify-content: start;
+  }
+
   // // Grid mixins
   // .example-container {
   //   width: 800px;