diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json index 074066390..da47da480 100644 --- a/.bundlewatch.config.json +++ b/.bundlewatch.config.json @@ -18,11 +18,11 @@ }, { "path": "./dist/css/bootstrap-utilities.css", - "maxSize": "7 kB" + "maxSize": "7.5 kB" }, { "path": "./dist/css/bootstrap-utilities.min.css", - "maxSize": "6.25 kB" + "maxSize": "6.75 kB" }, { "path": "./dist/css/bootstrap.css", diff --git a/.eslintrc.json b/.eslintrc.json index ec6aa589c..d5a54d46b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -43,15 +43,14 @@ ], "unicorn/consistent-function-scoping": "off", "unicorn/explicit-length-check": "off", - "unicorn/import-index": "off", - "unicorn/no-fn-reference-in-iterator": "off", + "unicorn/no-array-callback-reference": "off", "unicorn/no-for-loop": "off", "unicorn/no-null": "off", "unicorn/no-unused-properties": "error", "unicorn/no-useless-undefined": "off", - "unicorn/prefer-dataset": "off", - "unicorn/prefer-node-append": "off", - "unicorn/prefer-node-remove": "off", + "unicorn/prefer-dom-node-append": "off", + "unicorn/prefer-dom-node-dataset": "off", + "unicorn/prefer-dom-node-remove": "off", "unicorn/prefer-optional-catch-binding": "off", "unicorn/prefer-query-selector": "off", "unicorn/prevent-abbreviations": "off" diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 0913b5b5b..32b30cdb3 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -101,12 +101,12 @@ Example: Sometimes bugs reported to us are actually caused by bugs in the browser(s) themselves, not bugs in Bootstrap per se. -| Vendor(s) | Browser(s) | Rendering engine | Bug reporting website(s) | Notes | -| ------------- | ---------------------------- | ---------------- | --------------------------------------------------------------------- | -------------------------------------------------------- | -| Mozilla | Firefox | Gecko | https://bugzilla.mozilla.org/enter_bug.cgi | "Core" is normally the right product option to choose. | -| Apple | Safari | WebKit | https://bugs.webkit.org/enter_bug.cgi?product=WebKit | In Apple's bug reporter, choose "Safari" as the product. | -| Google, Opera | Chrome, Chromium, Opera v15+ | Blink | https://bugs.chromium.org/p/chromium/issues/list | Click the "New issue" button. | -| Microsoft | Edge | Blink | https://developer.microsoft.com/en-us/microsoft-edge/ | Go to "Help > Send Feedback" from the browser | +| Vendor(s) | Browser(s) | Rendering engine | Bug reporting website(s) | Notes | +| ------------- | ---------------------------- | ---------------- | ------------------------------------------------------ | -------------------------------------------------------- | +| Mozilla | Firefox | Gecko | https://bugzilla.mozilla.org/enter_bug.cgi | "Core" is normally the right product option to choose. | +| Apple | Safari | WebKit | https://bugs.webkit.org/enter_bug.cgi?product=WebKit | In Apple's bug reporter, choose "Safari" as the product. | +| Google, Opera | Chrome, Chromium, Opera v15+ | Blink | https://bugs.chromium.org/p/chromium/issues/list | Click the "New issue" button. | +| Microsoft | Edge | Blink | https://developer.microsoft.com/en-us/microsoft-edge/ | Go to "Help > Send Feedback" from the browser | ## Feature requests @@ -134,9 +134,9 @@ Please adhere to the [coding guidelines](#code-guidelines) used throughout the project (indentation, accurate comments, etc.) and any other requirements (such as test coverage). -**Do not edit `bootstrap.css`, or `bootstrap.js` -directly!** Those files are automatically generated. You should edit the -source files in [`/bootstrap/scss/`](https://github.com/twbs/bootstrap/tree/main/scss) +**Do not edit `bootstrap.css` or `bootstrap.js`, and do not commit +any dist files (`dist/` or `js/dist`).** Those files are automatically generated by our build tools. You should +edit the source files in [`/bootstrap/scss/`](https://github.com/twbs/bootstrap/tree/main/scss) and/or [`/bootstrap/js/src/`](https://github.com/twbs/bootstrap/tree/main/js/src) instead. Similarly, when contributing to Bootstrap's documentation, you should edit the diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 31976021e..29135b400 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -15,3 +15,10 @@ updates: - v5 versioning-strategy: increase rebase-strategy: disabled + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + day: tuesday + time: "12:00" + timezone: Europe/Athens diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index ae1367c89..e2b70e03e 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -4,6 +4,9 @@ prerelease: true exclude-labels: - 'skip-changelog' categories: + - title: '❗ Breaking Changes' + labels: + - 'breaking-change' - title: '🚀 Features' labels: - 'new-feature' @@ -14,6 +17,9 @@ categories: - 'fix' - 'bugfix' - 'bug' + - title: '⚡ Performance Improvements' + labels: + - 'performance' - title: '🎨 CSS' labels: - 'css' @@ -26,11 +32,19 @@ categories: - title: '🌎 Accessibility' labels: - 'accessibility' + - title: '🔧 Utility API' + labels: + - 'utility API' + - 'utilities' + - title: '🏭 Tests' + labels: + - 'tests' - title: '🧰 Misc' labels: - 'build' - 'meta' - 'chore' + - 'CI' - title: '📦 Dependencies' labels: - 'dependencies' diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml index 0b4cfbdaa..a12bffcf7 100644 --- a/.github/workflows/browserstack.yml +++ b/.github/workflows/browserstack.yml @@ -4,21 +4,21 @@ on: push: env: - CI: true FORCE_COLOR: 2 - NODE: 14.x + NODE: 14 jobs: browserstack: runs-on: ubuntu-latest if: github.repository == 'twbs/bootstrap' && (!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')) + timeout-minutes: 30 steps: - name: Clone repository uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: "${{ env.NODE }}" @@ -28,8 +28,8 @@ jobs: path: ~/.npm key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} restore-keys: | - ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} - ${{ runner.OS }}-node-v${{ env.NODE }}- + ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} + ${{ runner.os }}-node-v${{ env.NODE }}- - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/bundlewatch.yml b/.github/workflows/bundlewatch.yml index 966dfbf72..b2bd5eed5 100644 --- a/.github/workflows/bundlewatch.yml +++ b/.github/workflows/bundlewatch.yml @@ -7,9 +7,8 @@ on: pull_request: env: - CI: true FORCE_COLOR: 2 - NODE: 14.x + NODE: 14 jobs: bundlewatch: @@ -20,7 +19,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: "${{ env.NODE }}" @@ -30,8 +29,8 @@ jobs: path: ~/.npm key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} restore-keys: | - ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} - ${{ runner.OS }}-node-v${{ env.NODE }}- + ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} + ${{ runner.os }}-node-v${{ env.NODE }}- - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index f9dccfce0..469a5a4fc 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,15 +22,6 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 - - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/css.yml b/.github/workflows/css.yml index a75f018c5..a28059d79 100644 --- a/.github/workflows/css.yml +++ b/.github/workflows/css.yml @@ -7,9 +7,8 @@ on: pull_request: env: - CI: true FORCE_COLOR: 2 - NODE: 14.x + NODE: 14 jobs: css: @@ -20,7 +19,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: "${{ env.NODE }}" @@ -30,8 +29,8 @@ jobs: path: ~/.npm key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} restore-keys: | - ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} - ${{ runner.OS }}-node-v${{ env.NODE }}- + ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} + ${{ runner.os }}-node-v${{ env.NODE }}- - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 58b55fc7c..150e4d16c 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,9 +7,8 @@ on: pull_request: env: - CI: true FORCE_COLOR: 2 - NODE: 14.x + NODE: 14 jobs: docs: @@ -20,7 +19,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: "${{ env.NODE }}" @@ -32,8 +31,8 @@ jobs: path: ~/.npm key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} restore-keys: | - ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} - ${{ runner.OS }}-node-v${{ env.NODE }}- + ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} + ${{ runner.os }}-node-v${{ env.NODE }}- - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/js.yml b/.github/workflows/js.yml index 1ec0d6909..c56a2dfdd 100644 --- a/.github/workflows/js.yml +++ b/.github/workflows/js.yml @@ -7,7 +7,6 @@ on: pull_request: env: - CI: true FORCE_COLOR: 2 jobs: @@ -25,7 +24,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} @@ -35,8 +34,8 @@ jobs: path: ~/.npm key: ${{ runner.os }}-node-v${{ matrix.node }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }}} restore-keys: | - ${{ runner.OS }}-node-v${{ matrix.node }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} - ${{ runner.OS }}-node-v${{ matrix.node }}- + ${{ runner.os }}-node-v${{ matrix.node }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} + ${{ runner.os }}-node-v${{ matrix.node }}- - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e850a1f1b..369aaced3 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -7,9 +7,8 @@ on: pull_request: env: - CI: true FORCE_COLOR: 2 - NODE: 14.x + NODE: 14 jobs: lint: @@ -20,7 +19,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: "${{ env.NODE }}" @@ -30,8 +29,8 @@ jobs: path: ~/.npm key: ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} restore-keys: | - ${{ runner.OS }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} - ${{ runner.OS }}-node-v${{ env.NODE }}- + ${{ runner.os }}-node-v${{ env.NODE }}-${{ hashFiles('package.json') }}-${{ hashFiles('package-lock.json') }} + ${{ runner.os }}-node-v${{ env.NODE }}- - name: Install npm dependencies run: npm ci diff --git a/.github/workflows/node-sass.yml b/.github/workflows/node-sass.yml index 2db55f0ff..ee64b2152 100644 --- a/.github/workflows/node-sass.yml +++ b/.github/workflows/node-sass.yml @@ -7,9 +7,8 @@ on: pull_request: env: - CI: true FORCE_COLOR: 2 - NODE: 14.x + NODE: 14 jobs: css: @@ -20,7 +19,7 @@ jobs: uses: actions/checkout@v2 - name: Set up Node.js - uses: actions/setup-node@v1 + uses: actions/setup-node@v2 with: node-version: "${{ env.NODE }}" diff --git a/.gitignore b/.gitignore index 6208c57d7..0a0f88d15 100644 --- a/.gitignore +++ b/.gitignore @@ -1,19 +1,8 @@ # Ignore docs files /_gh_pages/ -# This is the old Jekyll docs dist folder; -# keeping it here so that when we switch branches it doesn't show up -/site/docs/**/dist/ -# Jekyll's cache folder; keeping it for the same reason as above -/site/.jekyll-cache/ # Hugo resources folder /resources/ -# Ignore ruby/bundler files; -# keeping them here so that when we switch branches they don't show up -/.bundle/ -/vendor/ -/.ruby-version - # Numerous always-ignore extensions *.diff *.err diff --git a/.stylelintrc b/.stylelintrc index 1c9ee1811..c068d30b5 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -3,6 +3,10 @@ "stylelint-config-twbs-bootstrap/scss" ], "rules": { + "declaration-property-value-disallowed-list": { + "border": "none", + "outline": "none" + }, "function-disallowed-list": [ "calc", "lighten", diff --git a/LICENSE b/LICENSE index 173a9ebbb..72dda234e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The MIT License (MIT) -Copyright (c) 2011-2020 Twitter, Inc. -Copyright (c) 2011-2020 The Bootstrap Authors +Copyright (c) 2011-2021 Twitter, Inc. +Copyright (c) 2011-2021 The Bootstrap Authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8a470260a..f41498691 100644 --- a/README.md +++ b/README.md @@ -236,4 +236,4 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com ## Copyright and license -Code and documentation copyright 2011–2020 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/). +Code and documentation copyright 2011–2021 the [Bootstrap Authors](https://github.com/twbs/bootstrap/graphs/contributors) and [Twitter, Inc.](https://twitter.com) Code released under the [MIT License](https://github.com/twbs/bootstrap/blob/main/LICENSE). Docs released under [Creative Commons](https://creativecommons.org/licenses/by/3.0/). diff --git a/build/build-plugins.js b/build/build-plugins.js index ea7477390..d1930b855 100644 --- a/build/build-plugins.js +++ b/build/build-plugins.js @@ -2,8 +2,8 @@ /*! * Script to build our plugins to use them separately. - * Copyright 2020 The Bootstrap Authors - * Copyright 2020 Twitter, Inc. + * Copyright 2020-2021 The Bootstrap Authors + * Copyright 2020-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ @@ -29,6 +29,7 @@ const bsPlugins = { Manipulator: path.resolve(__dirname, '../js/src/dom/manipulator.js'), SelectorEngine: path.resolve(__dirname, '../js/src/dom/selector-engine.js'), Alert: path.resolve(__dirname, '../js/src/alert.js'), + Base: path.resolve(__dirname, '../js/src/base-component.js'), Button: path.resolve(__dirname, '../js/src/button.js'), Carousel: path.resolve(__dirname, '../js/src/carousel.js'), Collapse: path.resolve(__dirname, '../js/src/collapse.js'), @@ -44,11 +45,13 @@ const bsPlugins = { const defaultPluginConfig = { external: [ bsPlugins.Data, + bsPlugins.Base, bsPlugins.EventHandler, bsPlugins.SelectorEngine ], globals: { [bsPlugins.Data]: 'Data', + [bsPlugins.Base]: 'Base', [bsPlugins.EventHandler]: 'EventHandler', [bsPlugins.SelectorEngine]: 'SelectorEngine' } @@ -73,6 +76,7 @@ const getConfigByPluginKey = pluginKey => { } if ( + pluginKey === 'Base' || pluginKey === 'Button' || pluginKey === 'Carousel' || pluginKey === 'Collapse' || @@ -112,11 +116,13 @@ const getConfigByPluginKey = pluginKey => { return { external: [ bsPlugins.Data, + bsPlugins.Base, bsPlugins.EventHandler, bsPlugins.Manipulator ], globals: { [bsPlugins.Data]: 'Data', + [bsPlugins.Base]: 'Base', [bsPlugins.EventHandler]: 'EventHandler', [bsPlugins.Manipulator]: 'Manipulator' } diff --git a/build/change-version.js b/build/change-version.js index b8a640fa8..8086ed774 100644 --- a/build/change-version.js +++ b/build/change-version.js @@ -2,8 +2,8 @@ /*! * Script to update version number references in the project. - * Copyright 2017-2020 The Bootstrap Authors - * Copyright 2017-2020 Twitter, Inc. + * Copyright 2017-2021 The Bootstrap Authors + * Copyright 2017-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ diff --git a/build/generate-sri.js b/build/generate-sri.js index 8a2e59360..221873b8f 100644 --- a/build/generate-sri.js +++ b/build/generate-sri.js @@ -5,8 +5,8 @@ * Remember to use the same vendor files as the CDN ones, * otherwise the hashes won't match! * - * Copyright 2017-2020 The Bootstrap Authors - * Copyright 2017-2020 Twitter, Inc. + * Copyright 2017-2021 The Bootstrap Authors + * Copyright 2017-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ diff --git a/build/vnu-jar.js b/build/vnu-jar.js index 90c1a12ab..c23b94d60 100644 --- a/build/vnu-jar.js +++ b/build/vnu-jar.js @@ -2,8 +2,8 @@ /*! * Script to run vnu-jar if Java is available. - * Copyright 2017-2020 The Bootstrap Authors - * Copyright 2017-2020 Twitter, Inc. + * Copyright 2017-2021 The Bootstrap Authors + * Copyright 2017-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ diff --git a/build/zip-examples.js b/build/zip-examples.js index bf50a0af6..b2f156502 100644 --- a/build/zip-examples.js +++ b/build/zip-examples.js @@ -3,7 +3,7 @@ /*! * Script to create the built examples zip archive; * requires the `zip` command to be present! - * Copyright 2020 The Bootstrap Authors + * Copyright 2020-2021 The Bootstrap Authors * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ @@ -12,36 +12,67 @@ const path = require('path') const sh = require('shelljs') -const { version, version_short: versionShort } = require('../package.json') +const pkg = require('../package.json') -const folderName = `bootstrap-${version}-examples` +const versionShort = pkg.config.version_short +const distFolder = `bootstrap-${pkg.version}-examples` +const rootDocsDir = '_gh_pages' +const docsDir = `${rootDocsDir}/docs/${versionShort}/` + +// these are the files we need in the examples +const cssFiles = [ + 'bootstrap.min.css', + 'bootstrap.min.css.map', + 'bootstrap.rtl.min.css', + 'bootstrap.rtl.min.css.map' +] +const jsFiles = [ + 'bootstrap.bundle.min.js', + 'bootstrap.bundle.min.js.map' +] +const imgFiles = [ + 'bootstrap-logo.svg', + 'bootstrap-logo-white.svg' +] sh.config.fatal = true -if (!sh.test('-d', '_gh_pages')) { - throw new Error('The "_gh_pages" folder does not exist, did you forget building the docs?') +if (!sh.test('-d', rootDocsDir)) { + throw new Error(`The "${rootDocsDir}" folder does not exist, did you forget building the docs?`) } // switch to the root dir sh.cd(path.join(__dirname, '..')) -// remove any previously created folder with the same name -sh.rm('-rf', folderName) -// create any folders so that `cp` works -sh.mkdir('-p', folderName) -sh.mkdir('-p', `${folderName}/assets/brand/`) +// remove any previously created folder/zip with the same name +sh.rm('-rf', [distFolder, `${distFolder}.zip`]) -sh.cp('-Rf', `_gh_pages/docs/${versionShort}/examples/*`, folderName) -sh.cp('-Rf', `_gh_pages/docs/${versionShort}/dist/`, `${folderName}/assets/`) -// also copy the two brand images we use in the examples -sh.cp('-f', [ - `_gh_pages/docs/${versionShort}/assets/brand/bootstrap-logo.svg`, - `_gh_pages/docs/${versionShort}/assets/brand/bootstrap-logo-white.svg` -], `${folderName}/assets/brand/`) -sh.rm(`${folderName}/index.html`) +// create any folders so that `cp` works +sh.mkdir('-p', [ + distFolder, + `${distFolder}/assets/brand/`, + `${distFolder}/assets/dist/css/`, + `${distFolder}/assets/dist/js/` +]) + +sh.cp('-Rf', `${docsDir}/examples/*`, distFolder) + +cssFiles.forEach(file => { + sh.cp('-f', `${docsDir}/dist/css/${file}`, `${distFolder}/assets/dist/css/`) +}) + +jsFiles.forEach(file => { + sh.cp('-f', `${docsDir}/dist/js/${file}`, `${distFolder}/assets/dist/js/`) +}) + +imgFiles.forEach(file => { + sh.cp('-f', `${docsDir}/assets/brand/${file}`, `${distFolder}/assets/brand/`) +}) + +sh.rm(`${distFolder}/index.html`) // get all examples' HTML files -sh.find(`${folderName}/**/*.html`).forEach(file => { +sh.find(`${distFolder}/**/*.html`).forEach(file => { const fileContents = sh.cat(file) .toString() .replace(new RegExp(`"/docs/${versionShort}/`, 'g'), '"../') @@ -53,7 +84,7 @@ sh.find(`${folderName}/**/*.html`).forEach(file => { }) // create the zip file -sh.exec(`zip -r9 "${folderName}.zip" "${folderName}"`, { fatal: true }) +sh.exec(`zip -r9 "${distFolder}.zip" "${distFolder}"`) // remove the folder we created -sh.rm('-rf', folderName) +sh.rm('-rf', distFolder) diff --git a/config.yml b/config.yml index c9e203164..a54d5bc6c 100644 --- a/config.yml +++ b/config.yml @@ -20,18 +20,6 @@ enableRobotsTXT: true metaDataFormat: "yaml" disableKinds: ["404", "taxonomy", "taxonomyTerm", "RSS"] -outputFormats: - OpenSearch: - baseName: opensearch - isPlainText: true - mediaType: application/xml - notAlternative: true - -outputs: - home: - - HTML - - OpenSearch - publishDir: "_gh_pages" module: @@ -87,5 +75,5 @@ params: js_hash: "sha384-pQQkAEnwaBkjpqZ8RU1fF1AKtTcHJwFl3pblpTlHXybJjHpMYo79HY3hIi4NKxyj" js_bundle: "https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" js_bundle_hash: "sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" - popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js" - popper_hash: "sha384-q2kxQ16AaE6UbzuKqyBE9/u/KzioAlnx2maXQHiDX9d4/zp8Ok3f+M7DPm+Ib6IU" + popper: "https://cdn.jsdelivr.net/npm/@popperjs/core@2.6.0/dist/umd/popper.min.js" + popper_hash: "sha384-KsvD1yqQ1/1+IA7gi3P0tyJcT3vR+NdBTt13hSJ2lnve8agRGXTTyNaBYmCR/Nwi" diff --git a/js/src/alert.js b/js/src/alert.js index e498d0324..96eda4c5f 100644 --- a/js/src/alert.js +++ b/js/src/alert.js @@ -7,7 +7,6 @@ import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, getElementFromSelector, getTransitionDurationFromElement @@ -33,9 +32,9 @@ const EVENT_CLOSE = `close${EVENT_KEY}` const EVENT_CLOSED = `closed${EVENT_KEY}` const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}` -const CLASSNAME_ALERT = 'alert' -const CLASSNAME_FADE = 'fade' -const CLASSNAME_SHOW = 'show' +const CLASS_NAME_ALERT = 'alert' +const CLASS_NAME_FADE = 'fade' +const CLASS_NAME_SHOW = 'show' /** * ------------------------------------------------------------------------ @@ -66,7 +65,7 @@ class Alert extends BaseComponent { // Private _getRootElement(element) { - return getElementFromSelector(element) || element.closest(`.${CLASSNAME_ALERT}`) + return getElementFromSelector(element) || element.closest(`.${CLASS_NAME_ALERT}`) } _triggerCloseEvent(element) { @@ -74,16 +73,16 @@ class Alert extends BaseComponent { } _removeElement(element) { - element.classList.remove(CLASSNAME_SHOW) + element.classList.remove(CLASS_NAME_SHOW) - if (!element.classList.contains(CLASSNAME_FADE)) { + if (!element.classList.contains(CLASS_NAME_FADE)) { this._destroyElement(element) return } const transitionDuration = getTransitionDurationFromElement(element) - EventHandler.one(element, TRANSITION_END, () => this._destroyElement(element)) + EventHandler.one(element, 'transitionend', () => this._destroyElement(element)) emulateTransitionEnd(element, transitionDuration) } diff --git a/js/src/carousel.js b/js/src/carousel.js index 299aadeda..06a391419 100644 --- a/js/src/carousel.js +++ b/js/src/carousel.js @@ -7,11 +7,11 @@ import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, getElementFromSelector, getTransitionDurationFromElement, isVisible, + isRTL, reflow, triggerTransitionEnd, typeCheckConfig @@ -93,10 +93,8 @@ const SELECTOR_INDICATORS = '.carousel-indicators' const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]' const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]' -const PointerType = { - TOUCH: 'touch', - PEN: 'pen' -} +const POINTER_TYPE_TOUCH = 'touch' +const POINTER_TYPE_PEN = 'pen' /** * ------------------------------------------------------------------------ @@ -253,12 +251,20 @@ class Carousel extends BaseComponent { // swipe left if (direction > 0) { - this.prev() + if (isRTL) { + this.next() + } else { + this.prev() + } } // swipe right if (direction < 0) { - this.next() + if (isRTL) { + this.prev() + } else { + this.next() + } } } @@ -279,7 +285,7 @@ class Carousel extends BaseComponent { _addTouchEventListeners() { const start = event => { - if (this._pointerEvent && PointerType[event.pointerType.toUpperCase()]) { + if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) { this.touchStartX = event.clientX } else if (!this._pointerEvent) { this.touchStartX = event.touches[0].clientX @@ -296,7 +302,7 @@ class Carousel extends BaseComponent { } const end = event => { - if (this._pointerEvent && PointerType[event.pointerType.toUpperCase()]) { + if (this._pointerEvent && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH)) { this.touchDeltaX = event.clientX - this.touchStartX } @@ -340,16 +346,20 @@ class Carousel extends BaseComponent { return } - switch (event.key) { - case ARROW_LEFT_KEY: - event.preventDefault() - this.prev() - break - case ARROW_RIGHT_KEY: - event.preventDefault() + if (event.key === ARROW_LEFT_KEY) { + event.preventDefault() + if (isRTL) { this.next() - break - default: + } else { + this.prev() + } + } else if (event.key === ARROW_RIGHT_KEY) { + event.preventDefault() + if (isRTL) { + this.prev() + } else { + this.next() + } } } @@ -436,19 +446,9 @@ class Carousel extends BaseComponent { const nextElementIndex = this._getItemIndex(nextElement) const isCycling = Boolean(this._interval) - let directionalClassName - let orderClassName - let eventDirectionName - - if (direction === DIRECTION_NEXT) { - directionalClassName = CLASS_NAME_START - orderClassName = CLASS_NAME_NEXT - eventDirectionName = DIRECTION_LEFT - } else { - directionalClassName = CLASS_NAME_END - orderClassName = CLASS_NAME_PREV - eventDirectionName = DIRECTION_RIGHT - } + const directionalClassName = direction === DIRECTION_NEXT ? CLASS_NAME_START : CLASS_NAME_END + const orderClassName = direction === DIRECTION_NEXT ? CLASS_NAME_NEXT : CLASS_NAME_PREV + const eventDirectionName = direction === DIRECTION_NEXT ? DIRECTION_LEFT : DIRECTION_RIGHT if (nextElement && nextElement.classList.contains(CLASS_NAME_ACTIVE)) { this._isSliding = false @@ -484,7 +484,7 @@ class Carousel extends BaseComponent { const transitionDuration = getTransitionDurationFromElement(activeElement) - EventHandler.one(activeElement, TRANSITION_END, () => { + EventHandler.one(activeElement, 'transitionend', () => { nextElement.classList.remove(directionalClassName, orderClassName) nextElement.classList.add(CLASS_NAME_ACTIVE) diff --git a/js/src/collapse.js b/js/src/collapse.js index 590615b72..0d3eeed54 100644 --- a/js/src/collapse.js +++ b/js/src/collapse.js @@ -7,7 +7,6 @@ import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, getSelectorFromElement, getElementFromSelector, @@ -203,7 +202,7 @@ class Collapse extends BaseComponent { const scrollSize = `scroll${capitalizedDimension}` const transitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, complete) + EventHandler.one(this._element, 'transitionend', complete) emulateTransitionEnd(this._element, transitionDuration) this._element.style[dimension] = `${this._element[scrollSize]}px` @@ -253,7 +252,7 @@ class Collapse extends BaseComponent { this._element.style[dimension] = '' const transitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, complete) + EventHandler.one(this._element, 'transitionend', complete) emulateTransitionEnd(this._element, transitionDuration) } @@ -372,7 +371,7 @@ class Collapse extends BaseComponent { EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function (event) { // preventDefault only for elements (which change the URL) not inside the collapsible element - if (event.target.tagName === 'A') { + if (event.target.tagName === 'A' || (event.delegateTarget && event.delegateTarget.tagName === 'A')) { event.preventDefault() } diff --git a/js/src/dom/event-handler.js b/js/src/dom/event-handler.js index 2ee13bafc..e3c685530 100644 --- a/js/src/dom/event-handler.js +++ b/js/src/dom/event-handler.js @@ -112,6 +112,7 @@ function bootstrapDelegationHandler(element, selector, fn) { event.delegateTarget = target if (handler.oneOff) { + // eslint-disable-next-line unicorn/consistent-destructuring EventHandler.off(element, event.type, fn) } diff --git a/js/src/dom/selector-engine.js b/js/src/dom/selector-engine.js index 727df7518..28287388e 100644 --- a/js/src/dom/selector-engine.js +++ b/js/src/dom/selector-engine.js @@ -23,9 +23,8 @@ const SelectorEngine = { }, children(element, selector) { - const children = [].concat(...element.children) - - return children.filter(child => child.matches(selector)) + return [].concat(...element.children) + .filter(child => child.matches(selector)) }, parents(element, selector) { diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 4720ed1ab..bada537c9 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -84,7 +84,7 @@ const DefaultType = { offset: '(number|string|function)', flip: 'boolean', boundary: '(string|element)', - reference: '(string|element)', + reference: '(string|element|object)', display: 'string', popperConfig: '(null|object)' } @@ -172,6 +172,8 @@ class Dropdown extends BaseComponent { if (typeof this._config.reference.jquery !== 'undefined') { referenceElement = this._config.reference[0] } + } else if (typeof this._config.reference === 'object') { + referenceElement = this._config.reference } this._popper = Popper.createPopper(referenceElement, this._menu, this._getPopperConfig()) @@ -257,6 +259,13 @@ class Dropdown extends BaseComponent { typeCheckConfig(NAME, config, this.constructor.DefaultType) + if (typeof config.reference === 'object' && !isElement(config.reference) && + typeof config.reference.getBoundingClientRect !== 'function' + ) { + // Popper virtual elements require a getBoundingClientRect method + throw new TypeError(`${NAME.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`) + } + return config } @@ -298,6 +307,12 @@ class Dropdown extends BaseComponent { altBoundary: this._config.flip, rootBoundary: this._config.boundary } + }, + { + name: 'flip', + options: { + fallbackPlacements: ['top', 'right', 'bottom', 'left'] + } }] } diff --git a/js/src/modal.js b/js/src/modal.js index 20fb215c6..fe1b5a4c6 100644 --- a/js/src/modal.js +++ b/js/src/modal.js @@ -7,7 +7,6 @@ import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, getElementFromSelector, getTransitionDurationFromElement, @@ -184,7 +183,7 @@ class Modal extends BaseComponent { if (transition) { const transitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, event => this._hideModal(event)) + EventHandler.one(this._element, 'transitionend', event => this._hideModal(event)) emulateTransitionEnd(this._element, transitionDuration) } else { this._hideModal() @@ -272,7 +271,7 @@ class Modal extends BaseComponent { if (transition) { const transitionDuration = getTransitionDurationFromElement(this._dialog) - EventHandler.one(this._dialog, TRANSITION_END, transitionComplete) + EventHandler.one(this._dialog, 'transitionend', transitionComplete) emulateTransitionEnd(this._dialog, transitionDuration) } else { transitionComplete() @@ -377,7 +376,7 @@ class Modal extends BaseComponent { const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop) - EventHandler.one(this._backdrop, TRANSITION_END, callback) + EventHandler.one(this._backdrop, 'transitionend', callback) emulateTransitionEnd(this._backdrop, backdropTransitionDuration) } else if (!this._isShown && this._backdrop) { this._backdrop.classList.remove(CLASS_NAME_SHOW) @@ -389,7 +388,7 @@ class Modal extends BaseComponent { if (this._element.classList.contains(CLASS_NAME_FADE)) { const backdropTransitionDuration = getTransitionDurationFromElement(this._backdrop) - EventHandler.one(this._backdrop, TRANSITION_END, callbackRemove) + EventHandler.one(this._backdrop, 'transitionend', callbackRemove) emulateTransitionEnd(this._backdrop, backdropTransitionDuration) } else { callbackRemove() @@ -413,11 +412,11 @@ class Modal extends BaseComponent { this._element.classList.add(CLASS_NAME_STATIC) const modalTransitionDuration = getTransitionDurationFromElement(this._dialog) - EventHandler.off(this._element, TRANSITION_END) - EventHandler.one(this._element, TRANSITION_END, () => { + EventHandler.off(this._element, 'transitionend') + EventHandler.one(this._element, 'transitionend', () => { this._element.classList.remove(CLASS_NAME_STATIC) if (!isModalOverflowing) { - EventHandler.one(this._element, TRANSITION_END, () => { + EventHandler.one(this._element, 'transitionend', () => { this._element.style.overflowY = '' }) emulateTransitionEnd(this._element, modalTransitionDuration) @@ -591,7 +590,7 @@ EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function ( data = new Modal(target, config) } - data.show(this) + data.toggle(this) }) /** diff --git a/js/src/scrollspy.js b/js/src/scrollspy.js index a8770ef08..baea49443 100644 --- a/js/src/scrollspy.js +++ b/js/src/scrollspy.js @@ -76,7 +76,7 @@ class ScrollSpy extends BaseComponent { this._activeTarget = null this._scrollHeight = 0 - EventHandler.on(this._scrollElement, EVENT_SCROLL, event => this._process(event)) + EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process()) this.refresh() this._process() diff --git a/js/src/tab.js b/js/src/tab.js index 3a48986c4..f1b17ac79 100644 --- a/js/src/tab.js +++ b/js/src/tab.js @@ -7,7 +7,6 @@ import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, getElementFromSelector, getTransitionDurationFromElement, @@ -82,13 +81,11 @@ class Tab extends BaseComponent { previous = previous[previous.length - 1] } - let hideEvent = null - - if (previous) { - hideEvent = EventHandler.trigger(previous, EVENT_HIDE, { + const hideEvent = previous ? + EventHandler.trigger(previous, EVENT_HIDE, { relatedTarget: this._element - }) - } + }) : + null const showEvent = EventHandler.trigger(this._element, EVENT_SHOW, { relatedTarget: previous @@ -132,7 +129,7 @@ class Tab extends BaseComponent { const transitionDuration = getTransitionDurationFromElement(active) active.classList.remove(CLASS_NAME_SHOW) - EventHandler.one(active, TRANSITION_END, complete) + EventHandler.one(active, 'transitionend', complete) emulateTransitionEnd(active, transitionDuration) } else { complete() diff --git a/js/src/toast.js b/js/src/toast.js index bda152af6..e277cdc06 100644 --- a/js/src/toast.js +++ b/js/src/toast.js @@ -7,7 +7,6 @@ import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, getTransitionDurationFromElement, reflow, @@ -116,7 +115,7 @@ class Toast extends BaseComponent { if (this._config.animation) { const transitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, complete) + EventHandler.one(this._element, 'transitionend', complete) emulateTransitionEnd(this._element, transitionDuration) } else { complete() @@ -143,7 +142,7 @@ class Toast extends BaseComponent { if (this._config.animation) { const transitionDuration = getTransitionDurationFromElement(this._element) - EventHandler.one(this._element, TRANSITION_END, complete) + EventHandler.one(this._element, 'transitionend', complete) emulateTransitionEnd(this._element, transitionDuration) } else { complete() diff --git a/js/src/tooltip.js b/js/src/tooltip.js index df0f0c19c..63a30cf2f 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -9,7 +9,6 @@ import * as Popper from '@popperjs/core' import { defineJQueryPlugin, - TRANSITION_END, emulateTransitionEnd, findShadowRoot, getTransitionDurationFromElement, @@ -52,7 +51,7 @@ const DefaultType = { selector: '(string|boolean)', placement: '(string|function)', container: '(string|element|boolean)', - fallbackPlacements: '(null|array)', + fallbackPlacements: 'array', boundary: '(string|element)', customClass: '(string|function)', sanitize: 'boolean', @@ -82,7 +81,7 @@ const Default = { selector: false, placement: 'top', container: false, - fallbackPlacements: null, + fallbackPlacements: ['top', 'right', 'bottom', 'left'], boundary: 'clippingParents', customClass: '', sanitize: true, @@ -223,7 +222,7 @@ class Tooltip extends BaseComponent { EventHandler.off(this._element, this.constructor.EVENT_KEY) EventHandler.off(this._element.closest(`.${CLASS_NAME_MODAL}`), 'hide.bs.modal', this._hideModalHandler) - if (this.tip) { + if (this.tip && this.tip.parentNode) { this.tip.parentNode.removeChild(this.tip) } @@ -317,7 +316,7 @@ class Tooltip extends BaseComponent { if (this.tip.classList.contains(CLASS_NAME_FADE)) { const transitionDuration = getTransitionDurationFromElement(this.tip) - EventHandler.one(this.tip, TRANSITION_END, complete) + EventHandler.one(this.tip, 'transitionend', complete) emulateTransitionEnd(this.tip, transitionDuration) } else { complete() @@ -367,7 +366,7 @@ class Tooltip extends BaseComponent { if (this.tip.classList.contains(CLASS_NAME_FADE)) { const transitionDuration = getTransitionDurationFromElement(tip) - EventHandler.one(tip, TRANSITION_END, complete) + EventHandler.one(tip, 'transitionend', complete) emulateTransitionEnd(tip, transitionDuration) } else { complete() @@ -467,21 +466,16 @@ class Tooltip extends BaseComponent { // Private _getPopperConfig(attachment) { - const flipModifier = { - name: 'flip', - options: { - altBoundary: true - } - } - - if (this.config.fallbackPlacements) { - flipModifier.options.fallbackPlacements = this.config.fallbackPlacements - } - const defaultBsConfig = { placement: attachment, modifiers: [ - flipModifier, + { + name: 'flip', + options: { + altBoundary: true, + fallbackPlacements: this.config.fallbackPlacements + } + }, { name: 'preventOverflow', options: { diff --git a/js/src/util/index.js b/js/src/util/index.js index 1bf9fe954..22d0a578b 100644 --- a/js/src/util/index.js +++ b/js/src/util/index.js @@ -111,15 +111,14 @@ const typeCheckConfig = (componentName, config, configTypes) => { Object.keys(configTypes).forEach(property => { const expectedTypes = configTypes[property] const value = config[property] - const valueType = value && isElement(value) ? - 'element' : - toType(value) + const valueType = value && isElement(value) ? 'element' : toType(value) if (!new RegExp(expectedTypes).test(valueType)) { - throw new Error( + throw new TypeError( `${componentName.toUpperCase()}: ` + `Option "${property}" provided type "${valueType}" ` + - `but expected type "${expectedTypes}".`) + `but expected type "${expectedTypes}".` + ) } }) } @@ -205,7 +204,6 @@ const defineJQueryPlugin = (name, plugin) => { } export { - TRANSITION_END, getUID, getSelectorFromElement, getElementFromSelector, diff --git a/js/src/util/sanitizer.js b/js/src/util/sanitizer.js index d908dd661..ce3d455a6 100644 --- a/js/src/util/sanitizer.js +++ b/js/src/util/sanitizer.js @@ -37,7 +37,7 @@ const allowedAttribute = (attr, allowedAttributeList) => { if (allowedAttributeList.includes(attrName)) { if (uriAttrs.has(attrName)) { - return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) + return Boolean(SAFE_URL_PATTERN.test(attr.nodeValue) || DATA_URL_PATTERN.test(attr.nodeValue)) } return true @@ -47,7 +47,7 @@ const allowedAttribute = (attr, allowedAttributeList) => { // Check if a regular expression validates the attribute. for (let i = 0, len = regExp.length; i < len; i++) { - if (attrName.match(regExp[i])) { + if (regExp[i].test(attrName)) { return true } } diff --git a/js/tests/browsers.js b/js/tests/browsers.js index 8df94cc53..2e1bd3a80 100644 --- a/js/tests/browsers.js +++ b/js/tests/browsers.js @@ -5,21 +5,21 @@ const browsers = { safariMac: { base: 'BrowserStack', os: 'OS X', - os_version: 'High Sierra', + os_version: 'Catalina', browser: 'Safari', browser_version: 'latest' }, chromeMac: { base: 'BrowserStack', os: 'OS X', - os_version: 'High Sierra', + os_version: 'Catalina', browser: 'Chrome', browser_version: 'latest' }, firefoxMac: { base: 'BrowserStack', os: 'OS X', - os_version: 'High Sierra', + os_version: 'Catalina', browser: 'Firefox', browser_version: 'latest' }, diff --git a/js/tests/karma.conf.js b/js/tests/karma.conf.js index d0dd8bdd9..cd4946525 100644 --- a/js/tests/karma.conf.js +++ b/js/tests/karma.conf.js @@ -1,5 +1,7 @@ /* eslint-env node */ +'use strict' + const path = require('path') const ip = require('ip') const { babel } = require('@rollup/plugin-babel') @@ -12,10 +14,11 @@ const { browsersKeys } = require('./browsers') -const { env } = process -const browserStack = env.BROWSER === 'true' -const debug = env.DEBUG === 'true' -const jQueryTest = env.JQUERY === 'true' +const ENV = process.env +const BROWSERSTACK = Boolean(ENV.BROWSERSTACK) +const DEBUG = Boolean(ENV.DEBUG) +const JQUERY_TEST = Boolean(ENV.JQUERY) + const frameworks = [ 'jasmine' ] @@ -30,16 +33,16 @@ const reporters = ['dots'] const detectBrowsers = { usePhantomJS: false, postDetection(availableBrowser) { - if (env.CI === true || availableBrowser.includes('Chrome')) { - return debug ? ['Chrome'] : ['ChromeHeadless'] + if (ENV.CI === true || availableBrowser.includes('Chrome')) { + return DEBUG ? ['Chrome'] : ['ChromeHeadless'] } if (availableBrowser.includes('Chromium')) { - return debug ? ['Chromium'] : ['ChromiumHeadless'] + return DEBUG ? ['Chromium'] : ['ChromiumHeadless'] } if (availableBrowser.includes('Firefox')) { - return debug ? ['Firefox'] : ['FirefoxHeadless'] + return DEBUG ? ['Firefox'] : ['FirefoxHeadless'] } throw new Error('Please install Chrome, Chromium or Firefox') @@ -59,7 +62,7 @@ const conf = { colors: true, autoWatch: false, singleRun: true, - concurrency: Infinity, + concurrency: Number.POSITIVE_INFINITY, client: { clearContext: false }, @@ -67,7 +70,7 @@ const conf = { 'node_modules/hammer-simulator/index.js', { pattern: 'js/tests/unit/**/!(jquery).spec.js', - watched: !browserStack + watched: !BROWSERSTACK } ], preprocessors: { @@ -101,11 +104,11 @@ const conf = { } } -if (browserStack) { +if (BROWSERSTACK) { conf.hostname = ip.address() conf.browserStack = { - username: env.BROWSER_STACK_USERNAME, - accessKey: env.BROWSER_STACK_ACCESS_KEY, + username: ENV.BROWSER_STACK_USERNAME, + accessKey: ENV.BROWSER_STACK_ACCESS_KEY, build: `bootstrap-${new Date().toISOString()}`, project: 'Bootstrap', retryLimit: 2 @@ -114,7 +117,7 @@ if (browserStack) { conf.customLaunchers = browsers conf.browsers = browsersKeys reporters.push('BrowserStack', 'kjhtml') -} else if (jQueryTest) { +} else if (JQUERY_TEST) { frameworks.push('detectBrowsers') plugins.push( 'karma-chrome-launcher', @@ -155,7 +158,7 @@ if (browserStack) { } } - if (debug) { + if (DEBUG) { conf.hostname = ip.address() plugins.push('karma-jasmine-html-reporter') reporters.push('kjhtml') @@ -169,7 +172,6 @@ conf.plugins = plugins conf.reporters = reporters module.exports = karmaConfig => { - // possible values: karmaConfig.LOG_DISABLE || karmaConfig.LOG_ERROR || karmaConfig.LOG_WARN || karmaConfig.LOG_INFO || karmaConfig.LOG_DEBUG - conf.logLevel = karmaConfig.LOG_ERROR || karmaConfig.LOG_WARN + conf.logLevel = karmaConfig.LOG_ERROR karmaConfig.set(conf) } diff --git a/js/tests/unit/carousel.spec.js b/js/tests/unit/carousel.spec.js index 07b8fc311..787a276de 100644 --- a/js/tests/unit/carousel.spec.js +++ b/js/tests/unit/carousel.spec.js @@ -905,7 +905,7 @@ describe('Carousel', () => { }) describe('to', () => { - it('should go directement to the provided index', done => { + it('should go directly to the provided index', done => { fixtureEl.innerHTML = [ ' @@ -206,6 +206,34 @@ Add `data-bs-interval=""` to a `.carousel-item` to change the amount of time to {{< /example >}} +### Disable touch swiping + +Carousels support swiping left/right on touchscreen devices to move between slides. This can be disabled using the `data-bs-touch` attribute. The example below also does not include the `data-bs-ride` attribute and has `data-bs-interval="false"` so it doesn't autoplay. + +{{< example >}} + +{{< /example >}} + ## Dark variant Add `.carousel-dark` to the `.carousel` for darker controls, indicators, and captions. Controls have been inverted from their default white fill with the `filter` CSS property. Captions and controls have additional Sass variables that customize the `color` and `background-color`. @@ -222,21 +250,21 @@ Add `.carousel-dark` to the `.carousel` for darker controls, indicators, and cap {{< placeholder width="800" height="400" class="bd-placeholder-img-lg d-block w-100" color="#aaa" background="#f5f5f5" text="First slide" >}} @@ -286,7 +314,7 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap interval number 5000 - The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle. + The amount of time to delay between automatically cycling an item. If false, carousel will not automatically cycle. keyboard @@ -297,15 +325,15 @@ Options can be passed via data attributes or JavaScript. For data attributes, ap pause string | boolean - "hover" -

If set to "hover", pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won't pause it.

-

On touch-enabled devices, when set to "hover", cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.

+ 'hover' +

If set to 'hover', pauses the cycling of the carousel on mouseenter and resumes the cycling of the carousel on mouseleave. If set to false, hovering over the carousel won't pause it.

+

On touch-enabled devices, when set to 'hover', cycling will pause on touchend (once the user finished interacting with the carousel) for two intervals, before automatically resuming. Note that this is in addition to the above mouse behavior.

- slide + ride string | boolean false - Autoplays the carousel after the user manually cycles the first item. If "carousel", autoplays the carousel on load. + Autoplays the carousel after the user manually cycles the first item. If set to 'carousel', autoplays the carousel on load. wrap diff --git a/site/content/docs/5.0/components/collapse.md b/site/content/docs/5.0/components/collapse.md index 0c23133b6..8546aaeb5 100644 --- a/site/content/docs/5.0/components/collapse.md +++ b/site/content/docs/5.0/components/collapse.md @@ -22,7 +22,7 @@ Click the buttons below to show and hide another element via class changes: - `.collapsing` is applied during transitions - `.collapse.show` shows content -You can use a link with the `href` attribute, or a button with the `data-bs-target` attribute. In both cases, the `data-bs-toggle="collapse"` is required. +Generally, we recommend using a button with the `data-bs-target` attribute. While not recommended from a semantic point of view, you can also use a link with the `href` attribute (and a `role="button"`). In both cases, the `data-bs-toggle="collapse"` is required. {{< example >}}

