]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Revamp some docs layout
authorMark Otto <markdotto@gmail.com>
Wed, 2 Apr 2025 17:03:10 +0000 (10:03 -0700)
committerMark Otto <markdotto@gmail.com>
Sat, 31 May 2025 03:32:44 +0000 (20:32 -0700)
26 files changed:
.browserslistrc
package.json
scss/layout/_grid.scss
site/src/components/DocsSidebar.astro
site/src/components/footer/Footer.astro
site/src/components/head/Stylesheet.astro
site/src/components/header/Navigation.astro
site/src/components/shortcodes/Code.astro
site/src/components/shortcodes/Example.astro
site/src/components/shortcodes/ScssDocs.astro
site/src/content/docs/components/alerts.mdx
site/src/content/docs/layout/breakpoints.mdx
site/src/layouts/DocsLayout.astro
site/src/layouts/partials/Icons.astro
site/src/libs/utils.ts
site/src/scss/_ads.scss
site/src/scss/_callouts.scss
site/src/scss/_clipboard-js.scss
site/src/scss/_color-contrast.scss [new file with mode: 0644]
site/src/scss/_component-examples.scss
site/src/scss/_masthead.scss
site/src/scss/_navbar.scss
site/src/scss/_sidebar.scss
site/src/scss/_syntax.scss
site/src/scss/_variables.scss
site/src/scss/docs.scss

index cddd230052469b8f3610f8c468d666759db37521..dcce24143c106a56a50421e196d4cebb6901149a 100644 (file)
@@ -3,10 +3,10 @@
 >= 0.5%
 last 2 major versions
 not dead
-Chrome >= 60
-Firefox >= 60
-Firefox ESR
-iOS >= 12
-Safari >= 12
+Chrome >= 120
+Firefox >= 121
+iOS >= 15.6
+Safari >= 15.6
 not Explorer <= 11
+Samsung >= 23
 not kaios <= 2.5 # fix floating label issues in Firefox (see https://github.com/postcss/autoprefixer/issues/1533)
index 39e2fb039dcb51bb136d4bba08645bed305a05f3..38592bad770a71ba1facde3aea0337e4f2b1bfdf 100644 (file)
     "scss/**/*.scss",
     "!scss/tests/**"
   ],
