components/elements/CircleInfographic/Circle.jsxjavascript
import "./Circle.scss";
import { useRef, useState, useEffect } from "react";
import { Card } from "../Card/Card";
import { IconBubbles } from "../IconBubbles/IconBubbles";
/**
* One selectable circle of the {@link CircleInfographic}. Toggles its detail
* {@link Card} on tap and closes on tap-outside.
*
* @param {Object} props
* @param {string} props.text - Label inside the circle.
* @param {"black"|"blue"|"white"|"orange"} props.color - Color/position variant class.
* @param {{headline: string|null, text: string|null, underline: string|null}} props.card - Detail card content.
* @param {Array<{small: string, big: string}>} props.icons - Orbiting {@link IconBubbles} definitions.
* @param {function(): void} props.handleCircleSelect - Notifies the parent to blur the other circles.
* @param {function(): void} props.close - Notifies the parent to lift the blur again.
*/
export const Circle = ({ text, color, card, icons, handleCircleSelect, close }) => {
const [selected, setSelected] = useState();
const circle = useRef(null);
const handleSelect = (e) => {
if (selected) {
close();
setSelected(false);
return;
}
handleCircleSelect(e);
setSelected(true);
};
useEffect(() => {
const handleClickOutside = (e) => {
if (circle.current && !circle.current.contains(e.target) && selected) {
close();
setSelected(false);
}
};
// console.log(preview);
document.addEventListener("click", handleClickOutside);
return () => {
document.removeEventListener("click", handleClickOutside);
};
}, [close, selected]);
return (
<div className={`circle-wrapper ${color} ${selected ? "selected--true" : ""}`}>
{icons.map((icon, index) => {
return <IconBubbles key={index} big={icon.big} small={icon.small} />;
})}
<div ref={circle} onClick={handleSelect} className={`circle ${color} selected--${selected}`}>
<div>{text}</div>
<div className="quartercircle"></div>
</div>
{selected ? (
<Card
position={color}
className={`selected--true card`}
headline={card?.headline}
text={card?.text}
underline={card?.underline}
/>
) : null}
</div>
);
};