From ffa4e6def6c81158e7d3ab9606351e1705558598 Mon Sep 17 00:00:00 2001 From: mrholek Date: Wed, 21 Aug 2024 23:40:16 +0200 Subject: [PATCH 01/19] refactor(Accordion): merge accordion selectors for `border-radius` rule --- scss/_accordion.scss | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/scss/_accordion.scss b/scss/_accordion.scss index c3a80a608..0c36f492b 100644 --- a/scss/_accordion.scss +++ b/scss/_accordion.scss @@ -134,17 +134,12 @@ &:last-child { border-bottom: 0; } // stylelint-disable selector-max-class - > .accordion-header .accordion-button { - &, - &.collapsed { - @include border-radius(0); - } - } - // stylelint-enable selector-max-class - - > .accordion-collapse { + > .accordion-collapse, + > .accordion-header .accordion-button, + > .accordion-header .accordion-button.collapsed { @include border-radius(0); } + // stylelint-enable selector-max-class } } From c1792adbb5cd3446325afaa4e7188ef2cdcecbd0 Mon Sep 17 00:00:00 2001 From: mrholek Date: Wed, 21 Aug 2024 23:46:10 +0200 Subject: [PATCH 02/19] docs: remove useless `crossorigin="anonymous"` attributes --- docs/layouts/partials/scripts.html | 2 +- docs/layouts/partials/stylesheet.html | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/layouts/partials/scripts.html b/docs/layouts/partials/scripts.html index fa3a625e7..275bd7e01 100644 --- a/docs/layouts/partials/scripts.html +++ b/docs/layouts/partials/scripts.html @@ -1,5 +1,5 @@ {{ if eq hugo.Environment "production" -}} - + {{ else -}} {{- end }} diff --git a/docs/layouts/partials/stylesheet.html b/docs/layouts/partials/stylesheet.html index 0bedb12cf..e602bf590 100644 --- a/docs/layouts/partials/stylesheet.html +++ b/docs/layouts/partials/stylesheet.html @@ -4,9 +4,9 @@ {{ if eq hugo.Environment "production" -}} {{ if eq .Page.Params.direction "rtl" -}} - + {{- else -}} - + {{- end -}} {{- else -}} From e2e85d7e1054f454744ab90305f894f75c4696db Mon Sep 17 00:00:00 2001 From: mrholek Date: Wed, 21 Aug 2024 23:51:11 +0200 Subject: [PATCH 03/19] build: update hugo server options --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a580b0878..8cf801372 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "docs-compile": "npm run docs-build", "docs-vnu": "node build/vnu-jar.mjs", "docs-lint": "npm run docs-vnu", - "docs-serve": "hugo server --port 9001 --disableFastRender --printUnusedTemplates", + "docs-serve": "hugo server --port 9001 --disableFastRender --noHTTPCache --renderToMemory --printPathWarnings --printUnusedTemplates", "docs-serve-only": "npx sirv-cli _gh_pages --port 9001", "lockfile-lint": "lockfile-lint --allowed-hosts npm --allowed-schemes https: --empty-hostname false --type npm --path package-lock.json", "update-deps": "ncu -u -x jasmine,karma-browserstack-launcher,karma-rollup-preprocessor,terser && echo Manually update docs/assets/js/vendor", From 636dc4d2c24944e652a9a0e9973618f8f81f2a49 Mon Sep 17 00:00:00 2001 From: mrholek Date: Wed, 21 Aug 2024 23:52:51 +0200 Subject: [PATCH 04/19] docs: fix position of search modal to avoid interface blocking at small breakpoints --- docs/assets/scss/_search.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/assets/scss/_search.scss b/docs/assets/scss/_search.scss index c487e640f..a6a355505 100644 --- a/docs/assets/scss/_search.scss +++ b/docs/assets/scss/_search.scss @@ -29,6 +29,7 @@ --docsearch-muted-color: var(--cui-secondary-color); --docsearch-hit-shadow: none; + position: fixed; z-index: 2000; // Make sure to be over all components showcased in the documentation cursor: auto; // Needed because of [role="button"] in Algolia search modal. Remove once https://github.com/algolia/docsearch/issues/1370 is tackled. From f86bcf777a9626a11b7394b879495d8a16d6d803 Mon Sep 17 00:00:00 2001 From: mrholek Date: Wed, 21 Aug 2024 23:54:47 +0200 Subject: [PATCH 05/19] docs: switch to using `hugo.IsProduction` --- docs/layouts/partials/scripts.html | 4 ++-- docs/layouts/partials/stylesheet.html | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/layouts/partials/scripts.html b/docs/layouts/partials/scripts.html index 275bd7e01..e9615467c 100644 --- a/docs/layouts/partials/scripts.html +++ b/docs/layouts/partials/scripts.html @@ -1,4 +1,4 @@ -{{ if eq hugo.Environment "production" -}} +{{ if hugo.IsProduction -}} {{ else -}} @@ -13,7 +13,7 @@ {{- $targetDocsJSPath := printf "/assets/js/docs.js" -}} {{- $docsJs := append $js $vendor | resources.Concat $targetDocsJSPath -}} -{{- if eq hugo.Environment "production" -}} +{{- if hugo.IsProduction -}} {{- $docsJs = $docsJs | resources.Minify -}} {{- end }} diff --git a/docs/layouts/partials/stylesheet.html b/docs/layouts/partials/stylesheet.html index e602bf590..45ec1fba7 100644 --- a/docs/layouts/partials/stylesheet.html +++ b/docs/layouts/partials/stylesheet.html @@ -2,7 +2,7 @@ {{- end }} -{{ if eq hugo.Environment "production" -}} +{{ if hugo.IsProduction -}} {{ if eq .Page.Params.direction "rtl" -}} {{- else -}} @@ -18,7 +18,7 @@ {{- $sassOptions := dict "targetPath" $targetDocsCssPath "outputStyle" "expanded" "precision" 6 -}} {{- $postcssOptions := dict "use" "autoprefixer" "noMap" true -}} -{{ if eq hugo.Environment "production" -}} +{{ if hugo.IsProduction -}} {{- $sassOptions = merge $sassOptions (dict "outputStyle" "compressed") -}} {{- end -}} From 2c455d69daa2d2838c3a5a071f17acf485c8f474 Mon Sep 17 00:00:00 2001 From: mrholek Date: Wed, 21 Aug 2024 23:59:09 +0200 Subject: [PATCH 06/19] docs: mention text transform classes --- docs/content/utilities/text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/utilities/text.md b/docs/content/utilities/text.md index 625cf6b78..590d0ed44 100644 --- a/docs/content/utilities/text.md +++ b/docs/content/utilities/text.md @@ -59,7 +59,7 @@ Note that [breaking words isn't possible in Arabic](https://rtlstyling.com/posts ## Text transform -Transform text in components with text capitalization classes. +Transform text in components with our text capitalization classes: `text-lowercase`, `text-uppercase` or `text-capitalize`. {{< example >}}

