Skip to content

Commit

Permalink
fix(a11y): ensure role on tooltip'ed elements & use strings on labels (
Browse files Browse the repository at this point in the history
…#3974)

* chore(tooltip): remove useless typography usage

* fix(a11y): role on tooltiped elements

---------

Co-authored-by: Bruno Henriques <zettca@users.noreply.github.com>
  • Loading branch information
zettca and zettca committed Jan 18, 2024
1 parent 8153821 commit edf0730
Show file tree
Hide file tree
Showing 20 changed files with 156 additions and 261 deletions.
9 changes: 1 addition & 8 deletions apps/app/src/components/common/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
HvHeaderNavigation,
HvButton,
HvTooltip,
HvTypography,
} from "@hitachivantara/uikit-react-core";

import logo from "~/assets/logo.png";
Expand Down Expand Up @@ -60,13 +59,7 @@ export const Header = () => {
>
TUTORIAL
</HvButton>
<HvTooltip
title={
<HvTypography>
{open ? "Close Theme Creator" : "Open Theme Creator"}
</HvTypography>
}
>
<HvTooltip title={open ? "Close Theme Creator" : "Open Theme Creator"}>
<HvButton icon onClick={() => setOpen?.((prev) => !prev)}>
<Menu />
</HvButton>
Expand Down
8 changes: 3 additions & 5 deletions apps/app/src/components/components/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,15 @@ export const Tooltip = () => {
},
};

const data = <HvTypography>Tooltip content</HvTypography>;