@@ -35,7 +35,7 @@ You can use a link with the `href` attribute, or a button with the `data-bs-targ

- Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. + Some placeholder content for the collapse component. This panel is hidden by default but revealed when the user activates the relevant trigger.
{{< /example >}} @@ -55,14 +55,14 @@ Multiple ` - - - - + + + + {{< /example >}} @@ -86,11 +86,11 @@ Add `.list-group-flush` to remove some borders and rounded corners to render lis {{< example >}} {{< /example >}} @@ -104,9 +104,9 @@ Add `.list-group-horizontal` to change the layout of list group items from verti {{< list-group.inline >}} {{- range $.Site.Data.breakpoints }} {{- end -}} {{< /list-group.inline >}} @@ -118,7 +118,7 @@ Use contextual classes to style list items with a stateful background and color. {{< example >}}
-

Raw denim you probably haven't heard of them jean shorts Austin. Nesciunt tofu stumptown aliqua, retro synth master cleanse. Mustache cliche tempor, williamsburg carles vegan helvetica. Reprehenderit butcher retro keffiyeh dreamcatcher synth. Cosby sweater eu banh mi, qui irure terry richardson ex squid. Aliquip placeat salvia cillum iphone. Seitan aliquip quis cardigan american apparel, butcher voluptate nisi qui.

