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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
- use the latest provided `onChange` function
- `<TextField />`, `<TextArea />`
- fix emoji false-positives in invisible character detection
- Focus outlines
- we use again bold focus outlines for input elements
- they are also used for clickable elements that are focused via keyboard (tab navigation)

### Changed

Expand Down
36 changes: 1 addition & 35 deletions src/_shame.scss
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
// Add stuff to test fast and dirty.
// This file should not contain any styles.

.#{$prefix}--assistive-text,
.#{$prefix}--visually-hidden {
/*
TODO: move to better place, originally from ~@carbon/styles/scss/css--helpers
but we cannot use it directly because of other included rules there.
*/
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
visibility: inherit;
border: 0;
}

/*
WORKAROUND: thinner scrollbars
*/

* {
scrollbar-width: thin;
scrollbar-color: #bbb transparent;
scrollbar-width: thin;

&::-webkit-scrollbar {
width: 0.25rem;
Expand All @@ -38,19 +20,3 @@
border-radius: 0.125rem;
}
}

/*
CHANGE: default focus behaviour
*/

:focus,
input:focus-visible,
textarea:focus-visible {
outline: none;
outline-offset: 0;
}

:focus-visible {
outline: eccgui-color-rgba($eccgui-color-accent, $eccgui-opacity-muted) solid 2px;
outline-offset: 1px;
}
84 changes: 84 additions & 0 deletions src/common/scss/_accessibility-defaults.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
.#{$prefix}--assistive-text,
.#{$prefix}--visually-hidden {
/*
TODO: move to better place, originally from ~@carbon/styles/scss/css--helpers
but we cannot use it directly because of other included rules there.
*/
position: absolute;
visibility: inherit;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
white-space: nowrap;
border: 0;
clip: rect(0, 0, 0, 0);
}

/*
default focus indicator
*/

:root {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-primary};
--#{$eccgui}-a11y-outline-style: solid;
--#{$eccgui}-a11y-outline-width: #{0.25 * $eccgui-size-block-whitespace};

// shift outline min 2px inside element to have a minimum 2px outline even with hidden overflow
--#{$eccgui}-a11y-outline-offset: min(calc(var(--#{$eccgui}-a11y-outline-width) * -0.5), -2px);
}

@keyframes outline-bounce {
0% {
outline-width: calc(var(--#{$eccgui}-a11y-outline-width) * 0.5);
outline-color: var(--#{$eccgui}-a11y-outline-color);
outline-offset: var(--#{$eccgui}-a11y-outline-offset);
}

33.3% {
outline-color: var(--#{$eccgui}-a11y-outline-color);
outline-offset: calc(var(--#{$eccgui}-a11y-outline-width));
}

66.6% {
outline-color: currentcolor;
outline-offset: calc(var(--#{$eccgui}-a11y-outline-width) * -2);
}

100% {
outline-width: var(--#{$eccgui}-a11y-outline-width);
outline-color: var(--#{$eccgui}-a11y-outline-color);
outline-offset: var(--#{$eccgui}-a11y-outline-offset);
}
}

.focus-by-keyboard {
outline: var(--#{$eccgui}-a11y-outline-color) var(--#{$eccgui}-a11y-outline-style)
var(--#{$eccgui}-a11y-outline-width);

// strong visual focus indication for keyboard devices
outline-offset: var(--#{$eccgui}-a11y-outline-offset);

@media (prefers-reduced-motion: no-preference) {
animation: outline-bounce 0.5s;
}
}

.focus-by-pointer {
outline: transparent none 0;

// limited visual focus indication for pointer devices
outline-offset: 0;
}

*[tabindex]:not([tabindex^="-"]):focus-visible,
:focus-visible {
@extend .focus-by-keyboard;
}

input:focus:not(:focus-visible),
textarea:focus:not(:focus-visible),
:focus:not(:focus-visible) {
@extend .focus-by-pointer;
}
34 changes: 25 additions & 9 deletions src/components/Application/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,31 @@ a.#{$prefix}--header__menu-item:active {
}

// $shell-header-focus
.#{$prefix}--header__action:focus,
.#{$prefix}--header__action.#{$prefix}--btn--icon-only:focus,
.#{$prefix}--header__action.#{$prefix}--btn--primary:focus,
a.#{$prefix}--header__name:focus,
a.#{$prefix}--header__menu-item:focus {
outline: 1px dotted $shell-header-focus;
outline-offset: -1px;
border: none;
box-shadow: none;
.#{$prefix}--header__action,
.#{$prefix}--header__action.#{$prefix}--btn--icon-only,
.#{$prefix}--header__action.#{$prefix}--btn--primary,
a.#{$prefix}--header__name,
a.#{$prefix}--header__menu-item {
&:focus {
@extend .focus-by-pointer;

border: none;
box-shadow: none;
}

&:focus-visible {
@extend .focus-by-keyboard;
}

&,
.#{$prefix}--popover--open & {
&:focus-visible {
@extend .focus-by-keyboard;

border: none;
box-shadow: none;
}
}
}
.#{$prefix}--header__menu-title[aria-expanded="true"] {
color: $shell-header-focus;
Expand Down
6 changes: 6 additions & 0 deletions src/components/Application/_sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,9 @@ $ui-02: $eccgui-color-workspace-background !default;
padding: $eccgui-size-block-whitespace calc(0.5 * (#{mini-units(8)} - 30px));
transition: none;
}

.#{$eccgui}-application__menu__toggler.cds--header__action {
&:focus-visible {
@extend .focus-by-keyboard;
}
}
6 changes: 3 additions & 3 deletions src/components/Application/_toolbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@ $shell-panel-focus: $shell-header-focus !default;
.#{$eccgui}-application__toolbar__panel-backdrop--onleave,
.#{$eccgui}-application__toolbar__panel-backdrop--onoutsideclick {
position: fixed;
inset: mini-units(8) 0 0 0;
inset: mini-units(8) 0 0;
}

.#{$eccgui}-application__toolbar__panel-backdrop--onoutsideclick {
top: 0;
}

// add rules for own class identiiers
// add rules for own class identifiers

.#{$eccgui}-application__toolbar {
flex-basis: auto;
flex-grow: 0;
flex-basis: auto;

.#{$prefix}--popover--bottom-right .#{$prefix}--popover-content {
// for some reason the original calculation still moves out the tooltip
Expand Down
6 changes: 5 additions & 1 deletion src/components/AutoSuggestion/AutoSuggestion.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@
}

&:has(.cm-editor.cm-focused) {
box-shadow: input-transition-shadow($input-shadow-color-focus, true), $input-box-shadow-focus;
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};

@extend .focus-by-keyboard;

animation: none;
}

.cm-editor {
Expand Down
14 changes: 13 additions & 1 deletion src/components/Checkbox/checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ $switch-checked-background-color-disabled: eccgui-color-rgba(
}

input:focus ~ .#{$ns}-control-indicator {
outline-offset: 0;
@extend .focus-by-keyboard;

animation: none;
}

input:disabled ~ .#{$ns}-control-indicator,
Expand All @@ -72,6 +74,16 @@ $switch-checked-background-color-disabled: eccgui-color-rgba(
background-image: url("~@carbon/icons/svg/32/checkbox--indeterminate.svg");
}
}

&.#{$ns}-switch {
--#{$eccgui}-a11y-outline-offset: 1px;

input:focus ~ .#{$ns}-control-indicator {
@extend .focus-by-keyboard;

animation: none;
}
}
}

.#{$ns}-control-indicator + *,
Expand Down
20 changes: 20 additions & 0 deletions src/components/MultiSuggestField/_multisuggestfield.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,23 @@
max-height: var(--eccgui-multisuggestfield-max-height, 45vh);
}
}

.#{$eccgui}-multisuggestfield {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};

&.#{$ns}-intent-success {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-success-text};
}
&.#{$ns}-intent-warning {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-warning-text};
}
&.#{$ns}-intent-danger {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-danger-text};
}

&:focus-within {
@extend .focus-by-keyboard;

animation: none;
}
}
8 changes: 7 additions & 1 deletion src/components/RadioButton/radiobutton.scss
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
// Checkbox need to be imported before, we won't double it here currently

.#{$ns}-control {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};
--#{$eccgui}-a11y-outline-width: 2px;
--#{$eccgui}-a11y-outline-offset: 0;

