Skip to content

Commit da7e347

Browse files
authored
Merge pull request #380 from eccenca/bugfix/keyboardFocusIndication-CMEM-7512
Fix keyboard focus indication (CMEM-7512)
2 parents 7986f20 + 5d7801c commit da7e347

18 files changed

Lines changed: 280 additions & 99 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
5757
- use the latest provided `onChange` function
5858
- `<TextField />`, `<TextArea />`
5959
- fix emoji false-positives in invisible character detection
60+
- Focus outlines
61+
- we use again bold focus outlines for input elements
62+
- they are also used for clickable elements that are focused via keyboard (tab navigation)
6063

6164
### Changed
6265

src/_shame.scss

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,13 @@
11
// Add stuff to test fast and dirty.
22
// This file should not contain any styles.
33

4-
.#{$prefix}--assistive-text,
5-
.#{$prefix}--visually-hidden {
6-
/*
7-
TODO: move to better place, originally from ~@carbon/styles/scss/css--helpers
8-
but we cannot use it directly because of other included rules there.
9-
*/
10-
position: absolute;
11-
width: 1px;
12-
height: 1px;
13-
padding: 0;
14-
margin: -1px;
15-
overflow: hidden;
16-
clip: rect(0, 0, 0, 0);
17-
white-space: nowrap;
18-
visibility: inherit;
19-
border: 0;
20-
}
21-
224
/*
235
WORKAROUND: thinner scrollbars
246
*/
257

