mirror of
https://github.com/better-auth/better-auth.git
synced 2026-05-25 16:36:34 -05:00
docs(api-method): fixed syntax highlighting refreshing on tab change (#4309)
This commit is contained in:
@@ -59,7 +59,7 @@ export default async function Page({
|
||||
>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
{!avoidLLMHeader.includes(page.data.title) && (
|
||||
<div className="flex flex-row gap-2 items-center border-b pb-3">
|
||||
<div className="flex flex-row gap-2 items-center pb-3 border-b">
|
||||
<LLMCopyButton />
|
||||
<ViewOptions
|
||||
markdownUrl={`${page.url}.mdx`}
|
||||
@@ -75,7 +75,7 @@ export default async function Page({
|
||||
return (
|
||||
<CodeBlockTabs
|
||||
{...props}
|
||||
className="bg-fd-secondary border-b p-0 rounded-lg"
|
||||
className="p-0 rounded-lg border-b bg-fd-secondary"
|
||||
>
|
||||
<div {...props}>{props.children}</div>
|
||||
</CodeBlockTabs>
|
||||
@@ -85,7 +85,7 @@ export default async function Page({
|
||||
return (
|
||||
<CodeBlockTabsList
|
||||
{...props}
|
||||
className="bg-fd-secondary my-0 pb-0 rounded-lg"
|
||||
className="pb-0 my-0 rounded-lg bg-fd-secondary"
|
||||
/>
|
||||
);
|
||||
},
|
||||
@@ -94,9 +94,9 @@ export default async function Page({
|
||||
},
|
||||
pre: (props) => {
|
||||
return (
|
||||
<CodeBlock className="bg-fd-muted rounded-xl" {...props}>
|
||||
<CodeBlock className="rounded-xl bg-fd-muted" {...props}>
|
||||
<div style={{ minWidth: "100%", display: "table" }}>
|
||||
<Pre className="bg-fd-muted py-3 px-0 focus-visible:outline-none">
|
||||
<Pre className="px-0 py-3 bg-fd-muted focus-visible:outline-none">
|
||||
{props.children}
|
||||
</Pre>
|
||||
</div>
|
||||
|
||||
98
docs/components/api-method-tabs.tsx
Normal file
98
docs/components/api-method-tabs.tsx
Normal file
@@ -0,0 +1,98 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const provider = React.createContext<{
|
||||
current: string | null;
|
||||
setCurrent: (value: string | null) => void;
|
||||
}>({
|
||||
current: null,
|
||||
setCurrent: () => {},
|
||||
});
|
||||
|
||||
function ApiMethodTabs({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { defaultValue: string | null }) {
|
||||
const [current, setCurrent] = React.useState<string | null>(
|
||||
props.defaultValue || null,
|
||||
);
|
||||
return (
|
||||
<provider.Provider value={{ current, setCurrent }}>
|
||||
<div
|
||||
data-slot="tabs"
|
||||
className={cn("flex flex-col gap-2", className)}
|
||||
{...props}
|
||||
/>
|
||||
</provider.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
const useApiMethodTabs = () => {
|
||||
return React.useContext(provider);
|
||||
};
|
||||
|
||||
function ApiMethodTabsList({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="tabs-list"
|
||||
className={cn(
|
||||
"inline-flex justify-center items-center p-1 h-9 rounded-lg bg-muted text-muted-foreground w-fit",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ApiMethodTabsTrigger({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"button"> & { value: string }) {
|
||||
const { setCurrent, current } = useApiMethodTabs();
|
||||
return (
|
||||
<button
|
||||
data-slot="tabs-trigger"
|
||||
className={cn(
|
||||
"data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className,
|
||||
)}
|
||||
data-state={props.value === current ? "active" : "inactive"}
|
||||
onClick={() => {
|
||||
setCurrent(props.value);
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function ApiMethodTabsContent({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { value: string }) {
|
||||
const { current } = useApiMethodTabs();
|
||||
return (
|
||||
<div
|
||||
data-slot="tabs-content"
|
||||
className={cn(
|
||||
"flex-1 outline-none",
|
||||
className,
|
||||
props.value === current && "block",
|
||||
props.value !== current && "hidden",
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
ApiMethodTabs,
|
||||
ApiMethodTabsList,
|
||||
ApiMethodTabsTrigger,
|
||||
ApiMethodTabsContent,
|
||||
};
|
||||
@@ -9,7 +9,12 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "./ui/table";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs";
|
||||
import {
|
||||
ApiMethodTabs,
|
||||
ApiMethodTabsContent,
|
||||
ApiMethodTabsList,
|
||||
ApiMethodTabsTrigger,
|
||||
} from "./api-method-tabs";
|
||||
import { JSX, ReactNode } from "react";
|
||||
import { Link } from "lucide-react";
|
||||
import { Button } from "./ui/button";
|
||||
@@ -153,12 +158,12 @@ export const APIMethod = ({
|
||||
className="absolute invisible -top-[100px]"
|
||||
/>
|
||||
</div>
|
||||
<Tabs
|
||||
<ApiMethodTabs
|
||||
defaultValue={isServerOnly ? "server" : "client"}
|
||||
className="w-full gap-0"
|
||||
className="gap-0 w-full"
|
||||
>
|
||||
<TabsList className="relative flex justify-start w-full p-0 bg-transparent hover:[&>div>a>button]:opacity-100">
|
||||
<TabsTrigger
|
||||
<ApiMethodTabsList className="relative flex justify-start w-full p-0 bg-transparent hover:[&>div>a>button]:opacity-100">
|
||||
<ApiMethodTabsTrigger
|
||||
value="client"
|
||||
className="transition-all duration-150 ease-in-out max-w-[100px] data-[state=active]:bg-border hover:bg-border/50 bg-border/50 border hover:border-primary/15 cursor-pointer data-[state=active]:border-primary/10 rounded-none"
|
||||
>
|
||||
@@ -179,8 +184,8 @@ export const APIMethod = ({
|
||||
<path fill="none" d="M0 0h36v36H0z" />
|
||||
</svg>
|
||||
<span>Client</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger
|
||||
</ApiMethodTabsTrigger>
|
||||
<ApiMethodTabsTrigger
|
||||
value="server"
|
||||
className="transition-all duration-150 ease-in-out max-w-[100px] data-[state=active]:bg-border hover:bg-border/50 bg-border/50 border hover:border-primary/15 cursor-pointer data-[state=active]:border-primary/10 rounded-none"
|
||||
>
|
||||
@@ -196,20 +201,20 @@ export const APIMethod = ({
|
||||
/>
|
||||
</svg>
|
||||
<span>Server</span>
|
||||
</TabsTrigger>
|
||||
</ApiMethodTabsTrigger>
|
||||
<div className="absolute right-0">
|
||||
<a href={`#api-method${pathId}`}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="transition-all duration-150 ease-in-out scale-90 opacity-100 md:opacity-0"
|
||||
className="opacity-100 transition-all duration-150 ease-in-out scale-90 md:opacity-0"
|
||||
size={"icon"}
|
||||
>
|
||||
<Link className="size-4" />
|
||||
</Button>
|
||||
</a>
|
||||
</div>
|
||||
</TabsList>
|
||||
<TabsContent value="client">
|
||||
</ApiMethodTabsList>
|
||||
<ApiMethodTabsContent value="client">
|
||||
{isServerOnly ? null : (
|
||||
<Endpoint
|
||||
method={method || "GET"}
|
||||
@@ -228,7 +233,7 @@ export const APIMethod = ({
|
||||
) : null}
|
||||
</Note>
|
||||
) : null}
|
||||
<div className={cn("w-full relative")}>
|
||||
<div className={cn("relative w-full")}>
|
||||
<DynamicCodeBlock
|
||||
code={`${code_prefix}${
|
||||
noResult
|
||||
@@ -240,14 +245,14 @@ export const APIMethod = ({
|
||||
lang="ts"
|
||||
/>
|
||||
{isServerOnly ? (
|
||||
<div className="absolute inset-0 flex items-center justify-center w-full h-full border rounded-lg backdrop-brightness-50 backdrop-blur-xs border-border">
|
||||
<div className="flex absolute inset-0 justify-center items-center w-full h-full rounded-lg border backdrop-brightness-50 backdrop-blur-xs border-border">
|
||||
<span>This is a server-only endpoint</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{!isServerOnly ? <TypeTable props={props} isServer={false} /> : null}
|
||||
</TabsContent>
|
||||
<TabsContent value="server">
|
||||
</ApiMethodTabsContent>
|
||||
<ApiMethodTabsContent value="server">
|
||||
{isClientOnly ? null : (
|
||||
<Endpoint
|
||||
method={method || "GET"}
|
||||
@@ -267,17 +272,17 @@ export const APIMethod = ({
|
||||
) : null}
|
||||
</Note>
|
||||
) : null}
|
||||
<div className={cn("w-full relative")}>
|
||||
<div className={cn("relative w-full")}>
|
||||
{serverCodeBlock}
|
||||
{isClientOnly ? (
|
||||
<div className="absolute inset-0 flex items-center justify-center w-full h-full border rounded-lg backdrop-brightness-50 backdrop-blur-xs border-border">
|
||||
<div className="flex absolute inset-0 justify-center items-center w-full h-full rounded-lg border backdrop-brightness-50 backdrop-blur-xs border-border">
|
||||
<span>This is a client-only endpoint</span>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
{!isClientOnly ? <TypeTable props={props} isServer /> : null}
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</ApiMethodTabsContent>
|
||||
</ApiMethodTabs>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -328,7 +333,7 @@ function TypeTable({
|
||||
if (!props.length) return null;
|
||||
|
||||
return (
|
||||
<Table className="mt-2 mb-0 overflow-hidden">
|
||||
<Table className="overflow-hidden mt-2 mb-0">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="text-primary w-[100px]">Prop</TableHead>
|
||||
@@ -354,7 +359,7 @@ function TypeTable({
|
||||
) : null}
|
||||
</TableCell>
|
||||
<TableCell className="max-w-[500px] overflow-hidden">
|
||||
<div className="w-full break-words h-fit text-wrap ">
|
||||
<div className="w-full break-words h-fit text-wrap">
|
||||
{tsxifyBackticks(prop.description ?? "")}
|
||||
</div>
|
||||
</TableCell>
|
||||
@@ -709,8 +714,8 @@ function createServerBody({
|
||||
|
||||
function Note({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="relative flex flex-col w-full gap-2 p-3 mb-2 break-words border rounded-md text-md text-wrap border-border bg-fd-secondary/50">
|
||||
<span className="w-full -mb-1 text-xs select-none text-muted-foreground">
|
||||
<div className="flex relative flex-col gap-2 p-3 mb-2 w-full break-words rounded-md border text-md text-wrap border-border bg-fd-secondary/50">
|
||||
<span className="-mb-1 w-full text-xs select-none text-muted-foreground">
|
||||
Notes
|
||||
</span>
|
||||
<p className="mt-0 mb-0 text-sm">{children as any}</p>
|
||||
|
||||
Reference in New Issue
Block a user