return (
<HvBox sx={styling.placeholder}>
<HvTooltip title={data} useSingle>
<HvTooltip title="Tooltip content" useSingle>
<HvTypography>Hover here</HvTypography>
</HvTooltip>
<HvTooltip title={data} open>
<HvTooltip title="Tooltip content" open>
<p>{`I'm always showing a tooltip`}</p>
</HvTooltip>
<HvTooltip title={data}>
<HvTooltip title="Tooltip content">
<HvButton icon variant="secondaryGhost">
<Add />
</HvButton>
Expand Down
6 changes: 1 addition & 5 deletions apps/app/src/generator/CodeEditor/CodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import JSON5 from "json5";
import {
HvButton,
HvTooltip,
HvTypography,
useTheme,
} from "@hitachivantara/uikit-react-core";
import { Download, Reset, Duplicate } from "@hitachivantara/uikit-react-icons";
Expand Down Expand Up @@ -100,10 +99,7 @@ const CodeEditor = ({
return (
<div className="relative">
<div className="flex items-center justify-between px-xs py-1 border border-b-0 border-atmo4">
<HvTooltip
enterDelay={500}
title={<HvTypography>Download</HvTypography>}
>
<HvTooltip enterDelay={500} title="Download">
<HvButton
variant="secondaryGhost"
component="a"
Expand Down
6 changes: 3 additions & 3 deletions packages/code-editor/src/CodeEditor/CodeEditor.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ const Header = (props: {
>
{fileName}
</HvTypography>
<HvTooltip title={<HvTypography>Open in new window</HvTypography>}>
<HvTooltip title="Open in new window">
<HvButton
className={styles.buttonMargin}
icon
Expand All @@ -91,7 +91,7 @@ const Header = (props: {
</HvTooltip>
</div>
<div className={styles.headerItemsWrapper}>
<HvTooltip title={<HvTypography>Fullscreen</HvTypography>}>
<HvTooltip title="Fullscreen">
<HvButton
icon
aria-label="Fullscreen"
Expand All @@ -102,7 +102,7 @@ const Header = (props: {
<Fullscreen />
</HvButton>
</HvTooltip>
<HvTooltip title={<HvTypography>Duplicate</HvTypography>}>
<HvTooltip title="Duplicate">
<HvButton className={styles.buttonMargin} icon aria-label="Duplicate">
<Duplicate />
</HvButton>
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/AppSwitcher/Action/Action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export const HvAppSwitcherAction = ({
<HvTooltip
disableFocusListener
disableTouchListener
title={<HvTypography>{description}</HvTypography>}
title={description}
>
<div>
<Info
Expand Down
5 changes: 2 additions & 3 deletions packages/core/src/AvatarGroup/stories/CustomOverflow.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import {
HvTooltip,
HvTypography,
HvAvatarGroup,
HvAvatar,
} from "@hitachivantara/uikit-react-core";

export const CustomOverflow = () => {
const overflowComponent = (overflowCount: number) => (
<HvTooltip title={<HvTypography>+{overflowCount}</HvTypography>}>
<HvAvatar backgroundColor="brand" color="atmo1" />
<HvTooltip title={`+${overflowCount}`}>
<HvAvatar backgroundColor="brand" color="atmo1" role="img" />
</HvTooltip>
);

Expand Down
9 changes: 3 additions & 6 deletions packages/core/src/Input/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ import {
computeValidationMessage,
HvInputValidity,
} from "../BaseInput/validations";
import { HvTypography } from "../Typography";
import { HvTooltip } from "../Tooltip";
import { useControlled } from "../hooks/useControlled";
import { useIsMounted } from "../hooks/useIsMounted";
Expand Down Expand Up @@ -651,11 +650,9 @@ export const HvInput = forwardRef<InputElement, HvInputProps>((props, ref) => {
disableFocusListener
disableTouchListener
title={
<HvTypography>
{revealPassword
? labels?.revealPasswordButtonClickToHideTooltip
: labels?.revealPasswordButtonClickToShowTooltip}
</HvTypography>
revealPassword
? labels?.revealPasswordButtonClickToHideTooltip
: labels?.revealPasswordButtonClickToShowTooltip
}
>
<HvAdornment
Expand Down
50 changes: 18 additions & 32 deletions packages/core/src/ScrollTo/Vertical/ScrollToVertical.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { useMemo } from "react";

import { useDefaultProps } from "../../hooks/useDefaultProps";
import { HvBaseProps } from "../../types/generic";
import { useUniqueId } from "../../hooks/useUniqueId";
Expand All @@ -14,7 +12,6 @@ import {
} from "./ScrollToVertical.styles";
import { HvVerticalScrollListItem } from "./VerticalScrollListItem";
import { useScrollTo } from "../useScrollTo";
import { withTooltip } from "../withTooltip";
import {
HvScrollToTooltipPositions,
HvScrollToVerticalOption,
Expand Down Expand Up @@ -118,36 +115,25 @@ export const HvScrollToVertical = (props: HvScrollToVerticalProps) => {
setScrollTo(event, value, index, wrappedOnChange);
};

const tooltipWrappers = useMemo(() => {
return options.map((option) => {
return withTooltip(option.label, "div", tooltipPosition, false);
});
}, [options, tooltipPosition]);

const tabs = options.map((option, index) => {
const selected = selectedIndex === index;
const tooltipWrapper = tooltipWrappers[index];

return (
<HvVerticalScrollListItem
id={setId(elementId, `item-${index}`)}
onClick={(event) => {
const tabs = options.map((option, index) => (
<HvVerticalScrollListItem
id={setId(elementId, `item-${index}`)}
onClick={(event) => {
handleSelection(event, option.value, index);
onClick?.(event, index);
}}
onKeyDown={(event) => {
if (isKey(event, "Enter") === true) {
handleSelection(event, option.value, index);
onClick?.(event, index);
}}
onKeyDown={(event) => {
if (isKey(event, "Enter") === true) {
handleSelection(event, option.value, index);
onEnter?.(event, index);
}
}}
tooltipWrapper={tooltipWrapper}
selected={selected}
key={option.key || option.label}
aria-label={option.label}
/>
);
});
onEnter?.(event, index);
}
}}
tooltipPlacement={tooltipPosition}
selected={selectedIndex === index}
key={option.key || option.label}
label={option.label}
/>
));

const positionOffset = calculateOffset(options.length);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,8 @@ export const { staticClasses, useClasses } = createClasses(name, {
display: "inline-block",
backgroundColor: theme.colors.secondary_60,
},
text: {
height: "16px",
width: "16px",
display: "flex",
justifyContent: "center",
alignItems: "center",
},
// TODO: remove in v6 (use classes.button)
text: {},
button: {
display: "flex",
justifyContent: "center",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { CurrentStep } from "@hitachivantara/uikit-react-icons";

import { HvBaseProps } from "../../../types/generic";
import { HvTypographyProps } from "../../../Typography";
import { HvTooltip, HvTooltipProps } from "../../../Tooltip";
import { ExtractNames } from "../../../utils/classes";
import { setId } from "../../../utils/setId";
import { useTheme } from "../../../hooks/useTheme";

import { useDefaultProps } from "../../../hooks/useDefaultProps";

import { staticClasses, useClasses } from "./VerticalScrollListItem.styles";
Expand All @@ -14,22 +12,14 @@ export { staticClasses as verticalScrollListItemClasses };

export type HvVerticalScrollListItemClasses = ExtractNames<typeof useClasses>;

export interface HvVerticalScrollListItemProps extends HvBaseProps {
/** A function component that renders a typography wrapped with a tooltip. */
tooltipWrapper: React.FunctionComponent<{
id?: string;
className?: string;
variant?: HvTypographyProps["variant"];
children?: React.ReactNode;
}>;
export interface HvVerticalScrollListItemProps
extends HvBaseProps<HTMLDivElement> {
/** A Jss Object used to override or extend the styles applied. */
classes?: HvVerticalScrollListItemClasses;
/** Whether the element is selected. */
selected?: boolean;
/** The function to be executed when the element is clicked. */
onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;
/** The function to be executed when the element is clicked. */
onKeyDown?: (event: React.KeyboardEvent<HTMLDivElement>) => void;
label?: React.ReactNode;
tooltipPlacement?: HvTooltipProps["placement"];
}

/**
Expand All @@ -43,49 +33,38 @@ export const HvVerticalScrollListItem = (
className,
classes: classesProp,
selected,
"aria-label": ariaLabel,
label,
onClick,
onKeyDown,
tooltipWrapper,
tooltipPlacement = "left",
...others
} = useDefaultProps("HvVerticalScrollListItem", props);
const { classes, cx } = useClasses(classesProp);
const { activeTheme } = useTheme();

const variant: HvTypographyProps["variant"] = selected ? "label" : "body";

const labelId = setId(id, "label");

const buttonId = setId(id, "button");

const Tooltip = tooltipWrapper;

const icon = selected ? (
<CurrentStep
height={activeTheme?.scrollTo.dotSelectedSize}
width={activeTheme?.scrollTo.dotSelectedSize}
/>
) : (
<div className={cx(classes.notSelected)} />
<div className={classes.notSelected} />
);

return (
<li id={id} className={cx(classes.root, className)} aria-current={selected}>
<div
id={buttonId}
role="button"
tabIndex={0}
onClick={onClick}
onKeyDown={onKeyDown}
className={classes.button}
aria-label={ariaLabel}
aria-labelledby={labelId}
{...others}
>
<Tooltip id={labelId} className={classes.text} variant={variant}>
<HvTooltip title={label} placement={tooltipPlacement}>
<div
role="button"
tabIndex={0}
onClick={onClick}
onKeyDown={onKeyDown}
className={cx(classes.button, classes.text)}
{...others}
>
{icon}
</Tooltip>
</div>
</div>
</HvTooltip>
</li>
);
};
8 changes: 2 additions & 6 deletions packages/core/src/ToggleButton/ToggleButton.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
HvToggleButton,
HvToggleButtonProps,
HvTooltip,
HvTypography,
} from "@hitachivantara/uikit-react-core";

import { ToggleEye } from "./ToggleEye";
Expand Down Expand Up @@ -142,7 +141,7 @@ export const Disabled: StoryObj<HvToggleButtonProps> = {
},
render: () => {
return (
<HvTooltip title={<HvTypography>Can not turn the light on</HvTypography>}>
<HvTooltip title="Can not turn the light on">
<span>
<HvToggleButton disabled aria-label="Light">
<LightOff />
Expand All @@ -166,11 +165,8 @@ export const Tooltip: StoryObj<HvToggleButtonProps> = {
render: () => {
const [selected, setSelected] = useState(false);

const tooltip = (
<HvTypography>{selected ? "Turn off" : "Turn on"}</HvTypography>
);
return (
<HvTooltip title={tooltip}>
<HvTooltip title={selected ? "Turn off" : "Turn on"}>
<HvToggleButton
aria-label="Light"
onClick={() => setSelected(!selected)}
Expand Down
10 changes: 4 additions & 6 deletions packages/core/src/Tooltip/Tooltip.test.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { describe, expect, it } from "vitest";

import { HvTypography } from "../Typography";

import { HvTooltip } from "./Tooltip";

const smallTitle = <HvTypography>Grid View</HvTypography>;
const smallTitle = <div>Grid View</div>;

const createTitle = (data: any) => (
<div>
<HvTypography variant="label">{data.title || ""}</HvTypography>
<div>{data.title || ""}</div>
{data.elements.map((element: any) => (
<div key={element.name}>
<HvTypography variant="label">{element.name}</HvTypography>
<div>{element.name}</div>
<div />
<HvTypography>{element.value}</HvTypography>
<div>{element.value}</div>
</div>
))}
</div>
Expand Down

0 comments on commit edf0730

Please sign in to comment.