@patreon/studio
Version:
Patreon Studio Design System
62 lines • 2.62 kB
JSX
'use client';
import cx from 'classnames';
import React, { useCallback, useRef } from 'react';
import styles from './ClickArea.module.css';
/**
* ClickArea provides an div which captures click events bubbling
* from clickable elements internally.
*/
function ClickArea({ id, 'data-tag': dataTag, onClick, children, style, className, }) {
const areaRef = useRef(null);
return (
// We are catching events during the bubbling phase here on purpose
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div ref={areaRef} onClick={onClick} className={cx(styles.root, className)} style={style} id={id} data-tag={dataTag}>
{children}
</div>);
}
/**
* When using `ClickArea`, the `AbsorbClick` can be used to absorb events bubbling which should
* trigger the ClickArea target element. This is useful to nest a link or button inside of a click
* area which should not trigger the ClickArea.
*/
export function AbsorbClick({ style, className, children }) {
return (
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
<div onClick={(e) => e.stopPropagation()} style={style} className={className}>
{children}
</div>);
}
/**
* The useClickArea hook can be used to provide an accessible click area
* which automatically focuses and clicks a provided element without
* adding unnecessary elements to the accessbility tree.
*/
export function useClickArea() {
const targetElementRef = useRef(null);
const ClickAreaReturn = useCallback(({ 'data-tag': dataTag, children, className, style }) => (<ClickArea data-tag={dataTag} className={className} style={style} onClick={(ev) => {
const target = targetElementRef.current;
// click area should be inert if not target is specified
if (!target) {
return;
}
// click area should do nothing if the click originated
// inside the target element
if (targetElementRef.current?.contains(ev.target)) {
return;
}
// cancel orignal event since we're about to create another
ev.preventDefault();
ev.stopPropagation();
// focus and click on the target element
targetElementRef.current?.focus();
targetElementRef.current?.click();
}}>
{children}
</ClickArea>), [targetElementRef]);
return {
ClickArea: ClickAreaReturn,
targetElementRef,
};
}
//# sourceMappingURL=index.jsx.map