Skip to content

fix(icons): fix icons invisible in high contrast mode #19352

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 26, 2025
Merged
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
2 changes: 1 addition & 1 deletion packages/react/src/components/Tooltip/story.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}

.sb-tooltip-trigger svg {
fill: theme.$background-inverse;
fill: theme.$icon-secondary;
}

// DefinitionTooltip
Expand Down
3 changes: 2 additions & 1 deletion packages/styles/scss/_reset.scss
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@

@include type.reset();

/// Makes SVGs accessible in high contrast mode
/// Makes SVGs accessible in high contrast mode, although it only works sporadically as other CSS selectors
/// routinely override this one.
/// @link https://github.com/IBM/carbon-elements/issues/345#issuecomment-466577293 Carbon-elements #345
@media screen and (-ms-high-contrast: active) {
svg {
Expand Down
49 changes: 49 additions & 0 deletions packages/styles/scss/_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,61 @@
@forward './theme/theme' hide theme;
@use './theme/theme';
@use './layer/layer-tokens';
@use './utilities/custom-property';

/// Include the CSS Custom Properties for the active theme or a given theme on
/// a selector
@mixin theme($args...) {
@include theme.theme($args...);

// If the system is in high-contrast mode, use the system defined colors. This mostly happens automatically, but
// we need to do it manually for icons and selected backgrounds. Importantly, the custom properties we set here
// need to override the CSS custom properties set above. See:
// - https://github.com/carbon-design-system/carbon/issues/19015
// - https://developer.mozilla.org/en-US/docs/Web/CSS/system-color.
// - https://carbondesignsystem.com/elements/color/tokens/#icon
@media screen and (-ms-high-contrast: active), (forced-colors: active) {
// Icon colors specified by "fill".
@include custom-property.declaration('icon-primary', ButtonText);
@include custom-property.declaration('icon-secondary', ButtonText);
@include custom-property.declaration('icon-interactive', ButtonText);
@include custom-property.declaration('icon-disabled', GrayText);
@include custom-property.declaration('icon-on-color-disabled', GrayText);

// Since icon-inverse and icon-on-color are generally used to indicated selected icons, use SelectedItemText.
@include custom-property.declaration('icon-inverse', SelectedItemText);
@include custom-property.declaration('icon-on-color', SelectedItemText);

// Some components currently set these values for fill, although unclear if that's valid.
@include custom-property.declaration('button-disabled', GrayText);
@include custom-property.declaration('interactive', ButtonText);
@include custom-property.declaration('link-primary', LinkText);
@include custom-property.declaration('link-primary-hover', LinkText);
@include custom-property.declaration('link-secondary', LinkText);
@include custom-property.declaration('link-inverse', SelectedItemText);
@include custom-property.declaration(
'link-inverse-hover',
SelectedItemText
);
@include custom-property.declaration(
'link-inverse-visited',
SelectedItemText
);
@include custom-property.declaration('link-visited', VisitedText);

// Force a background-color for selected buttons etc., otherwise the user won't know they are selected.
@include custom-property.declaration('background-selected', SelectedItem);
@include custom-property.declaration(
'background-selected-hover',
SelectedItem
);
@include custom-property.declaration('background-inverse', SelectedItem);
@include custom-property.declaration(
'layer-selected-inverse',
SelectedItem
);
}

// Note: we need to re-emit the contextual layer tokens as part of the theme
// mixin. Otherwise, the layer tokens are defined at the :root level and will
// not pick up the theme-specific, or zone-specific, value from the first
Expand Down
7 changes: 0 additions & 7 deletions packages/styles/scss/components/accordion/_accordion.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
@use '../../utilities/convert';
@use '../../utilities/layout';
@use '../../utilities/focus-outline' as *;
@use '../../utilities/high-contrast-mode' as *;

/// @type Value
/// @access public
Expand Down Expand Up @@ -385,12 +384,6 @@ $content-padding: 0 0 0 $spacing-05 !default;
margin-inline-start: $spacing-05;
}

// Windows HCM fix
.#{$prefix}--accordion__arrow,
.#{$prefix}--accordion__item--active .#{$prefix}--accordion__arrow {
@include high-contrast-mode('icon-fill');
}

// RTL overrides
[dir='rtl'] .#{$prefix}--accordion--start .#{$prefix}--accordion__heading {
padding-inline: layout.density('padding-inline') 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@
.#{$prefix}--breadcrumb-item
.#{$prefix}--overflow-menu:active
.#{$prefix}--overflow-menu__icon {
fill: $text-primary;
fill: $icon-primary;
}

.#{$prefix}--breadcrumb-menu-options:focus {
Expand Down
9 changes: 0 additions & 9 deletions packages/styles/scss/components/button/_button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -421,15 +421,6 @@
@include high-contrast-mode('focus');
}

