From a7b631f0f1414fe454fa8af53916a5fe980fcc6e Mon Sep 17 00:00:00 2001 From: mkrds Date: Tue, 1 Feb 2022 14:50:42 +0100 Subject: [PATCH] fix(split-button): fix tabbing order issues --- cypress/integration/common/splitButton.feature | 10 +++++++++- cypress/locators/split-button/index.js | 2 ++ cypress/locators/split-button/locators.js | 1 + .../step-definitions/split-button-steps.js | 17 +++++++++++++++++ .../split-button/split-button.component.js | 9 +++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cypress/integration/common/splitButton.feature b/cypress/integration/common/splitButton.feature index 3d1dda4ab6..77187a02c4 100644 --- a/cypress/integration/common/splitButton.feature +++ b/cypress/integration/common/splitButton.feature @@ -77,4 +77,12 @@ Feature: Split Button component Given I open "Split Button" component page "in overflow hidden container" And I expand accordionRow using "Enter" key When I hover mouse onto "dropdown" icon - Then Split Button is expanded \ No newline at end of file + Then Split Button is expanded + + @positive + Scenario: I press tab key while Split Button is open + Given I open "Split Button" component page "button types" + And I click split button toggle + And I focus second additional button + When I press tab key on split button + Then Second Split Button component is focused \ No newline at end of file diff --git a/cypress/locators/split-button/index.js b/cypress/locators/split-button/index.js index 79c023faa5..8797eda82d 100644 --- a/cypress/locators/split-button/index.js +++ b/cypress/locators/split-button/index.js @@ -2,6 +2,7 @@ import { SPLIT_TOGGLE_BUTTON, ADDITIONAL_BUTTONS, SPLIT_MAIN_BUTTON, + MAIN_BUTTON, } from "./locators"; // component preview locators @@ -10,3 +11,4 @@ export const additionalButton = (index) => cy.get(ADDITIONAL_BUTTONS).children().eq(index); export const splitMainButtonDataComponent = (index) => cy.get(SPLIT_MAIN_BUTTON).children().eq(index); +export const mainButton = () => cy.get(MAIN_BUTTON); diff --git a/cypress/locators/split-button/locators.js b/cypress/locators/split-button/locators.js index 8f6511002d..43829e39ab 100644 --- a/cypress/locators/split-button/locators.js +++ b/cypress/locators/split-button/locators.js @@ -2,3 +2,4 @@ export const SPLIT_TOGGLE_BUTTON = '[data-element="toggle-button"]'; export const ADDITIONAL_BUTTONS = '[data-element="additional-buttons"]'; export const SPLIT_MAIN_BUTTON = '[data-component="split-button"]'; +export const MAIN_BUTTON = '[data-element="main-button"]'; diff --git a/cypress/support/step-definitions/split-button-steps.js b/cypress/support/step-definitions/split-button-steps.js index 6de0ce9f1f..fd1d74a4eb 100644 --- a/cypress/support/step-definitions/split-button-steps.js +++ b/cypress/support/step-definitions/split-button-steps.js @@ -2,6 +2,7 @@ import { splitToggleButton, additionalButton, splitMainButtonDataComponent, + mainButton, } from "../../locators/split-button"; import { positionOfElement } from "../helper"; @@ -106,6 +107,22 @@ When("I hover mouse onto split button", () => { .trigger("mouseover"); }); +When("I click split button toggle", () => { + splitToggleButton().eq(0).click(); +}); + +When("I press tab key on split button", () => { + splitToggleButton().eq(0).tab(); +}); + +When("I focus second additional button", () => { + additionalButton(1).focus(); +}); + +Then("Second Split Button component is focused", () => { + mainButton(1).should("be.focused"); +}); + When("I click {string} element of Split Button component", (element) => { if (element === "first" || element === "second" || element === "third") { additionalButton(positionOfElement(element)).click(); diff --git a/src/components/split-button/split-button.component.js b/src/components/split-button/split-button.component.js index d2b45b9107..b0e7cc4635 100644 --- a/src/components/split-button/split-button.component.js +++ b/src/components/split-button/split-button.component.js @@ -18,6 +18,7 @@ import guid from "../../__internal__/utils/helpers/guid"; import Popover from "../../__internal__/popover"; import { filterStyledSystemMarginProps } from "../../style/utils"; import { baseTheme } from "../../style/themes"; +import { defaultFocusableSelectors } from "../../__internal__/focus-trap/focus-trap-utils"; const marginPropTypes = filterStyledSystemMarginProps( styledSystemPropTypes.space @@ -44,6 +45,7 @@ const SplitButton = ({ const buttonLabelId = useRef(guid()); const additionalButtons = useRef([]); const splitButtonNode = useRef(); + const toggleButton = useRef(); const buttonContainer = useRef(); const [showAdditionalButtons, setShowAdditionalButtons] = useState(false); const [minWidth, setMinWidth] = useState(0); @@ -88,6 +90,12 @@ const SplitButton = ({ nextIndex = currentIndex < numOfChildren ? currentIndex + 1 : 0; ev.preventDefault(); } else if (Events.isTabKey(ev)) { + const elements = Array.from( + document.querySelectorAll(defaultFocusableSelectors) + ).filter((el) => Number(el.tabIndex) !== -1); + const indexOf = elements.indexOf(toggleButton.current); + elements[indexOf]?.focus(); + // timeout enforces that the "hideButtons" method will be run after browser focuses on the next element setTimeout(hideButtons, 0); } @@ -186,6 +194,7 @@ const SplitButton = ({ data-element="toggle-button" key="toggle-button" type="button" + ref={toggleButton} {...toggleButtonProps()} >