268
* {
27-
scrollbar-width: thin;
289
scrollbar-color: #bbb transparent;
10+
scrollbar-width: thin;
2911

3012
&::-webkit-scrollbar {
3113
width: 0.25rem;
@@ -38,19 +20,3 @@
3820
border-radius: 0.125rem;
3921
}
4022
}
41-
42-
/*
43-
CHANGE: default focus behaviour
44-
*/
45-
46-
:focus,
47-
input:focus-visible,
48-
textarea:focus-visible {
49-
outline: none;
50-
outline-offset: 0;
51-
}
52-
53-
:focus-visible {
54-
outline: eccgui-color-rgba($eccgui-color-accent, $eccgui-opacity-muted) solid 2px;
55-
outline-offset: 1px;
56-
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
.#{$prefix}--assistive-text,
2+
.#{$prefix}--visually-hidden {
3+
/*
4+
originally from ~@carbon/styles/scss/css--helpers
5+
but we cannot use it directly because of other included rules there.
6+
*/
7+
position: absolute;
8+
visibility: inherit;
9+
width: 1px;
10+
height: 1px;
11+
padding: 0;
12+
margin: -1px;
13+
overflow: hidden;
14+
white-space: nowrap;
15+
border: 0;
16+
clip-path: rect(0, 0, 0, 0);
17+
}
18+
19+
/*
20+
default focus indicator
21+
*/
22+
23+
:root {
24+
--#{$eccgui}-a11y-outline-color: #{eccgui-color-var("layout", "magenta", "900")};
25+
--#{$eccgui}-a11y-outline-style: solid;
26+
--#{$eccgui}-a11y-outline-width: #{0.25 * $eccgui-size-block-whitespace};
27+
28+
// shift outline min 2px inside element to have a minimum 2px outline even with hidden overflow
29+
--#{$eccgui}-a11y-outline-offset: min(calc(var(--#{$eccgui}-a11y-outline-width) * -0.5), -2px);
30+
}
31+
32+
@keyframes outline-bounce {
33+
0% {
34+
outline-width: calc(var(--#{$eccgui}-a11y-outline-width) * 0.5);
35+
outline-color: var(--#{$eccgui}-a11y-outline-color);
36+
outline-offset: var(--#{$eccgui}-a11y-outline-offset);
37+
}
38+
39+
33.3% {
40+
outline-color: var(--#{$eccgui}-a11y-outline-color);
41+
outline-offset: calc(var(--#{$eccgui}-a11y-outline-width));
42+
}
43+
44+
66.6% {
45+
outline-color: currentcolor;
46+
outline-offset: calc(var(--#{$eccgui}-a11y-outline-width) * -2);
47+
}
48+
49+
100% {
50+
outline-width: var(--#{$eccgui}-a11y-outline-width);
51+
outline-color: var(--#{$eccgui}-a11y-outline-color);
52+
outline-offset: var(--#{$eccgui}-a11y-outline-offset);
53+
}
54+
}
55+
56+
@mixin focus-by-keyboard-static {
57+
// strong visual focus indication for keyboard devices
58+
59+
outline: var(--#{$eccgui}-a11y-outline-color) var(--#{$eccgui}-a11y-outline-style)
60+
var(--#{$eccgui}-a11y-outline-width);
61+
outline-offset: var(--#{$eccgui}-a11y-outline-offset);
62+
}
63+
64+
@mixin focus-by-keyboard-animation {
65+
@media (prefers-reduced-motion: no-preference) {
66+
animation: outline-bounce 0.5s;
67+
}
68+
}
69+
70+
.#{$eccgui}-a11y-focus-by-keyboard-animated {
71+
@include focus-by-keyboard-static;
72+
@include focus-by-keyboard-animation;
73+
}
74+
75+
.#{$eccgui}-a11y-focus-by-keyboard-static {
76+
@include focus-by-keyboard-static;
77+
78+
animation: none;
79+
}
80+
81+
@mixin focus-by-pointer {
82+
// limited visual focus indication for pointer devices
83+
84+
outline: transparent none 0;
85+
outline-offset: 0;
86+
}
87+
88+
.#{$eccgui}-a11y-focus-by-pointer {
89+
@include focus-by-pointer;
90+
}
91+
92+
*[tabindex]:not([tabindex^="-"]):focus-visible,
93+
:focus-visible {
94+
@extend .#{$eccgui}-a11y-focus-by-keyboard-animated;
95+
}
96+
97+
input:focus:not(:focus-visible),
98+
textarea:focus:not(:focus-visible),
99+
:focus:not(:focus-visible) {
100+
@extend .#{$eccgui}-a11y-focus-by-pointer;
101+
}

src/components/Application/_header.scss

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,27 @@ a.#{$prefix}--header__menu-item:active {
190190
}
191191

192192
// $shell-header-focus
193-
.#{$prefix}--header__action:focus,
194-
.#{$prefix}--header__action.#{$prefix}--btn--icon-only:focus,
195-
.#{$prefix}--header__action.#{$prefix}--btn--primary:focus,
196-
a.#{$prefix}--header__name:focus,
197-
a.#{$prefix}--header__menu-item:focus {
198-
outline: 1px dotted $shell-header-focus;
199-
outline-offset: -1px;
200-
border: none;
201-
box-shadow: none;
193+
.#{$prefix}--header__action,
194+
.#{$prefix}--header__action.#{$prefix}--btn--icon-only,
195+
.#{$prefix}--header__action.#{$prefix}--btn--primary,
196+
a.#{$prefix}--header__name,
197+
a.#{$prefix}--header__menu-item {
198+
&:focus {
199+
@extend .#{$eccgui}-a11y-focus-by-pointer;
200+
201+
border: none;
202+
box-shadow: none;
203+
}
204+
205+
&,
206+
.#{$prefix}--popover--open & {
207+
&:focus-visible {
208+
@extend .#{$eccgui}-a11y-focus-by-keyboard-animated;
209+
210+
border: none;
211+
box-shadow: none;
212+
}
213+
}
202214
}
203215
.#{$prefix}--header__menu-title[aria-expanded="true"] {
204216
color: $shell-header-focus;

src/components/Application/_sidebar.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,9 @@ $ui-02: $eccgui-color-workspace-background !default;
2828
padding: $eccgui-size-block-whitespace calc(0.5 * (#{mini-units(8)} - 30px));
2929
transition: none;
3030
}
31+
32+
.#{$eccgui}-application__menu__toggler.cds--header__action {
33+
&:focus-visible {
34+
@extend .#{$eccgui}-a11y-focus-by-keyboard-animated;
35+
}
36+
}

src/components/Application/_toolbar.scss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,18 @@ $shell-panel-focus: $shell-header-focus !default;
5151
.#{$eccgui}-application__toolbar__panel-backdrop--onleave,
5252
.#{$eccgui}-application__toolbar__panel-backdrop--onoutsideclick {
5353
position: fixed;
54-
inset: mini-units(8) 0 0 0;
54+
inset: mini-units(8) 0 0;
5555
}
5656

5757
.#{$eccgui}-application__toolbar__panel-backdrop--onoutsideclick {
5858
top: 0;
5959
}
6060

61-
// add rules for own class identiiers
61+
// add rules for own class identifiers
6262

6363
.#{$eccgui}-application__toolbar {
64-
flex-basis: auto;
6564
flex-grow: 0;
65+
flex-basis: auto;
6666

6767
.#{$prefix}--popover--bottom-right .#{$prefix}--popover-content {
6868
// for some reason the original calculation still moves out the tooltip

src/components/AutoSuggestion/AutoSuggestion.scss

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
}
4040

4141
&:has(.cm-editor.cm-focused) {
42-
box-shadow: input-transition-shadow($input-shadow-color-focus, true), $input-box-shadow-focus;
42+
--#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};
43+
44+
@extend .#{$eccgui}-a11y-focus-by-keyboard-static;
4345
}
4446

4547
.cm-editor {

src/components/Checkbox/checkbox.scss

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ $switch-checked-background-color-disabled: eccgui-color-rgba(
4747
}
4848

4949
input:focus ~ .#{$ns}-control-indicator {
50-
outline-offset: 0;
50+
@extend .#{$eccgui}-a11y-focus-by-keyboard-static;
5151
}
5252

5353
input:disabled ~ .#{$ns}-control-indicator,
@@ -72,6 +72,14 @@ $switch-checked-background-color-disabled: eccgui-color-rgba(
7272
background-image: url("~@carbon/icons/svg/32/checkbox--indeterminate.svg");
7373
}
7474
}
75+
76+
&.#{$ns}-switch {
77+
--#{$eccgui}-a11y-outline-offset: 1px;
78+
79+
input:focus ~ .#{$ns}-control-indicator {
80+
@extend .#{$eccgui}-a11y-focus-by-keyboard-static;
81+
}
82+
}
7583
}
7684

7785
.#{$ns}-control-indicator + *,

src/components/Dialog/dialog.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ $eccgui-color-modal-backdrop: eccgui-color-rgba(
2222
z-index: $eccgui-zindex-modals;
2323
}
2424

25+
.#{$ns}-overlay-start-focus-trap,
26+
.#{$ns}-overlay-end-focus-trap {
27+
// do not show focus on trap elements, we need to fix keeping focus on modal elements differently later
28+
&[tabindex]:not([tabindex^="-"]):focus-visible {
29+
@extend .#{$eccgui}-a11y-focus-by-pointer;
30+
}
31+
}
32+
2533
.#{$eccgui}-dialog__backdrop {
2634
background-color: $eccgui-color-modal-backdrop;
2735
}

src/components/Link/link.scss

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,12 @@
3131
}
3232
}
3333

34-
&:focus {
35-
outline: none;
36-
outline-offset: 0;
34+
&:focus:not(.#{$prefix}--link--disabled) {
35+
@include focus-by-pointer;
3736
}
3837

39-
&:focus-visible {
40-
outline: eccgui-color-rgba($eccgui-color-accent, $eccgui-opacity-muted) solid 2px;
41-
outline-offset: 1px;
38+
&:focus-visible:not(.#{$prefix}--link--disabled) {
39+
@include focus-by-keyboard-static;
40+
@include focus-by-keyboard-animation;
4241
}
4342
}

0 commit comments

Comments
 (0)