]> git.ipfire.org Git - thirdparty/bootstrap.git/commitdiff
Docs: fix and restore live code snippet updates in interactive playgrounds (#42593)
authorJulien Déramond <juderamond@gmail.com>
Sun, 28 Jun 2026 15:33:33 +0000 (17:33 +0200)
committerGitHub <noreply@github.com>
Sun, 28 Jun 2026 15:33:33 +0000 (08:33 -0700)
site/src/components/shortcodes/ButtonPlayground.astro
site/src/components/shortcodes/MenuPlacementPlayground.astro
site/src/components/shortcodes/NavbarPlacementPlayground.astro
site/src/scss/_clipboard-js.scss
site/src/scss/_component-examples.scss
site/src/scss/_masthead.scss

index 87e7e2192894c92291cf654fa2b00aaf3586adc0..e4b946f3d041a5a6e7db8cfd82704139b49c35b3 100644 (file)
@@ -156,6 +156,7 @@ const rounded = ['default', 'pill', 'square']
 
 <script>
   import { Menu } from '@bootstrap'
+  import { highlightCode } from '@libs/highlight'
 
   const colorMenuButton = document.querySelector('#btn-color-menu') as HTMLButtonElement
   const colorMenuItems = document.querySelectorAll('#btn-color-menu + .menu .menu-item')
@@ -164,11 +165,11 @@ const rounded = ['default', 'pill', 'square']
   const styleInputs = document.querySelectorAll('input[name="btn-style"]')
   const roundedInputs = document.querySelectorAll('input[name="btn-rounded"]')
   const previewButtons = document.querySelectorAll('#button-preview button')
-  // Find the code snippet inside the Example component
-  const codeSnippet = document
+  // Find the code snippet pre element inside the Example component
+  let codeSnippetPre = document
     .querySelector('#button-preview')
     ?.closest('.bd-example-snippet')
-    ?.querySelector('.highlight code') as HTMLElement
+    ?.querySelector('.astro-code') as HTMLElement | null
 
   // Get all theme color names for removal
   const themeColorNames = Array.from(colorMenuItems).map((item) => (item as HTMLElement).dataset.color || '')
@@ -202,15 +203,20 @@ const rounded = ['default', 'pill', 'square']
     return html
   }
 