&.#{$ns}-radio {
input ~ .#{$ns}-control-indicator,
input:checked ~ .#{$ns}-control-indicator {
box-shadow: none;
}

input:focus ~ .#{$ns}-control-indicator {
outline-offset: 1px;
@extend .focus-by-keyboard;

animation: none;
}

input:disabled ~ .#{$ns}-control-indicator,
Expand Down
22 changes: 22 additions & 0 deletions src/components/TextField/textfield.scss
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ $eccgui-map-intent-bgcolors: (
}

.#{$ns}-input {
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};

.#{$ns}-input-group[class*="#{$eccgui}-intent--"] & {
animation-duration: 1s;
animation-delay: 0.5s;
Expand All @@ -111,16 +113,23 @@ $eccgui-map-intent-bgcolors: (
@each $each-intent, $each-bgcolor in $eccgui-map-intent-bgcolors {
.#{$ns}-input-group.#{$ns}-intent-#{$each-intent} & {
background-color: eccgui-color-var("semantic", $each-intent, "100");

--#{$eccgui}-a11y-outline-color: eccgui-color-var("semantic", $each-intent, "900");

animation-name: intent-state-flash-#{$each-intent};
}
}

.#{$ns}-input-group.#{$eccgui}-intent--info & {
@include pt-input-intent($eccgui-color-info-text);

--#{$eccgui}-a11y-outline-color: #{$eccgui-color-info-text};
}

.#{$ns}-input-group.#{$eccgui}-intent--accent & {
@include pt-input-intent($eccgui-color-primary);

--#{$eccgui}-a11y-outline-color: #{$eccgui-color-primary};
}

.#{$ns}-input-group.#{$eccgui}-intent--neutral & {
Expand All @@ -138,6 +147,12 @@ $eccgui-map-intent-bgcolors: (

text-decoration: line-through $eccgui-color-danger-text 2px;
}

&:focus-visible {
@extend .focus-by-keyboard;

animation: none;
}
}

.#{$eccgui}-textarea {
Expand All @@ -151,16 +166,23 @@ $eccgui-map-intent-bgcolors: (
@each $each-intent, $each-bgcolor in $eccgui-map-intent-bgcolors {
&.#{$eccgui}-intent--#{$each-intent} {
background-color: eccgui-color-var("semantic", $each-intent, "100");

--#{$eccgui}-a11y-outline-color: eccgui-color-var("semantic", $each-intent, "900");

animation-name: intent-state-flash-#{$each-intent};
}
}

&.#{$eccgui}-intent--info {
@include pt-input-intent($eccgui-color-info-text);

--#{$eccgui}-a11y-outline-color: #{$eccgui-color-info-text};
}

&.#{$eccgui}-intent--accent {
@include pt-input-intent($eccgui-color-primary);

--#{$eccgui}-a11y-outline-color: #{$eccgui-color-primary};
}

&.#{$eccgui}-intent--neutral {
Expand Down
3 changes: 2 additions & 1 deletion src/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ export const Tooltip = ({
}, swapDelayTime);
if (placeholderRef.current !== null) {
const eventType = ev.type === "focusin" ? "focusout" : "mouseleave";
(placeholderRef.current as HTMLElement).addEventListener(eventType, () => {
const innerFocusTarget = (placeholderRef.current as HTMLElement).querySelector("[tabindex='0']")?.children[0];
(innerFocusTarget as HTMLElement).addEventListener(eventType, () => {
if (
(eventType === "focusout" && eventMemory.current === "afterfocus") ||
(eventType === "mouseleave" && eventMemory.current === "afterhover")
Expand Down
4 changes: 4 additions & 0 deletions src/configuration/stories/customproperties.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ const groups: { title: string; filterName: (name: string) => boolean }[] = [
title: "Color aliases",
filterName: (name) => name.startsWith(`--${eccgui}-color`) && !name.startsWith(`--${eccgui}-color-palette`),
},
{
title: "Accessibility",
filterName: (name) => name.startsWith(`--${eccgui}-a11y`),
},
{
title: "Opacity",
filterName: (name) => name.startsWith(`--${eccgui}-opacity`),
Expand Down
Loading
Loading