Skip to content

Commit

Permalink
improvement: tabindex and enter on icon with onClick
Browse files Browse the repository at this point in the history
When an icon has onClick functionality, users should also be able to
focus the icon and trigger the onclick with the keyboard.

Added onKeyUp event to Icon to trigger onclick when pressing enter.
Added tabindex to make icon focusable with the keyboard when onClick is
specified.
  • Loading branch information
Gido Manders committed Dec 11, 2024
1 parent a680e19 commit b97df8c
Show file tree
Hide file tree
Showing 12 changed files with 38 additions and 1 deletion.
6 changes: 6 additions & 0 deletions src/core/Button/__snapshots__/Button.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ exports[`Component: Button ui icon only disabled is disabled 1`] = `
<i
class="icon material-icons material-icons__filled text-primary icon--disabled"
style="font-size: 24px;"
tabindex="0"
>
save
</i>
Expand All @@ -377,6 +378,7 @@ exports[`Component: Button ui icon only disabled is enabled 1`] = `
<i
class="icon material-icons material-icons__filled text-primary clickable"
style="font-size: 24px;"
tabindex="0"
>
save
</i>
Expand All @@ -392,6 +394,7 @@ exports[`Component: Button ui icon only full-width full width and icon left 1`]
<i
class="icon material-icons material-icons__filled text-primary clickable"
style="font-size: 24px;"
tabindex="0"
>
save
</i>
Expand All @@ -407,6 +410,7 @@ exports[`Component: Button ui icon only full-width full width and icon right 1`]
<i
class="icon material-icons material-icons__filled text-primary clickable"
style="font-size: 24px;"
tabindex="0"
>
save
</i>
Expand All @@ -422,6 +426,7 @@ exports[`Component: Button ui icon only inProgress inProgress is false 1`] = `
<i
class="icon material-icons material-icons__filled text-primary clickable"
style="font-size: 24px;"
tabindex="0"
>
save
</i>
Expand Down Expand Up @@ -463,6 +468,7 @@ exports[`Component: Button ui icon only that when no icon is provided it will fa
<i
class="icon material-icons material-icons__filled text-primary clickable"
style="font-size: 24px;"
tabindex="0"
>
block
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ exports[`Component: ConfirmButton ui only icon 1`] = `
<i
class="icon material-icons material-icons__filled text-danger clickable"
style="font-size: 24px;"
tabindex="0"
>
delete
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ exports[`Component: CopyToClipboard ui default 1`] = `
<i
class="icon material-icons material-icons__filled text-primary clickable"
style="font-size: 24px;"
tabindex="0"
>
content_copy
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports[`Component: FavoriteIcon ui favorite 1`] = `
<div>
<i
class="icon material-icons material-icons__filled text-primary clickable"
tabindex="0"
>
star
</i>
Expand All @@ -14,6 +15,7 @@ exports[`Component: FavoriteIcon ui not favorite 1`] = `
<div>
<i
class="icon material-icons material-icons__filled text-secondary clickable"
tabindex="0"
>
star_border
</i>
Expand Down
9 changes: 9 additions & 0 deletions src/core/Icon/Icon.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ describe('Icon', () => {

expect(onClickSpy).toHaveBeenCalledTimes(1);
});
it('should call the "onClick" event when the icon has focus and the enter key is pressed', () => {
const onClickSpy = jest.fn();

render(<Icon icon="alarm" onClick={onClickSpy} />);

fireEvent.keyUp(screen.getByText('alarm'), { key: 'Enter' });

expect(onClickSpy).toHaveBeenCalledTimes(1);
});

it('should call the "onClick" event when the icon is clicked and is explicitly enabled', () => {
const onClickSpy = jest.fn();
Expand Down
11 changes: 10 additions & 1 deletion src/core/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ export type Props = {
/**
* Optional onClick event for when the Icon is clicked.
*/
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
onClick?: (
event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>
) => void;

/**
* Optionally whether the button is disabled
Expand Down Expand Up @@ -117,9 +119,16 @@ export function Icon({
onClick(event);
}
}}
onKeyUp={(event) => {
if (event.key === 'Enter') {
const target = event.target as HTMLElement;
target.click();
}
}}
className={classes}
{...hoverEvents}
autoFocus={autoFocus}
tabIndex={onClick ? 0 : undefined}
>
{icon}
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ exports[`Component: SearchInput ui with value 1`] = `
>
<i
class="icon material-icons material-icons__filled cancel-search clickable"
tabindex="0"
>
close
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ exports[`Component: DateTimeInput ui visible label 1`] = `
>
<i
class="icon material-icons material-icons__filled date-time-input__clear-icon clickable"
tabindex="0"
>
close
</i>
Expand Down
4 changes: 4 additions & 0 deletions src/form/ImageUpload/__snapshots__/ImageUpload.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ exports[`Component: ImageUpload ui edit as circle 1`] = `
<i
class="icon material-icons material-icons__filled text-secondary clickable"
style="font-size: 24px;"
tabindex="0"
>
rotate_left
</i>
Expand All @@ -45,6 +46,7 @@ exports[`Component: ImageUpload ui edit as circle 1`] = `
<i
class="icon material-icons material-icons__filled text-secondary clickable"
style="font-size: 24px;"
tabindex="0"
>
rotate_right
</i>
Expand Down Expand Up @@ -129,6 +131,7 @@ exports[`Component: ImageUpload ui edit as rect 1`] = `
<i
class="icon material-icons material-icons__filled text-secondary clickable"
style="font-size: 24px;"
tabindex="0"
>
rotate_left
</i>
Expand All @@ -139,6 +142,7 @@ exports[`Component: ImageUpload ui edit as rect 1`] = `
<i
class="icon material-icons material-icons__filled text-secondary clickable"
style="font-size: 24px;"
tabindex="0"
>
rotate_right
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ exports[`Component: EpicDetail ui 1`] = `
>
<i
class="icon material-icons material-icons__filled text-muted py-2 px-1 clickable"
tabindex="0"
>
close
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ exports[`Component: EpicExpander ui is open 1`] = `
<i
class="icon material-icons material-icons__filled text-dark clickable"
style="font-size: 24px;"
tabindex="0"
>
expand_less
</i>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ exports[`Component: EpicSort ui is ASC 1`] = `
<div>
<i
class="icon material-icons material-icons__filled py-1 ps-2 clickable"
tabindex="0"
>
arrow_drop_up
</i>
Expand Down

0 comments on commit b97df8c

Please sign in to comment.