Updates
This commit is contained in:
@@ -20,7 +20,10 @@ export default function TWUIDocsAside({
|
||||
return (
|
||||
<aside
|
||||
{...props}
|
||||
className={twMerge("py-10 hidden xl:flex", props.className)}
|
||||
className={twMerge(
|
||||
"pb-10 hidden xl:flex sticky top-6",
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
<Stack>
|
||||
{before}
|
||||
|
||||
@@ -8,7 +8,7 @@ import Stack from "../../layout/Stack";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import Row from "../../layout/Row";
|
||||
import Divider from "../../layout/Divider";
|
||||
import { ChevronDown } from "lucide-react";
|
||||
import { ChevronDown, Circle } from "lucide-react";
|
||||
import Button from "../../layout/Button";
|
||||
|
||||
type Props = DetailedHTMLProps<
|
||||
@@ -20,6 +20,7 @@ type Props = DetailedHTMLProps<
|
||||
strict?: boolean;
|
||||
childWrapperProps?: ComponentProps<typeof Stack>;
|
||||
autoExpandAll?: boolean;
|
||||
child?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -34,6 +35,7 @@ export default function TWUIDocsLink({
|
||||
childWrapperProps,
|
||||
strict,
|
||||
autoExpandAll,
|
||||
child,
|
||||
...props
|
||||
}: Props) {
|
||||
const [isActive, setIsActive] = React.useState(false);
|
||||
@@ -68,16 +70,19 @@ export default function TWUIDocsLink({
|
||||
{...wrapperProps}
|
||||
>
|
||||
<Row className="flex-nowrap grow justify-between w-full">
|
||||
{child && <Circle size={6} />}
|
||||
<a
|
||||
href={docLink.href}
|
||||
title={docLink.title}
|
||||
{...props}
|
||||
className={twMerge(
|
||||
"twui-docs-left-aside-link whitespace-nowrap",
|
||||
"grow",
|
||||
"grow overflow-hidden overflow-ellipsis",
|
||||
isActive ? "active" : "",
|
||||
props.className
|
||||
)}
|
||||
ref={linkRef}
|
||||
data-strict={strict || docLink.strict}
|
||||
>
|
||||
{docLink.title}
|
||||
</a>
|
||||
@@ -91,6 +96,7 @@ export default function TWUIDocsLink({
|
||||
expand ? "rotate-180 opacity-30" : "opacity-70"
|
||||
)}
|
||||
onClick={() => setExpand(!expand)}
|
||||
title="Docs Aside Links Dropdown Button"
|
||||
>
|
||||
<ChevronDown className="text-slate-500" size={20} />
|
||||
</Button>
|
||||
@@ -98,19 +104,20 @@ export default function TWUIDocsLink({
|
||||
</Row>
|
||||
{docLink.children && expand && (
|
||||
<Row className="items-stretch gap-4 grow w-full flex-nowrap">
|
||||
<Divider vertical className="h-auto" />
|
||||
<Stack
|
||||
className={twMerge(
|
||||
"gap-2 w-full",
|
||||
"gap-2 w-full pl-3",
|
||||
childWrapperProps?.className
|
||||
)}
|
||||
{...childWrapperProps}
|
||||
>
|
||||
{docLink.children.map((link, index) => (
|
||||
<TWUIDocsLink
|
||||
docLink={link}
|
||||
key={index}
|
||||
className="text-sm"
|
||||
docLink={link}
|
||||
className="text-sm opacity-70"
|
||||
autoExpandAll={autoExpandAll}
|
||||
child
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
import React, { DetailedHTMLProps, HTMLAttributes } from "react";
|
||||
import { DocsLinkType } from ".";
|
||||
import Stack from "../../layout/Stack";
|
||||
import TWUIDocsLink from "./TWUIDocsLink";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import Span from "../../layout/Span";
|
||||
import Row from "../../layout/Row";
|
||||
import { ArrowUpRight, LinkIcon, ListIcon } from "lucide-react";
|
||||
import Link from "../../layout/Link";
|
||||
|
||||
type Props = DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement> & {
|
||||
before?: React.ReactNode;
|
||||
after?: React.ReactNode;
|
||||
autoExpandAll?: boolean;
|
||||
editPageURL?: string;
|
||||
};
|
||||
export default function TWUIDocsRightAside({
|
||||
after,
|
||||
before,
|
||||
autoExpandAll,
|
||||
editPageURL,
|
||||
...props
|
||||
}: Props) {
|
||||
const [links, setLinks] = React.useState<DocsLinkType[]>([]);
|
||||
const [ready, setReady] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!ready) return;
|
||||
|
||||
const headerHrefs = document.querySelectorAll(
|
||||
".twui-docs-header-anchor"
|
||||
);
|
||||
|
||||
const linksArr: DocsLinkType[] = [];
|
||||
|
||||
for (let i = 0; i < headerHrefs.length; i++) {
|
||||
const anchorEl = headerHrefs[i] as HTMLAnchorElement;
|
||||
|
||||
const isH2Element = anchorEl.querySelector("h2") !== null;
|
||||
|
||||
if (isH2Element) {
|
||||
let newLink: DocsLinkType = {
|
||||
title: anchorEl.textContent || "",
|
||||
href: `#${anchorEl.id}`,
|
||||
};
|
||||
|
||||
let nexElIndex = i + 1;
|
||||
|
||||
while (nexElIndex < headerHrefs.length) {
|
||||
const nextElement = headerHrefs[
|
||||
nexElIndex
|
||||
] as HTMLAnchorElement;
|
||||
|
||||
const nextElementH3 = nextElement.querySelector("h3");
|
||||
|
||||
console.log("nextElement", nextElement);
|
||||
|
||||
const isNextElementH2 =
|
||||
nextElement.querySelector("h2") !== null;
|
||||
|
||||
if (isNextElementH2) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nextElementH3) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!newLink.children) {
|
||||
newLink.children = [];
|
||||
}
|
||||
|
||||
newLink.children.push({
|
||||
title: nextElementH3.textContent || "",
|
||||
href: `#${nextElement.id}`,
|
||||
});
|
||||
|
||||
nexElIndex++;
|
||||
}
|
||||
|
||||
linksArr.push(newLink);
|
||||
}
|
||||
}
|
||||
|
||||
setLinks(linksArr);
|
||||
}, [ready]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!links.length) return;
|
||||
|
||||
const headerHrefs = document.querySelectorAll(
|
||||
"a.twui-docs-header-anchor"
|
||||
);
|
||||
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach((entry) => {
|
||||
if (entry.isIntersecting) {
|
||||
const id = entry.target.id;
|
||||
|
||||
const link = document.querySelector(
|
||||
`.twui-docs-right-aside a[href="#${id}"]`
|
||||
);
|
||||
if (link) {
|
||||
link.classList.add("active");
|
||||
}
|
||||
} else {
|
||||
const id = entry.target.id;
|
||||
const link = document.querySelector(
|
||||
`.twui-docs-right-aside a[href="#${id}"]`
|
||||
);
|
||||
if (link) {
|
||||
link.classList.remove("active");
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
headerHrefs.forEach((headerHref) => {
|
||||
observer.observe(headerHref);
|
||||
});
|
||||
}, [links]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setTimeout(() => {
|
||||
setReady(true);
|
||||
}, 100);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<aside
|
||||
{...props}
|
||||
className={twMerge(
|
||||
"pb-10 hidden xl:flex min-w-[150px] max-w-[200px]",
|
||||
"sticky top-6 twui-docs-right-aside",
|
||||
props.className
|
||||
)}
|
||||
>
|
||||
<Stack className="w-full overflow-hidden">
|
||||
{before}
|
||||
<Stack className="w-full">
|
||||
<Row>
|
||||
<ListIcon size={12} opacity={0.5} />
|
||||
<Span size="smaller" variant="faded">
|
||||
On this page
|
||||
</Span>
|
||||
</Row>
|
||||
{links.map((link, index) => (
|
||||
<TWUIDocsLink
|
||||
docLink={link}
|
||||
key={index}
|
||||
autoExpandAll
|
||||
childWrapperProps={{
|
||||
className: "pl-2",
|
||||
}}
|
||||
wrapperProps={{
|
||||
className:
|
||||
"[&_svg]:hidden [&_a]:text-xs [&_a]:overflow-hidden [&_a]:overflow-ellipsis",
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
{after}
|
||||
{editPageURL && (
|
||||
<Link
|
||||
href={editPageURL}
|
||||
target="_blank"
|
||||
className="text-[12px] mt-2"
|
||||
>
|
||||
<Row className="gap-2">
|
||||
<LinkIcon size={12} opacity={0.5} />
|
||||
<span>Edit This Page</span>
|
||||
<ArrowUpRight size={15} className="-ml-1" />
|
||||
</Row>
|
||||
</Link>
|
||||
)}
|
||||
</Stack>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
@@ -7,9 +7,18 @@ import {
|
||||
import Stack from "../../layout/Stack";
|
||||
import Container from "../../layout/Container";
|
||||
import Row from "../../layout/Row";
|
||||
import Divider from "../../layout/Divider";
|
||||
import TWUIDocsAside from "./TWUIDocsAside";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import Paper from "../../elements/Paper";
|
||||
import TWUIDocsRightAside from "./TWUIDocsRightAside";
|
||||
|
||||
export type DocsLinkType = {
|
||||
title: string;
|
||||
href: string;
|
||||
strict?: boolean;
|
||||
children?: DocsLinkType[];
|
||||
editPage?: string;
|
||||
};
|
||||
|
||||
type Props = PropsWithChildren & {
|
||||
DocsLinks: DocsLinkType[];
|
||||
@@ -22,12 +31,7 @@ type Props = PropsWithChildren & {
|
||||
HTMLElement
|
||||
>;
|
||||
autoExpandAll?: boolean;
|
||||
};
|
||||
|
||||
export type DocsLinkType = {
|
||||
title: string;
|
||||
href: string;
|
||||
children?: DocsLinkType[];
|
||||
editPageURL?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,6 +47,7 @@ export default function TWUIDocs({
|
||||
docsContentProps,
|
||||
leftAsideProps,
|
||||
autoExpandAll,
|
||||
editPageURL,
|
||||
}: Props) {
|
||||
return (
|
||||
<Stack
|
||||
@@ -51,25 +56,32 @@ export default function TWUIDocs({
|
||||
className={twMerge("w-full px-4 sm:px-6", wrapperProps?.className)}
|
||||
>
|
||||
<Container>
|
||||
<Row
|
||||
{...docsContentProps}
|
||||
className={twMerge(
|
||||
"items-stretch gap-6 w-full flex-nowrap",
|
||||
docsContentProps?.className
|
||||
)}
|
||||
>
|
||||
<TWUIDocsAside
|
||||
DocsLinks={DocsLinks}
|
||||
after={docsAsideAfter}
|
||||
before={docsAsideBefore}
|
||||
autoExpandAll={autoExpandAll}
|
||||
{...leftAsideProps}
|
||||
/>
|
||||
<Divider vertical className="h-auto hidden xl:flex" />
|
||||
<div className="block twui-docs-content py-10 pl-0 xl:pl-6 grow">
|
||||
{children}
|
||||
</div>
|
||||
</Row>
|
||||
<Paper className="xl:p-8 mobile-paper-hidden">
|
||||
<Row
|
||||
{...docsContentProps}
|
||||
className={twMerge(
|
||||
"items-start gap-8 w-full flex-nowrap",
|
||||
docsContentProps?.className
|
||||
)}
|
||||
>
|
||||
<TWUIDocsAside
|
||||
DocsLinks={DocsLinks}
|
||||
after={docsAsideAfter}
|
||||
before={docsAsideBefore}
|
||||
autoExpandAll={autoExpandAll}
|
||||
{...leftAsideProps}
|
||||
/>
|
||||
<div
|
||||
className={twMerge(
|
||||
"block twui-docs-content pl-0 xl:pl-6 grow",
|
||||
"overflow-hidden"
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<TWUIDocsRightAside editPageURL={editPageURL} />
|
||||
</Row>
|
||||
</Paper>
|
||||
</Container>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user