Some changes ported from the work on the makerkit.dev website related… (#89)

* Some changes ported from the work on the makerkit.dev website related to the marketing sections of the kit, such as documentation
* Added slight background hue to make darker theme better looking
* Support more complex configurations for documentation navigations.
* Do not fetch content from Keystatic when non-needed
* Add cursor pointers in dropdown
* Updated packages
This commit is contained in:
Giancarlo Buomprisco
2024-12-09 05:58:17 +01:00
committed by GitHub
parent a682b991f3
commit 079a8f857a
44 changed files with 762 additions and 456 deletions

View File

@@ -61,13 +61,15 @@ async function DocumentationPage({ params }: DocumentationPageProps) {
);
return (
<div className={'flex flex-1 flex-col space-y-4'}>
<div className={'flex'}>
<article className={cn(styles.HTML, 'container space-y-12')}>
<div className={'flex flex-1 flex-col space-y-4 overflow-y-hidden'}>
<div className={'flex overflow-y-hidden'}>
<article
className={cn(styles.HTML, 'container space-y-12 overflow-y-auto')}
>
<section className={'flex flex-col space-y-4 pt-6'}>
<h1 className={'!my-0'}>{page.title}</h1>
<h2 className={'!mb-0 !font-normal text-muted-foreground'}>
<h2 className={'!mb-0 !font-normal !text-muted-foreground'}>
{description}
</h2>
</section>

View File

@@ -1,13 +1,20 @@
'use client';
import { useRef } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { SidebarMenuButton, SidebarMenuItem } from '@kit/ui/shadcn-sidebar';
import { cn, isRouteActive } from '@kit/ui/utils';
export function DocsNavLink({ label, url }: { label: string; url: string }) {
export function DocsNavLink({
label,
url,
children,
}: React.PropsWithChildren<{ label: string; url: string }>) {
const currentPath = usePathname();
const ref = useRef<HTMLElement>(null);
const isCurrent = isRouteActive(url, currentPath, true);
return (
@@ -15,10 +22,16 @@ export function DocsNavLink({ label, url }: { label: string; url: string }) {
<SidebarMenuButton
asChild
isActive={isCurrent}
className={cn('border-l-3 transition-background !font-normal')}
className={cn('border-l-3 transition-background !font-normal', {
'font-bold text-secondary-foreground': isCurrent,
})}
>
<Link href={url}>
<span className="block max-w-full truncate">{label}</span>
<span ref={ref} className="block max-w-full truncate">
{label}
</span>
{children}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>

View File

@@ -0,0 +1,30 @@
'use client';
import { usePathname } from 'next/navigation';
import { Cms } from '@kit/cms';
import { Collapsible } from '@kit/ui/collapsible';
import { isRouteActive } from '@kit/ui/utils';
export function DocsNavigationCollapsible(
props: React.PropsWithChildren<{
node: Cms.ContentItem;
prefix: string;
}>,
) {
const currentPath = usePathname();
const prefix = props.prefix;
const isChildActive = props.node.children.some((child) =>
isRouteActive(prefix + '/' + child.url, currentPath, false),
);
return (
<Collapsible
className={'group/collapsible'}
defaultOpen={isChildActive ? true : !props.node.collapsed}
>
{props.children}
</Collapsible>
);
}

View File

@@ -1,66 +1,137 @@
import { ChevronDown } from 'lucide-react';
import { Cms } from '@kit/cms';
import { CollapsibleContent, CollapsibleTrigger } from '@kit/ui/collapsible';
import {
Sidebar,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
} from '@kit/ui/shadcn-sidebar';
import { DocsNavLink } from '~/(marketing)/docs/_components/docs-nav-link';
import { DocsNavigationCollapsible } from '~/(marketing)/docs/_components/docs-navigation-collapsible';
import { FloatingDocumentationNavigation } from './floating-docs-navigation';
function Node({ node, level }: { node: Cms.ContentItem; level: number }) {
const pathPrefix = `/docs`;
const url = `${pathPrefix}/${node.slug}`;
function Node({
node,
level,
prefix,
}: {
node: Cms.ContentItem;
level: number;
prefix: string;
}) {
const url = `${prefix}/${node.slug}`;
const label = node.label ? node.label : node.title;
const Container = (props: React.PropsWithChildren) => {
if (node.collapsible) {
return (
<DocsNavigationCollapsible node={node} prefix={prefix}>
{props.children}
</DocsNavigationCollapsible>
);
}
return props.children;
};
const ContentContainer = (props: React.PropsWithChildren) => {
if (node.collapsible) {
return <CollapsibleContent>{props.children}</CollapsibleContent>;
}
return props.children;
};
const Trigger = () => {
if (node.collapsible) {
return (
<CollapsibleTrigger asChild>
<SidebarMenuItem>
<SidebarMenuButton>
{label}
<ChevronDown className="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-180" />
</SidebarMenuButton>
</SidebarMenuItem>
</CollapsibleTrigger>
);
}
return <DocsNavLink label={label} url={url} />;
};
return (
<>
<DocsNavLink label={node.title} url={url} />
<Container>
<Trigger />
{(node.children ?? []).length > 0 && (
<Tree pages={node.children ?? []} level={level + 1} />
)}
</>
<ContentContainer>
<Tree pages={node.children ?? []} level={level + 1} prefix={prefix} />
</ContentContainer>
</Container>
);
}
function Tree({ pages, level }: { pages: Cms.ContentItem[]; level: number }) {
function Tree({
pages,
level,
prefix,
}: {
pages: Cms.ContentItem[];
level: number;
prefix: string;
}) {
if (level === 0) {
return pages.map((treeNode, index) => (
<SidebarGroup key={index}>
<SidebarGroupContent>
<SidebarMenu>
<Node key={index} node={treeNode} level={level} />
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<Node key={index} node={treeNode} level={level} prefix={prefix} />
));
}
return (
<SidebarMenuSub>
{pages.map((treeNode, index) => (
<Node key={index} node={treeNode} level={level} />
<Node key={index} node={treeNode} level={level} prefix={prefix} />
))}
</SidebarMenuSub>
);
}
export function DocsNavigation({ pages }: { pages: Cms.ContentItem[] }) {
export function DocsNavigation({
pages,
prefix = '/docs',
}: {
pages: Cms.ContentItem[];
prefix?: string;
}) {
return (
<>
<Sidebar
variant={'ghost'}
className={'z-1 sticky max-h-full overflow-y-auto'}
>
<Tree pages={pages} level={0} />
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
<Tree pages={pages} level={0} prefix={prefix} />
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</Sidebar>
<div className={'lg:hidden'}>
<FloatingDocumentationNavigation>
<Tree pages={pages} level={0} />
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
<Tree pages={pages} level={0} prefix={prefix} />
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</FloatingDocumentationNavigation>
</div>
</>

View File

@@ -18,7 +18,8 @@ async function docsLoader(language: string | undefined) {
const data = await cms.getContentItems({
collection: 'documentation',
language,
limit: 500,
limit: Infinity,
content: false,
});
return data.items;

View File

@@ -15,7 +15,7 @@ async function DocsLayout({ children }: React.PropsWithChildren) {
return (
<SidebarProvider
style={{ '--sidebar-width': '20em' } as React.CSSProperties}
className={'lg:container'}
className={'h-[calc(100vh-72px)] overflow-y-hidden lg:container'}
>
<DocsNavigation pages={tree} />