mirror of
https://github.com/bendtherules/UiQuestions.git
synced 2026-08-18 22:02:42 +00:00
Accordion - Handle auto-open if inner element is linked to
This commit is contained in:
@@ -1,10 +1,57 @@
|
|||||||
import React from "react";
|
import React, { useRef, useEffect } from "react";
|
||||||
|
|
||||||
const Accordion = ({ children, title = "More" }) => (
|
const Accordion = ({ children, title = "More" }) => {
|
||||||
<details>
|
const detailsRef = useRef(null);
|
||||||
<summary>{title}</summary>
|
const summaryRef = useRef(null);
|
||||||
|
|
||||||
|
function openAccordionOnHash() {
|
||||||
|
const hash = location.hash.substring(1);
|
||||||
|
if (hash.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let targetElement;
|
||||||
|
targetElement = document.getElementById(hash);
|
||||||
|
if (targetElement === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. If target is within current details element
|
||||||
|
const detailsElement = detailsRef.current;
|
||||||
|
const summaryElement = summaryRef.current;
|
||||||
|
if (
|
||||||
|
detailsElement !== null &&
|
||||||
|
summaryElement.current !== null &&
|
||||||
|
detailsElement.contains(targetElement)
|
||||||
|
) {
|
||||||
|
// 2. and it is not open,
|
||||||
|
if (!detailsElement.open) {
|
||||||
|
// 3. Then open it
|
||||||
|
detailsElement.open = true;
|
||||||
|
// 4. and scroll into view, focus on summary
|
||||||
|
summaryElement.focus();
|
||||||
|
targetElement.scrollIntoView({ behavior: "smooth", block: "center" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 1. Add event listener for future hash changes
|
||||||
|
window.addEventListener("hashchange", openAccordionOnHash);
|
||||||
|
// 2. Do it anyway now if initial url has hash
|
||||||
|
openAccordionOnHash()
|
||||||
|
|
||||||
|
// Cleanup - remove listener
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("hashchange", openAccordionOnHash);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<details ref={detailsRef}>
|
||||||
|
<summary ref={summaryRef}>{title}</summary>
|
||||||
{children}
|
{children}
|
||||||
</details>
|
</details>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Accordion;
|
export default Accordion;
|
||||||
|
|||||||
Reference in New Issue
Block a user