-  "browserslist": [
-    ">= 0.5%",
-    "last 2 major versions",
-    "not dead",
-    "Chrome >= 120",
-    "Firefox >= 121",
-    "iOS >= 15.6",
-    "Safari >= 15.6",
-    "not Explorer <= 11",
-    "Samsung >= 23",
-    "not kaios <= 2.5"
-  ],
   "jspm": {
     "registry": "npm",
     "main": "js/bootstrap",
index 17fac456c723f469ec24926a742cbca1c25a5627..89a5e1ff5a1a33f9e0a6a066b973d47e25dd0539 100644 (file)
@@ -29,6 +29,7 @@
 
   @each $breakpoint in map.keys($breakpoints) {
     $infix: breakpoint-infix($breakpoint, $breakpoints);
+    $infix: if($infix == "", "", "-" + $infix);
 
     @include media-breakpoint-up($breakpoint, $breakpoints) {
       @if $grid-columns > 0 {
   .grid-cols-4 {
     --#{$prefix}columns: 4;
   }
+  .grid-cols-5 {
+    --#{$prefix}columns: 5;
+  }
   .grid-cols-6 {
     --#{$prefix}columns: 6;
   }
+
 }
index 1282ed7026e1ae60f079724f202217fbca271321..c36ea79bc8ee07306084488984d7dec5bba05734 100644 (file)
@@ -17,7 +17,7 @@ const sidebar = getData('sidebar')
           return (
             <li class="bd-links-group py-2">
               <strong class="bd-links-heading d-flex w-100 align-items-center fw-semibold">
-                {group.icon && (
+                {/* {group.icon && (
                   <svg
                     class="bi me-2"
                     style={group.icon_color && `color: var(--bs-${group.icon_color});`}
@@ -25,7 +25,7 @@ const sidebar = getData('sidebar')
                   >
                     <use xlink:href={`#${group.icon}`} />
                   </svg>
-                )}
+                )} */}
                 {group.title}
               </strong>
               <ul class="list-unstyled fw-normal pb-2 small">
@@ -49,7 +49,7 @@ const sidebar = getData('sidebar')
                     <li>
                       <a
                         href={url}
-                        class:list={['bd-links-link d-inline-block rounded', { active }]}
+                        class:list={['bd-links-link d-block rounded', { active }]}
                         aria-current={active ? 'page' : undefined}
                       >
                         {page.title}
index 5232081ede0545c8add4d3e9fd27e7bc22fbb076..1042e401441c4457dd4a9f8394a8e58074b032e0 100644 (file)
@@ -4,10 +4,10 @@ import { getConfig } from '@libs/config'
 import { getVersionedDocsPath } from '@libs/path'
 ---
 
-<footer class="bd-footer py-4 py-md-5 mt-5 bg-body-tertiary">
-  <div class="container py-4 py-md-5 px-4 px-md-3 text-body-secondary">
-    <div class="row">
-      <div class="col-lg-3 mb-3">
+<footer class="bd-footer py-4 py-md-5 mt-5 bg-1">
+  <div class="container-2xl py-4 py-md-5 px-4 px-md-3 fg-3">
+    <div class="grid grid-fill grid-cols-5">
+      <div class="col-lg-2 mb-3">
         <a
           class="d-inline-flex align-items-center mb-2 text-body-emphasis text-decoration-none"
           href="/"
@@ -32,7 +32,7 @@ import { getVersionedDocsPath } from '@libs/path'
           <li class="mb-2">Currently v{getConfig().current_version}.</li>
         </ul>
       </div>
-      <div class="col-6 col-lg-2 offset-lg-1 mb-3">
+      <div class="mb-3">
         <h5>Links</h5>
         <ul class="list-unstyled">
           <li class="mb-2"><a href="/">Home</a></li>
@@ -44,7 +44,7 @@ import { getVersionedDocsPath } from '@libs/path'
           <li class="mb-2"><a href={getConfig().swag} target="_blank" rel="noopener">Swag Store</a></li>
         </ul>
       </div>
-      <div class="col-6 col-lg-2 mb-3">
+      <div class="mb-3">
         <h5>Guides</h5>
         <ul class="list-unstyled">
           <li class="mb-2"><a href={getVersionedDocsPath('getting-started')}>Getting started</a></li>
@@ -54,7 +54,7 @@ import { getVersionedDocsPath } from '@libs/path'
           <li class="mb-2"><a href={getVersionedDocsPath('getting-started/vite')}>Vite</a></li>
         </ul>
       </div>
-      <div class="col-6 col-lg-2 mb-3">
+      <div class="mb-3">
         <h5>Projects</h5>
         <ul class="list-unstyled">
           <li class="mb-2">
@@ -70,7 +70,7 @@ import { getVersionedDocsPath } from '@libs/path'
           </li>
         </ul>
       </div>
-      <div class="col-6 col-lg-2 mb-3">
+      <div class="mb-3">
         <h5>Community</h5>
         <ul class="list-unstyled">
           <li class="mb-2">
index d0203893a478d758153f1e2919a89d9551073209..0a64de1f06ee47900731b04c794ab6a3fbd4eb55 100644 (file)
@@ -1,5 +1,5 @@
 ---
-import { getVersionedBsCssProps } from '@libs/bootstrap'
+// import { getVersionedBsCssProps } from '@libs/bootstrap'
 import type { Layout } from '@libs/layout'
 
 interface Props {
@@ -10,4 +10,5 @@ interface Props {
 const { direction } = Astro.props
 ---
 
-<link {...getVersionedBsCssProps(direction)} />
+<!-- <link {...getVersionedBsCssProps(direction)} /> -->
+<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3" />
index e33c30069cd8b2cc81a6eebe711acaefafc21341..43d8fb7521bd71eb695fdafe2b9bb03814cb97a3 100644 (file)
@@ -85,7 +85,6 @@ const { addedIn, layout, title } = Astro.props
           </LinkItem>
           <LinkItem active={title === 'Examples'} href={getVersionedDocsPath('examples/')} track>Examples</LinkItem>
           <LinkItem href={getConfig().icons} target="_blank" rel="noopener" track>Icons</LinkItem>
-          <LinkItem href={getConfig().themes} target="_blank" rel="noopener" track>Themes</LinkItem>
           <LinkItem href={getConfig().blog} target="_blank" rel="noopener" track>Blog</LinkItem>
         </ul>
 
index 231002a50b622fed5c884f6983b596de7b07e2e4..0d75c52fe1e6ac98d701b20ffe755b2b877b4ab4 100644 (file)
@@ -33,9 +33,14 @@ interface Props {
    * This takes precedence over the `code` prop.
    */
   filePath?: string
+  /**
+   * The theme to use for the code block.
+   * @see https://getbootstrap.com/docs/6.0/customize/color-scheme/
+   */
+  theme?: string
 }
 
-const { class: className, code, containerClass, fileMatch, filePath, lang } = Astro.props
+const { class: className, code, containerClass, fileMatch, filePath, lang, theme } = Astro.props
 
 let codeToDisplay = filePath
   ? fs.readFileSync(path.join(process.cwd(), filePath), 'utf8')
@@ -144,7 +149,7 @@ if (filePath && fileMatch && codeToDisplay) {
       </div>
     )
   }
-  <div class="highlight">
+  <div class="highlight" data-bs-theme={theme}>
     {
       codeToDisplay && lang ? (
         <Prism code={codeToDisplay} lang={lang} />
index 7bfd41417cd24c942e1e24fec05797d1a3ee7a46..34d4b511c1cddd504b4d65b99205ed74c4f90520 100644 (file)
@@ -80,7 +80,7 @@ const simplifiedMarkup = markup
     showMarkup && (
       <>
         {showPreview && (
-          <div class="d-flex align-items-center highlight-toolbar ps-3 pe-2 py-1 border-0 border-top border-bottom">
+          <div class="d-flex align-items-center highlight-toolbar ps-3 pe-2 py-1" data-bs-theme="dark">
             <small class="font-monospace text-body-secondary text-uppercase">{lang}</small>
             <div class="d-flex ms-auto">
               <button
index 6c267570eb3eae0918f4858d46e37d7f624469ae..91fac7c0c3c582511ff5975113ce56d452b8be97 100644 (file)
@@ -55,7 +55,7 @@ try {
 ---
 
 <Code containerClass="bd-example-snippet bd-file-ref" code={content} lang="scss">
-  <div slot="pre" class="d-flex align-items-center highlight-toolbar ps-3 pe-2 py-1 border-bottom">
+  <div slot="pre" class="d-flex align-items-center highlight-toolbar ps-3 pe-2 py-1">
     <a
       class="font-monospace link-secondary link-underline-secondary link-underline-opacity-0 link-underline-opacity-100-hover small"
       href={`${getConfig().repo}/blob/v${getConfig().current_version}/${file}`.replaceAll('\\', '/')}
@@ -63,7 +63,7 @@ try {
       {file}
     </a>
     <div class="d-flex ms-auto">
-      <button type="button" class="btn-clipboard mt-0 me-0" title="Copy to clipboard">
+      <button type="button" class="btn-clipboard m-0" title="Copy to clipboard">
         <svg class="bi" aria-hidden="true"><use xlink:href="#clipboard"></use></svg>
       </button>
     </div>
index a173cfa895bd1dacdf5f381c452752d5e25c6cb9..3503eddb4673f58f51b091e01e262f0d1abd4708 100644 (file)
@@ -10,11 +10,7 @@ import { getData } from '@libs/data'
 
 Alerts are available for any length of text, as well as an optional close button. For proper styling, use one of the eight **required** contextual classes (e.g., `.alert-success`). For inline dismissal, use the [alerts JavaScript plugin](#dismissing).
 
-<Callout>
-**Heads up!** As of v5.3.0, the `alert-variant()` Sass mixin is deprecated. Alert variants now have their CSS variables overridden in [a Sass loop](#sass-loops).
-</Callout>
-
-<Example code={getData('theme-colors').map((themeColor) => `<div class="alert theme-${themeColor.name}" role="alert">
+<Example code={getData('theme-colors').map((themeColor) => `<div class="alert alert-${themeColor.name}" role="alert">
   A simple ${themeColor.name} alert—check it out!
 </div>`)} />
 
@@ -136,17 +132,7 @@ As part of Bootstrap’s evolving CSS variables approach, alerts now use local C
 
 <ScssDocs name="alert-variables" file="scss/_variables.scss" />
 
-<<<<<<< HEAD
-### Sass mixins
-
-<DeprecatedIn version="5.3.0" />
-
-<ScssDocs name="alert-variant-mixin" file="scss/mixins/_alert.scss" removeIndentation={false} />
-
-### Sass loops
-=======
 ### Sass loop
->>>>>>> 29c34e4cd (Update Alerts variables and remove deprecation mentions)
 
 Loop that generates the modifier classes with an overriding of CSS variables.
 
index 3c99e78ca2952263b01c7ed051b7e166d29af5d7..7d0b80dd55790f811c3ab3d9ec24bb753dfe62c2 100644 (file)
@@ -66,11 +66,7 @@ Bootstrap primarily uses media queries that target a specific minimum `width`, o
 ```scss
 // Source mixins
 
-<<<<<<< HEAD
-// No media query necessary for xs breakpoint as it’s effectively `@media (min-width: 0) { ... }`
-=======
-// No media query necessary for xs breakpoint as it's effectively `@media (width > 0) { ... }`
->>>>>>> ca2d5f613 (Breakpoints edits)
+// No media query necessary for xs breakpoint as it’s effectively `@media (width > 0) { ... }`
 @include media-breakpoint-up(sm) { ... }
 @include media-breakpoint-up(md) { ... }
 @include media-breakpoint-up(lg) { ... }
@@ -117,11 +113,7 @@ These Sass mixins translate in our compiled CSS using the values declared in our
 We occasionally use media queries that go in the other direction (the given screen size _or smaller_):
 
 ```scss
-<<<<<<< HEAD
-// No media query necessary for xs breakpoint as it’s effectively `@media (max-width: 0) { ... }`
-=======
-// No media query necessary for xs breakpoint as it's effectively `@media (width < 0) { ... }`
->>>>>>> ca2d5f613 (Breakpoints edits)
+// No media query necessary for xs breakpoint as it’s effectively `@media (width < 0) { ... }`
 @include media-breakpoint-down(sm) { ... }
 @include media-breakpoint-down(md) { ... }
 @include media-breakpoint-down(lg) { ... }
index 63dde15f688050b5e07414af95cd96aeab11900b..1a82a447afbddb30dc76cfa2a4f321eead7062e0 100644 (file)
@@ -9,6 +9,17 @@ import Ads from '@components/Ads.astro'
 import BaseLayout from '@layouts/BaseLayout.astro'
 import DocsSidebar from '@components/DocsSidebar.astro'
 import TableOfContents from '@components/TableOfContents.astro'
+import { readFileSync } from 'node:fs'
+import { parse } from 'yaml'
+import { fileURLToPath } from 'node:url'
+import { join, dirname } from 'node:path'
+import GitHubIcon from '@components/icons/GitHubIcon.astro'
+
+interface NavigationPage {
+  title: string
+  url: string
+  groupTitle: string
+}
 
 interface Props {
   frontmatter: CollectionEntry<'docs'>['data']
@@ -16,7 +27,18 @@ interface Props {
   id: CollectionEntry<'docs'>['id']
 }
 
+// Read and parse the YAML file directly
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = dirname(__filename)
+const sidebarPath = join(__dirname, '../../data/sidebar.yml')
+const sidebarContent = readFileSync(sidebarPath, 'utf8')
+const sidebar = parse(sidebarContent) as Array<{
+  title: string
+  pages?: Array<{ title: string }>
+}>
+
 const { frontmatter, headings, id } = Astro.props
+const { slug } = Astro.params
 
 // Extract the directory/section from the ID (format: "directory/filename.mdx")
 const parentDirectory = id.includes('/') ? id.split('/')[0] : ''
@@ -27,6 +49,33 @@ if (frontmatter.toc) {
   bodyProps['data-bs-spy'] = 'scroll'
   bodyProps['data-bs-target'] = '#TableOfContents'
 }
+
+// Find previous and next pages for navigation
+let prevPage: NavigationPage | undefined
+let nextPage: NavigationPage | undefined
+
+// Create a flat array of all pages with their groups
+const allPages = sidebar.flatMap((group) => {
+  if (!group.pages) return []
+  return group.pages.map((page) => ({
+    title: page.title,
+    url: `/docs/${getConfig().docs_version}/${getSlug(group.title)}/${getSlug(page.title)}/`,
+    groupTitle: group.title
+  }))
+})
+
+// Find the current page index
+const currentPageIndex = allPages.findIndex(
+  (page) => page.url === `/docs/${getConfig().docs_version}/${slug}/`
+)
+
+if (currentPageIndex > 0) {
+  prevPage = allPages[currentPageIndex - 1]
+}
+
+if (currentPageIndex < allPages.length - 1) {
+  nextPage = allPages[currentPageIndex + 1]
+}
 ---
 
 <BaseLayout {...Astro.props} layout="docs" overrides={{ body: bodyProps }}>
@@ -51,33 +100,31 @@ if (frontmatter.toc) {
 
     <main class="bd-main order-1">
       <div class="bd-intro pt-2 ps-lg-2">
-        <div class="d-md-flex flex-md-row-reverse align-items-center justify-content-between">
-          <div class="mb-3 mb-md-0 d-flex text-nowrap">
-            {
-              // This is needed because we want to show the badge if show_badge isn't present or is set to false
-              frontmatter.added &&
-                ((frontmatter.added.show_badge !== undefined && frontmatter.added.show_badge === true) ||
-                  frontmatter.added.show_badge === undefined) && (
-                  <small class="d-inline-flex px-2 py-1 fw-semibold text-success-emphasis bg-success-subtle border border-success-subtle rounded-2 me-2">
-                    Added in v{frontmatter.added.version}
-                  </small>
-                )
-            }
-            <a
-              class="btn btn-sm btn-bd-light rounded-2"
-              href={`${getConfig().repo}/blob/v${getConfig().current_version}/site/src/content/docs/${id}`}
-              title="View and edit this file on GitHub"
-              target="_blank"
-              rel="noopener"
-            >
-              View on GitHub
-            </a>
-          </div>
-          <h1 class="bd-title mb-0" id="content">{frontmatter.title}</h1>
-        </div>
+        <h1 class="bd-title mb-0" id="content">{frontmatter.title}</h1>
         <div class="bd-subtitle">
           {frontmatter.description && <Fragment set:html={processMarkdownToHtml(frontmatter.description)} />}
         </div>
+        <div class="mb-3 mb-md-0 d-flex text-nowrap">
+          {
+            frontmatter.added &&
+              ((frontmatter.added.show_badge !== undefined && frontmatter.added.show_badge === true) ||
+                frontmatter.added.show_badge === undefined) && (
+                <small class="d-inline-flex px-2 py-1 fw-semibold text-success-emphasis bg-success-subtle border border-success-subtle rounded-2 me-2">
+                  Added in v{frontmatter.added.version}
+                </small>
+              )
+          }
+          <a
+            class="btn btn-secondary-text btn-sm"
+            href={`${getConfig().repo}/blob/v${getConfig().current_version}/site/src/content/docs/${id}`}
+            title="View and edit this file on GitHub"
+            target="_blank"
+            rel="noopener"
+          >
+            <GitHubIcon height={16} width={16} class="bi" />
+            View on GitHub
+          </a>
+        </div>
       </div>
 
 
@@ -112,7 +159,7 @@ if (frontmatter.toc) {
       <div class="docs-content-body prose ps-lg-2">
         {
           frontmatter.sections && (
-            <div class="row g-3">
+            <div class="grid mb-5">
               {frontmatter.sections.map((section) => (
                 <div class="col-md-6">
                   <a
@@ -131,6 +178,33 @@ if (frontmatter.toc) {
         }
 
         <slot />
+
+        <nav class="bd-links-nav py-5 mt-5 border-top">
+          <div class="grid">
+            <div class="col-6">
+              {
+                prevPage && (
+                  <a href={prevPage.url} class="d-block p-3 text-decoration-none rounded-3">
+                    <div class="text-secondary small">Previous</div>
+                    <div class="fw-semibold">← {prevPage.title}</div>
+                    <div class="text-secondary small">{prevPage.groupTitle}</div>
+                  </a>
+                )
+              }
+            </div>
+            <div class="col-6">
+              {
+                nextPage && (
+                  <a href={nextPage.url} class="d-block p-3 text-decoration-none text-end rounded-3">
+                    <div class="text-secondary small">Next</div>
+                    <div class="fw-semibold">{nextPage.title} →</div>
+                    <div class="text-secondary small">{nextPage.groupTitle}</div>
+                  </a>
+                )
+              }
+            </div>
+          </div>
+        </nav>
       </div>
     </main>
   </div>
index 408ac4a1810d9353c2ac6a282794d7a435d6d9ee..679256882e7c3c162b04f7f047630eded6ed1ef0 100644 (file)
@@ -7,6 +7,9 @@
   <symbol id="circle-half" viewBox="0 0 16 16">
     <path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"></path>
   </symbol>
+  <symbol id="github" viewBox="0 0 16 16">
+    <path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27s1.36.09 2 .27c1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8"></path>
+  </symbol>
   <symbol id="moon-stars-fill" viewBox="0 0 16 16">
     <path
       d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"
index fcdd33e7841ef5984ec05c0003365de429e1a231..0a1fbb63fcc9888a979a77809be64d1b35ae3de8 100644 (file)
@@ -39,6 +39,8 @@ export function stripMarkdown(str: string) {
 
 export function processMarkdownToHtml(markdown: string): string {
   // Use remark to process markdown to HTML
-  const result = remark().use(remarkHtml).processSync(markdown)
+  const result = remark()
+    .use(remarkHtml)
+    .processSync(markdown)
   return result.toString()
 }
index 87a7a889956b11211ffa3cdc7059d8a0ca153abf..df88fb338128477dbcee757eb6c2925cc656d143 100644 (file)
@@ -17,7 +17,7 @@
   @include font-size(.8125rem);
   line-height: 1.4;
   text-align: left;
-  background-color: var(--bs-tertiary-bg);
+  background-color: var(--bs-bg-1);
 
   a {
     color: var(--bs-body-color);
index 1e34331ff74c920c3f181ddf626eec0841518bbd..252082770a7051c83dbb4385631e2d49ace3c205 100644 (file)
@@ -6,39 +6,41 @@
 // Callouts
 //
 
-.bd-callout {
-  --#{$prefix}link-color: var(--bd-callout-link);
-  --#{$prefix}code-color: var(--bd-callout-code-color);
-
-  padding: 1.25rem;
-  margin-top: 1.25rem;
-  margin-bottom: 1.25rem;
-  color: var(--bd-callout-color, inherit);
-  background-color: var(--bd-callout-bg, var(--bs-gray-100));
-  border-left: .25rem solid var(--bd-callout-border, var(--bs-gray-300));
-
-  h4 {
-    margin-bottom: .25rem;
+@layer custom {
+  .bd-callout {
+    --#{$prefix}link-color: var(--bd-callout-link);
+    --#{$prefix}code-color: var(--bd-callout-code-color);
+
+    padding: 1.25rem;
+    margin-top: 1.25rem;
+    margin-bottom: 1.25rem;
+    color: var(--bd-callout-color, inherit);
+    background-color: var(--bd-callout-bg, var(--bs-gray-100));
+    border-left: .25rem solid var(--bd-callout-border, var(--bs-gray-300));
+
+    h4 {
+      margin-bottom: .25rem;
+    }
+
+    > :last-child {
+      margin-bottom: 0;
+    }
+
+    + .bd-callout {
+      margin-top: -.25rem;
+    }
+
+    .highlight {
+      background-color: rgba($black, .05);
+    }
   }
 
-  > :last-child {
-    margin-bottom: 0;
-  }
-
-  + .bd-callout {
-    margin-top: -.25rem;
-  }
-
-  .highlight {
-    background-color: rgba($black, .05);
-  }
-}
-
-// Variations
-@each $variant in $bd-callout-variants {
-  .bd-callout-#{$variant} {
-    --bd-callout-color: var(--bs-#{$variant}-text);
-    --bd-callout-bg: var(--bs-#{$variant}-bg-subtle);
-    --bd-callout-border: var(--bs-#{$variant}-border);
+  // Variations
+  @each $variant in $bd-callout-variants {
+    .bd-callout-#{$variant} {
+      --bd-callout-color: var(--bs-#{$variant}-text);
+      --bd-callout-bg: var(--bs-#{$variant}-bg-subtle);
+      --bd-callout-border: var(--bs-#{$variant}-border);
+    }
   }
 }
index a4c71c8ccfaefbf89f645114a5373526f30c3352..8bee4426bef187ffa85290e15b7a7973420c66e0 100644 (file)
@@ -5,43 +5,45 @@
 //
 // JS-based `Copy` buttons for code snippets.
 
-.bd-clipboard,
-.bd-edit {
-  position: relative;
-  display: none;
-  float: right;
-
-  + .highlight {
-    margin-top: 0;
+@layer custom {
+  .bd-clipboard,
+  .bd-edit {
+    position: relative;
+    display: none;
+    float: right;
+
+    + .highlight {
+      margin-top: 0;
+    }
+
+    @include media-breakpoint-up(md) {
+      display: block;
+    }
   }
 
-  @include media-breakpoint-up(md) {
+  .btn-clipboard,
+  .btn-edit {
     display: block;
-  }
-}
-
-.btn-clipboard,
-.btn-edit {
-  display: block;
-  padding: .5em;
-  line-height: 1;
-  color: var(--bs-body-color);
-  background-color: var(--bd-pre-bg);
-  border: 0;
-  @include border-radius(.25rem);
-
-  &:hover {
-    color: var(--bs-link-hover-color);
+    padding: .5em;
+    line-height: 1;
+    color: var(--bs-body-color);
+    background-color: var(--bd-pre-bg);
+    border: 0;
+    @include border-radius(.25rem);
+
+    &:hover {
+      color: var(--bs-link-hover-color);
+    }
+
+    &:focus {
+      z-index: 3;
+    }
   }
 
-  &:focus {
-    z-index: 3;
+  .btn-clipboard {
+    position: relative;
+    z-index: 2;
+    margin-top: 1.25rem;
+    margin-right: .75rem;
   }
 }
-
-.btn-clipboard {
-  position: relative;
-  z-index: 2;
-  margin-top: 1.25rem;
-  margin-right: .75rem;
-}
diff --git a/site/src/scss/_color-contrast.scss b/site/src/scss/_color-contrast.scss
new file mode 100644 (file)
index 0000000..ce242a7
--- /dev/null
@@ -0,0 +1,51 @@
+// Color contrast
+// See https://github.com/twbs/bootstrap/pull/30168
+
+// A list of pre-calculated numbers of pow(divide((divide($value, 255) + .055), 1.055), 2.4). (from 0 to 255)
+// stylelint-disable-next-line scss/dollar-variable-default, scss/dollar-variable-pattern
+$_luminance-list: .0008 .001 .0011 .0013 .0015 .0017 .002 .0022 .0025 .0027 .003 .0033 .0037 .004 .0044 .0048 .0052 .0056 .006 .0065 .007 .0075 .008 .0086 .0091 .0097 .0103 .011 .0116 .0123 .013 .0137 .0144 .0152 .016 .0168 .0176 .0185 .0194 .0203 .0212 .0222 .0232 .0242 .0252 .0262 .0273 .0284 .0296 .0307 .0319 .0331 .0343 .0356 .0369 .0382 .0395 .0409 .0423 .0437 .0452 .0467 .0482 .0497 .0513 .0529 .0545 .0561 .0578 .0595 .0612 .063 .0648 .0666 .0685 .0704 .0723 .0742 .0762 .0782 .0802 .0823 .0844 .0865 .0887 .0908 .0931 .0953 .0976 .0999 .1022 .1046 .107 .1095 .1119 .1144 .117 .1195 .1221 .1248 .1274 .1301 .1329 .1356 .1384 .1413 .1441 .147 .15 .1529 .1559 .159 .162 .1651 .1683 .1714 .1746 .1779 .1812 .1845 .1878 .1912 .1946 .1981 .2016 .2051 .2086 .2122 .2159 .2195 .2232 .227 .2307 .2346 .2384 .2423 .2462 .2502 .2542 .2582 .2623 .2664 .2705 .2747 .2789 .2831 .2874 .2918 .2961 .3005 .305 .3095 .314 .3185 .3231 .3278 .3325 .3372 .3419 .3467 .3515 .3564 .3613 .3663 .3712 .3763 .3813 .3864 .3916 .3968 .402 .4072 .4125 .4179 .4233 .4287 .4342 .4397 .4452 .4508 .4564 .4621 .4678 .4735 .4793 .4851 .491 .4969 .5029 .5089 .5149 .521 .5271 .5333 .5395 .5457 .552 .5583 .5647 .5711 .5776 .5841 .5906 .5972 .6038 .6105 .6172 .624 .6308 .6376 .6445 .6514 .6584 .6654 .6724 .6795 .6867 .6939 .7011 .7084 .7157 .7231 .7305 .7379 .7454 .7529 .7605 .7682 .7758 .7835 .7913 .7991 .807 .8148 .8228 .8308 .8388 .8469 .855 .8632 .8714 .8796 .8879 .8963 .9047 .9131 .9216 .9301 .9387 .9473 .956 .9647 .9734 .9823 .9911 1;
+
+@function color-contrast($background, $color-contrast-dark: $color-contrast-dark, $color-contrast-light: $color-contrast-light, $min-contrast-ratio: $min-contrast-ratio) {
+  $foregrounds: $color-contrast-light, $color-contrast-dark, #fff, #000;
+  $max-ratio: 0;
+  $max-ratio-color: null;
+
+  @each $color in $foregrounds {
+    $contrast-ratio: contrast-ratio($background, $color);
+    @if $contrast-ratio > $min-contrast-ratio {
+      @return $color;
+    } @else if $contrast-ratio > $max-ratio {
+      $max-ratio: $contrast-ratio;
+      $max-ratio-color: $color;
+    }
+  }
+
+  @warn "Found no color leading to #{$min-contrast-ratio}:1 contrast ratio against #{$background}...";
+
+  @return $max-ratio-color;
+}
+
+@function contrast-ratio($background, $foreground: $color-contrast-light) {
+  $l1: luminance($background);
+  $l2: luminance(opaque($background, $foreground));
+
+  @return if($l1 > $l2, math.div($l1 + .05, $l2 + .05), math.div($l2 + .05, $l1 + .05));
+}
+
+// Return WCAG2.2 relative luminance
+// See https://www.w3.org/TR/WCAG/#dfn-relative-luminance
+// See https://www.w3.org/TR/WCAG/#dfn-contrast-ratio
+@function luminance($color) {
+  $rgb: (
+    "r": red($color),
+    "g": green($color),
+    "b": blue($color)
+  );
+
+  @each $name, $value in $rgb {
+    $value: if(math.div($value, 255) < .04045, math.div(math.div($value, 255), 12.92), nth($_luminance-list, $value + 1));
+    $rgb: map-merge($rgb, ($name: $value));
+  }
+
+  @return (map-get($rgb, "r") * .2126) + (map-get($rgb, "g") * .7152) + (map-get($rgb, "b") * .0722);
+}
index 63b69142c1a21b864b4f62aeb857cb5d5745fee8..eed4c5e1853b1e0272fc54ab1081cabebb81ad30 100644 (file)
 
 .highlight-toolbar {
   background-color: var(--bd-pre-bg);
-
-  + .highlight {
-    @include border-top-radius(0);
-  }
+  border-bottom: 1px solid var(--bs-border-color);
 }
 
 .bd-file-ref {
   .highlight-toolbar {
-    @include media-breakpoint-up(md) {
-      @include border-top-radius(calc(var(--bs-border-radius) - 1px));
-    }
+    @include border-top-radius(calc(var(--bs-border-radius) + 1px));
   }
 }
 
index 314080cb190b3d21dc3873a91fb208a1207a5f31..b009486f268e8705533cd3e9270345c720cfbcc2 100644 (file)
 .bd-masthead {
   // --bd-pink: #{$pink};
   padding: 3rem 0;
-  // stylelint-disable
   // background-image: linear-gradient(180deg, color-mix(in srgb, var(--bs-body-bg) 1%, transparent), color-mix(in srgb, var(--bs-body-bg) 85%, transparent)),
   //                   radial-gradient(ellipse at top left, color-mix(in srgb, var(--bs-primary), transparent)),
   //                   radial-gradient(ellipse at top right, color-mix(in srgb, var(--bd-accent), transparent)),
   //                   radial-gradient(ellipse at center right, color-mix(in srgb, var(--bd-violet), transparent)),
-  //                   radial-gradient(ellipse at center left, color-mix(in srgb, var(--bd-pink), transparent));
-  // stylelint-enable
+  //                   radial-gradient(ellipse at center left, color-mix(in srgb, var(--bs-pink), transparent));
 
   h1 {
     --bs-heading-color: var(--bs-emphasis-color);
index 7c6ed299b2e0db3d05bdb659138edd9e71ed09d0..fb4882a939269f1cedc9ff4f7fea17b2a6610e0f 100644 (file)
         color: $white;
       }
 
-<<<<<<< HEAD
-  .offcanvas-lg {
-    background-color: var(--bd-violet-bg);
-    border-left: 0;
-
-    @include media-breakpoint-down(lg) {
-      box-shadow: var(--bs-box-shadow-lg);
-    }
-  }
-
-  .dropdown-toggle {
-    &:focus:not(:focus-visible) {
-      outline: 0;
-    }
-  }
-
-  .dropdown-menu {
-    --bs-dropdown-min-width: 12rem;
-    --bs-dropdown-padding-x: .25rem;
-    --bs-dropdown-padding-y: .25rem;
-    --bs-dropdown-link-hover-bg: rgba(var(--bd-violet-rgb), .1);
-    --bs-dropdown-link-active-bg: rgba(var(--bd-violet-rgb), 1);
-    @include rfs(.875rem, --bs-dropdown-font-size);
-    @include font-size(.875rem);
-    @include border-radius(.5rem);
-    box-shadow: $dropdown-box-shadow;
-
-    li + li {
-      margin-top: .125rem;
-=======
       &.active {
         font-weight: 600;
         color: $white;
       }
->>>>>>> 9c2140328 (fix some docs Sass)
     }
 
     .navbar-nav-svg {
index b92e7063702687771d7bdc950bec35cb12d7f078..c38d4ccafd3c97f57e422f6239282f3053df6731 100644 (file)
@@ -25,7 +25,8 @@
 }
 
 .bd-links-heading {
-  color: var(--bs-emphasis-color);
+  padding-inline-start: .5rem;
+  color: var(--bs-fg-0);
 }
 
 .bd-links-nav {
 }
 
 .bd-links-link {
-  padding: .1875rem .5rem;
+  padding: .375rem .5rem;
   margin-top: .125rem;
-  margin-left: 1.125rem;
-  color: var(--bs-body-color);
+  line-height: 20px;
+  color: var(--bs-fg-1);
   text-decoration: if($link-decoration == none, null, none);
 
   &:hover,
   &:focus,
   &.active {
-    color: var(--bs-emphasis-color);
+    color: var(--bs-fg-0);
     text-decoration: if($link-hover-decoration == underline, none, null);
-    background-color: var(--bd-sidebar-link-bg);
+    background-color: var(--bs-bg-1);
   }
 
   &.active {
-    font-weight: 600;
+    font-weight: 500;
   }
 }
index d1bf33a0b2d7efe28cf779db6679989da76a65ee..16857588d68154e3840c93a17b4be68143b52272 100644 (file)
@@ -1,3 +1,4 @@
+@use "../../../scss/variables" as *;
 @use "../../../scss/config" as *;
 @use "../../../scss/colors" as *;
 @use "../../../scss/mixins/color-mode" as *;
index 370ea492ee9d81ef6bca59dcfd9397c5f1483d6a..73b67ba0dbc75f3eb3cc42e6636df07fab7b337d 100644 (file)
@@ -13,8 +13,7 @@ $bd-gutter-x: 3rem;
 $bd-callout-variants: info, warning, danger !default;
 
 @layer custom {
-  :root,
-  [data-bs-theme="light"] {
+  :root {
     --bd-purple: #{$bd-purple};
     --bd-violet: #{$bd-violet};
     --bd-accent: #{$bd-accent};
@@ -23,11 +22,12 @@ $bd-callout-variants: info, warning, danger !default;
     // --bd-pink-rgb: #{to-rgb($pink-500)};
     // --bd-teal-rgb: #{to-rgb($teal-500)};
     --bd-violet-bg: var(--bd-violet);
-    --bd-toc-color: var(--bd-violet);
+    --bd-toc-color: light-dark(var(--bd-violet), var(--bs-indigo-300));
     --bd-sidebar-link-bg: color-mix(in srgb, var(--bd-violet), transparent 90%);
     --bd-callout-link: #{$blue-600};
-    --bd-callout-code-color: #{$pink-600};
+    --bd-callout-code-color: light-dark(var(--bs-pink-600), var(--bs-pink-300));
     --bd-pre-bg: light-dark(var(--bs-gray-100), color-mix(in srgb, var(--bs-gray-900), var(--bs-black) 25%));
+    --bd-swatch-shadow: inset 0 0 0 1px light-dark(rgb(0 0 0 / .1), rgb(255 255 255 / .1));
   }
 
   // @include color-mode(dark, true) {
index 9758ad40a98b29752d5810b2cca79880d3c80d92..72ba90217f5a98cddb217fe0d7218cd437b62682 100644 (file)
@@ -22,6 +22,8 @@
 //
 // Happy Bootstrapping!
 
+@use "../../../scss/bootstrap" as *;
+
 // Load docs components
 @use "variables";
 @use "navbar";