React Popover

by Sebastian Kay

HTML

<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
<div id="root"></div>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script
  src="https://unpkg.com/[email protected]/umd/react.development.js"
  crossorigin
></script>
<script
  src="https://unpkg.com/[email protected]/umd/react-dom.development.js"
  crossorigin
></script>

CSS

.popover-button {
  anchor-name: --my--popover-button;
}

:has(:popover-open) .popover-button {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.popover-list {
  --base-color: hsl(from red h s l);
  --complementary-color: hsl(from var(--base-color) calc(h + 180) s l);
  position: absolute;
  position-anchor: --my--popover-button;
  position-area: bottom span-right;
  height: calc(anchor-size(height) * 4);
  width: anchor-size(width);

  &::-webkit-scrollbar {
    width: 0;
  }
}

Babel + JSX

const html = document.querySelector("html")
const body = document.querySelector("body")

html.classList.add("dark:bg-gray-800")
body.classList.add("m-5")

const Popover = ({ listElements }) => {

  const listItems = listElements.map(listItem =>
    <li key={listItem} className="py-2 px-4 hover:bg-blue-700">{listItem}</li>
  );

  return (
      <>
        <button
          className="popover-button w-[200px] text-white font-bold py-2 px-4 rounded bg-blue-500 hover:bg-blue-700"
          popovertarget="popoverListReact"
        >
          Popover
        </button>
        <ul
          id="popoverListReact"
          className="popover-list text-white rounded rounded-tl-none bg-gray-900"
          popover="true"
        >{listItems}</ul>
      </>
    );
}

class App extends React.Component {
  render() {
    return (
      <div className="mb-4">
        <p className="text-lg text-white">Top-Level Component</p>
        <Popover listElements={["Element 1", "Element 2", "Element 3", "Element 4"]} />
      </div>
    )
  }
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />)