Changeset 257411 in webkit


Ignore:
Timestamp:
Feb 25, 2020 11:18:43 PM (4 years ago)
Author:
Nikita Vasilyev
Message:

Web Inspector: AXI: buttons should be focusable when navigating by pressing Tab
https://bugs.webkit.org/show_bug.cgi?id=208163
<rdar://problem/59745448>

Reviewed by Brian Burg.

Buttons now accessible with Tab navigation. The focused button has the native focus outline.

Clicking on the button does NOT move the focus. For example, when you're focused on the
console prompt, clicking on the icon to hide the right sidebar keeps you focused where
you were — the console prompt. This behavior matches macOS.

Convert WI.NavigationItem with role=button from <div> to <button> elements.
Button elements have implicit tabIndex=0. When focused, pressing Space or Enter
triggers "click" event.

  • UserInterface/Views/ActivateButtonNavigationItem.js:

(WI.ActivateButtonNavigationItem.prototype.set activated):
Add "aria-pressed" and "aria-label" attributes for VoiceOver.

  • UserInterface/Views/ButtonNavigationItem.css:

(.navigation-bar .item.button:not(.image-only):focus,):
(.navigation-bar .item.button.image-only:focus):
(.navigation-bar .item.button:not(.disabled):matches(.activate.activated, .radio.selected) > .glyph):
(.navigation-bar .item.button:not(.disabled):active:matches(.activate.activated, .radio.selected) > .glyph):
Before this patch, focused button looked the same as activated buttons.
For example, the focused (non-active) bullseye icon looked exactly the
same as unfocused active bullseye icon, which was misleading.

  • UserInterface/Views/ButtonNavigationItem.js:

(WI.ButtonNavigationItem):
(WI.ButtonNavigationItem.prototype._mouseClicked):
(WI.ButtonNavigationItem.prototype._handleMouseDown):
Clicking on a button shouldn't move focus. For example, when you're focused on the console prompt,
clicking on the icon to hide the right sidebar should keep you focused where you were - the console prompt.

(WI.ButtonNavigationItem.prototype._handleKeyDown):

  • UserInterface/Views/ButtonToolbarItem.css:

(.toolbar .item.button):
Adjust outline offset to remove the gap between the outline and the border of the button.

(.toolbar .item.button:not(.disabled).activate.activated):
(@media (prefers-color-scheme: dark) body:not(.window-inactive) .toolbar .item.button:not(.disabled).activate.activated > .glyph):

  • UserInterface/Views/ControlToolbarItem.css:

(.toolbar .item.control:focus):
(.toolbar .item.control:focus > .glyph):
Draw the outline around the X (close button) glyph, not the button itself (which is much wider than the glyph).

  • UserInterface/Views/NavigationBar.css:

(.navigation-bar .item):
(.navigation-bar .item:focus):

  • UserInterface/Views/NavigationBar.js:

(WI.NavigationBar):
"focus" and "blur" events don't bubble. These event handlers didn't capture the event.

(WI.NavigationBar.prototype._mouseDown):
(WI.NavigationBar.prototype._keyDown):

  • UserInterface/Views/NavigationItem.js:

(WI.NavigationItem):

  • UserInterface/Views/RadioButtonNavigationItem.css:

(.navigation-bar .item.radio.button:focus):

  • UserInterface/Views/Toolbar.css:

(.toolbar .item):

Location:
trunk/Source/WebInspectorUI
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r257410 r257411  
     12020-02-25  Nikita Vasilyev  <nvasilyev@apple.com>
     2
     3        Web Inspector: AXI: buttons should be focusable when navigating by pressing Tab
     4        https://bugs.webkit.org/show_bug.cgi?id=208163
     5        <rdar://problem/59745448>
     6
     7        Reviewed by Brian Burg.
     8
     9        Buttons now accessible with Tab navigation. The focused button has the native focus outline.
     10
     11        Clicking on the button does NOT move the focus. For example, when you're focused on the
     12        console prompt, clicking on the icon to hide the right sidebar keeps you focused where
     13        you were — the console prompt. This behavior matches macOS.
     14
     15        Convert WI.NavigationItem with role=button from `<div>` to `<button>` elements.
     16        Button elements have implicit tabIndex=0. When focused, pressing Space or Enter
     17        triggers "click" event.
     18
     19        * UserInterface/Views/ActivateButtonNavigationItem.js:
     20        (WI.ActivateButtonNavigationItem.prototype.set activated):
     21        Add "aria-pressed" and "aria-label" attributes for VoiceOver.
     22
     23        * UserInterface/Views/ButtonNavigationItem.css:
     24        (.navigation-bar .item.button:not(.image-only):focus,):
     25        (.navigation-bar .item.button.image-only:focus):
     26        (.navigation-bar .item.button:not(.disabled):matches(.activate.activated, .radio.selected) > .glyph):
     27        (.navigation-bar .item.button:not(.disabled):active:matches(.activate.activated, .radio.selected) > .glyph):
     28        Before this patch, focused button looked the same as activated buttons.
     29        For example, the focused (non-active) bullseye icon looked exactly the
     30        same as unfocused active bullseye icon, which was misleading.
     31
     32        * UserInterface/Views/ButtonNavigationItem.js:
     33        (WI.ButtonNavigationItem):
     34        (WI.ButtonNavigationItem.prototype._mouseClicked):
     35        (WI.ButtonNavigationItem.prototype._handleMouseDown):
     36        Clicking on a button shouldn't move focus. For example, when you're focused on the console prompt,
     37        clicking on the icon to hide the right sidebar should keep you focused where you were - the console prompt.
     38
     39        (WI.ButtonNavigationItem.prototype._handleKeyDown):
     40        * UserInterface/Views/ButtonToolbarItem.css:
     41        (.toolbar .item.button):
     42        Adjust outline offset to remove the gap between the outline and the border of the button.
     43
     44        (.toolbar .item.button:not(.disabled).activate.activated):
     45        (@media (prefers-color-scheme: dark) body:not(.window-inactive) .toolbar .item.button:not(.disabled).activate.activated > .glyph):
     46        * UserInterface/Views/ControlToolbarItem.css:
     47        (.toolbar .item.control:focus):
     48        (.toolbar .item.control:focus > .glyph):
     49        Draw the outline around the X (close button) glyph, not the button itself (which is much wider than the glyph).
     50
     51        * UserInterface/Views/NavigationBar.css:
     52        (.navigation-bar .item):
     53        (.navigation-bar .item:focus):
     54        * UserInterface/Views/NavigationBar.js:
     55        (WI.NavigationBar):
     56        "focus" and "blur" events don't bubble. These event handlers didn't capture the event.
     57
     58        (WI.NavigationBar.prototype._mouseDown):
     59        (WI.NavigationBar.prototype._keyDown):
     60        * UserInterface/Views/NavigationItem.js:
     61        (WI.NavigationItem):
     62        * UserInterface/Views/RadioButtonNavigationItem.css:
     63        (.navigation-bar .item.radio.button:focus):
     64        * UserInterface/Views/Toolbar.css:
     65        (.toolbar .item):
     66
    1672020-02-25  Devin Rousso  <drousso@apple.com>
    268
  • trunk/Source/WebInspectorUI/UserInterface/Views/ActivateButtonNavigationItem.js

    r253085 r257411  
    7070    set activated(flag)
    7171    {
     72        flag = !!flag;
    7273        this.element.classList.toggle(WI.ActivateButtonNavigationItem.ActivatedStyleClassName, flag);
    7374
    74         if (flag) {
    75             this.tooltip = this._activatedToolTip;
    76             if (this._role === "tab")
    77                 this.element.setAttribute("aria-selected", "true");
    78         } else {
    79             this.tooltip = this._defaultToolTip;
    80             if (this._role === "tab")
    81                 this.element.removeAttribute("aria-selected");
    82         }
     75        this.tooltip = flag ? this._activatedToolTip : this._defaultToolTip;
     76
     77        this.element.ariaPressed = flag;
     78        this.element.ariaLabel = this.tooltip;
    8379    }
    8480
  • trunk/Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.css

    r256086 r257411  
    2727    justify-content: center;
    2828    color: hsl(0, 0%, 18%);
     29}
     30
     31.navigation-bar .item.button:not(.image-only):focus,
     32.navigation-bar .item.button.image-only:focus > .glyph {
     33    outline: auto -webkit-focus-ring-color;
     34}
     35
     36.navigation-bar .item.button.image-only:focus {
     37    outline: none;
    2938}
    3039
     
    6271}
    6372
    64 .navigation-bar .item.button:not(.disabled):matches(:focus, .activate.activated, .radio.selected) > .glyph {
     73.navigation-bar .item.button:not(.disabled):matches(.activate.activated, .radio.selected) > .glyph {
    6574    color: var(--glyph-color-active);
    6675}
    6776
    68 .navigation-bar .item.button:not(.disabled):active:matches(:focus, .activate.activated, .radio.selected) > .glyph {
     77.navigation-bar .item.button:not(.disabled):active:matches(.activate.activated, .radio.selected) > .glyph {
    6978    color: var(--glyph-color-active-pressed);
    7079}
  • trunk/Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.js

    r256086 r257411  
    2828    constructor(identifier, toolTipOrLabel, image, imageWidth, imageHeight, role, label)
    2929    {
    30         super(identifier, role || "button");
     30        role = role || "button";
     31        super(identifier, role);
    3132
    3233        console.assert(identifier);
     
    3637
    3738        this.element.addEventListener("click", this._mouseClicked.bind(this));
     39
     40        // Don't move the focus on the button when clicking on it. This matches macOS behavior.
     41        this.element.addEventListener("mousedown", this._handleMouseDown.bind(this), true);
     42
     43        if (role === "button") {
     44            this.element.tabIndex = 0;
     45            this.element.addEventListener("keydown", this._handleKeyDown.bind(this));
     46        }
    3847
    3948        if (label)
     
    142151
    143152    _mouseClicked(event)
     153    {
     154        this._buttonPressed(event);
     155    }
     156
     157    _handleMouseDown(event)
     158    {
     159        // Clicking on a button should NOT focus on it.
     160        event.stop();
     161    }
     162
     163    _handleKeyDown(event)
     164    {
     165        if (event.code === "Enter" || event.code === "Space") {
     166            event.stop();
     167            this._buttonPressed(event);
     168        }
     169    }
     170
     171    _buttonPressed(event)
    144172    {
    145173        if (!this.enabled)
  • trunk/Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.css

    r256086 r257411  
    3232
    3333    color: hsl(0, 0%, 45%);
     34    outline-offset: -2px;
    3435}
    3536
     
    3839}
    3940
    40 .toolbar .item.button:not(.disabled):matches(:focus, .activate.activated) {
     41.toolbar .item.button:not(.disabled).activate.activated {
    4142    color: var(--glyph-color-active);
    4243}
     
    7071    }
    7172
    72     body:not(.window-inactive) .toolbar .item.button:not(.disabled):matches(:focus, .activate.activated) > .glyph {
     73    body:not(.window-inactive) .toolbar .item.button:not(.disabled).activate.activated > .glyph {
    7374        filter: brightness(1.35);
    7475    }
  • trunk/Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.css

    r256086 r257411  
    5353}
    5454
     55.toolbar .item.control:focus {
     56    outline: none;
     57}
     58
     59.toolbar .item.control:focus > .glyph {
     60    outline: auto -webkit-focus-ring-color;
     61}
     62
    5563body.window-inactive .toolbar .item.control {
    5664    opacity: 0.35;
  • trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.css

    r248818 r257411  
    4747
    4848    height: auto;
    49     outline: none;
     49    outline-offset: -4px;
     50}
     51
     52.navigation-bar .item:focus {
     53    outline: auto -webkit-focus-ring-color;
    5054}
    5155
  • trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js

    r256652 r257411  
    3737            this.element.setAttribute("aria-label", label);
    3838
    39         this.element.addEventListener("focus", this._focus.bind(this), false);
    40         this.element.addEventListener("blur", this._blur.bind(this), false);
    4139        this.element.addEventListener("keydown", this._keyDown.bind(this), false);
    42         this.element.addEventListener("mousedown", this._mouseDown.bind(this), false);
    43 
     40        this.element.addEventListener("mousedown", this._mouseDown.bind(this), true);
     41
     42        this._role = role;
    4443        this._mouseMovedEventListener = this._mouseMoved.bind(this);
    4544        this._mouseUpEventListener = this._mouseUp.bind(this);
     
    289288            return;
    290289
    291         // Remove the tabIndex so clicking the navigation bar does not give it focus.
    292         // Only keep the tabIndex if already focused from keyboard navigation. This matches Xcode.
    293         if (!this._focused)
    294             this.element.removeAttribute("tabindex");
    295 
    296290        var itemElement = event.target.closest("." + WI.RadioButtonNavigationItem.StyleClassName);
    297291        if (!itemElement || !itemElement.navigationItem)
    298292            return;
     293
     294        if (this._role === "tablist") {
     295            if (this.element.contains(document.activeElement)) {
     296                // If clicking on a tab, stop the event from being handled by the button element. Instead,
     297                // pass focus to the selected tab. Otherwise, let the button become activated normally.
     298                event.stopPropagation();
     299            }
     300        }
    299301
    300302        this._previousSelectedNavigationItem = this.selectedNavigationItem;
     
    311313        document.addEventListener("mousemove", this._mouseMovedEventListener, false);
    312314        document.addEventListener("mouseup", this._mouseUpEventListener, false);
    313 
    314         event.stopPropagation();
    315315    }
    316316
     
    374374    _keyDown(event)
    375375    {
    376         if (!this._focused)
    377             return;
    378 
    379376        if (event.keyIdentifier !== "Left" && event.keyIdentifier !== "Right")
    380377            return;
     
    402399
    403400        this.selectedNavigationItem = this._navigationItems[selectedNavigationItemIndex];
    404     }
    405 
    406     _focus(event)
    407     {
    408         this._focused = true;
    409     }
    410 
    411     _blur(event)
    412     {
    413         this._focused = false;
     401        this.selectedNavigationItem?.element.focus();
    414402    }
    415403
  • trunk/Source/WebInspectorUI/UserInterface/Views/NavigationItem.js

    r249301 r257411  
    3838        this._cachedWidth = NaN;
    3939
    40         if (role)
    41             this._element.setAttribute("role", role);
    4240        if (label)
    4341            this._element.setAttribute("aria-label", label);
    4442
    4543        this._element.classList.add(...this._classNames);
     44        this._element.role = role;
    4645        this._element.navigationItem = this;
    4746    }
  • trunk/Source/WebInspectorUI/UserInterface/Views/RadioButtonNavigationItem.css

    r255894 r257411  
    3030.navigation-bar.collapsed .item.radio.button:not(.text-only) {
    3131    width: 24px;
     32}
     33
     34.navigation-bar .item.radio.button:focus {
     35    outline-offset: -1px;
    3236}
    3337
  • trunk/Source/WebInspectorUI/UserInterface/Views/Toolbar.css

    r256086 r257411  
    9696.toolbar .item {
    9797    display: flex;
    98     outline: none;
    9998}
    10099
Note: See TracChangeset for help on using the changeset viewer.