Files
gitbook/packages/gitbook/src/components/DocumentView/Expandable/Details.tsx
T
2026-10-21 11:31:59 +02:00

79 lines
2.2 KiB
TypeScript

'use client';
import React from 'react';
import { useHash } from '@/components/hooks';
import { type ClassValue, tcls } from '@/lib/tailwind';
/**
* Details component rendered on client so it can expand dependent on url hash changes.
*/
export function Details(props: {
children: React.ReactNode;
id: string;
contentIds?: string[];
open?: boolean;
className?: ClassValue;
/** Node key of the expandable, so comments can anchor to it. */
commentKey?: string;
}) {
const { children, id, className } = props;
const ref = React.useRef<HTMLDetailsElement>(null);
const [openFromHash, setOpenFromHash] = React.useState(false);
const hash = useHash();
/**
* Open the details element if the url hash refers to the id of the details element
* or the id of some element contained within the details element.
*/
React.useEffect(() => {
if (!hash || !ref.current) {
return;
}
if (hash === id) {
setOpenFromHash(true);
return;
}
const activeElement = document.getElementById(hash);
const isOpen = Boolean(activeElement && ref.current.contains(activeElement));
setOpenFromHash(isOpen);
}, [hash, id]);
return (
<details
ref={ref}
id={id}
data-block-key={props.commentKey}
open={props.open || openFromHash}
className={tcls(
className,
'group/expandable',
'bg-tint-base',
'border',
'border-b-0',
'border-tint-subtle',
//all
'mt-0!',
'mb-0',
//select first child
'first:mt-5!',
'first:rounded-t-lg',
//select first in group
'[:not(&)_+_&]:mt-5!',
'[:not(&)_+_&]:rounded-t-lg',
//select last in group
'[&:not(:has(+_&))]:mb-5',
'[&:not(:has(+_&))]:rounded-b-lg',
'[&:not(:has(+_&))]:border-b'
)}
>
{children}
</details>
);
}