// Windows HCM fix

.#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only
.#{$prefix}--btn__icon
path:not([data-icon-path]):not([fill='none']),
.#{$prefix}--btn--ghost.#{$prefix}--btn--icon-only .#{$prefix}--btn__icon {
@include high-contrast-mode('icon-fill');
}

// RTL overrides
[dir='rtl'] .#{$prefix}--btn-set .#{$prefix}--btn:not(:focus) {
box-shadow: convert.to-rem(1px) 0 0 0 $button-separator;
Expand Down
17 changes: 17 additions & 0 deletions packages/styles/scss/components/checkbox/_checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@use '../../type' as *;
@use '../../utilities/component-reset';
@use '../../utilities/convert';
@use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/skeleton' as *;
@use '../../utilities/visually-hidden' as *;

Expand Down Expand Up @@ -91,6 +92,9 @@
position: absolute;
border: 1px solid $icon-primary;
border-radius: 2px;
@include high-contrast-mode {
border: 1px solid ButtonBorder;
}

// Checkboxes with a background color look visually off against a parent container.
background-color: transparent;
Expand Down Expand Up @@ -136,6 +140,13 @@
border: none;
border-width: 1px;
background-color: $icon-primary;

// According to https://developer.mozilla.org/en-US/docs/Web/CSS/system-color, in high contrast mode, the
// checkbox should be displayed using SelectedItem and SelectedItemText.
@include high-contrast-mode {
border: 1px solid ButtonBorder;
background-color: SelectedItem;
}
}

// Display the check
Expand Down Expand Up @@ -326,6 +337,12 @@
.#{$prefix}--checkbox:checked
+ .#{$prefix}--checkbox-label::after {
border-color: $text-primary;

// According to https://developer.mozilla.org/en-US/docs/Web/CSS/system-color, in high contrast mode, the
// checkbox should be displayed using SelectedItem and SelectedItemText.
@include high-contrast-mode {
fill: SelectedItemText;
}
}

//-----------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,11 +555,6 @@ $copy-btn-feedback: $background-inverse !default;
}

// Windows HCM fix

.#{$prefix}--snippet__icon {
@include high-contrast-mode('icon-fill');
}

.#{$prefix}--snippet--inline:focus {
@include high-contrast-mode('focus');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,4 @@
.#{$prefix}--table-expand__button:focus .#{$prefix}--table-expand__svg {
@include high-contrast-mode('focus');
}

.#{$prefix}--table-expand__svg {
@include high-contrast-mode('icon-fill');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
@use '../../../utilities/button-reset';
@use '../../../utilities/convert';
@use '../../../utilities/focus-outline' as *;
@use '../../../utilities/high-contrast-mode' as *;

/// Data table sort styles
/// @access public
Expand Down Expand Up @@ -270,10 +269,4 @@
display: block;
margin-inline-end: convert.to-rem(8px);
}

// Windows HCM fix
.#{$prefix}--table-sort__icon,
.#{$prefix}--table-sort__icon-unsorted {
@include high-contrast-mode('icon-fill');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
@use '../../utilities/component-reset';
@use '../../utilities/convert';
@use '../../utilities/focus-outline' as *;
@use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/placeholder-colors' as *;
@use '../../utilities/skeleton' as *;

Expand Down Expand Up @@ -262,10 +261,4 @@
block-size: convert.to-rem(14px);
inline-size: convert.to-rem(75px);
}

// Windows HCM fix

.#{$prefix}--date-picker__icon {
@include high-contrast-mode('icon-fill');
}
}
2 changes: 0 additions & 2 deletions packages/styles/scss/components/date-picker/_flatpickr.scss
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,6 @@
transform: scale(1, 1) #{'/*rtl: scale(-1,1)*/'};
transition: background-color $duration-fast-01 motion(standard, productive);
user-select: none;
// Windows HCM fix
@include high-contrast-mode('icon-fill');

@media screen and (prefers-reduced-motion: reduce) {
transition: none;
Expand Down
1 change: 0 additions & 1 deletion packages/styles/scss/components/dialog/_dialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
@use '../../utilities/convert';
@use '../../utilities/component-reset';
@use '../../utilities/focus-outline' as *;
@use '../../utilities/high-contrast-mode' as *;

/// Dialog styles
/// @access public
Expand Down
4 changes: 0 additions & 4 deletions packages/styles/scss/components/dropdown/_dropdown.scss
Original file line number Diff line number Diff line change
Expand Up @@ -481,10 +481,6 @@
}
}

.#{$prefix}--list-box__menu-item__selected-icon {
@include high-contrast-mode('icon-fill');
}

// readonly
.#{$prefix}--dropdown--readonly,
.#{$prefix}--dropdown--readonly:hover {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@
}

