31 lines
844 B
TypeScript
31 lines
844 B
TypeScript
|
|
import type { KeyboardEvent } from 'react';
|
||
|
|
|
||
|
|
export interface ClickableProps {
|
||
|
|
role: 'button';
|
||
|
|
tabIndex: number;
|
||
|
|
onClick: () => void;
|
||
|
|
onKeyDown: (e: KeyboardEvent) => void;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Props to spread onto a non-interactive element (typically a `<div>`) that
|
||
|
|
* acts like a button (e.g. a clickable list row or grid tile), so it
|
||
|
|
* becomes keyboard-operable: `role="button"`, a tab stop, and Enter/Space
|
||
|
|
* activation in addition to the existing click behavior.
|
||
|
|
*
|
||
|
|
* Usage: `<div {...clickableProps(() => doThing())}>...</div>`
|
||
|
|
*/
|
||
|
|
export function clickableProps(onActivate: () => void): ClickableProps {
|
||
|
|
return {
|
||
|
|
role: 'button',
|
||
|
|
tabIndex: 0,
|
||
|
|
onClick: onActivate,
|
||
|
|
onKeyDown: (e: KeyboardEvent) => {
|
||
|
|
if (e.key === 'Enter' || e.key === ' ') {
|
||
|
|
e.preventDefault();
|
||
|
|
onActivate();
|
||
|
|
}
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|