mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-26 10:55:57 +00:00
Docs: Create components documentation
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
---
|
||||
title: Breadcrumb
|
||||
description: The navigation component at the top of screen
|
||||
---
|
||||
|
||||
The navigation component at the top of screen.
|
||||
|
||||
```
|
||||
next-docs/breadcrumb
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
it exports a `useBreadcrumb` hook:
|
||||
|
||||
```tsx
|
||||
import { useBreadcrumb } from "next-docs/breadcrumb";
|
||||
|
||||
const tree: TreeNode[] = buildPageTree(allMeta, allDocs);
|
||||
const pathname = usePathname();
|
||||
|
||||
const items = useBreadcrumb(pathname, tree);
|
||||
```
|
||||
|
||||
### Breadcrumb Item
|
||||
|
||||
| Prop | Type | Description |
|
||||
| ------ | ---------------- | ------------ |
|
||||
| `name` | `string` | Name of item |
|
||||
| `url` | `string \| null` | Href link |
|
||||
|
||||
## Example
|
||||
|
||||
Using `lucide-react` for icons.
|
||||
|
||||
```tsx
|
||||
import { usePathname } from "next/navigation";
|
||||
import type { TreeNode } from "next-docs/server";
|
||||
import { useBreadcrumb } from "next-docs/breadcrumb";
|
||||
import clsx from "clsx";
|
||||
import { ChevronRightIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { Fragment } from "react";
|
||||
|
||||
const itemStyles = "overflow-hidden overflow-ellipsis whitespace-nowrap";
|
||||
|
||||
export function Breadcrumb({ tree }: { tree: TreeNode[] }) {
|
||||
const pathname = usePathname();
|
||||
//get breadcrumb items
|
||||
const items = useBreadcrumb(pathname, tree);
|
||||
|
||||
return (
|
||||
<div className="flex flex-row gap-1 text-sm text-muted-foreground items-center">
|
||||
<p className={itemStyles}>Docs</p>
|
||||
{items.map((item, i) => {
|
||||
const active = items.length === i + 1;
|
||||
const style = clsx(itemStyles, active && "text-foreground");
|
||||
|
||||
return (
|
||||
<Fragment key={i}>
|
||||
<ChevronRightIcon className="w-4 h-4 flex-shrink-0" />
|
||||
{item.url != null ? (
|
||||
<Link href={item.url} className={style}>
|
||||
{item.name}
|
||||
</Link>
|
||||
) : (
|
||||
<p className={style}>{item.name}</p>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "Components",
|
||||
"pages": ["breadcrumb", "sidebar", "toc"]
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
title: Sidebar
|
||||
description: The navigation bar at aside of viewport
|
||||
---
|
||||
|
||||
Handles device resizing and remove scroll bar automatically.
|
||||
|
||||
```
|
||||
next-docs/sidebar
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import * as Base from "next-docs/sidebar";
|
||||
|
||||
return (
|
||||
<Base.SidebarProvider>
|
||||
<Base.SidebarTrigger />
|
||||
<Base.SidebarList />
|
||||
</Base.SidebarProvider>
|
||||
);
|
||||
```
|
||||
|
||||
### Sidebar Provider
|
||||
|
||||
| Prop | Type | Description |
|
||||
| -------------- | ---------------------- | ----------- |
|
||||
| `open` | `boolean?` | - |
|
||||
| `onOpenChange` | `(v: boolean) => void` | - |
|
||||
|
||||
### Sidebar Trigger
|
||||
|
||||
Opens the sidebar on click.
|
||||
|
||||
| Prop | Type | Description |
|
||||
| ---- | ------------- | ----------- |
|
||||
| `as` | `ElementType` | - |
|
||||
|
||||
### Sidebar List
|
||||
|
||||
| Data Attribute | Values | Description |
|
||||
| -------------- | ------------- | ------------------ |
|
||||
| `data-open` | `true, false` | Is sidebar opening |
|
||||
|
||||
## Example
|
||||
|
||||
Using `@radix-ui/react-collapsible` and `lucide-react`:
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import clsx from "clsx";
|
||||
import { ChevronDownIcon, MenuIcon } from "lucide-react";
|
||||
import { ReactNode, useEffect, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import type { TreeNode, FileNode, FolderNode } from "next-docs/server";
|
||||
import * as Base from "next-docs/sidebar";
|
||||
import * as Collapsible from "@radix-ui/react-collapsible";
|
||||
|
||||
export function SidebarProvider({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<Base.SidebarProvider>
|
||||
<Base.SidebarTrigger className="flex flex-row gap-2 text-sm px-8 items-center">
|
||||
<MenuIcon className="w-4 h-4" />
|
||||
Menu
|
||||
</Base.SidebarTrigger>
|
||||
{children}
|
||||
</Base.SidebarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export function Sidebar({ items }: { items: TreeNode[] }) {
|
||||
return (
|
||||
<Base.SidebarList
|
||||
minWidth={1024} // when should it being displayed (ignore the trigger)
|
||||
className={clsx(
|
||||
"flex flex-col gap-3 fixed inset-0 top-24 overflow-auto",
|
||||
"lg:sticky lg:top-12 lg:py-16 lg:max-h-[calc(100vh-3rem)]",
|
||||
"max-lg:py-4 max-lg:px-8 max-lg:sm:px-14 max-lg:bg-background/50 max-lg:backdrop-blur-xl max-lg:z-40 max-lg:data-[open=false]:hidden"
|
||||
)}
|
||||
>
|
||||
{items.map((item, i) => (
|
||||
<SidebarItem key={i} item={item} />
|
||||
))}
|
||||
</Base.SidebarList>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
_It doesn't include the implementation of `SidebarItem`_
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: TOC
|
||||
description: Table of Content
|
||||
---
|
||||
|
||||
A Table of Contents with active anchor observer.
|
||||
|
||||
```
|
||||
next-docs/toc
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import * as Base from "next-docs/toc";
|
||||
|
||||
return (
|
||||
<Base.TOCProvider>
|
||||
<Base.TOCItem />
|
||||
</Base.TOCProvider>
|
||||
);
|
||||
```
|
||||
|
||||
### TOC Provider
|
||||
|
||||
| Prop | Type | Description |
|
||||
| ---------- | ----------------- | ----------------- |
|
||||
| `toc` | `TableOfContents` | Table of contents |
|
||||
| `children` | `ReactNode` | - |
|
||||
|
||||
### TOC Item
|
||||
|
||||
| Prop | Type | Description |
|
||||
| ------ | ------------- | ----------- |
|
||||
| `item` | `TOCItemType` | The item |
|
||||
|
||||
| Data Attribute | Values | Description |
|
||||
| -------------- | ------------- | ---------------- |
|
||||
| `data-active` | `true, false` | Is active anchor |
|
||||
|
||||
## Example
|
||||
|
||||
```tsx
|
||||
"use client";
|
||||
import * as Primitive from "next-docs/toc";
|
||||
import type { TOCItemType } from "next-docs/server";
|
||||
|
||||
export function TOC({ items }: { items: TOCItemType[] }) {
|
||||
return (
|
||||
<Primitive.TOCProvider toc={items}>
|
||||
{items.map((item, i) => (
|
||||
<TOCItem key={i} item={item} />
|
||||
))}
|
||||
</Primitive.TOCProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function TOCItem({ item }: { item: TOCItemType }) {
|
||||
return (
|
||||
<div>
|
||||
<Primitive.TOCItem
|
||||
href={item.url}
|
||||
item={item}
|
||||
className="text-sm text-muted-foreground transition-colors data-[active=true]:font-semibold data-[active=true]:text-foreground"
|
||||
>
|
||||
{item.title}
|
||||
</Primitive.TOCItem>
|
||||
<div className="flex flex-col pl-4">
|
||||
{item.items?.map((item, i) => (
|
||||
<TOCItem key={i} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user