]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Update theme life while here
authorMark Otto <markdotto@gmail.com>
Thu, 2 Oct 2025 19:24:54 +0000 (12:24 -0700)
committerMark Otto <markdotto@gmail.com>
Thu, 2 Oct 2025 19:24:54 +0000 (12:24 -0700)
scss/_theme.scss
site/src/components/shortcodes/Swatch.astro
site/src/content/docs/customize/theme.mdx

index 22ceac745a5a08af20a1cc3b11ecd3a780e5e618..6ccb7a1dc53d4be49b3a181bbcad3b70f3ac2132 100644 (file)
@@ -138,7 +138,7 @@ $theme-fgs: (
 $theme-borders: (
   null: light-dark(var(--#{$prefix}gray-300), var(--#{$prefix}gray-700)),
   "muted": light-dark(var(--#{$prefix}gray-200), var(--#{$prefix}gray-800)),
-  "subtle": light-dark(var(--#{$prefix}gray-100), color-mix(in srgb, var(--#{$prefix}gray-800), var(--#{$prefix}gray-900))),
+  "subtle": light-dark(var(--#{$prefix}gray-100), var(--#{$prefix}gray-900)),
   "emphasized": light-dark(var(--#{$prefix}gray-400), var(--#{$prefix}gray-600)),
 ) !default;
 
index bca1db31cdd18a1dd43a5f7dcf2fd702c3b11c4e..5ce9f4ba4fb1e6ce3b0dacf39751595df6f0f3ef 100644 (file)
@@ -5,9 +5,11 @@ export interface Props {
   size?: 'inline' | 'medium' | 'large'
   contrast?: string
   contrastDark?: string
+  cssVar?: string
+  showVar?: boolean
 }
 
-const { bg, fg, size = 'inline', contrast, contrastDark } = Astro.props
+const { bg, fg, size = 'inline', contrast, contrastDark, cssVar, showVar = true } = Astro.props
 
 // Styles for different sizes
 const baseStyles = {
@@ -52,6 +54,9 @@ const contrastStyles = {
 }
 
 const combinedStyles = { ...baseStyles, ...sizeStyles[size] }
+
+// Determine which CSS variable to display
+const displayCssVar = cssVar || bg
 ---
 
 <style>
@@ -72,14 +77,47 @@ const combinedStyles = { ...baseStyles, ...sizeStyles[size] }
   :global([data-bs-theme="dark"]) .contrast-dark {
     display: inline;
   }
+
+  /* CSS variable display styles */
+  .css-var {
+    margin-left: 0.25rem;
+    font-family: var(--bs-font-monospace);
+    font-size: 0.875rem;
+    color: var(--bs-color-3);
+  }
+
+  .css-var-light {
+    display: inline;
+  }
+
+  .css-var-dark {
+    display: none;
+  }
+
+  /* Show dark value in dark mode */
+  :global([data-bs-theme="dark"]) .css-var-light {
+    display: none;
+  }
+
+  :global([data-bs-theme="dark"]) .css-var-dark {
+    display: inline;
+  }
 </style>
 
 {size === 'inline' ? (
-  <span style={combinedStyles}>
-    <slot />
-    {contrast && <span style={contrastStyles} class="contrast-light">{contrast}</span>}
-    {contrastDark && <span style={{...contrastStyles, color: isLowContrastDark ? 'red' : 'inherit'}} class="contrast-dark">{contrastDark}</span>}
-  </span>
+  <>
+    <span style={combinedStyles}>
+      <slot />
+      {contrast && <span style={contrastStyles} class="contrast-light">{contrast}</span>}
+      {contrastDark && <span style={{...contrastStyles, color: isLowContrastDark ? 'red' : 'inherit'}} class="contrast-dark">{contrastDark}</span>}
+    </span>
+    {showVar && displayCssVar && (
+      <span class="css-var" data-css-var={`--bs-${displayCssVar}`}>
+        <span class="css-var-light">Loading...</span>
+        <span class="css-var-dark">Loading...</span>
+      </span>
+    )}
+  </>
 ) : size === 'large' ? (
   <span style={combinedStyles}>
     <slot />
@@ -93,3 +131,73 @@ const combinedStyles = { ...baseStyles, ...sizeStyles[size] }
     {contrastDark && <span style={{...contrastStyles, color: isLowContrastDark ? 'red' : 'inherit'}} class="contrast-dark">{contrastDark}</span>}
   </div>
 )}
+
+<script>
+  // Handle dynamic CSS variable display with light-dark() function support
+  document.addEventListener('DOMContentLoaded', () => {
+    const cssVarElements = document.querySelectorAll('.css-var[data-css-var]')
+
+    cssVarElements.forEach(element => {
+      const cssVarName = element.getAttribute('data-css-var')
+
+      if (cssVarName) {
+        // Try to get the raw CSS variable definition from stylesheets
+        let rawValue = null
+        for (const stylesheet of document.styleSheets) {
+          try {
+            for (const rule of stylesheet.cssRules) {
+              if (rule.type === CSSRule.STYLE_RULE) {
+                const styleRule = rule as CSSStyleRule
+                for (const prop of styleRule.style) {
+                  if (prop === cssVarName) {
+                    rawValue = styleRule.style.getPropertyValue(cssVarName)
+                    break
+                  }
+                }
+              }
+            }
+          } catch (e) {
+            // Skip stylesheets we can't access (CORS)
+            continue
+          }
+        }
+
+        // If we couldn't get the raw value, fall back to computed value
+        if (!rawValue) {
+          rawValue = getComputedStyle(document.documentElement).getPropertyValue(cssVarName)
+        }
+
+        if (rawValue) {
+          // Check if the value contains light-dark function
+          if (rawValue.includes('light-dark(')) {
+            // Parse the light-dark function to extract light and dark values
+            const lightDarkMatch = rawValue.match(/light-dark\(([^,]+),\s*(.+)\)$/)
+            if (lightDarkMatch) {
+              const lightValue = lightDarkMatch[1].trim()
+              const darkValue = lightDarkMatch[2].trim()
+
+              // Update the spans with the parsed values
+              const lightSpan = element.querySelector('.css-var-light')
+              const darkSpan = element.querySelector('.css-var-dark')
+
+              if (lightSpan) lightSpan.textContent = lightValue
+              if (darkSpan) darkSpan.textContent = darkValue
+            } else {
+              // Fallback: show the full value
+              element.innerHTML = `<span class="css-var-light">${rawValue}</span>`
+            }
+          } else if (rawValue.includes('color-mix(')) {
+            // Handle color-mix functions - show the full function
+            element.innerHTML = `<span class="css-var-light">${rawValue}</span>`
+          } else {
+            // Single value - show it in both light and dark spans
+            element.innerHTML = `<span class="css-var-light">${rawValue}</span>`
+          }
+        } else {
+          // Fallback: show the variable name
+          element.innerHTML = `<span class="css-var-light">${cssVarName}</span>`
+        }
+      }
+    })
+  })
+</script>
index 9e64d07d176a8dd75d81c4527ab92ab022d31e3e..4a7c63f1ffe4d8ad0545539141ed42a158a0cc8e 100644 (file)
@@ -93,38 +93,52 @@ Every token is available as a CSS variable, and most are then consumed by our ut
   })}
 </div>
 
-## Theme `fg` and `bg`
+## `fg`, `bg`, and `border`
 
-Theme foreground and background tokens are defined in their respective `$theme-fgs` and `$theme-bgs` Sass maps. These maps are used to generate color mode adaptive `color` and `background-color` values that are then consumed by our utilities and components. You'll find these values in the `_theme.scss` file.
+While several text, background, and border colors are configured in the base `$new-theme-colors` Sass map, there are several additional options available for more nuanced theming with regards to foreground, background, and border colors.
 
-Theme backgrounds include the following semantic colors:
+Tokens for these three themes are defined in their respective `$theme-fgs`, `$theme-bgs`, and `$theme-borders` Sass maps. These maps are used to generate color mode adaptive `color`, `background-color`, and `border-color` values that are then consumed by our utilities and components. You'll find these values in the `_theme.scss` file.
+
+Theme backgrounds include several practical and semantic color options.
 
 <BsTable>
 | Background | Default value | Description |
 | --- | --- | --- |
-| `null` | <Swatch bg="bg" size="inline" /> `var(--bs-white)` | Default background color |
-| `1` | <Swatch bg="bg-1" size="inline" /> `var(--bs-gray-025)` | Lowest contrast background color |
-| `2` | <Swatch bg="bg-2" size="inline" /> `var(--bs-gray-050)` | Lower contrast background color |
-| `3` | <Swatch bg="bg-3" size="inline" /> `var(--bs-gray-100)` | Medium contrast background color, typically used for disabled states |
-| `white` | <Swatch bg="bg-white" size="inline" /> `var(--bs-white)` | Pure white background color |
-| `black` | <Swatch bg="bg-black" size="inline" /> `var(--bs-black)` | Pure black background color |
-| `transparent` | <Swatch bg="bg-transparent" size="inline" /> `transparent` | Transparent background color |
+| `null` | <Swatch bg="bg" size="inline" cssVar="bg" /> | Default background color |
+| `1` | <Swatch bg="bg-1" size="inline" cssVar="bg-1" /> | Lowest contrast background color |
+| `2` | <Swatch bg="bg-2" size="inline" cssVar="bg-2" /> | Lower contrast background color |
+| `3` | <Swatch bg="bg-3" size="inline" cssVar="bg-3" /> | Medium contrast background color, typically used for disabled states |
+| `white` | <Swatch bg="bg-white" size="inline" cssVar="bg-white" /> | Pure white background color |
+| `black` | <Swatch bg="bg-black" size="inline" cssVar="bg-black" /> | Pure black background color |
+| `transparent` | <Swatch bg="bg-transparent" size="inline" cssVar="bg-transparent" /> | Transparent background color |
 | `inherit` |`inherit` | Inherited background color |
 </BsTable>
 
+Almost all those options are also available for foreground text colors.
+
 <BsTable>
 | Foreground | Default value | Description |
 | --- | --- | --- |
-| `null` | <Swatch bg="fg" size="inline" /> `var(--bs-gray-900)` | Default foreground color |
-| `1` | <Swatch bg="fg-1" size="inline" /> `var(--bs-gray-800)` | Lowest contrast foreground color |
-| `2` | <Swatch bg="fg-2" size="inline" /> `var(--bs-gray-700)` | Lower contrast foreground color |
-| `3` | <Swatch bg="fg-3" size="inline" /> `var(--bs-gray-600)` | Medium contrast foreground color |
-| `white` | <Swatch bg="fg-white" size="inline" /> `var(--bs-white)` | Pure white foreground color |
-| `black` | <Swatch bg="fg-black" size="inline" /> `var(--bs-black)` | Pure black foreground color |
-| `transparent` | <Swatch bg="fg-transparent" size="inline" /> `transparent` | Transparent foreground color |
+| `null` | <Swatch bg="fg" size="inline" cssVar="fg" /> | Default foreground color |
+| `1` | <Swatch bg="fg-1" size="inline" cssVar="fg-1" /> | Lowest contrast foreground color |
+| `2` | <Swatch bg="fg-2" size="inline" cssVar="fg-2" /> | Lower contrast foreground color |
+| `3` | <Swatch bg="fg-3" size="inline" cssVar="fg-3" /> | Medium contrast foreground color |
+| `white` | <Swatch bg="fg-white" size="inline" cssVar="fg-white" /> | Pure white foreground color |
+| `black` | <Swatch bg="fg-black" size="inline" cssVar="fg-black" /> | Pure black foreground color |
 | `inherit` | `inherit` | Inherited foreground color |
 </BsTable>
 
+Border colors have similar levels, but different naming.
+
+<BsTable>
+| Border | Default value | Description |
+| --- | --- | --- |
+| `null` | <Swatch bg="border" size="inline" cssVar="border" /> | Default border color |
+| `muted` | <Swatch bg="border-muted" size="inline" cssVar="border-muted" /> | Muted border color |
+| `subtle` | <Swatch bg="border-subtle" size="inline" cssVar="border-subtle" /> | Subtle border color |
+| `emphasized` | <Swatch bg="border-emphasized" size="inline" cssVar="border-emphasized" /> | Emphasized border color |
+</BsTable>
+
 ### Suggested pairings
 
 Not all foreground colors are appropriate for all background colors. To maintain color contrast for accessibility, here are some recommended pairings.