WIP: Añade componente para la gestión de menús #8
109 changed files with 536 additions and 173 deletions
|
|
@ -4,10 +4,7 @@ use std::env;
|
|||
use std::path::Path;
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
StaticFilesBundle::from_scss(
|
||||
"./static/bootstrap-5.3.3/bootstrap.scss",
|
||||
"bootstrap.min.css",
|
||||
)
|
||||
StaticFilesBundle::from_scss("./static/bootstrap/bootstrap.scss", "bootstrap.min.css")
|
||||
.with_name("bootsier")
|
||||
.build()?;
|
||||
StaticFilesBundle::from_dir("./static/js", Some(bootstrap_js_files))
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ use pagetop::prelude::*;
|
|||
pub type BootsierRegion = ThemeRegion;
|
||||
|
||||
// Versión de la librería Bootstrap.
|
||||
const BOOTSTRAP_VERSION: &str = "5.3.3";
|
||||
const BOOTSTRAP_VERSION: &str = "5.3.8";
|
||||
|
||||
/// Tema basado en [Bootstrap](https://getbootstrap.com/) para los componentes base de PageTop.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
@mixin box-shadow($shadow...) {
|
||||
@if $enable-shadows {
|
||||
$result: ();
|
||||
|
||||
@each $value in $shadow {
|
||||
@if $value != null {
|
||||
$result: append($result, $value, "comma");
|
||||
}
|
||||
@if $value == none and length($shadow) > 1 {
|
||||
@warn "The keyword 'none' must be used as a single argument.";
|
||||
}
|
||||
}
|
||||
|
||||
@if (length($result) > 0) {
|
||||
box-shadow: $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -134,17 +134,12 @@
|
|||
&:last-child { border-bottom: 0; }
|
||||
|
||||
// stylelint-disable selector-max-class
|
||||
> .accordion-header .accordion-button {
|
||||
&,
|
||||
&.collapsed {
|
||||
> .accordion-collapse,
|
||||
> .accordion-header .accordion-button,
|
||||
> .accordion-header .accordion-button.collapsed {
|
||||
@include border-radius(0);
|
||||
}
|
||||
}
|
||||
// stylelint-enable selector-max-class
|
||||
|
||||
> .accordion-collapse {
|
||||
@include border-radius(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
// Prevent double borders when buttons are next to each other
|
||||
> :not(.btn-check:first-child) + .btn,
|
||||
> .btn-group:not(:first-child) {
|
||||
margin-left: calc(#{$btn-border-width} * -1); // stylelint-disable-line function-disallowed-list
|
||||
margin-left: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list
|
||||
}
|
||||
|
||||
// Reset rounded corners
|
||||
|
|
@ -126,7 +126,7 @@
|
|||
|
||||
> .btn:not(:first-child),
|
||||
> .btn-group:not(:first-child) {
|
||||
margin-top: calc(#{$btn-border-width} * -1); // stylelint-disable-line function-disallowed-list
|
||||
margin-top: calc(-1 * #{$btn-border-width}); // stylelint-disable-line function-disallowed-list
|
||||
}
|
||||
|
||||
// Reset rounded corners
|
||||
|
|
@ -135,7 +135,12 @@
|
|||
@include border-bottom-radius(0);
|
||||
}
|
||||
|
||||
> .btn ~ .btn,
|
||||
// The top radius should be 0 if the button is:
|
||||
// - the "third or more" child
|
||||
// - the second child and the previous element isn't `.btn-check` (making it the first child visually)
|
||||
// - part of a btn-group which isn't the first child
|
||||
> .btn:nth-child(n + 3),
|
||||
> :not(.btn-check) + .btn,
|
||||
> .btn-group:not(:first-child) > .btn {
|
||||
@include border-top-radius(0);
|
||||
}
|
||||
|
|
@ -193,8 +193,7 @@
|
|||
// The child selector allows nested `.card` within `.card-group`
|
||||
// to display properly.
|
||||
> .card {
|
||||
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
|
||||
flex: 1 0 0%;
|
||||
flex: 1 0 0;
|
||||
margin-bottom: 0;
|
||||
|
||||
+ .card {
|
||||
|
|
@ -207,13 +206,13 @@
|
|||
&:not(:last-child) {
|
||||
@include border-end-radius(0);
|
||||
|
||||
.card-img-top,
|
||||
.card-header {
|
||||
> .card-img-top,
|
||||
> .card-header {
|
||||
// stylelint-disable-next-line property-disallowed-list
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
.card-img-bottom,
|
||||
.card-footer {
|
||||
> .card-img-bottom,
|
||||
> .card-footer {
|
||||
// stylelint-disable-next-line property-disallowed-list
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
|
@ -222,13 +221,13 @@
|
|||
&:not(:first-child) {
|
||||
@include border-start-radius(0);
|
||||
|
||||
.card-img-top,
|
||||
.card-header {
|
||||
> .card-img-top,
|
||||
> .card-header {
|
||||
// stylelint-disable-next-line property-disallowed-list
|
||||
border-top-left-radius: 0;
|
||||
}
|
||||
.card-img-bottom,
|
||||
.card-footer {
|
||||
> .card-img-bottom,
|
||||
> .card-footer {
|
||||
// stylelint-disable-next-line property-disallowed-list
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
|
@ -99,6 +99,7 @@
|
|||
color: $carousel-control-color;
|
||||
text-align: center;
|
||||
background: none;
|
||||
filter: var(--#{$prefix}carousel-control-icon-filter);
|
||||
border: 0;
|
||||
opacity: $carousel-control-opacity;
|
||||
@include transition($carousel-control-transition);
|
||||
|
|
@ -168,7 +169,7 @@
|
|||
margin-left: $carousel-indicator-spacer;
|
||||
text-indent: -999px;
|
||||
cursor: pointer;
|
||||
background-color: $carousel-indicator-active-bg;
|
||||
background-color: var(--#{$prefix}carousel-indicator-active-bg);
|
||||
background-clip: padding-box;
|
||||
border: 0;
|
||||
// Use transparent borders to increase the hit area by 10px on top and bottom.
|
||||
|
|
@ -195,42 +196,31 @@
|
|||
left: (100% - $carousel-caption-width) * .5;
|
||||
padding-top: $carousel-caption-padding-y;
|
||||
padding-bottom: $carousel-caption-padding-y;
|
||||
color: $carousel-caption-color;
|
||||
color: var(--#{$prefix}carousel-caption-color);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
// Dark mode carousel
|
||||
|
||||
@mixin carousel-dark() {
|
||||
.carousel-control-prev-icon,
|
||||
.carousel-control-next-icon {
|
||||
filter: $carousel-dark-control-icon-filter;
|
||||
}
|
||||
|
||||
.carousel-indicators [data-bs-target] {
|
||||
background-color: $carousel-dark-indicator-active-bg;
|
||||
}
|
||||
|
||||
.carousel-caption {
|
||||
color: $carousel-dark-caption-color;
|
||||
}
|
||||
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg-dark};
|
||||
--#{$prefix}carousel-caption-color: #{$carousel-caption-color-dark};
|
||||
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter-dark};
|
||||
}
|
||||
|
||||
.carousel-dark {
|
||||
@include carousel-dark();
|
||||
}
|
||||
|
||||
:root,
|
||||
[data-bs-theme="light"] {
|
||||
--#{$prefix}carousel-indicator-active-bg: #{$carousel-indicator-active-bg};
|
||||
--#{$prefix}carousel-caption-color: #{$carousel-caption-color};
|
||||
--#{$prefix}carousel-control-icon-filter: #{$carousel-control-icon-filter};
|
||||
}
|
||||
|
||||
@if $enable-dark-mode {
|
||||
@include color-mode(dark) {
|
||||
@if $color-mode-type == "media-query" {
|
||||
.carousel {
|
||||
@include carousel-dark();
|
||||
}
|
||||
} @else {
|
||||
.carousel,
|
||||
&.carousel {
|
||||
@include color-mode(dark, true) {
|
||||
@include carousel-dark();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@
|
|||
--#{$prefix}btn-close-focus-shadow: #{$btn-close-focus-shadow};
|
||||
--#{$prefix}btn-close-focus-opacity: #{$btn-close-focus-opacity};
|
||||
--#{$prefix}btn-close-disabled-opacity: #{$btn-close-disabled-opacity};
|
||||
--#{$prefix}btn-close-white-filter: #{$btn-close-white-filter};
|
||||
// scss-docs-end close-css-vars
|
||||
|
||||
box-sizing: content-box;
|
||||
|
|
@ -21,6 +20,7 @@
|
|||
padding: $btn-close-padding-y $btn-close-padding-x;
|
||||
color: var(--#{$prefix}btn-close-color);
|
||||
background: transparent var(--#{$prefix}btn-close-bg) center / $btn-close-width auto no-repeat; // include transparent for button elements
|
||||
filter: var(--#{$prefix}btn-close-filter);
|
||||
border: 0; // for button elements
|
||||
@include border-radius();
|
||||
opacity: var(--#{$prefix}btn-close-opacity);
|
||||
|
|
@ -47,17 +47,20 @@
|
|||
}
|
||||
|
||||
@mixin btn-close-white() {
|
||||
filter: var(--#{$prefix}btn-close-white-filter);
|
||||
--#{$prefix}btn-close-filter: #{$btn-close-filter-dark};
|
||||
}
|
||||
|
||||
.btn-close-white {
|
||||
@include btn-close-white();
|
||||
}
|
||||
|
||||
:root,
|
||||
[data-bs-theme="light"] {
|
||||
--#{$prefix}btn-close-filter: #{$btn-close-filter};
|
||||
}
|
||||
|
||||
@if $enable-dark-mode {
|
||||
@include color-mode(dark) {
|
||||
.btn-close {
|
||||
@include color-mode(dark, true) {
|
||||
@include btn-close-white();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ $_luminance-list: .0008 .001 .0011 .0013 .0015 .0017 .002 .0022 .0025 .0027 .003
|
|||
|
||||
@each $color in $foregrounds {
|
||||
$contrast-ratio: contrast-ratio($background, $color);
|
||||
@if $contrast-ratio > $min-contrast-ratio {
|
||||
@if $contrast-ratio >= $min-contrast-ratio {
|
||||
@return $color;
|
||||
} @else if $contrast-ratio > $max-ratio {
|
||||
$max-ratio: $contrast-ratio;
|
||||
|
|
@ -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) {
|
||||
|
|
@ -43,31 +43,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Interactive list items
|
||||
//
|
||||
// Use anchor or button elements instead of `li`s or `div`s to create interactive
|
||||
// list items. Includes an extra `.active` modifier class for selected items.
|
||||
|
||||
.list-group-item-action {
|
||||
width: 100%; // For `<button>`s (anchors become 100% by default though)
|
||||
color: var(--#{$prefix}list-group-action-color);
|
||||
text-align: inherit; // For `<button>`s (anchors inherit)
|
||||
|
||||
// Hover state
|
||||
&:hover,
|
||||
&:focus {
|
||||
z-index: 1; // Place hover/focus items above their siblings for proper border styling
|
||||
color: var(--#{$prefix}list-group-action-hover-color);
|
||||
text-decoration: none;
|
||||
background-color: var(--#{$prefix}list-group-action-hover-bg);
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--#{$prefix}list-group-action-active-color);
|
||||
background-color: var(--#{$prefix}list-group-action-active-bg);
|
||||
}
|
||||
}
|
||||
|
||||
// Individual list items
|
||||
//
|
||||
// Use on `li`s or `div`s within the `.list-group` parent.
|
||||
|
|
@ -115,6 +90,33 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Interactive list items
|
||||
//
|
||||
// Use anchor or button elements instead of `li`s or `div`s to create interactive
|
||||
// list items. Includes an extra `.active` modifier class for selected items.
|
||||
|
||||
.list-group-item-action {
|
||||
width: 100%; // For `<button>`s (anchors become 100% by default though)
|
||||
color: var(--#{$prefix}list-group-action-color);
|
||||
text-align: inherit; // For `<button>`s (anchors inherit)
|
||||
|
||||
&:not(.active) {
|
||||
// Hover state
|
||||
&:hover,
|
||||
&:focus {
|
||||
z-index: 1; // Place hover/focus items above their siblings for proper border styling
|
||||
color: var(--#{$prefix}list-group-action-hover-color);
|
||||
text-decoration: none;
|
||||
background-color: var(--#{$prefix}list-group-action-hover-bg);
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: var(--#{$prefix}list-group-action-active-color);
|
||||
background-color: var(--#{$prefix}list-group-action-active-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal
|
||||
//
|
||||
// Change the layout of list group items from vertical (default) to horizontal.
|
||||
|
|
@ -59,8 +59,8 @@
|
|||
|
||||
// When fading in the modal, animate it to slide down
|
||||
.modal.fade & {
|
||||
@include transition($modal-transition);
|
||||
transform: $modal-fade-transform;
|
||||
@include transition($modal-transition);
|
||||
}
|
||||
.modal.show & {
|
||||
transform: $modal-show-transform;
|
||||
|
|
@ -132,7 +132,11 @@
|
|||
|
||||
.btn-close {
|
||||
padding: calc(var(--#{$prefix}modal-header-padding-y) * .5) calc(var(--#{$prefix}modal-header-padding-x) * .5);
|
||||
margin: calc(-.5 * var(--#{$prefix}modal-header-padding-y)) calc(-.5 * var(--#{$prefix}modal-header-padding-x)) calc(-.5 * var(--#{$prefix}modal-header-padding-y)) auto;
|
||||
// Split properties to avoid invalid calc() function if value is 0
|
||||
margin-top: calc(-.5 * var(--#{$prefix}modal-header-padding-y));
|
||||
margin-right: calc(-.5 * var(--#{$prefix}modal-header-padding-x));
|
||||
margin-bottom: calc(-.5 * var(--#{$prefix}modal-header-padding-y));
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,8 +169,8 @@
|
|||
.nav-justified {
|
||||
> .nav-link,
|
||||
.nav-item {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
flex-basis: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
|
@ -139,8 +139,8 @@
|
|||
// the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
|
||||
// on the `.navbar` parent.
|
||||
.navbar-collapse {
|
||||
flex-basis: 100%;
|
||||
flex-grow: 1;
|
||||
flex-basis: 100%;
|
||||
// For always expanded or extra full navbars, ensure content aligns itself
|
||||
// properly vertically. Can be easily overridden with flex utilities.
|
||||
align-items: center;
|
||||
|
|
@ -127,7 +127,11 @@
|
|||
|
||||
.btn-close {
|
||||
padding: calc(var(--#{$prefix}offcanvas-padding-y) * .5) calc(var(--#{$prefix}offcanvas-padding-x) * .5);
|
||||
margin: calc(-.5 * var(--#{$prefix}offcanvas-padding-y)) calc(-.5 * var(--#{$prefix}offcanvas-padding-x)) calc(-.5 * var(--#{$prefix}offcanvas-padding-y)) auto;
|
||||
// Split properties to avoid invalid calc() function if value is 0
|
||||
margin-top: calc(-.5 * var(--#{$prefix}offcanvas-padding-y));
|
||||
margin-right: calc(-.5 * var(--#{$prefix}offcanvas-padding-x));
|
||||
margin-bottom: calc(-.5 * var(--#{$prefix}offcanvas-padding-y));
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
margin-left: $pagination-margin-start;
|
||||
}
|
||||
|
||||
@if $pagination-margin-start == calc(#{$pagination-border-width} * -1) {
|
||||
@if $pagination-margin-start == calc(-1 * #{$pagination-border-width}) {
|
||||
&:first-child {
|
||||
.page-link {
|
||||
@include border-start-radius(var(--#{$prefix}pagination-border-radius));
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
// scss-docs-start progress-keyframes
|
||||
@if $enable-transitions {
|
||||
@keyframes progress-bar-stripes {
|
||||
0% { background-position-x: $progress-height; }
|
||||
0% { background-position-x: var(--#{$prefix}progress-height); }
|
||||
}
|
||||
}
|
||||
// scss-docs-end progress-keyframes
|
||||
|
|
@ -499,9 +499,9 @@ legend {
|
|||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: $legend-margin-bottom;
|
||||
@include font-size($legend-font-size);
|
||||
font-weight: $legend-font-weight;
|
||||
line-height: inherit;
|
||||
@include font-size($legend-font-size);
|
||||
|
||||
+ * {
|
||||
clear: left; // 2
|
||||
|
|
@ -534,6 +534,12 @@ legend {
|
|||
[type="search"] {
|
||||
-webkit-appearance: textfield; // 1
|
||||
outline-offset: -2px; // 2
|
||||
|
||||
// 3. Better affordance and consistent appearance for search cancel button
|
||||
&::-webkit-search-cancel-button {
|
||||
cursor: pointer;
|
||||
filter: grayscale(1);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. A few input types should stay LTR
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
.spinner-grow,
|
||||
.spinner-border {
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
width: var(--#{$prefix}spinner-width);
|
||||
height: var(--#{$prefix}spinner-height);
|
||||
vertical-align: var(--#{$prefix}spinner-vertical-align);
|
||||
|
|
@ -34,11 +34,11 @@
|
|||
// Type display classes
|
||||
@each $display, $font-size in $display-font-sizes {
|
||||
.display-#{$display} {
|
||||
@include font-size($font-size);
|
||||
font-family: $display-font-family;
|
||||
font-style: $display-font-style;
|
||||
font-weight: $display-font-weight;
|
||||
line-height: $display-line-height;
|
||||
@include font-size($font-size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,6 +82,21 @@ $form-invalid-border-color-dark: $red-300 !default;
|
|||
$accordion-icon-color-dark: $primary-text-emphasis-dark !default;
|
||||
$accordion-icon-active-color-dark: $primary-text-emphasis-dark !default;
|
||||
|
||||
$accordion-button-icon-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/></svg>") !default;
|
||||
$accordion-button-active-icon-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-active-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z'/></svg>") !default;
|
||||
$accordion-button-icon-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/></svg>") !default;
|
||||
$accordion-button-active-icon-dark: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$accordion-icon-active-color-dark}'><path fill-rule='evenodd' d='M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708'/></svg>") !default;
|
||||
// scss-docs-end sass-dark-mode-vars
|
||||
|
||||
|
||||
//
|
||||
// Carousel
|
||||
//
|
||||
|
||||
$carousel-indicator-active-bg-dark: $carousel-dark-indicator-active-bg !default;
|
||||
$carousel-caption-color-dark: $carousel-dark-caption-color !default;
|
||||
$carousel-control-icon-filter-dark: $carousel-dark-control-icon-filter !default;
|
||||
|
||||
//
|
||||
// Close button
|
||||
//
|
||||
|
||||
$btn-close-filter-dark: $btn-close-white-filter !default;
|
||||
|
|
@ -67,8 +67,8 @@ $colors: (
|
|||
) !default;
|
||||
// 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
|
||||
// The contrast ratio to reach against white, to determine if color changes from "light" to "dark". Acceptable values for WCAG 2.2 are 3, 4.5 and 7.
|
||||
// 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.
|
||||
|
|
@ -1091,7 +1091,7 @@ $form-feedback-valid-color: $success !default;
|
|||
$form-feedback-invalid-color: $danger !default;
|
||||
|
||||
$form-feedback-icon-valid-color: $form-feedback-valid-color !default;
|
||||
$form-feedback-icon-valid: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/></svg>") !default;
|
||||
$form-feedback-icon-valid: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><path fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1'/></svg>") !default;
|
||||
$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;
|
||||
$form-feedback-icon-invalid: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12' width='12' height='12' fill='none' stroke='#{$form-feedback-icon-invalid-color}'><circle cx='6' cy='6' r='4.5'/><path stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/><circle cx='6' cy='8.2' r='.6' fill='#{$form-feedback-icon-invalid-color}' stroke='none'/></svg>") !default;
|
||||
// scss-docs-end form-feedback-variables
|
||||
|
|
@ -1302,7 +1302,7 @@ $pagination-color: var(--#{$prefix}link-color) !default;
|
|||
$pagination-bg: var(--#{$prefix}body-bg) !default;
|
||||
$pagination-border-radius: var(--#{$prefix}border-radius) !default;
|
||||
$pagination-border-width: var(--#{$prefix}border-width) !default;
|
||||
$pagination-margin-start: calc(#{$pagination-border-width} * -1) !default; // stylelint-disable-line function-disallowed-list
|
||||
$pagination-margin-start: calc(-1 * #{$pagination-border-width}) !default; // stylelint-disable-line function-disallowed-list
|
||||
$pagination-border-color: var(--#{$prefix}border-color) !default;
|
||||
|
||||
$pagination-focus-color: var(--#{$prefix}link-hover-color) !default;
|
||||
|
|
@ -1394,8 +1394,8 @@ $accordion-icon-active-color: $primary-text-emphasis !default;
|
|||
$accordion-icon-transition: transform .2s ease-in-out !default;
|
||||
$accordion-icon-transform: rotate(-180deg) !default;
|
||||
|
||||
$accordion-button-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='#{$accordion-icon-color}' stroke-linecap='round' stroke-linejoin='round'><path d='M2 5L8 11L14 5'/></svg>") !default;
|
||||
$accordion-button-active-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='#{$accordion-icon-active-color}' stroke-linecap='round' stroke-linejoin='round'><path d='M2 5L8 11L14 5'/></svg>") !default;
|
||||
$accordion-button-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='#{$accordion-icon-color}' stroke-linecap='round' stroke-linejoin='round'><path d='m2 5 6 6 6-6'/></svg>") !default;
|
||||
$accordion-button-active-icon: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='#{$accordion-icon-active-color}' stroke-linecap='round' stroke-linejoin='round'><path d='m2 5 6 6 6-6'/></svg>") !default;
|
||||
// scss-docs-end accordion-variables
|
||||
|
||||
// Tooltips
|
||||
|
|
@ -1507,7 +1507,7 @@ $modal-dialog-margin-y-sm-up: 1.75rem !default;
|
|||
|
||||
$modal-title-line-height: $line-height-base !default;
|
||||
|
||||
$modal-content-color: null !default;
|
||||
$modal-content-color: var(--#{$prefix}body-color) !default;
|
||||
$modal-content-bg: var(--#{$prefix}body-bg) !default;
|
||||
$modal-content-border-color: var(--#{$prefix}border-color-translucent) !default;
|
||||
$modal-content-border-width: var(--#{$prefix}border-width) !default;
|
||||
|
|
@ -1652,6 +1652,7 @@ $carousel-control-width: 15% !default;
|
|||
$carousel-control-opacity: .5 !default;
|
||||
$carousel-control-hover-opacity: .9 !default;
|
||||
$carousel-control-transition: opacity .15s ease !default;
|
||||
$carousel-control-icon-filter: null !default;
|
||||
|
||||
$carousel-indicator-width: 30px !default;
|
||||
$carousel-indicator-height: 3px !default;
|
||||
|
|
@ -1669,17 +1670,17 @@ $carousel-caption-spacer: 1.25rem !default;
|
|||
|
||||
$carousel-control-icon-width: 2rem !default;
|
||||
|
||||
$carousel-control-prev-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$carousel-control-color}'><path d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/></svg>") !default;
|
||||
$carousel-control-next-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$carousel-control-color}'><path d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/></svg>") !default;
|
||||
$carousel-control-prev-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$carousel-control-color}'><path d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0'/></svg>") !default;
|
||||
$carousel-control-next-icon-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$carousel-control-color}'><path d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708'/></svg>") !default;
|
||||
|
||||
$carousel-transition-duration: .6s !default;
|
||||
$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
|
||||
// scss-docs-end carousel-variables
|
||||
|
||||
// scss-docs-start carousel-dark-variables
|
||||
$carousel-dark-indicator-active-bg: $black !default;
|
||||
$carousel-dark-caption-color: $black !default;
|
||||
$carousel-dark-control-icon-filter: invert(1) grayscale(100) !default;
|
||||
$carousel-dark-indicator-active-bg: $black !default; // Deprecated in v5.3.4
|
||||
$carousel-dark-caption-color: $black !default; // Deprecated in v5.3.4
|
||||
$carousel-dark-control-icon-filter: invert(1) grayscale(100) !default; // Deprecated in v5.3.4
|
||||
// scss-docs-end carousel-dark-variables
|
||||
|
||||
|
||||
|
|
@ -1706,13 +1707,14 @@ $btn-close-height: $btn-close-width !default;
|
|||
$btn-close-padding-x: .25em !default;
|
||||
$btn-close-padding-y: $btn-close-padding-x !default;
|
||||
$btn-close-color: $black !default;
|
||||
$btn-close-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$btn-close-color}'><path d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/></svg>") !default;
|
||||
$btn-close-bg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#{$btn-close-color}'><path d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/></svg>") !default;
|
||||
$btn-close-focus-shadow: $focus-ring-box-shadow !default;
|
||||
$btn-close-opacity: .5 !default;
|
||||
$btn-close-hover-opacity: .75 !default;
|
||||
$btn-close-focus-opacity: 1 !default;
|
||||
$btn-close-disabled-opacity: .25 !default;
|
||||
$btn-close-white-filter: invert(1) grayscale(100%) brightness(200%) !default;
|
||||
$btn-close-filter: null !default;
|
||||
$btn-close-white-filter: invert(1) grayscale(100%) brightness(200%) !default; // Deprecated in v5.3.4
|
||||
// scss-docs-end close-variables
|
||||
|
||||
|
||||
|
|
@ -14,9 +14,11 @@
|
|||
top: 0;
|
||||
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;
|
||||
|
|
@ -49,6 +51,7 @@
|
|||
> .form-select {
|
||||
padding-top: $form-floating-input-padding-t;
|
||||
padding-bottom: $form-floating-input-padding-b;
|
||||
padding-left: $form-floating-padding-x;
|
||||
}
|
||||
|
||||
> .form-control:focus,
|
||||
|
|
@ -56,10 +59,18 @@
|
|||
> .form-control-plaintext,
|
||||
> .form-select {
|
||||
~ label {
|
||||
color: rgba(var(--#{$prefix}body-color-rgb), #{$form-floating-label-opacity});
|
||||
transform: $form-floating-label-transform;
|
||||
|
||||
&::after {
|
||||
}
|
||||
}
|
||||
// Duplicated because `:-webkit-autofill` invalidates other selectors when grouped
|
||||
> .form-control:-webkit-autofill {
|
||||
~ label {
|
||||
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;
|
||||
|
|
@ -69,13 +80,8 @@
|
|||
@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:disabled ~ label::after {
|
||||
background-color: $input-disabled-bg;
|
||||
}
|
||||
|
||||
> .form-control-plaintext {
|
||||
|
|
@ -87,9 +93,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
}
|
||||
|
||||
> :not(:first-child):not(.dropdown-menu)#{$validation-messages} {
|
||||
margin-left: calc(#{$input-border-width} * -1); // stylelint-disable-line function-disallowed-list
|
||||
margin-left: calc(-1 * #{$input-border-width}); // stylelint-disable-line function-disallowed-list
|
||||
@include border-start-radius(0);
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
@mixin bsBanner($file) {
|
||||
/*!
|
||||
* Bootstrap #{$file} v5.3.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Bootstrap #{$file} v5.3.8 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2025 The Bootstrap Authors
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
@mixin box-shadow($shadow...) {
|
||||
@if $enable-shadows {
|
||||
$result: ();
|
||||
$has-single-value: false;
|
||||
$single-value: null;
|
||||
|
||||
@each $value in $shadow {
|
||||
@if $value != null {
|
||||
@if $value == none or $value == initial or $value == inherit or $value == unset {
|
||||
$has-single-value: true;
|
||||
$single-value: $value;
|
||||
} @else {
|
||||
$result: append($result, $value, "comma");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if $has-single-value {
|
||||
box-shadow: $single-value;
|
||||
} @else if (length($result) > 0) {
|
||||
box-shadow: $result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
@include media-breakpoint-up($breakpoint, $breakpoints) {
|
||||
// Provide basic `.col-{bp}` classes for equal-width flexbox columns
|
||||
.col#{$infix} {
|
||||
flex: 1 0 0%; // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
|
||||
flex: 1 0 0;
|
||||
}
|
||||
|
||||
.row-cols#{$infix}-auto > * {
|
||||
|
|
@ -19,12 +19,17 @@
|
|||
&:not(caption) {
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
// Fix to prevent overflowing children to become focusable
|
||||
* {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
|
@ -0,0 +1,188 @@
|
|||
@import "../../functions";
|
||||
@import "../../variables";
|
||||
@import "../../mixins";
|
||||
|
||||
// Store original value
|
||||
$original-enable-shadows: $enable-shadows;
|
||||
|
||||
// Enable shadows for all tests
|
||||
$enable-shadows: true !global;
|
||||
|
||||
@include describe("box-shadow mixin") {
|
||||
@include it("handles single none value") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(none);
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles multiple none values by consolidating them") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(none, none, none);
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles other single-value keywords (initial, inherit, unset)") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test-initial {
|
||||
@include box-shadow(initial);
|
||||
}
|
||||
.test-inherit {
|
||||
@include box-shadow(inherit);
|
||||
}
|
||||
.test-unset {
|
||||
@include box-shadow(unset);
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test-initial {
|
||||
box-shadow: initial;
|
||||
}
|
||||
.test-inherit {
|
||||
box-shadow: inherit;
|
||||
}
|
||||
.test-unset {
|
||||
box-shadow: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles multiple single-value keywords by using the last one") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(initial, inherit, unset);
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles regular box-shadow values") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(0 0 10px rgba(0, 0, 0, .5));
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles multiple regular box-shadow values") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(0 0 10px rgba(0, 0, 0, .5), 0 0 20px rgba(0, 0, 0, .3));
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, .5), 0 0 20px rgba(0, 0, 0, .3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles null values by ignoring them") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(null, 0 0 10px rgba(0, 0, 0, .5), null);
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, .5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles mixed values with keywords and regular shadows") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(none, 0 0 10px rgba(0, 0, 0, .5));
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("handles empty input") {
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow();
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test { // stylelint-disable-line block-no-empty
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include it("respects $enable-shadows variable") {
|
||||
$enable-shadows: false !global;
|
||||
|
||||
@include assert() {
|
||||
@include output() {
|
||||
.test {
|
||||
@include box-shadow(0 0 10px rgba(0, 0, 0, .5));
|
||||
}
|
||||
}
|
||||
|
||||
@include expect() {
|
||||
.test { // stylelint-disable-line block-no-empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$enable-shadows: true !global;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore original value
|
||||
$enable-shadows: $original-enable-shadows !global;
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
@import "../../functions";
|
||||
@import "../../variables";
|
||||
@import "../../variables-dark";
|
||||
@import "../../maps";
|
||||
@import "../../mixins";
|
||||
|
||||
@include describe("color-contrast function") {
|
||||
@include it("should return a color when contrast ratio equals minimum requirement (WCAG 2.1 compliance)") {
|
||||
// Test case: Background color that produces contrast ratio close to 4.5:1
|
||||
// This tests the WCAG 2.1 requirement that contrast should be "at least 4.5:1" (>= 4.5)
|
||||
// rather than "strictly greater than 4.5:1" (> 4.5)
|
||||
|
||||
// #777777 produces 4.4776:1 contrast ratio with white text
|
||||
// Since this is below the 4.5:1 threshold, it should return the highest available contrast color
|
||||
$test-background: #777;
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
@include assert-equal($result, $black, "Should return black (highest available contrast) for background with 4.4776:1 contrast ratio (below threshold)");
|
||||
}
|
||||
|
||||
@include it("should return a color when contrast ratio is above minimum requirement") {
|
||||
// Test case: Background color that produces contrast ratio above 4.5:1
|
||||
// #767676 produces 4.5415:1 contrast ratio with white text
|
||||
$test-background: #767676;
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
@include assert-equal($result, $white, "Should return white for background with 4.5415:1 contrast ratio (above threshold)");
|
||||
}
|
||||
|
||||
@include it("should return a color when contrast ratio is below minimum requirement") {
|
||||
// Test case: Background color that produces contrast ratio below 4.5:1
|
||||
// #787878 produces 4.4155:1 contrast ratio with white text
|
||||
$test-background: #787878;
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
// Should return the color with the highest available contrast ratio
|
||||
@include assert-equal($result, $black, "Should return black (highest available contrast) for background with 4.4155:1 contrast ratio (below threshold)");
|
||||
}
|
||||
|
||||
@include it("should handle edge case with very light background") {
|
||||
// Test case: Very light background that should return dark text
|
||||
$test-background: #f8f9fa; // Very light gray
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
@include assert-equal($result, $color-contrast-dark, "Should return dark text for very light background");
|
||||
}
|
||||
|
||||
@include it("should handle edge case with very dark background") {
|
||||
// Test case: Very dark background that should return light text
|
||||
$test-background: #212529; // Very dark gray
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
@include assert-equal($result, $color-contrast-light, "Should return light text for very dark background");
|
||||
}
|
||||
|
||||
@include it("should work with custom minimum contrast ratio") {
|
||||
// Test case: Using a custom minimum contrast ratio
|
||||
$test-background: #666;
|
||||
$result: color-contrast($test-background, $color-contrast-dark, $color-contrast-light, 3);
|
||||
|
||||
@include assert-equal($result, $white, "Should return white when using custom minimum contrast ratio of 3.0");
|
||||
}
|
||||
|
||||
@include it("should test contrast ratio calculation accuracy") {
|
||||
// Test case: Verify that contrast-ratio function works correctly
|
||||
$background: #767676;
|
||||
$foreground: $white;
|
||||
$ratio: contrast-ratio($background, $foreground);
|
||||
// Bootstrap's implementation calculates this as ~4.5415, not exactly 4.5, due to its luminance math.
|
||||
// We use 4.54 as the threshold for this test to match the actual implementation.
|
||||
@include assert-true($ratio >= 4.54 and $ratio <= 4.55, "Contrast ratio should be approximately 4.54:1 (Bootstrap's math)");
|
||||
}
|
||||
|
||||
@include it("should test luminance calculation") {
|
||||
// Test case: Verify luminance function works correctly
|
||||
$white-luminance: luminance($white);
|
||||
$black-luminance: luminance($black);
|
||||
|
||||
@include assert-equal($white-luminance, 1, "White should have luminance of 1");
|
||||
@include assert-equal($black-luminance, 0, "Black should have luminance of 0");
|
||||
}
|
||||
|
||||
@include it("should handle rgba colors correctly") {
|
||||
// Test case: Test with rgba colors
|
||||
$test-background: rgba(118, 118, 118, 1); // Same as #767676
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
@include assert-equal($result, $white, "Should handle rgba colors correctly");
|
||||
}
|
||||
|
||||
@include it("should test the WCAG 2.1 boundary condition with color below threshold") {
|
||||
// Test case: Background color that produces contrast ratio below 4.5:1
|
||||
// #787878 produces 4.4155:1 contrast ratio with white
|
||||
$test-background: #787878; // Produces 4.4155:1 contrast ratio
|
||||
$contrast-ratio: contrast-ratio($test-background, $white);
|
||||
|
||||
// Verify the contrast ratio is below 4.5:1
|
||||
@include assert-true($contrast-ratio < 4.5, "Contrast ratio should be below 4.5:1 threshold");
|
||||
|
||||
// The color-contrast function should return the color with highest available contrast
|
||||
$result: color-contrast($test-background);
|
||||
@include assert-equal($result, $black, "color-contrast should return black (highest available contrast) for below-threshold ratio");
|
||||
}
|
||||
|
||||
@include it("should test the WCAG 2.1 boundary condition with color at threshold") {
|
||||
// Test case: Background color that produces contrast ratio close to 4.5:1
|
||||
// #777777 produces 4.4776:1 contrast ratio with white
|
||||
$test-background: #777; // Produces 4.4776:1 contrast ratio
|
||||
$contrast-ratio: contrast-ratio($test-background, $white);
|
||||
|
||||
// Verify the contrast ratio is below 4.5:1 threshold
|
||||
@include assert-true($contrast-ratio < 4.5, "Contrast ratio is below threshold, function should handle gracefully");
|
||||
}
|
||||
|
||||
@include it("should demonstrate the difference between > and >= operators") {
|
||||
// Test case: Demonstrates the difference between > and >= operators
|
||||
// Uses #767676 with a custom minimum contrast ratio that matches its actual ratio (4.5415)
|
||||
// With > 4.5415: should return black (fallback to highest available)
|
||||
// With >= 4.5415: should return white (meets threshold)
|
||||
|
||||
$test-background: #767676; // Produces 4.5415:1 contrast ratio
|
||||
$actual-ratio: contrast-ratio($test-background, $white);
|
||||
|
||||
// Test with a custom minimum that matches the actual ratio
|
||||
$result: color-contrast($test-background, $color-contrast-dark, $color-contrast-light, $actual-ratio);
|
||||
|
||||
// Should return white when using >= implementation
|
||||
@include assert-equal($result, $white, "color-contrast should return white when using exact ratio as threshold (>= implementation)");
|
||||
}
|
||||
|
||||
@include it("should test additional working colors above threshold") {
|
||||
// Test case: Background color that produces contrast ratio well above 4.5:1
|
||||
// #757575 produces 4.6047:1 contrast ratio with white text
|
||||
$test-background: #757575; // Produces 4.6047:1 contrast ratio
|
||||
$result: color-contrast($test-background);
|
||||
|
||||
@include assert-equal($result, $white, "Should return white for background with 4.6047:1 contrast ratio (well above threshold)");
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue