From 816038ec2dc406a018789038715f36024a810d25 Mon Sep 17 00:00:00 2001 From: Yossi Saadi Date: Mon, 12 Feb 2024 09:42:07 +0200 Subject: [PATCH] feat(IconButton): add aria-hidden prop (#1937) --- .../src/components/IconButton/IconButton.tsx | 8 +++- .../__tests__/iconButton-tests.jest.tsx | 44 ++++++++++++------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/packages/core/src/components/IconButton/IconButton.tsx b/packages/core/src/components/IconButton/IconButton.tsx index 0a6746909c..4d3c23f490 100644 --- a/packages/core/src/components/IconButton/IconButton.tsx +++ b/packages/core/src/components/IconButton/IconButton.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef, Fragment, useMemo, useRef } from "react"; +import React, { AriaAttributes, forwardRef, Fragment, useMemo, useRef } from "react"; import cx from "classnames"; import { noop as NOOP } from "lodash-es"; import useMergeRef from "../../hooks/useMergeRef"; @@ -43,6 +43,10 @@ export interface IconButtonProps extends VibeComponentProps { * a11y property to be added, used for screen reader to know if the button is expanded */ ariaExpanded?: boolean; + /** + * a11y property to be added, used for screen reader to know if the button is hidden + */ + "aria-hidden"?: AriaAttributes["aria-hidden"]; /** * Size of the icon */ @@ -101,6 +105,7 @@ const IconButton: VibeComponent & { tooltipContent, ariaLabel, ariaExpanded, + "aria-hidden": ariaHidden, hideTooltip = false, kind = IconButton.kinds.TERTIARY, active, @@ -183,6 +188,7 @@ const IconButton: VibeComponent & { kind={kind} ariaLabel={buttonAriaLabel} ariaExpanded={ariaExpanded} + aria-hidden={ariaHidden} ref={mergedRef} id={id} data-testid={overrideDataTestId || getTestId(ComponentDefaultTestId.ICON_BUTTON, id)} diff --git a/packages/core/src/components/IconButton/__tests__/iconButton-tests.jest.tsx b/packages/core/src/components/IconButton/__tests__/iconButton-tests.jest.tsx index 04a6d88ea6..1ecbea9dc0 100644 --- a/packages/core/src/components/IconButton/__tests__/iconButton-tests.jest.tsx +++ b/packages/core/src/components/IconButton/__tests__/iconButton-tests.jest.tsx @@ -1,12 +1,15 @@ import React from "react"; import { fireEvent, render, cleanup, screen } from "@testing-library/react"; +import "@testing-library/jest-dom"; import { act } from "@testing-library/react-hooks"; import IconButton, { IconButtonProps } from "../IconButton"; jest.useFakeTimers(); -const renderComponent = (props: IconButtonProps) => { - return render(); +const ariaLabel = "Button Icon"; + +const renderComponent = (props: IconButtonProps = {}) => { + return render(); }; describe("IconButton tests", () => { @@ -17,8 +20,7 @@ describe("IconButton tests", () => { describe("click", () => { it("should call the callback function when clicked ", () => { const onClick = jest.fn(); - const ariaLabel = "Button Icon"; - renderComponent({ onClick, ariaLabel }); + renderComponent({ onClick }); const component = screen.getByLabelText(ariaLabel); fireEvent.click(component); expect(onClick.mock.calls.length).toBe(1); @@ -26,8 +28,7 @@ describe("IconButton tests", () => { it("should not call the callback if disabled when clicked ", () => { const onClick = jest.fn(); - const ariaLabel = "Button Icon"; - renderComponent({ onClick, ariaLabel, disabled: true }); + renderComponent({ onClick, disabled: true }); const component = screen.getByLabelText(ariaLabel); fireEvent.click(component); expect(onClick.mock.calls.length).toBe(0); @@ -35,11 +36,10 @@ describe("IconButton tests", () => { }); describe("Tooltips", () => { - it("should display the tooltip content", () => { + it("should display the tooltip content", async () => { const tooltipContent = "My Text"; - const ariaLabel = "Button Icon"; - renderComponent({ tooltipContent, ariaLabel }); + renderComponent({ tooltipContent }); const component = screen.getByLabelText(ariaLabel); act(() => { fireEvent.mouseEnter(component); @@ -54,9 +54,7 @@ describe("IconButton tests", () => { }); it("should display the tooltip with aria label", () => { - const ariaLabel = "Button Icon"; - - renderComponent({ ariaLabel }); + renderComponent(); const component = screen.getByLabelText(ariaLabel); act(() => { fireEvent.mouseEnter(component); @@ -71,10 +69,9 @@ describe("IconButton tests", () => { }); it("should display not disabledReason if disabled is false", () => { - const ariaLabel = "Button Icon"; const disabledReason = "I'm a disabled button"; - renderComponent({ ariaLabel, disabledReason }); + renderComponent({ disabledReason }); const component = screen.getByLabelText(ariaLabel); act(() => { fireEvent.mouseEnter(component); @@ -89,10 +86,9 @@ describe("IconButton tests", () => { }); it("should display disabledReason if disabled is true", () => { - const ariaLabel = "Button Icon"; const disabledReason = "I'm a disabled button"; - renderComponent({ ariaLabel, disabledReason, disabled: true }); + renderComponent({ disabledReason, disabled: true }); const component = screen.getByLabelText(ariaLabel); act(() => { fireEvent.mouseEnter(component); @@ -106,4 +102,20 @@ describe("IconButton tests", () => { jest.advanceTimersByTime(1000); }); }); + + describe("a11y", () => { + describe("aria-hidden", () => { + it("should pass aria-hidden attribute to Button component", () => { + const { getByRole } = renderComponent({ "aria-hidden": true }); + const buttonComponent = getByRole("button", { hidden: true }); + expect(buttonComponent).toHaveAttribute("aria-hidden", "true"); + }); + + it("should not have aria-hidden attribute on Button component if not specified", () => { + const { getByRole } = renderComponent(); + const buttonComponent = getByRole("button"); + expect(buttonComponent).not.toHaveAttribute("aria-hidden"); + }); + }); + }); });