Lowercased text.

From d0a9142a5dbd2b102104d400cf3f20815fc98743 Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 22 Aug 2024 00:07:44 +0200 Subject: [PATCH 07/19] docs: update WCAG links and references --- .github/CONTRIBUTING.md | 2 +- docs/content/getting-started/accessibility.md | 6 +++--- scss/_functions.scss | 2 +- scss/_variables.scss | 2 +- scss/mixins/_visually-hidden.scss | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5f36aa167..5995b2cfc 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -165,7 +165,7 @@ Please use following commit message format. [Adhere to the Code Guide.](http://codeguide.co/#css) -- When feasible, default color palettes should comply with [WCAG color contrast guidelines](http://www.w3.org/TR/WCAG20/#visual-audio-contrast). +- When feasible, default color palettes should comply with [WCAG color contrast guidelines](https://www.w3.org/TR/WCAG/#distinguishable). - Except in rare cases, don't remove default `:focus` styles (via e.g. `outline: none;`) without providing alternative styles. See [this A11Y Project post](http://a11yproject.com/posts/never-remove-css-outlines) for more details. ### JS diff --git a/docs/content/getting-started/accessibility.md b/docs/content/getting-started/accessibility.md index d39e86a74..ae166353f 100644 --- a/docs/content/getting-started/accessibility.md +++ b/docs/content/getting-started/accessibility.md @@ -10,7 +10,7 @@ CoreUI for Bootstrap provides an easy-to-use framework of ready-made styles, lay ## Overview and limitations -The overall accessibility of any project built with CoreUI for Bootstrap depends in large part on the author's markup, additional styling, and scripting they've included. However, provided that these have been implemented correctly, it should be perfectly possible to create websites and applications with CoreUI for Bootstrap that fulfill [WCAG 2.1](https://www.w3.org/TR/WCAG21/) (A/AA/AAA), [Section 508](https://www.section508.gov/), and similar accessibility standards and requirements. +The overall accessibility of any project built with Bootstrap depends in large part on the author's markup, additional styling, and scripting they've included. However, provided that these have been implemented correctly, it should be perfectly possible to create websites and applications with Bootstrap that fulfill [WCAG 2.2](https://www.w3.org/TR/WCAG/) (A/AA/AAA), [Section 508](https://www.section508.gov/), and similar accessibility standards and requirements. ### Structural markup @@ -24,7 +24,7 @@ Because CoreUI for Bootstrap components are purposely designed to be fairly gene ### Color contrast -Some combinations of colors that currently make up CoreUI for Bootstrap default palette—used throughout the framework for things such as button variations, alert variations, form validation indicators—may lead to *insufficient* color contrast (below the recommended [WCAG 2.1 text color contrast ratio of 4.5:1](https://www.w3.org/TR/WCAG21/#contrast-minimum) and the [WCAG 2.1 non-text color contrast ratio of 3:1](https://www.w3.org/TR/WCAG21/#non-text-contrast)), particularly when used against a light background. Authors are encouraged to test their specific uses of color and, where necessary, manually modify/extend these default colors to ensure adequate color contrast ratios. +Some combinations of colors that currently make up Bootstrap's default palette—used throughout the framework for things such as button variations, alert variations, form validation indicators—may lead to *insufficient* color contrast (below the recommended [WCAG 2.2 text color contrast ratio of 4.5:1](https://www.w3.org/TR/WCAG/#contrast-minimum) and the [WCAG 2.2 non-text color contrast ratio of 3:1](https://www.w3.org/TR/WCAG/#non-text-contrast)), particularly when used against a light background. Authors are encouraged to test their specific uses of color and, where necessary, manually modify/extend these default colors to ensure adequate color contrast ratios. ### Visually hidden content @@ -51,7 +51,7 @@ On browsers that support `prefers-reduced-motion`, and where the user has *not* ## Additional resources -- [Web Content Accessibility Guidelines (WCAG) 2.1](https://www.w3.org/TR/WCAG21/) +- [Web Content Accessibility Guidelines (WCAG) 2.2](https://www.w3.org/TR/WCAG/) - [The A11Y Project](https://www.a11yproject.com/) - [MDN accessibility documentation](https://developer.mozilla.org/en-US/docs/Web/Accessibility) - [Tenon.io Accessibility Checker](https://tenon.io/) diff --git a/scss/_functions.scss b/scss/_functions.scss index 5e469e2dc..9d8dc52a4 100644 --- a/scss/_functions.scss +++ b/scss/_functions.scss @@ -177,7 +177,7 @@ $_luminance-list: .0008 .001 .0011 .0013 .0015 .0017 .002 .0022 .0025 .0027 .003 @return if($l1 > $l2, divide($l1 + .05, $l2 + .05), divide($l2 + .05, $l1 + .05)); } -// Return WCAG2.1 relative luminance +// 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) { diff --git a/scss/_variables.scss b/scss/_variables.scss index 75783646c..d518e72a3 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -79,7 +79,7 @@ $colors: ( // scss-docs-end colors-map // The contrast ratio to reach against white, to determine if color changes from "light" to "dark". Acceptable values for WCAG 2.0 are 3, 4.5 and 7. -// See https://www.w3.org/TR/WCAG20/#visual-audio-contrast-contrast +// See https://www.w3.org/TR/WCAG/#contrast-minimum $min-contrast-ratio: 4.5 !default; // Customize the light and dark text colors for use in our color contrast function. diff --git a/scss/mixins/_visually-hidden.scss b/scss/mixins/_visually-hidden.scss index 082aeec95..388916ccf 100644 --- a/scss/mixins/_visually-hidden.scss +++ b/scss/mixins/_visually-hidden.scss @@ -24,7 +24,7 @@ // Use to only display content when it's focused, or one of its child elements is focused // (i.e. when focus is within the element/container that the class was applied to) // -// Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 +// Useful for "Skip to main content" links; see https://www.w3.org/WAI/WCAG22/Techniques/general/G1.html @mixin visually-hidden-focusable() { &:not(:focus):not(:focus-within) { From 2f1fbbe246783f51d72611251d1f7206e3d56b5b Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 22 Aug 2024 00:19:06 +0200 Subject: [PATCH 08/19] fix: `this` reference for JavaScript functions --- js/src/dropdown.js | 2 +- js/src/tooltip.js | 4 +-- js/src/util/index.js | 2 +- js/src/util/template-factory.js | 2 +- js/tests/unit/dropdown.spec.js | 5 ++- js/tests/unit/popover.spec.js | 54 ++++++++++++++++++++++++++++++++ js/tests/unit/tooltip.spec.js | 40 ++++++++++++++++++++--- js/tests/unit/util/index.spec.js | 4 +-- 8 files changed, 101 insertions(+), 12 deletions(-) diff --git a/js/src/dropdown.js b/js/src/dropdown.js index 45a47f141..9422ad9b3 100644 --- a/js/src/dropdown.js +++ b/js/src/dropdown.js @@ -323,7 +323,7 @@ class Dropdown extends BaseComponent { return { ...defaultBsPopperConfig, - ...execute(this._config.popperConfig, [defaultBsPopperConfig]) + ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig]) } } diff --git a/js/src/tooltip.js b/js/src/tooltip.js index 5c662b12f..cb71cf77c 100644 --- a/js/src/tooltip.js +++ b/js/src/tooltip.js @@ -395,7 +395,7 @@ class Tooltip extends BaseComponent { } _resolvePossibleFunction(arg) { - return execute(arg, [this._element]) + return execute(arg, [this._element, this._element]) } _getPopperConfig(attachment) { @@ -441,7 +441,7 @@ class Tooltip extends BaseComponent { return { ...defaultBsPopperConfig, - ...execute(this._config.popperConfig, [defaultBsPopperConfig]) + ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig]) } } diff --git a/js/src/util/index.js b/js/src/util/index.js index 81191e118..80c8c0c20 100644 --- a/js/src/util/index.js +++ b/js/src/util/index.js @@ -226,7 +226,7 @@ const defineJQueryPlugin = plugin => { } const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => { - return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue + return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue } const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => { diff --git a/js/src/util/template-factory.js b/js/src/util/template-factory.js index c0462ec5f..c0a9313bd 100644 --- a/js/src/util/template-factory.js +++ b/js/src/util/template-factory.js @@ -146,7 +146,7 @@ class TemplateFactory extends Config { } _resolvePossibleFunction(arg) { - return execute(arg, [this]) + return execute(arg, [undefined, this]) } _putElementInTemplate(element, templateElement) { diff --git a/js/tests/unit/dropdown.spec.js b/js/tests/unit/dropdown.spec.js index 65b8de4f5..1bca03ef1 100644 --- a/js/tests/unit/dropdown.spec.js +++ b/js/tests/unit/dropdown.spec.js @@ -172,7 +172,10 @@ describe('Dropdown', () => { const popperConfig = dropdown._getPopperConfig() - expect(getPopperConfig).toHaveBeenCalled() + // Ensure that the function was called with the default config. + expect(getPopperConfig).toHaveBeenCalledWith(jasmine.objectContaining({ + placement: jasmine.any(String) + })) expect(popperConfig.placement).toEqual('left') }) }) diff --git a/js/tests/unit/popover.spec.js b/js/tests/unit/popover.spec.js index 6841103fc..34acf4952 100644 --- a/js/tests/unit/popover.spec.js +++ b/js/tests/unit/popover.spec.js @@ -95,6 +95,60 @@ describe('Popover', () => { }) }) + it('should call content and title functions with trigger element', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS twitter' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + title(el) { + return el.dataset.foo + }, + content(el) { + return el.dataset.foo + } + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('bar') + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('bar') + resolve() + }) + + popover.show() + }) + }) + + it('should call content and title functions with correct this value', () => { + return new Promise(resolve => { + fixtureEl.innerHTML = 'BS twitter' + + const popoverEl = fixtureEl.querySelector('a') + const popover = new Popover(popoverEl, { + title() { + return this.dataset.foo + }, + content() { + return this.dataset.foo + } + }) + + popoverEl.addEventListener('shown.bs.popover', () => { + const popoverDisplayed = document.querySelector('.popover') + + expect(popoverDisplayed).not.toBeNull() + expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('bar') + expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('bar') + resolve() + }) + + popover.show() + }) + }) + it('should show a popover with just content without having header', () => { return new Promise(resolve => { fixtureEl.innerHTML = 'Nice link' diff --git a/js/tests/unit/tooltip.spec.js b/js/tests/unit/tooltip.spec.js index a88dcb72d..9ca059e85 100644 --- a/js/tests/unit/tooltip.spec.js +++ b/js/tests/unit/tooltip.spec.js @@ -177,7 +177,10 @@ describe('Tooltip', () => { const popperConfig = tooltip._getPopperConfig('top') - expect(getPopperConfig).toHaveBeenCalled() + // Ensure that the function was called with the default config. + expect(getPopperConfig).toHaveBeenCalledWith(jasmine.objectContaining({ + placement: jasmine.any(String) + })) expect(popperConfig.placement).toEqual('left') }) @@ -919,10 +922,12 @@ describe('Tooltip', () => { it('should show a tooltip with custom class provided as a function in config', () => { return new Promise(resolve => { - fixtureEl.innerHTML = '' + fixtureEl.innerHTML = '' - const spy = jasmine.createSpy('customClass').and.returnValue('custom-class') const tooltipEl = fixtureEl.querySelector('a') + const spy = jasmine.createSpy('customClass').and.callFake(function (el) { + return `${el.dataset.classA} ${this.dataset.classB}` + }) const tooltip = new Tooltip(tooltipEl, { customClass: spy }) @@ -931,7 +936,8 @@ describe('Tooltip', () => { const tip = document.querySelector('.tooltip') expect(tip).not.toBeNull() expect(spy).toHaveBeenCalled() - expect(tip).toHaveClass('custom-class') + expect(tip).toHaveClass('custom-class-a') + expect(tip).toHaveClass('custom-class-b') resolve() }) @@ -1339,6 +1345,32 @@ describe('Tooltip', () => { }) }) + it('should call title function with trigger element', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + title(el) { + return el.dataset.foo + } + }) + + expect(tooltip._getTitle()).toEqual('bar') + }) + + it('should call title function with correct this value', () => { + fixtureEl.innerHTML = '' + + const tooltipEl = fixtureEl.querySelector('a') + const tooltip = new Tooltip(tooltipEl, { + title() { + return this.dataset.foo + } + }) + + expect(tooltip._getTitle()).toEqual('bar') + }) + describe('getInstance', () => { it('should return tooltip instance', () => { fixtureEl.innerHTML = '
' diff --git a/js/tests/unit/util/index.spec.js b/js/tests/unit/util/index.spec.js index a00f2b68c..1efbf1e89 100644 --- a/js/tests/unit/util/index.spec.js +++ b/js/tests/unit/util/index.spec.js @@ -521,10 +521,10 @@ describe('Util', () => { it('should execute if arg is function & return the result', () => { const functionFoo = (num1, num2 = 10) => num1 + num2 - const resultFoo = Util.execute(functionFoo, [4, 5]) + const resultFoo = Util.execute(functionFoo, [undefined, 4, 5]) expect(resultFoo).toBe(9) - const resultFoo1 = Util.execute(functionFoo, [4]) + const resultFoo1 = Util.execute(functionFoo, [undefined, 4]) expect(resultFoo1).toBe(14) const functionBar = () => 'foo' From 09c0776ae0d69847c3a0668390349edb46f44993 Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 22 Aug 2024 00:24:16 +0200 Subject: [PATCH 09/19] docs: fix default values and description content in options table --- docs/content/components/popovers.md | 8 ++++---- docs/content/components/tooltips.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/content/components/popovers.md b/docs/content/components/popovers.md index cef6efacd..edbd39634 100644 --- a/docs/content/components/popovers.md +++ b/docs/content/components/popovers.md @@ -173,15 +173,15 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt | `delay` | number, object | `0` | Delay showing and hiding the popover (ms)—doesn't apply to manual trigger type. If a number is supplied, delay is applied to both hide/show. Object structure is: `delay: { "show": 500, "hide": 100 }`. | | `fallbackPlacements` | string, 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](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements). | | `html` | boolean | `false` | Allow HTML in the popover. If true, HTML tags in the popover's `title` will be rendered in the popover. If false, `innerText` property will be used to insert content into the DOM. Use text if you're worried about XSS attacks. | -| `offset` | number, string, function | `[0, 0]` | Offset of the popover relative to its target. You can pass a string in data attributes with comma separated values like: `data-coreui-offset="10,20"`. When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: [skidding](https://popper.js.org/docs/v2/modifiers/offset/#skidding-1), [distance](https://popper.js.org/docs/v2/modifiers/offset/#distance-1). For more information refer to Popper's [offset docs](https://popper.js.org/docs/v2/modifiers/offset/#options). | -| `placement` | string, function | `'top'` | How to position the popover: auto, top, bottom, left, right. When `auto` is specified, it will dynamically reorient the popover. When a function is used to determine the placement, it is called with the popover DOM node as its first argument and the triggering element DOM node as its second. The `this` context is set to the popover instance. | +| `offset` | number, string, function | `[0, 8]` | Offset of the popover relative to its target. You can pass a string in data attributes with comma separated values like: `data-coreui-offset="10,20"`. When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: [skidding](https://popper.js.org/docs/v2/modifiers/offset/#skidding-1), [distance](https://popper.js.org/docs/v2/modifiers/offset/#distance-1). For more information refer to Popper's [offset docs](https://popper.js.org/docs/v2/modifiers/offset/#options). | +| `placement` | string, function | `'right'` | How to position the popover: auto, top, bottom, left, right. When `auto` is specified, it will dynamically reorient the popover. When a function is used to determine the placement, it is called with the popover DOM node as its first argument and the triggering element DOM node as its second. The `this` context is set to the popover instance. | | `popperConfig` | null, object, function | `null` | To change CoreUI for Bootstrap's default Popper config, see [Popper's configuration](https://popper.js.org/docs/v2/constructors/#options). When a function is used to create the Popper configuration, it's called with an object that contains the CoreUI for Bootstrap's default Popper configuration. It helps you use and merge the default with your own configuration. The function must return a configuration object for Popper.| | `sanitize` | boolean | `true` | Enable or disable the sanitization. If activated `'template'`, `'content'` and `'title'` options will be sanitized. | | `sanitizeFn` | null, function | `null` | Here you can supply your own sanitize function. This can be useful if you prefer to use a dedicated library to perform sanitization. | | `selector` | string, false | `false` | If a selector is provided, popover objects will be delegated to the specified targets. In practice, this is used to also apply popovers to dynamically added DOM elements (`jQuery.on` support). See [this issue]({{< param repo >}}/issues/4215) and [an informative example](https://codepen.io/Johann-S/pen/djJYPb). **Note**: `title` attribute must not be used as a selector. | -| `template` | string | `'
'` | Base HTML to use when creating the popover. The popover's `title` will be injected into the `.popover-inner`. `.popover-arrow` will become the popover's arrow. The outermost wrapper element should have the `.popover` class and `role="popover"`. | +| `template` | string | `'
'` | Base HTML to use when creating the popover. The popover's `title` will be injected into the `.popover-body`. `.popover-arrow` will become the popover's arrow. The outermost wrapper element should have the `.popover` class and `role="popover"`. | | `title` | string, element, function | `''` | Default title value if `title` attribute isn't present. If a function is given, it will be called with its `this` reference set to the element that the popover is attached to. | -| `trigger` | string | `'hover focus'` | How popover is triggered: click, hover, focus, manual. You may pass multiple triggers; separate them with a space. `'manual'` indicates that the popover will be triggered programmatically via the `.popover('show')`, `.popover('hide')` and `.popover('toggle')` methods; this value cannot be combined with any other trigger. `'hover'` on its own will result in popovers that cannot be triggered via the keyboard, and should only be used if alternative methods for conveying the same information for keyboard users is present. | +| `trigger` | string | `'click'` | How popover is triggered: click, hover, focus, manual. You may pass multiple triggers; separate them with a space. `'manual'` indicates that the popover will be triggered programmatically via the `.popover('show')`, `.popover('hide')` and `.popover('toggle')` methods; this value cannot be combined with any other trigger. `'hover'` on its own will result in popovers that cannot be triggered via the keyboard, and should only be used if alternative methods for conveying the same information for keyboard users is present. | {{< /bs-table >}} {{< callout info >}} diff --git a/docs/content/components/tooltips.md b/docs/content/components/tooltips.md index 1f9d743d3..c07707ae2 100644 --- a/docs/content/components/tooltips.md +++ b/docs/content/components/tooltips.md @@ -206,7 +206,7 @@ Note that for security reasons the `sanitize`, `sanitizeFn`, and `allowList` opt | `title` | string, element, function | `''` | Default title value if `title` attribute isn't present. If a function is given, it will be called with its `this` reference set to the element that the popover is attached to. | | `customClass` | string, function | `''` | Add classes to the tooltip when it is shown. Note that these classes will be added in addition to any classes specified in the template. To add multiple classes, separate them with spaces: `'class-1 class-2'`. You can also pass a function that should return a single string containing additional class names. | | `trigger` | string | `'hover focus'` | How tooltip is triggered: click, hover, focus, manual. You may pass multiple triggers; separate them with a space. `'manual'` indicates that the tooltip will be triggered programmatically via the `.tooltip('show')`, `.tooltip('hide')` and `.tooltip('toggle')` methods; this value cannot be combined with any other trigger. `'hover'` on its own will result in tooltips that cannot be triggered via the keyboard, and should only be used if alternative methods for conveying the same information for keyboard users is present. | -| `offset` | array, string, function | `[0, 0]` | Offset of the tooltip relative to its target. You can pass a string in data attributes with comma separated values like: `data-coreui-offset="10,20"`. When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: [skidding](https://popper.js.org/docs/v2/modifiers/offset/#skidding-1), [distance](https://popper.js.org/docs/v2/modifiers/offset/#distance-1). For more information refer to Popper's [offset docs](https://popper.js.org/docs/v2/modifiers/offset/#options). | +| `offset` | array, string, function | `[0, 6]` | Offset of the tooltip relative to its target. You can pass a string in data attributes with comma separated values like: `data-coreui-offset="10,20"`. When a function is used to determine the offset, it is called with an object containing the popper placement, the reference, and popper rects as its first argument. The triggering element DOM node is passed as the second argument. The function must return an array with two numbers: [skidding](https://popper.js.org/docs/v2/modifiers/offset/#skidding-1), [distance](https://popper.js.org/docs/v2/modifiers/offset/#distance-1). For more information refer to Popper's [offset docs](https://popper.js.org/docs/v2/modifiers/offset/#options). | | `fallbackPlacements` | string, 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](https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements. | | `boundary` | string, element | `'clippingParents'` | Overflow constraint boundary of the tooltip (applies only to Popper's preventOverflow modifier). By default, it's `'clippingParents'` and can accept an HTMLElement reference (via JavaScript only). For more information refer to Popper's [detectOverflow docs](https://popper.js.org/docs/v2/utils/detect-overflow/#boundary). | | `sanitize` | boolean | `true` | Enable or disable the sanitization. If activated `'template'`, `'content'` and `'title'` options will be sanitized. | From b2f5ecd712f19fa028cd3076e56ff328f4538750 Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 22 Aug 2024 00:32:53 +0200 Subject: [PATCH 10/19] fix(Floating Labels): `max-width` and `background-color` --- js/tests/visual/floating-label.html | 337 ++++++++++++++++++++++++++++ scss/forms/_floating-labels.scss | 33 +-- 2 files changed, 354 insertions(+), 16 deletions(-) create mode 100644 js/tests/visual/floating-label.html diff --git a/js/tests/visual/floating-label.html b/js/tests/visual/floating-label.html new file mode 100644 index 000000000..9602fc6bf --- /dev/null +++ b/js/tests/visual/floating-label.html @@ -0,0 +1,337 @@ + + + + + + + Form + + + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + + + \ No newline at end of file diff --git a/scss/forms/_floating-labels.scss b/scss/forms/_floating-labels.scss index 08a7a1c21..557c8c9e4 100644 --- a/scss/forms/_floating-labels.scss +++ b/scss/forms/_floating-labels.scss @@ -14,9 +14,11 @@ top: 0; @include ltr-rtl("left", 0); z-index: 2; + max-width: 100%; height: 100%; // allow textareas padding: $form-floating-padding-y $form-floating-padding-x; overflow: hidden; + color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity}); text-align: start; text-overflow: ellipsis; white-space: nowrap; @@ -56,27 +58,30 @@ > .form-control-plaintext, > .form-select { ~ label { - color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity}); transform: $form-floating-label-transform; - - &::after { - position: absolute; - inset: $form-floating-padding-y ($form-floating-padding-x * .5); - z-index: -1; - height: $form-floating-label-height; - content: ""; - background-color: $input-bg; - @include border-radius($input-border-radius); - } } } // Duplicated because `:-webkit-autofill` invalidates other selectors when grouped > .form-control:-webkit-autofill { ~ label { - color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity}); transform: $form-floating-label-transform; } } + > textarea:focus, + > textarea:not(:placeholder-shown) { + ~ label::after { + position: absolute; + inset: $form-floating-padding-y ($form-floating-padding-x * .5); + z-index: -1; + height: $form-floating-label-height; + content: ""; + background-color: $input-bg; + @include border-radius($input-border-radius); + } + } + > textarea:disabled ~ label::after { + background-color: $input-disabled-bg; + } > .form-control-plaintext { ~ label { @@ -87,9 +92,5 @@ > :disabled ~ label, > .form-control:disabled ~ label { // Required for `.form-control`s because of specificity color: $form-floating-label-disabled-color; - - &::after { - background-color: $input-disabled-bg; - } } } From ba36c66d7b83986b355d2ae4bb1aef3b3ad0e854 Mon Sep 17 00:00:00 2001 From: mrholek Date: Thu, 22 Aug 2024 00:38:00 +0200 Subject: [PATCH 11/19] fix(Button Group): `.btn-group-vertical` border radius with dropdown as first element --- docs/content/components/button-group.md | 4 ++-- scss/_button-group.scss | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/content/components/button-group.md b/docs/content/components/button-group.md index cfdb22dcd..b9ea1eb55 100644 --- a/docs/content/components/button-group.md +++ b/docs/content/components/button-group.md @@ -205,8 +205,6 @@ Create a set of buttons that appear vertically stacked rather than horizontally. {{< example >}}
- -
+ +