Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions dist/css/bootstrap.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/css/bootstrap.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/css/bootstrap.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/css/bootstrap.min.css.map

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions dist/css/bootstrap.rtl.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/css/bootstrap.rtl.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/css/bootstrap.rtl.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/css/bootstrap.rtl.min.css.map

Large diffs are not rendered by default.

78 changes: 51 additions & 27 deletions scss/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
line-height: var(--#{$prefix}btn-line-height);
color: var(--#{$prefix}btn-color);
text-align: center;
text-decoration: if($link-decoration == none, null, none);
text-decoration: if($link-decoration ==none, null, none);
white-space: $btn-white-space;
vertical-align: middle;
cursor: if($enable-button-pointers, pointer, null);
Expand All @@ -42,12 +42,12 @@

&:hover {
color: var(--#{$prefix}btn-hover-color);
text-decoration: if($link-hover-decoration == underline, none, null);
text-decoration: if($link-hover-decoration ==underline, none, null);
background-color: var(--#{$prefix}btn-hover-bg);
border-color: var(--#{$prefix}btn-hover-border-color);
}

.btn-check + &:hover {
.btn-check+&:hover {
// override for the checkbox/radio buttons
color: var(--#{$prefix}btn-color);
background-color: var(--#{$prefix}btn-bg);
Expand All @@ -59,27 +59,41 @@
@include gradient-bg(var(--#{$prefix}btn-hover-bg));
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;

// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-box-shadow),
var(--#{$prefix}btn-focus-box-shadow);
}

@else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}

// High contrast mode fallback - provides visible focus indicator when box-shadow is disabled
@media (prefers-contrast: high) {
outline: 2px solid;
outline-offset: 2px;
}
}

.btn-check:focus-visible + & {
.btn-check:focus-visible+& {
border-color: var(--#{$prefix}btn-hover-border-color);
outline: 0;

// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-box-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-box-shadow),
var(--#{$prefix}btn-focus-box-shadow);
}

@else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}

.btn-check:checked + &,
:not(.btn-check) + &:active,
.btn-check:checked+&,
:not(.btn-check)+&:active,
&:first-child:active,
&.active,
&.show {
Expand All @@ -91,20 +105,28 @@
@include box-shadow(var(--#{$prefix}btn-active-shadow));

&:focus-visible {

// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-active-shadow),
var(--#{$prefix}btn-focus-box-shadow);
}

@else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
}

.btn-check:checked:focus-visible + & {
.btn-check:checked:focus-visible+& {

// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: var(--#{$prefix}btn-active-shadow), var(--#{$prefix}btn-focus-box-shadow);
} @else {
box-shadow: var(--#{$prefix}btn-active-shadow),
var(--#{$prefix}btn-focus-box-shadow);
}

@else {
box-shadow: var(--#{$prefix}btn-focus-box-shadow);
}
}
Expand All @@ -130,25 +152,25 @@
// scss-docs-start btn-variant-loops
@each $color, $value in $theme-colors {
.btn-#{$color} {
@if $color == "light" {
@include button-variant(
$value,
@if $color =="light" {
@include button-variant($value,
$value,
$hover-background: shade-color($value, $btn-hover-bg-shade-amount),
$hover-border: shade-color($value, $btn-hover-border-shade-amount),
$active-background: shade-color($value, $btn-active-bg-shade-amount),
$active-border: shade-color($value, $btn-active-border-shade-amount)
);
} @else if $color == "dark" {
@include button-variant(
$value,
$active-border: shade-color($value, $btn-active-border-shade-amount));
}

@else if $color =="dark" {
@include button-variant($value,
$value,
$hover-background: tint-color($value, $btn-hover-bg-tint-amount),
$hover-border: tint-color($value, $btn-hover-border-tint-amount),
$active-background: tint-color($value, $btn-active-bg-tint-amount),
$active-border: tint-color($value, $btn-active-border-tint-amount)
);
} @else {
$active-border: tint-color($value, $btn-active-border-tint-amount));
}

@else {
@include button-variant($value, $value);
}
}
Expand All @@ -159,6 +181,7 @@
@include button-outline-variant($value);
}
}

// scss-docs-end btn-variant-loops


Expand All @@ -182,6 +205,7 @@
--#{$prefix}btn-focus-shadow-rgb: #{$btn-link-focus-shadow-rgb};

text-decoration: $link-decoration;

@if $enable-gradients {
background-image: none;
}
Expand Down Expand Up @@ -213,4 +237,4 @@

.btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $btn-font-size-sm, $btn-border-radius-sm);
}
}
25 changes: 20 additions & 5 deletions scss/forms/_form-control.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,21 @@
background-color: $input-focus-bg;
border-color: $input-focus-border-color;
outline: 0;

@if $enable-shadows {
@include box-shadow($input-box-shadow, $input-focus-box-shadow);
} @else {
}

@else {
// Avoid using mixin so we can pass custom focus shadow properly
box-shadow: $input-focus-box-shadow;
}

// High contrast mode fallback - provides visible focus indicator when box-shadow is disabled
@media (prefers-contrast: high) {
outline: 2px solid;
outline-offset: 2px;
}
}

&::-webkit-date-and-time-value {
Expand All @@ -56,7 +65,7 @@
// https://github.com/twbs/bootstrap/issues/23307
// TODO: we can remove this workaround once https://bugs.webkit.org/show_bug.cgi?id=198959 is resolved
// Multiply line-height by 1em if it has no unit
height: if(unit($input-line-height) == "", $input-line-height * 1em, $input-line-height);
height: if(unit($input-line-height)=="", $input-line-height * 1em, $input-line-height);

// Android Chrome type="date" is taller than the other inputs
// because of "margin: 1px 24px 1px 4px" inside the shadow DOM
Expand Down Expand Up @@ -188,6 +197,7 @@ textarea {
min-height: $input-height-lg;
}
}

// stylelint-enable selector-no-qualifying-type

.form-control-color {
Expand All @@ -209,6 +219,11 @@ textarea {
@include border-radius($input-border-radius);
}

&.form-control-sm { height: $input-height-sm; }
&.form-control-lg { height: $input-height-lg; }
}
&.form-control-sm {
height: $input-height-sm;
}

&.form-control-lg {
height: $input-height-lg;
}
}
53 changes: 53 additions & 0 deletions test-high-contrast-focus.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>High Contrast Focus Test</title>
<link href="dist/css/bootstrap.css" rel="stylesheet">
<style>
/* Simulate high contrast mode for testing */
@media (prefers-contrast: high) {
body {
background: black;
color: white;
}
}
</style>
</head>

<body>
<div class="container mt-5">
<h1>High Contrast Focus Indicator Test</h1>
<p>This page demonstrates the improved focus indicators for high contrast mode.</p>

<div class="mb-3">
<label for="testInput" class="form-label">Test Input</label>
<input type="text" class="form-control" id="testInput" placeholder="Focus on this input">
</div>

<div class="mb-3">
<label for="testTextarea" class="form-label">Test Textarea</label>
<textarea class="form-control" id="testTextarea" rows="3" placeholder="Focus on this textarea"></textarea>
</div>

<div class="mb-3">
<button type="button" class="btn btn-primary">Primary Button</button>
<button type="button" class="btn btn-secondary">Secondary Button</button>
</div>

<div class="alert alert-info">
<strong>Testing Instructions:</strong>
<ul>
<li>Tab through the form elements to see focus indicators</li>
<li>In normal mode, you'll see the blue box-shadow focus ring</li>
<li>In high contrast mode (or when box-shadow is disabled), you'll see a solid outline</li>
<li>To test high contrast mode: Enable it in your OS settings or use browser dev tools to simulate it
</li>
</ul>
</div>
</div>
</body>

</html>