+

Placeholder content for the tab panel. This one relates to the home tab. Takes you miles high, so high, 'cause she’s got that one international smile. There's a stranger in my bed, there's a pounding in my head. Oh, no. In another life I would make you stay. ‘Cause I, I’m capable of anything. Suiting up for my crowning battle. Used to steal your parents' liquor and climb to the roof. Tone, tan fit and ready, turn it up cause its gettin' heavy. Her love is like a drug. I guess that I forgot I had a choice.

-

Food truck fixie locavore, accusamus mcsweeney's marfa nulla single-origin coffee squid. Exercitation +1 labore velit, blog sartorial PBR leggings next level wes anderson artisan four loko farm-to-table craft beer twee. Qui photo booth letterpress, commodo enim craft beer mlkshk aliquip jean shorts ullamco ad vinyl cillum PBR. Homo nostrud organic, assumenda labore aesthetic magna delectus mollit. Keytar helvetica VHS salvia yr, vero magna velit sapiente labore stumptown. Vegan fanny pack odio cillum wes anderson 8-bit, sustainable jean shorts beard ut DIY ethical culpa terry richardson biodiesel. Art party scenester stumptown, tumblr butcher vero sint qui sapiente accusamus tattooed echo park.

+

Placeholder content for the tab panel. This one relates to the profile tab. You got the finest architecture. Passport stamps, she's cosmopolitan. Fine, fresh, fierce, we got it on lock. Never planned that one day I'd be losing you. She eats your heart out. Your kiss is cosmic, every move is magic. I mean the ones, I mean like she's the one. Greetings loved ones let's take a journey. Just own the night like the 4th of July! But you'd rather get wasted.

-

Etsy mixtape wayfarers, ethical wes anderson tofu before they sold out mcsweeney's organic lomo retro fanny pack lo-fi farm-to-table readymade. Messenger bag gentrify pitchfork tattooed craft beer, iphone skateboard locavore carles etsy salvia banksy hoodie helvetica. DIY synth PBR banksy irony. Leggings gentrify squid 8-bit cred pitchfork. Williamsburg banh mi whatever gluten-free, carles pitchfork biodiesel fixie etsy retro mlkshk vice blog. Scenester cred you probably haven't heard of them, vinyl craft beer blog stumptown. Pitchfork sustainable tofu synth chambray yr.

+

Placeholder content for the tab panel. This one relates to the contact tab. Her love is like a drug. All my girls vintage Chanel baby. Got a motel and built a fort out of sheets. 'Cause she's the muse and the artist. (This is how we do) So you wanna play with magic. So just be sure before you give it all to me. I'm walking, I'm walking on air (tonight). Skip the talk, heard it all, time to walk the walk. Catch her if you can. Stinging like a bee I earned my stripes.

@@ -368,13 +368,13 @@ To help fit your needs, this works with `
-

Consequat occaecat ullamco amet non eiusmod nostrud dolore irure incididunt est duis anim sunt officia. Fugiat velit proident aliquip nisi incididunt nostrud exercitation proident est nisi. Irure magna elit commodo anim ex veniam culpa eiusmod id nostrud sit cupidatat in veniam ad. Eiusmod consequat eu adipisicing minim anim aliquip cupidatat culpa excepteur quis. Occaecat sit eu exercitation irure Lorem incididunt nostrud.

+

Placeholder content for the tab panel. This one relates to the home tab. Takes you miles high, so high, 'cause she’s got that one international smile. There's a stranger in my bed, there's a pounding in my head. Oh, no. In another life I would make you stay. ‘Cause I, I’m capable of anything. Suiting up for my crowning battle. Used to steal your parents' liquor and climb to the roof. Tone, tan fit and ready, turn it up cause its gettin' heavy. Her love is like a drug. I guess that I forgot I had a choice.

-

Ad pariatur nostrud pariatur exercitation ipsum ipsum culpa mollit commodo mollit ex. Aute sunt incididunt amet commodo est sint nisi deserunt pariatur do. Aliquip ex eiusmod voluptate exercitation cillum id incididunt elit sunt. Qui minim sit magna Lorem id et dolore velit Lorem amet exercitation duis deserunt. Anim id labore elit adipisicing ut in id occaecat pariatur ut ullamco ea tempor duis.

+

Placeholder content for the tab panel. This one relates to the profile tab. You got the finest architecture. Passport stamps, she's cosmopolitan. Fine, fresh, fierce, we got it on lock. Never planned that one day I'd be losing you. She eats your heart out. Your kiss is cosmic, every move is magic. I mean the ones, I mean like she's the one. Greetings loved ones let's take a journey. Just own the night like the 4th of July! But you'd rather get wasted.

-

Est quis nulla laborum officia ad nisi ex nostrud culpa Lorem excepteur aliquip dolor aliqua irure ex. Nulla ut duis ipsum nisi elit fugiat commodo sunt reprehenderit laborum veniam eu veniam. Eiusmod minim exercitation fugiat irure ex labore incididunt do fugiat commodo aliquip sit id deserunt reprehenderit aliquip nostrud. Amet ex cupidatat excepteur aute veniam incididunt mollit cupidatat esse irure officia elit do ipsum ullamco Lorem. Ullamco ut ad minim do mollit labore ipsum laboris ipsum commodo sunt tempor enim incididunt. Commodo quis sunt dolore aliquip aute tempor irure magna enim minim reprehenderit. Ullamco consectetur culpa veniam sint cillum aliqua incididunt velit ullamco sunt ullamco quis quis commodo voluptate. Mollit nulla nostrud adipisicing aliqua cupidatat aliqua pariatur mollit voluptate voluptate consequat non.

+

Placeholder content for the tab panel. This one relates to the contact tab. Her love is like a drug. All my girls vintage Chanel baby. Got a motel and built a fort out of sheets. 'Cause she's the muse and the artist. (This is how we do) So you wanna play with magic. So just be sure before you give it all to me. I'm walking, I'm walking on air (tonight). Skip the talk, heard it all, time to walk the walk. Catch her if you can. Stinging like a bee I earned my stripes.

@@ -452,16 +452,16 @@ And with vertical pills.
-

Cillum ad ut irure tempor velit nostrud occaecat ullamco aliqua anim Lorem sint. Veniam sint duis incididunt do esse magna mollit excepteur laborum qui. Id id reprehenderit sit est eu aliqua occaecat quis et velit excepteur laborum mollit dolore eiusmod. Ipsum dolor in occaecat commodo et voluptate minim reprehenderit mollit pariatur. Deserunt non laborum enim et cillum eu deserunt excepteur ea incididunt minim occaecat.

+

Placeholder content for the tab panel. This one relates to the home tab. Saw you downtown singing the Blues. Watch you circle the drain. Why don't you let me stop by? Heavy is the head that wears the crown. Yes, we make angels cry, raining down on earth from up above. Wanna see the show in 3D, a movie. Do you ever feel, feel so paper thin. It’s a yes or no, no maybe.

-

Culpa dolor voluptate do laboris laboris irure reprehenderit id incididunt duis pariatur mollit aute magna pariatur consectetur. Eu veniam duis non ut dolor deserunt commodo et minim in quis laboris ipsum velit id veniam. Quis ut consectetur adipisicing officia excepteur non sit. Ut et elit aliquip labore Lorem enim eu. Ullamco mollit occaecat dolore ipsum id officia mollit qui esse anim eiusmod do sint minim consectetur qui.

+

Placeholder content for the tab panel. This one relates to the profile tab. Takes you miles high, so high, 'cause she’s got that one international smile. There's a stranger in my bed, there's a pounding in my head. Oh, no. In another life I would make you stay. ‘Cause I, I’m capable of anything. Suiting up for my crowning battle. Used to steal your parents' liquor and climb to the roof. Tone, tan fit and ready, turn it up cause its gettin' heavy. Her love is like a drug. I guess that I forgot I had a choice.

-

Fugiat id quis dolor culpa eiusmod anim velit excepteur proident dolor aute qui magna. Ad proident laboris ullamco esse anim Lorem Lorem veniam quis Lorem irure occaecat velit nostrud magna nulla. Velit et et proident Lorem do ea tempor officia dolor. Reprehenderit Lorem aliquip labore est magna commodo est ea veniam consectetur.

+

Placeholder content for the tab panel. This one relates to the messages tab. You got the finest architecture. Passport stamps, she's cosmopolitan. Fine, fresh, fierce, we got it on lock. Never planned that one day I'd be losing you. She eats your heart out. Your kiss is cosmic, every move is magic. I mean the ones, I mean like she's the one. Greetings loved ones let's take a journey. Just own the night like the 4th of July! But you'd rather get wasted.

-

Eu dolore ea ullamco dolore Lorem id cupidatat excepteur reprehenderit consectetur elit id dolor proident in cupidatat officia. Voluptate excepteur commodo labore nisi cillum duis aliqua do. Aliqua amet qui mollit consectetur nulla mollit velit aliqua veniam nisi id do Lorem deserunt amet. Culpa ullamco sit adipisicing labore officia magna elit nisi in aute tempor commodo eiusmod.

+

Placeholder content for the tab panel. This one relates to the settings tab. Her love is like a drug. All my girls vintage Chanel baby. Got a motel and built a fort out of sheets. 'Cause she's the muse and the artist. (This is how we do) So you wanna play with magic. So just be sure before you give it all to me. I'm walking, I'm walking on air (tonight). Skip the talk, heard it all, time to walk the walk. Catch her if you can. Stinging like a bee I earned my stripes.

diff --git a/site/content/docs/5.0/components/popovers.md b/site/content/docs/5.0/components/popovers.md index 41b482d03..ccaf1f63f 100644 --- a/site/content/docs/5.0/components/popovers.md +++ b/site/content/docs/5.0/components/popovers.md @@ -62,40 +62,20 @@ var popover = new bootstrap.Popover(document.querySelector('.example-popover'), Four options are available: top, right, bottom, and left aligned. Directions are mirrored when using Bootstrap in RTL. -
-
- - - - -
-
- -```html - - - - - - - -``` +{{< /example >}} ### Dismiss on next click @@ -119,13 +99,13 @@ var popover = new bootstrap.Popover(document.querySelector('.popover-dismiss'), ### Disabled elements -Elements with the `disabled` attribute aren't interactive, meaning users cannot hover or click them to trigger a popover (or tooltip). As a workaround, you'll want to trigger the popover from a wrapper `
` or `` and override the `pointer-events` on the disabled element. +Elements with the `disabled` attribute aren't interactive, meaning users cannot hover or click them to trigger a popover (or tooltip). As a workaround, you'll want to trigger the popover from a wrapper `
` or ``, ideally made keyboard-focusable using `tabindex="0"`. -For disabled popover triggers, you may also prefer `data-bs-trigger="hover"` so that the popover appears as immediate visual feedback to your users as they may not expect to _click_ on a disabled element. +For disabled popover triggers, you may also prefer `data-bs-trigger="hover focus"` so that the popover appears as immediate visual feedback to your users as they may not expect to _click_ on a disabled element. {{< example >}} - - + + {{< /example >}} @@ -248,23 +228,17 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt How popover is triggered - click | hover | focus | manual. You may pass multiple triggers; separate them with a space. manual cannot be combined with any other trigger. - offset - number | string - 0 - Offset of the popover relative to its target. For more information refer to Popper's offset docs. - - - fallbackPlacement - string | array - 'flip' - Allow to specify which position Popper will use on fallback. For more information refer to - Popper's behavior docs + fallbackPlacements + array + ['top', 'right', 'bottom', 'left'] + Define fallback placements by providing a list of placements in array (in order of preference). For more information refer to + Popper's behavior docs boundary string | element 'scrollParent' - Overflow constraint boundary of the popover. Accepts the values of 'viewport', 'window', 'scrollParent', or an HTMLElement reference (JavaScript only). For more information refer to Popper's preventOverflow docs. + Overflow constraint boundary of the popover. Accepts the values of 'viewport', 'window', 'scrollParent', or an HTMLElement reference (JavaScript only). For more information refer to Popper's preventOverflow docs. customClass @@ -297,7 +271,7 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt popperConfig null | object null - To change Bootstrap's default Popper config, see Popper's configuration + To change Bootstrap's default Popper config, see Popper's configuration diff --git a/site/content/docs/5.0/components/scrollspy.md b/site/content/docs/5.0/components/scrollspy.md index 0d099c08c..3904990af 100644 --- a/site/content/docs/5.0/components/scrollspy.md +++ b/site/content/docs/5.0/components/scrollspy.md @@ -49,17 +49,16 @@ Scroll the area below the navbar and watch the active class change. The dropdown

@fat

-

Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

+

Placeholder content for the scrollspy example. You got the finest architecture. Passport stamps, she's cosmopolitan. Fine, fresh, fierce, we got it on lock. Never planned that one day I'd be losing you. She eats your heart out. Your kiss is cosmic, every move is magic. I mean the ones, I mean like she's the one. Greetings loved ones let's take a journey. Just own the night like the 4th of July! But you'd rather get wasted.

@mdo

-

Veniam marfa mustache skateboard, adipisicing fugiat velit pitchfork beard. Freegan beard aliqua cupidatat mcsweeney's vero. Cupidatat four loko nisi, ea helvetica nulla carles. Tattooed cosby sweater food truck, mcsweeney's quis non freegan vinyl. Lo-fi wes anderson +1 sartorial. Carles non aesthetic exercitation quis gentrify. Brooklyn adipisicing craft beer vice keytar deserunt.

+

Placeholder content for the scrollspy example. 'Cause she's the muse and the artist. (This is how we do) So you wanna play with magic. So just be sure before you give it all to me. I'm walking, I'm walking on air (tonight). Skip the talk, heard it all, time to walk the walk.

one

-

Occaecat commodo aliqua delectus. Fap craft beer deserunt skateboard ea. Lomo bicycle rights adipisicing banh mi, velit ea sunt next level locavore single-origin coffee in magna veniam. High life id vinyl, echo park consequat quis aliquip banh mi pitchfork. Vero VHS est adipisicing. Consectetur nisi DIY minim messenger bag. Cred ex in, sustainable delectus consectetur fanny pack iphone.

+

Placeholder content for the scrollspy example. Takes you miles high, so high, 'cause she’s got that one international smile. There's a stranger in my bed, there's a pounding in my head. Oh, no. In another life I would make you stay. ‘Cause I, I’m capable of anything. Suiting up for my crowning battle. Used to steal your parents' liquor and climb to the roof. Tone, tan fit and ready, turn it up cause its gettin' heavy. Her love is like a drug. I guess that I forgot I had a choice.

two

-

In incididunt echo park, officia deserunt mcsweeney's proident master cleanse thundercats sapiente veniam. Excepteur VHS elit, proident shoreditch +1 biodiesel laborum craft beer. Single-origin coffee wayfarers irure four loko, cupidatat terry richardson master cleanse. Assumenda you probably haven't heard of them art party fanny pack, tattooed nulla cardigan tempor ad. Proident wolf nesciunt sartorial keffiyeh eu banh mi sustainable. Elit wolf voluptate, lo-fi ea portland before they sold out four loko. Locavore enim nostrud mlkshk brooklyn nesciunt.

+

Placeholder content for the scrollspy example. It's time to bring out the big balloons. I'm walking, I'm walking on air (tonight). Yeah, we maxed our credit cards and got kicked out of the bar. Yo, shout out to all you kids, buying bottle service, with your rent money. I'm ma get your heart racing in my skin-tight jeans. If you get the chance you better keep her. Yo, shout out to all you kids, buying bottle service, with your rent money.

three

-

Ad leggings keytar, brunch id art party dolor labore. Pitchfork yr enim lo-fi before they sold out qui. Tumblr farm-to-table bicycle rights whatever. Anim keffiyeh carles cardigan. Velit seitan mcsweeney's photo booth 3 wolf moon irure. Cosby sweater lomo jean shorts, williamsburg hoodie minim qui you probably haven't heard of them et cardigan trust fund culpa biodiesel wes anderson aesthetic. Nihil tattooed accusamus, cred irony biodiesel keffiyeh artisan ullamco consequat.

-

Keytar twee blog, culpa messenger bag marfa whatever delectus food truck. Sapiente synth id assumenda. Locavore sed helvetica cliche irony, thundercats you probably haven't heard of them consequat hoodie gluten-free lo-fi fap aliquip. Labore elit placeat before they sold out, terry richardson proident brunch nesciunt quis cosby sweater pariatur keffiyeh ut helvetica artisan. Cardigan craft beer seitan readymade velit. VHS chambray laboris tempor veniam. Anim mollit minim commodo ullamco thundercats. -

+

Placeholder content for the scrollspy example. If you wanna dance, if you want it all, you know that I'm the girl that you should call. Walk through the storm I would. So let me get you in your birthday suit. The one that got away. Last Friday night, yeah I think we broke the law, always say we're gonna stop. 'Cause she's a little bit of Yoko, And she's a little bit of 'Oh no'. I want the jaw droppin', eye poppin', head turnin', body shockin'. Yeah, we maxed our credit cards and got kicked out of the bar.

+

And some more placeholder content, for good measure.

@@ -125,19 +124,19 @@ Scrollspy also works with nested `.nav`s. If a nested `.nav` is `.active`, its p

Item 1

-

Ex consequat commodo adipisicing exercitation aute excepteur occaecat ullamco duis aliqua id magna ullamco eu. Do aute ipsum ipsum ullamco cillum consectetur ut et aute consectetur labore. Fugiat laborum incididunt tempor eu consequat enim dolore proident. Qui laborum do non excepteur nulla magna eiusmod consectetur in. Aliqua et aliqua officia quis et incididunt voluptate non anim reprehenderit adipisicing dolore ut consequat deserunt mollit dolore. Aliquip nulla enim veniam non fugiat id cupidatat nulla elit cupidatat commodo velit ut eiusmod cupidatat elit dolore.

+

Placeholder content for the scrollspy example. This one relates to item 1. Takes you miles high, so high, 'cause she’s got that one international smile. There's a stranger in my bed, there's a pounding in my head. Oh, no. In another life I would make you stay. ‘Cause I, I’m capable of anything. Suiting up for my crowning battle. Used to steal your parents' liquor and climb to the roof. Tone, tan fit and ready, turn it up cause its gettin' heavy. Her love is like a drug. I guess that I forgot I had a choice.

Item 1-1
-

Amet tempor mollit aliquip pariatur excepteur commodo do ea cillum commodo Lorem et occaecat elit qui et. Aliquip labore ex ex esse voluptate occaecat Lorem ullamco deserunt. Aliqua cillum excepteur irure consequat id quis ea. Sit proident ullamco aute magna pariatur nostrud labore. Reprehenderit aliqua commodo eiusmod aliquip est do duis amet proident magna consectetur consequat eu commodo fugiat non quis. Enim aliquip exercitation ullamco adipisicing voluptate excepteur minim exercitation minim minim commodo adipisicing exercitation officia nisi adipisicing. Anim id duis qui consequat labore adipisicing sint dolor elit cillum anim et fugiat.

+

Placeholder content for the scrollspy example. This one relates to the item 1-1. You got the finest architecture. Passport stamps, she's cosmopolitan. Fine, fresh, fierce, we got it on lock. Never planned that one day I'd be losing you. She eats your heart out. Your kiss is cosmic, every move is magic. I mean the ones, I mean like she's the one. Greetings loved ones let's take a journey. Just own the night like the 4th of July! But you'd rather get wasted.

Item 1-2
-

Cillum nisi deserunt magna eiusmod qui eiusmod velit voluptate pariatur laborum sunt enim. Irure laboris mollit consequat incididunt sint et culpa culpa incididunt adipisicing magna magna occaecat. Nulla ipsum cillum eiusmod sint elit excepteur ea labore enim consectetur in labore anim. Proident ullamco ipsum esse elit ut Lorem eiusmod dolor et eiusmod. Anim occaecat nulla in non consequat eiusmod velit incididunt.

+

Placeholder content for the scrollspy example. This one relates to the item 1-2. Her love is like a drug. All my girls vintage Chanel baby. Got a motel and built a fort out of sheets. 'Cause she's the muse and the artist. (This is how we do) So you wanna play with magic. So just be sure before you give it all to me. I'm walking, I'm walking on air (tonight). Skip the talk, heard it all, time to walk the walk. Catch her if you can. Stinging like a bee I earned my stripes.

Item 2

-

Quis magna Lorem anim amet ipsum do mollit sit cillum voluptate ex nulla tempor. Laborum consequat non elit enim exercitation cillum aliqua consequat id aliqua. Esse ex consectetur mollit voluptate est in duis laboris ad sit ipsum anim Lorem. Incididunt veniam velit elit elit veniam Lorem aliqua quis ullamco deserunt sit enim elit aliqua esse irure. Laborum nisi sit est tempor laborum mollit labore officia laborum excepteur commodo non commodo dolor excepteur commodo. Ipsum fugiat ex est consectetur ipsum commodo tempor sunt in proident.

+

Placeholder content for the scrollspy example. This one relates to item 2. Don't need apologies. There is no fear now, let go and just be free, I will love you unconditionally. Last Friday night. Don't be a shy kinda guy I'll bet it's beautiful. Summer after high school when we first met. 'Cause she's the muse and the artist. What? Wait. No, no, no, no. Thought that I was the exception.

Item 3

-

Quis anim sit do amet fugiat dolor velit sit ea ea do reprehenderit culpa duis. Nostrud aliqua ipsum fugiat minim proident occaecat excepteur aliquip culpa aute tempor reprehenderit. Deserunt tempor mollit elit ex pariatur dolore velit fugiat mollit culpa irure ullamco est ex ullamco excepteur.

+

Placeholder content for the scrollspy example. This one relates to item 3. Word on the street, you got somethin' to show me, me. All this money can't buy me a time machine. Make it like your birthday everyday. So we hit the boulevard. You make me feel like I'm livin' a teenage dream, the way you turn me on Skip the talk, heard it all, time to walk the walk. Word on the street, you got somethin' to show me, me. It's no big deal, it's no big deal, it's no big deal.

Item 3-1
-

Deserunt quis elit Lorem eiusmod amet enim enim amet minim Lorem proident nostrud. Ea id dolore anim exercitation aute fugiat labore voluptate cillum do laboris labore. Ex velit exercitation nisi enim labore reprehenderit labore nostrud ut ut. Esse officia sunt duis aliquip ullamco tempor eiusmod deserunt irure nostrud irure. Ullamco proident veniam laboris ea consectetur magna sunt ex exercitation aliquip minim enim culpa occaecat exercitation. Est tempor excepteur aliquip laborum consequat do deserunt laborum esse eiusmod irure proident ipsum esse qui.

+

Placeholder content for the scrollspy example. This one relates to item 3-1. Baby do you dare to do this? This is no big deal. Yeah, you're lucky if you're on her plane. Just own the night like the 4th of July! Standing on the frontline when the bombs start to fall. So just be sure before you give it all to me.

Item 3-2
-

Labore sit culpa commodo elit adipisicing sit aliquip elit proident voluptate minim mollit nostrud aute reprehenderit do. Mollit excepteur eu Lorem ipsum anim commodo sint labore Lorem in exercitation velit incididunt. Occaecat consectetur nisi in occaecat proident minim enim sunt reprehenderit exercitation cupidatat et do officia. Aliquip consequat ad labore labore mollit ut amet. Sit pariatur tempor proident in veniam culpa aliqua excepteur elit magna fugiat eiusmod amet officia.

+

Placeholder content for the scrollspy example. This one relates to item 3-2. You're original, cannot be replaced. All night they're playing, your song. California girls we're undeniable. Like a bird without a cage. There is no fear now, let go and just be free, I will love you unconditionally. I can see the writing on the wall. You could travel the world but nothing comes close to the golden coast.

@@ -196,13 +195,13 @@ Scrollspy also works with `.list-group`s. Scroll the area next to the list group

Item 1

-

Ex consequat commodo adipisicing exercitation aute excepteur occaecat ullamco duis aliqua id magna ullamco eu. Do aute ipsum ipsum ullamco cillum consectetur ut et aute consectetur labore. Fugiat laborum incididunt tempor eu consequat enim dolore proident. Qui laborum do non excepteur nulla magna eiusmod consectetur in. Aliqua et aliqua officia quis et incididunt voluptate non anim reprehenderit adipisicing dolore ut consequat deserunt mollit dolore. Aliquip nulla enim veniam non fugiat id cupidatat nulla elit cupidatat commodo velit ut eiusmod cupidatat elit dolore.

+

Placeholder content for the scrollspy list-group example. This one relates to item 1. Don't need apologies. There is no fear now, let go and just be free, I will love you unconditionally. Last Friday night. Don't be a shy kinda guy I'll bet it's beautiful. Summer after high school when we first met. 'Cause she's the muse and the artist. What? Wait. Thought that I was the exception.

Item 2

-

Quis magna Lorem anim amet ipsum do mollit sit cillum voluptate ex nulla tempor. Laborum consequat non elit enim exercitation cillum aliqua consequat id aliqua. Esse ex consectetur mollit voluptate est in duis laboris ad sit ipsum anim Lorem. Incididunt veniam velit elit elit veniam Lorem aliqua quis ullamco deserunt sit enim elit aliqua esse irure. Laborum nisi sit est tempor laborum mollit labore officia laborum excepteur commodo non commodo dolor excepteur commodo. Ipsum fugiat ex est consectetur ipsum commodo tempor sunt in proident.

+

Placeholder content for the scrollspy list-group example. This one relates to item 2. Yeah, she dances to her own beat. Oh, no. You could've been the greatest. 'Cause, baby, you're a firework. Maybe a reason why all the doors are closed. Open up your heart and just let it begin. So très chic, yeah, she's a classic.

Item 3

-

Quis anim sit do amet fugiat dolor velit sit ea ea do reprehenderit culpa duis. Nostrud aliqua ipsum fugiat minim proident occaecat excepteur aliquip culpa aute tempor reprehenderit. Deserunt tempor mollit elit ex pariatur dolore velit fugiat mollit culpa irure ullamco est ex ullamco excepteur.

+

Placeholder content for the scrollspy list-group example. This one relates to item 3. We go higher and higher. Never one without the other, we made a pact. I'm walking on air. Someone said you had your tattoo removed. Now I’m floating like a butterfly. Tone, tan fit and ready, turn it up cause its gettin' heavy. Cause once you’re mine, once you’re mine. You just gotta ignite the light and let it shine! So we hit the boulevard. Do you ever feel, feel so paper thin. I see it all, I see it now.

Item 4

-

Quis anim sit do amet fugiat dolor velit sit ea ea do reprehenderit culpa duis. Nostrud aliqua ipsum fugiat minim proident occaecat excepteur aliquip culpa aute tempor reprehenderit. Deserunt tempor mollit elit ex pariatur dolore velit fugiat mollit culpa irure ullamco est ex ullamco excepteur.

+

Placeholder content for the scrollspy list-group example. This one relates to item 4. Summer after high school when we first met. There is no fear now, let go and just be free, I will love you unconditionally. Sun-kissed skin so hot we'll melt your popsicle. This love will make you levitate.

@@ -227,7 +226,6 @@ Scrollspy also works with `.list-group`s. Scroll the area next to the list group ``` - ## Usage ### Via data attributes diff --git a/site/content/docs/5.0/components/toasts.md b/site/content/docs/5.0/components/toasts.md index 740a926f9..bd7bcae9c 100644 --- a/site/content/docs/5.0/components/toasts.md +++ b/site/content/docs/5.0/components/toasts.md @@ -43,7 +43,7 @@ Toasts are as flexible as you need and have very little required markup. At a mi ### Translucent -Toasts are slightly translucent, too, so they blend over whatever they might appear over. For browsers that support the `backdrop-filter` CSS property, we'll also attempt to blur the elements under a toast. +Toasts are slightly translucent, too, so they blend over whatever they might appear over. {{< example class="bg-dark" >}}