UNPKG

@patreon/studio

Version:

Patreon Studio Design System

62 lines 2.62 kB
'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