-  function updateCodeSnippet() {
-    if (!codeSnippet) return
+  async function updateCodeSnippet() {
+    if (!codeSnippetPre) return
 
     const htmlSnippets = Array.from(previewButtons).map((button) => generateHTML(button as HTMLElement))
     const htmlCode = htmlSnippets.join('\n\n')
 
-    // Update the code content
-    codeSnippet.className = 'language-html'
-    codeSnippet.textContent = htmlCode
+    const highlighted = await highlightCode(htmlCode, 'html')
+    const parser = new DOMParser()
+    const doc = parser.parseFromString(highlighted, 'text/html')
+    const newPre = doc.querySelector('pre')
+    if (newPre) {
+      codeSnippetPre.replaceWith(newPre)
+      codeSnippetPre = newPre
+    }
   }
 
   function updateButtons() {
index ab408c7acea93f9f4aebe52cec678359ea813249..b0cbbaad830500414ca0ea54065c5bf5c22ab928 100644 (file)
@@ -103,13 +103,16 @@ const logicalPlacements = [
 
 <script>
   import { Menu } from '@bootstrap'
+  import { highlightCode } from '@libs/highlight'
 
   const selectorButton = document.querySelector('#menu-placement-selector') as HTMLButtonElement
   const selectorItems = document.querySelectorAll('#menu-placement-selector-menu .menu-item')
   const placementTypeInputs = document.querySelectorAll('input[name="menu-placement-type"]')
   const previewContainer = document.querySelector('#menu-placement-preview')
   const previewToggle = previewContainer?.querySelector('[data-bs-toggle="menu"]') as HTMLButtonElement
-  const codeSnippet = previewContainer?.closest('.bd-example-snippet')?.querySelector('.highlight code') as HTMLElement
+  let codeSnippetPre = previewContainer
+    ?.closest('.bd-example-snippet')
+    ?.querySelector('.astro-code') as HTMLElement | null
 
   function updateSelectorItems() {
     const selectedType =
@@ -155,8 +158,8 @@ const logicalPlacements = [
     updateCodeSnippet(placement)
   }
 
-  function updateCodeSnippet(placement: string) {
-    if (!codeSnippet) return
+  async function updateCodeSnippet(placement: string) {
+    if (!codeSnippetPre) return
 
     const htmlCode = `<button class="btn-solid theme-primary" type="button" data-bs-toggle="menu" data-bs-placement="${placement}" aria-expanded="false">
   Toggle menu
@@ -167,8 +170,14 @@ const logicalPlacements = [
   <button class="menu-item" type="button">Something else here</button>
 </div>`
 
-    codeSnippet.className = 'language-html'
-    codeSnippet.textContent = htmlCode
+    const highlighted = await highlightCode(htmlCode, 'html')
+    const parser = new DOMParser()
+    const doc = parser.parseFromString(highlighted, 'text/html')
+    const newPre = doc.querySelector('pre')
+    if (newPre) {
+      codeSnippetPre.replaceWith(newPre)
+      codeSnippetPre = newPre
+    }
   }
 
   if (selectorButton) {
index a4d05d746c15a555a9fda24c5d0c2d5bc58698c0..b6ed8e3a88480dcd256d4153fe740beb81bf72cc 100644 (file)
@@ -51,12 +51,15 @@ const placements = [
 
 <script>
   import { Menu } from '@bootstrap'
+  import { highlightCode } from '@libs/highlight'
 
   const placementMenuButton = document.querySelector('#navbar-placement-menu') as HTMLButtonElement
   const placementMenuItems = document.querySelectorAll('#navbar-placement-menu + .menu .menu-item')
   const previewContainer = document.querySelector('#navbar-placement-preview') as HTMLElement
   const previewNavbar = previewContainer?.querySelector('.navbar') as HTMLElement
-  const codeSnippet = previewContainer?.closest('.bd-example-snippet')?.querySelector('.highlight code') as HTMLElement
+  let codeSnippetPre = previewContainer
+    ?.closest('.bd-example-snippet')
+    ?.querySelector('.astro-code') as HTMLElement | null
 
   const placementClasses = ['fixed-top', 'fixed-bottom', 'sticky-top', 'sticky-bottom']
 
@@ -104,8 +107,8 @@ const placements = [
     updateCodeSnippet(placement)
   }
 
-  function updateCodeSnippet(placement: string) {
-    if (!codeSnippet) return
+  async function updateCodeSnippet(placement: string) {
+    if (!codeSnippetPre) return
 
     const placementClass = placement ? ` ${placement}` : ''
     const label = placementLabels[placement] || 'Default'
@@ -116,8 +119,14 @@ const placements = [
   </div>
 </nav>`
 
-    codeSnippet.className = 'language-html'
-    codeSnippet.textContent = htmlCode
+    const highlighted = await highlightCode(htmlCode, 'html')
+    const parser = new DOMParser()
+    const doc = parser.parseFromString(highlighted, 'text/html')
+    const newPre = doc.querySelector('pre')
+    if (newPre) {
+      codeSnippetPre.replaceWith(newPre)
+      codeSnippetPre = newPre
+    }
   }
 
   if (placementMenuButton) {
index 0f4c0914c58b16d0cb0e063b0af417c6bee881ca..600e4422c3728f51fb9be6b1aac4e63e5712dfda 100644 (file)
     display: none;
     float: inline-end;
 
-    // + .highlight {
-    //   margin-top: 0;
-    // }
-
     @include media-breakpoint-up(md) {
       display: block;
     }
index 5cb8cff0658082ba23338bf956161a14277bc10a..ec3a27b76b8d99e909fbeff172e2d8accbd31aee 100644 (file)
   // Code snippets
   //
 
-  .bd-example-snippet .highlight pre {
-    margin-inline-end: 0;
-  }
-
-
   .bd-colors-grid {
     grid-template-columns: repeat(7, 1fr);
     gap: 4px;
index cd43d2647573a87fbd9d060fda9e3fd2625e5df1..b1e4b77d02126c91069f39d1ecaa051a019408e4 100644 (file)
       color: var(--bs-fg-3);
     }
 
-    .bd-code-snippet {
-      margin: 0;
-      border-color: var(--bs-border-color-translucent);
-      border-width: 1px;
-      @include border-radius(.5rem);
-    }
-
-    .highlight {
-      width: 100%;
-      padding: .5rem 1rem;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      background-color: color-mix(in oklch, var(--bs-fg-body) #{math.percentage(.075)}, transparent);
-      @include border-radius(calc(.5rem - 1px));
-
-      @include media-breakpoint-up(lg) {
-        padding-inline-end: 4rem;
-      }
-
-      pre {
-        padding: 0;
-        margin: .625rem 0;
-        overflow: hidden;
-      }
-    }
     .btn-clipboard {
       position: absolute;
       top: -.625rem;