.#{$prefix}--file__state-container .#{$prefix}--file-complete {
// TODO: Should this be $icon-interactive instead?
fill: $interactive;
inline-size: $spacing-06;

Expand Down Expand Up @@ -412,12 +413,7 @@
}

// Windows HCM fix

.#{$prefix}--file__selected-file {
@include high-contrast-mode('outline');
}

.#{$prefix}--file__state-container .#{$prefix}--file-close svg path {
@include high-contrast-mode('icon-fill');
}
}
6 changes: 0 additions & 6 deletions packages/styles/scss/components/list-box/_list-box.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1145,12 +1145,6 @@ $list-box-menu-width: convert.to-rem(300px);
@include high-contrast-mode('focus');
}

.#{$prefix}--list-box__menu-icon > svg,
.#{$prefix}--list-box__selection > svg,
.#{$prefix}--list-box__selection--multi > svg {
@include high-contrast-mode('icon-fill');
}

.#{$prefix}--list-box__field:has(.#{$prefix}--list-box__menu-icon)
.#{$prefix}--list-box__selection::after {
position: absolute;
Expand Down
5 changes: 0 additions & 5 deletions packages/styles/scss/components/modal/_modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -489,11 +489,6 @@
}

// Windows HCM fix

.#{$prefix}--modal-close__icon {
@include high-contrast-mode('icon-fill');
}

.#{$prefix}--modal-close:focus {
@include high-contrast-mode('focus');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -486,11 +486,4 @@
.#{$prefix}--btn.#{$prefix}--btn--ghost.#{$prefix}--actionable-notification__action-button:focus {
@include high-contrast-mode('focus');
}

.#{$prefix}--actionable-notification .#{$prefix}--inline-notification__icon,
.#{$prefix}--actionable-notification .#{$prefix}--toast-notification__icon,
.#{$prefix}--actionable-notification
.#{$prefix}--actionable-notification__close-icon {
@include high-contrast-mode('icon-fill');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -316,12 +316,4 @@
.#{$prefix}--btn.#{$prefix}--btn--ghost.#{$prefix}--inline-notification__action-button:focus {
@include high-contrast-mode('focus');
}

.#{$prefix}--inline-notification .#{$prefix}--inline-notification__icon {
@include high-contrast-mode('icon-fill');
}
.#{$prefix}--inline-notification
.#{$prefix}--inline-notification__close-icon {
@include high-contrast-mode('icon-fill');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,4 @@
.#{$prefix}--toast-notification__close-button:focus {
@include high-contrast-mode('focus');
}
.#{$prefix}--toast-notification .#{$prefix}--toast-notification__close-icon {
@include high-contrast-mode('icon-fill');
}
.#{$prefix}--toast-notification .#{$prefix}--toast-notification__icon {
@include high-contrast-mode('icon-fill');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -677,10 +677,6 @@
.#{$prefix}--number__control-btn {
@include high-contrast-mode('outline');
}

.#{$prefix}--number__control-btn svg {
@include high-contrast-mode('icon-fill');
}
}

.#{$prefix}--number__controls:hover .#{$prefix}--number__control-btn::after {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,10 +361,6 @@
.#{$prefix}--overflow-menu-options__btn:focus {
@include high-contrast-mode('focus');
}

.#{$prefix}--overflow-menu svg {
@include high-contrast-mode('icon-fill');
}
/*stylelint-enable */

$popover-offset: custom-property.get-var('popover-offset', 2.5rem);
Expand Down
10 changes: 0 additions & 10 deletions packages/styles/scss/components/page-header/_page-header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,9 @@

@use '../../config' as *;
@use '../../breakpoint' as *;
// @use '../../motion' as *;
@use '../../spacing' as *;
// @use '../../theme' as *;
@use '../../type' as *;
// @use '../../layer' as *;
// @use '../../utilities/box-shadow' as *;
// @use '../../utilities/button-reset';
// @use '../../utilities/component-reset';
// @use '../../utilities/focus-outline' as *;
// @use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/convert';
// @use '../../utilities/z-index' as *;
// @use '../../utilities/custom-property';

/// Page header styles
/// @access public
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
@use '../../theme' as *;
@use '../../utilities/button-reset';
@use '../../utilities/focus-outline' as *;
@use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/layout';
@use '../../utilities/visually-hidden' as *;

Expand Down
1 change: 0 additions & 1 deletion packages/styles/scss/components/popover/_popover.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
@use '../../utilities/button-reset';
@use '../../utilities/component-reset';
@use '../../utilities/custom-property';
@use '../../utilities/high-contrast-mode' as *;
@use '../../utilities/focus-outline' as *;
@use '../../utilities/' as *;
@use '../../utilities/convert';
Expand Down
Loading
Loading