docs: smooth animation for sidebar links and changelogs (#336)

This commit is contained in:
Ali Samadi
2024-10-26 00:14:49 +03:00
committed by GitHub
parent 2351599227
commit fcd6db39c8
13 changed files with 412 additions and 760 deletions
+4 -6
View File
@@ -1,6 +1,4 @@
import type { GetOutput } from "fumadocs-mdx/config";
export declare const changelog: GetOutput<
typeof import("../source.config.ts").changelog
>;
export declare const docs: GetOutput<typeof import("../source.config.ts").docs>;
export declare const meta: GetOutput<typeof import("../source.config.ts").meta>;
import type { GetOutput } from "fumadocs-mdx/config"
export declare const changelog: GetOutput<typeof import("../source.config.ts").changelog>
export declare const docs: GetOutput<typeof import("../source.config.ts").docs>
export declare const meta: GetOutput<typeof import("../source.config.ts").meta>
+60 -336
View File
File diff suppressed because one or more lines are too long
+28 -20
View File
@@ -1,30 +1,38 @@
// source.config.ts
import { defineCollections, defineDocs } from "fumadocs-mdx/config";
import {
defineCollections,
defineDocs
} from "fumadocs-mdx/config";
import { defineConfig } from "fumadocs-mdx/config";
import { remarkInstall } from "fumadocs-docgen";
import { z } from "zod";
var source_config_default = defineConfig({
mdxOptions: {
remarkPlugins: [
[
remarkInstall,
{
persist: {
id: "persist-install",
},
},
],
],
},
mdxOptions: {
remarkPlugins: [
[
remarkInstall,
{
persist: {
id: "persist-install"
}
}
]
]
}
});
var changelog = defineCollections({
type: "doc",
dir: "./content/changelog",
schema: z.object({
title: z.string(),
}),
type: "doc",
dir: "./content/changelog",
schema: z.object({
title: z.string()
})
});
var { docs, meta } = defineDocs({
dir: "./content/docs",
dir: "./content/docs"
});
export { changelog, source_config_default as default, docs, meta };
export {
changelog,
source_config_default as default,
docs,
meta
};
+35
View File
@@ -0,0 +1,35 @@
export function BookIcon(props: React.ComponentPropsWithoutRef<"svg">) {
return (
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
<path d="M7 3.41a1 1 0 0 0-.668-.943L2.275 1.039a.987.987 0 0 0-.877.166c-.25.192-.398.493-.398.812V12.2c0 .454.296.853.725.977l3.948 1.365A1 1 0 0 0 7 13.596V3.41ZM9 13.596a1 1 0 0 0 1.327.946l3.948-1.365c.429-.124.725-.523.725-.977V2.017c0-.32-.147-.62-.398-.812a.987.987 0 0 0-.877-.166L9.668 2.467A1 1 0 0 0 9 3.41v10.186Z" />
</svg>
);
}
export function GitHubIcon(props: React.ComponentPropsWithoutRef<"svg">) {
return (
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
<path d="M8 .198a8 8 0 0 0-8 8 7.999 7.999 0 0 0 5.47 7.59c.4.076.547-.172.547-.384 0-.19-.007-.694-.01-1.36-2.226.482-2.695-1.074-2.695-1.074-.364-.923-.89-1.17-.89-1.17-.725-.496.056-.486.056-.486.803.056 1.225.824 1.225.824.714 1.224 1.873.87 2.33.666.072-.518.278-.87.507-1.07-1.777-.2-3.644-.888-3.644-3.954 0-.873.31-1.586.823-2.146-.09-.202-.36-1.016.07-2.118 0 0 .67-.214 2.2.82a7.67 7.67 0 0 1 2-.27 7.67 7.67 0 0 1 2 .27c1.52-1.034 2.19-.82 2.19-.82.43 1.102.16 1.916.08 2.118.51.56.82 1.273.82 2.146 0 3.074-1.87 3.75-3.65 3.947.28.24.54.73.54 1.48 0 1.07-.01 1.93-.01 2.19 0 .21.14.46.55.38A7.972 7.972 0 0 0 16 8.199a8 8 0 0 0-8-8Z" />
</svg>
);
}
export function FeedIcon(props: React.ComponentPropsWithoutRef<"svg">) {
return (
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M2.5 3a.5.5 0 0 1 .5-.5h.5c5.523 0 10 4.477 10 10v.5a.5.5 0 0 1-.5.5h-.5a.5.5 0 0 1-.5-.5v-.5A8.5 8.5 0 0 0 3.5 4H3a.5.5 0 0 1-.5-.5V3Zm0 4.5A.5.5 0 0 1 3 7h.5A5.5 5.5 0 0 1 9 12.5v.5a.5.5 0 0 1-.5.5H8a.5.5 0 0 1-.5-.5v-.5a4 4 0 0 0-4-4H3a.5.5 0 0 1-.5-.5v-.5Zm0 5a1 1 0 1 1 2 0 1 1 0 0 1-2 0Z"
/>
</svg>
);
}
export function XIcon(props: React.ComponentPropsWithoutRef<"svg">) {
return (
<svg viewBox="0 0 16 16" aria-hidden="true" fill="currentColor" {...props}>
<path d="M9.51762 6.77491L15.3459 0H13.9648L8.90409 5.88256L4.86212 0H0.200195L6.31244 8.89547L0.200195 16H1.58139L6.92562 9.78782L11.1942 16H15.8562L9.51728 6.77491H9.51762ZM7.62588 8.97384L7.00658 8.08805L2.07905 1.03974H4.20049L8.17706 6.72795L8.79636 7.61374L13.9654 15.0075H11.844L7.62588 8.97418V8.97384Z" />
</svg>
);
}
-51
View File
@@ -1,51 +0,0 @@
import { AnimatePresence } from "@/components/ui/fade-in";
const ChangelogOne = () => {
return (
<AnimatePresence>
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
<img
src="https://camo.githubusercontent.com/3282afc585d07e52e883ac2345467841e5c9cbe3befdec9dd6f84c603748e0d4/68747470733a2f2f726573656e642e636f6d2f5f6e6578742f696d6167653f75726c3d253246737461746963253246706f737473253246776562686f6f6b732e6a706726773d36343026713d3735"
className="w-full h-[400px] rounded-lg"
/>
<div className="flex flex-col gap-2">
<h2 className="text-2xl font-bold tracking-tighter">
Commit message suggestions
</h2>
<hr className="h-px bg-gray-200 w-full" />
</div>
<p className="text-gray-300 text-[0.855rem]">
In the latest release, I've added support for commit message and
description suggestions via an integration with OpenAI. Commit looks
at all of your changes, and feeds that into the machine with a bit of
prompt-tuning to get back a commit message that does a surprisingly
good job at describing the intent of your changes. It's also been a
pretty helpful way to remind myself what the hell I was working on at
the end of the day yesterday when I get back to my computer and
realize I didn't commit any of my work.
</p>
<div className="flex flex-col gap-2">
<h4 className="text-xl tracking-tighter"> Improvement</h4>
<hr className="h-px bg-gray-200 w-full" />
</div>
<ul className="list-disc ml-10 text-[0.855rem]">
<li>
Added commit message and description suggestions powered by OpenAI
</li>
<li>
Started commit message and description suggestions powered by OpenAI
</li>
<li>
Restored message and description suggestions powered by OpenAI
</li>
<li>
Added commit message and description suggestions powered by OpenAI
</li>
</ul>
</div>
</AnimatePresence>
);
};
export default ChangelogOne;
-36
View File
@@ -1,36 +0,0 @@
import { AnimatePresence } from "@/components/ui/fade-in";
const listOfFeatures = [
"Multiple framework support",
"Email & Password Authentication",
"OAuth Authentication",
"Account & Session Management",
"Rate Limiting",
"Multiple Plugins",
"Migration CLI",
"Multiple Plugins",
"And more...",
];
const ChangelogOne = () => {
return (
<AnimatePresence>
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
<div className="flex flex-col gap-2">
<h2 className="text-2xl font-bold tracking-tighter">Beta Release</h2>
<p>The first beta release of better-auth is now available!</p>
</div>
<p className="text-gray-600 dark:text-gray-300 text-[0.855rem]"></p>
<div className="flex flex-col gap-2">
<h4 className="text-xl tracking-tighter">Features</h4>
</div>
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
{listOfFeatures.map((change, i) => (
<li key={i}>{change}</li>
))}
</ul>
</div>
</AnimatePresence>
);
};
export default ChangelogOne;
-48
View File
@@ -1,48 +0,0 @@
import { Badge } from "@/components/ui/badge";
import { AnimatePresence } from "@/components/ui/fade-in";
import Link from "next/link";
const listOfFeatures = [
"Database adapters support including prisma, drizzle and mongo db.",
"Database hooks",
"CrossDomain cookies",
"onRequest and onResponse plugin hooks",
"init interface for plugins",
];
const ChangelogOne = () => {
return (
<AnimatePresence>
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
<div className="flex flex-col gap-2">
<h2 className="text-2xl font-bold tracking-tighter">v0.2.0</h2>
<p>
We have added support for database adapters including prisma,
drizzle and mongo db and other changes.
</p>
</div>
<p className="text-gray-600 dark:text-gray-300 text-[0.855rem]"></p>
<div className="flex flex-col gap-2">
<h4 className="text-xl tracking-tighter">Changes</h4>
</div>
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
{listOfFeatures.map((change, i) => (
<li key={i}>{change}</li>
))}
</ul>
<p>
see{" "}
<Link href="https://github.com/better-auth/better-auth/releases/tag/v0.2.0">
Changelog
</Link>
for full list of changes.
</p>
<Badge variant="secondary">
🚧 We still in beta and we don't recommend to use better-auth in
production just yet.
</Badge>
</div>
</AnimatePresence>
);
};
export default ChangelogOne;
-56
View File
@@ -1,56 +0,0 @@
import { Badge } from "@/components/ui/badge";
import { AnimatePresence } from "@/components/ui/fade-in";
import Link from "next/link";
const listOfFeatures = [
"Database Schema Generation",
"Phone Number Plugin",
"Anonymous Plugin",
"Better type Inference",
"User Delete API",
"Custom table/model names",
"Removed flat db config",
"new core table for verification use cases",
"moved passkey challenge keys to be stored on db ",
"and many bug fixes and improvements",
];
const ChangelogThree = () => {
return (
<AnimatePresence>
<div className="flex flex-col gap-4 items-start justify-center max-w-full md:max-w-2xl">
<div className="flex flex-col gap-2">
<h2 className="text-2xl font-bold tracking-tighter">v0.3.0</h2>
<p>
Database Schema Generation, Phone Number Plugin, Anonymous Plugin,
Better type Inference, Custom table names, and many more.
</p>
</div>
<p className="text-gray-600 dark:text-gray-300 text-[0.855rem]"></p>
<div className="flex flex-col gap-2">
<h4 className="text-xl tracking-tighter">Features & Changes</h4>
</div>
<ul className="list-disc ml-10 text-[0.855rem] text-gray-600 dark:text-gray-300">
{listOfFeatures.map((change, i) => (
<li key={i}>{change}</li>
))}
</ul>
<p>
see{" "}
<Link
href="https://github.com/better-auth/better-auth/releases/tag/v0.3.0"
className="underline"
>
release note{" "}
</Link>
for full list of changes.
</p>
<Badge variant="secondary">
🚧 We still in beta and we don't recommend to use better-auth in
production just yet.
</Badge>
</div>
</AnimatePresence>
);
};
export default ChangelogThree;
-20
View File
@@ -1,20 +0,0 @@
import ChangeLogTwo from "./2024-09-29";
import ChangelogOne from "./2024-09-28";
import ChangeLogThree from "./2024-10-04";
export const Logs = [
{
name: "Changelog 3",
date: "2024-10-04",
component: ChangeLogThree,
},
{
name: "Changelog 2",
date: "2024-09-29",
component: ChangeLogTwo,
},
{
name: "Changelog 1",
date: "2024-09-28",
component: ChangelogOne,
},
];
-112
View File
@@ -1,112 +0,0 @@
import { Layout } from "./_components/_layout";
import { useId } from "react";
import { Intro, IntroFooter } from "./_components/changelog-layout";
import { StarField } from "./_components/stat-field";
function Timeline() {
let id = useId();
return (
<div className="pointer-events-none absolute inset-0 z-50 overflow-hidden lg:right-[calc(max(2rem,50%-38rem)+40rem)] lg:min-w-[32rem] lg:overflow-visible">
<svg
className="absolute left-[max(0px,calc(50%-18.125rem))] top-0 h-full w-1.5 lg:left-full lg:ml-1 xl:left-auto xl:right-1 xl:ml-0"
aria-hidden="true"
>
<defs>
<pattern id={id} width="6" height="8" patternUnits="userSpaceOnUse">
<path
d="M0 0H6M0 8H6"
className="stroke-sky-900/10 xl:stroke-white/10 dark:stroke-white/10"
fill="none"
/>
</pattern>
</defs>
<rect width="100%" height="100%" fill={`url(#${id})`} />
</svg>
</div>
);
}
function Glow() {
let id = useId();
return (
<div className="absolute inset-0 -z-10 overflow-hidden bg-gradient-to-tr from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10 lg:right-[calc(max(2rem,50%-38rem)+40rem)] lg:min-w-[32rem]">
<svg
className="absolute -bottom-48 left-[-40%] h-[80rem] w-[180%] lg:-right-40 lg:bottom-auto lg:left-auto lg:top-[-40%] lg:h-[180%] lg:w-[80rem]"
aria-hidden="true"
>
<defs>
<radialGradient id={`${id}-desktop`} cx="100%">
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.4)" />
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
</radialGradient>
<radialGradient id={`${id}-mobile`} cy="100%">
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.3)" />
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
</radialGradient>
</defs>
<rect
width="100%"
height="100%"
fill={`url(#${id}-desktop)`}
className="hidden lg:block"
/>
<rect
width="100%"
height="100%"
fill={`url(#${id}-mobile)`}
className="lg:hidden"
/>
</svg>
<div className="absolute inset-x-0 bottom-0 right-0 h-px dark:bg-white/5 mix-blend-overlay lg:left-auto lg:top-0 lg:h-auto lg:w-px" />
</div>
);
}
function FixedSidebar({
main,
footer,
}: {
main: React.ReactNode;
footer: React.ReactNode;
}) {
return (
<div className="relative flex-none overflow-hidden px-10 lg:pointer-events-none md:fixed lg:inset-0 lg:z-40 lg:flex lg:px-0">
<Glow />
<div className="relative flex w-full lg:pointer-events-auto lg:mr-[calc(max(2rem,50%-35rem)+40rem)] lg:min-w-[32rem] lg:overflow-y-auto lg:overflow-x-hidden lg:pl-[max(4rem,calc(50%-44rem))]">
<div className="mx-auto pr-20 max-w-lg lg:mx-auto lg:flex lg:max-w-4xl lg:flex-col lg:before:flex-1 lg:before:pt-6">
<div className="pb-16 pt-20 sm:pb-20 sm:pt-32 lg:py-20">
<div className="relative ">
<StarField className="-right-44 top-14" />
{main}
</div>
</div>
<div className="flex flex-1 items-end justify-center pb-4 lg:justify-start lg:pb-6">
{footer}
</div>
</div>
</div>
</div>
);
}
const ChangeLogLayout = ({ children }: { children: React.ReactNode }) => {
return (
<div className="h-full font-sans overflow-y-auto">
<FixedSidebar main={<Intro />} footer={<IntroFooter />} />
<div />
<div className="relative overflow-y-auto flex gap-2 justify-start items-start">
<Timeline />
<div className="space-y-20 py-20 w-[80%] mx-auto md:mx-0 md:ml-auto md:w-1/2 h-screen sm:space-y-20 sm:py-20">
{children}
</div>
</div>
</div>
);
};
export default ChangeLogLayout;
+140 -17
View File
@@ -1,25 +1,148 @@
import { AnimatePresence } from "@/components/ui/fade-in";
import { Logs } from "./_logs";
import { FormattedDate } from "./_components/fmt-dates";
import Link from "next/link";
import { useId } from "react";
import { changelog } from "@/app/source";
import { notFound } from "next/navigation";
import { cn } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
import { IconLink } from "./_components/changelog-layout";
import { BookIcon, GitHubIcon, XIcon } from "./_components/icons";
import { DiscordLogoIcon } from "@radix-ui/react-icons";
import { StarField } from "./_components/stat-field";
const ChangelogPage = () => {
// @ts-ignore
const page = changelog.getPage();
if (page == null) {
notFound();
}
const MDX = page.data.body;
return (
<div>
<div className="mt-10 overflow-visible h-full flex flex-col gap-10">
{Logs.map((log) => {
return (
<div className="relative my-5 h-auto">
<div className="sticky top-2 flex-1 h-full">
<FormattedDate
className="absolute md:-left-36 left-0 text-sm -top-8 md:top-0 font-light"
date={log.date}
<div className="grid md:grid-cols-2 items-start">
<div className="bg-gradient-to-tr overflow-hidden px-12 py-24 md:py-0 -mt-[100px] md:h-dvh relative md:sticky top-0 from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10">
<StarField className="top-1/2 -translate-y-1/2 left-1/2 -translate-x-1/2" />
<Glow />
<div className="flex flex-col justify-center max-w-xl mx-auto h-full">
<h1 className="mt-14 font-sans font-semibold tracking-tighter text-5xl">
All of the changes made will be{" "}
<span className="">available here.</span>
</h1>
<p className="mt-4 text-sm text-gray-600 dark:text-gray-300">
Better Auth is comprehensive authentication library for TypeScript
that provides a wide range of features to make authentication easier
and more secure.
</p>
<hr className="h-px bg-gray-300 mt-5" />
<div className="mt-8 flex flex-wrap text-gray-600 dark:text-gray-300 justify-center gap-x-1 gap-y-3 sm:gap-x-2 lg:justify-start">
<IconLink
href="/docs"
icon={BookIcon}
className="flex-none text-gray-600 dark:text-gray-300"
>
Documentation
</IconLink>
<IconLink
href="https://github.com/better-auth/better-auth"
icon={GitHubIcon}
className="flex-none text-gray-600 dark:text-gray-300"
>
GitHub
</IconLink>
<IconLink
href="https://discord.gg/GYC3W7tZzb"
icon={DiscordLogoIcon}
className="flex-none text-gray-600 dark:text-gray-300"
>
Community
</IconLink>
</div>
<p className="flex items-baseline absolute bottom-4 max-md:left-1/2 max-md:-translate-x-1/2 gap-x-2 text-[0.8125rem]/6 text-gray-500">
Brought to you by{" "}
<IconLink href="#" icon={XIcon} compact>
BETTER-AUTH.
</IconLink>
</p>
</div>
</div>
<div className="px-4 md:px-8 pb-12 md:py-12">
<div className="max-w-2xl">
<MDX
components={{
h2: (props) => (
<h2
className="text-2xl mt-16 font-bold tracking-tighter"
{...props}
/>
</div>
<log.component />
</div>
);
})}
),
h3: (props) => (
<h3 className="text-xl tracking-tighter" {...props} />
),
p: (props) => <p className="my-4" {...props} />,
ul: (props) => (
<ul
className="list-disc ml-10 my-4 text-[0.855rem] text-gray-600 dark:text-gray-300"
{...props}
/>
),
li: (props) => <li className="my-px" {...props} />,
a: ({ className, ...props }: any) => (
<Link
className={cn("font-medium underline", className)}
{...props}
/>
),
Badge: (props) => (
<Badge variant="secondary" className="py-0" {...props} />
),
}}
/>
</div>
</div>
</div>
);
};
export default ChangelogPage;
function Glow() {
let id = useId();
return (
<div className="absolute inset-0 -z-10 overflow-hidden bg-gradient-to-tr from-transparent dark:via-stone-950/5 via-stone-100/30 to-stone-200/20 dark:to-transparent/10">
<svg
className="absolute -bottom-48 left-[-40%] h-[80rem] w-[180%] lg:-right-40 lg:bottom-auto lg:left-auto lg:top-[-40%] lg:h-[180%] lg:w-[80rem]"
aria-hidden="true"
>
<defs>
<radialGradient id={`${id}-desktop`} cx="100%">
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.4)" />
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
</radialGradient>
<radialGradient id={`${id}-mobile`} cy="100%">
<stop offset="0%" stopColor="rgba(41, 37, 36, 0.3)" />
<stop offset="53.95%" stopColor="rgba(28, 25, 23, 0.09)" />
<stop offset="100%" stopColor="rgba(0, 0, 0, 0)" />
</radialGradient>
</defs>
<rect
width="100%"
height="100%"
fill={`url(#${id}-desktop)`}
className="hidden lg:block"
/>
<rect
width="100%"
height="100%"
fill={`url(#${id}-mobile)`}
className="lg:hidden"
/>
</svg>
<div className="absolute inset-x-0 bottom-0 right-0 h-px dark:bg-white/5 mix-blend-overlay lg:left-auto lg:top-0 lg:h-auto lg:w-px" />
</div>
);
}
+84 -58
View File
@@ -1,17 +1,13 @@
"use client";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { AnimatePresence, motion, MotionConfig } from "framer-motion";
import { AsideLink } from "@/components/ui/aside-link";
import { FadeIn, FadeInStagger } from "@/components/ui/fade-in";
import { Suspense, useEffect, useState } from "react";
import { useSearchContext } from "fumadocs-ui/provider";
import { usePathname, useRouter } from "next/navigation";
import { contents, examples } from "./sidebar-content";
import { Search } from "lucide-react";
import { ChevronDownIcon, Search } from "lucide-react";
import {
Select,
SelectContent,
@@ -20,8 +16,11 @@ import {
SelectValue,
} from "./ui/select";
import { loglib } from "@loglib/tracker";
import { cn } from "@/lib/utils";
export default function ArticleLayout() {
const [currentOpen, setCurrentOpen] = useState<number>(0);
const { setOpenSearch } = useSearchContext();
const pathname = usePathname();
@@ -131,58 +130,85 @@ export default function ArticleLayout() {
</p>
</div>
<Accordion
type="single"
collapsible
defaultValue={`item-${getDefaultValue()}`}
>
{cts.map((item, i) => (
<AccordionItem value={`item-${i}`} key={item.title}>
<AccordionTrigger className="border-b border-lines px-5 py-2.5 text-left">
<div className="flex items-center gap-2">
{item.Icon && <item.Icon className="w-5 h-5" />}
{item.title}
</div>
</AccordionTrigger>
<AccordionContent className=" space-y-1 p-0">
<FadeInStagger faster>
{item.list.map((listItem, j) => (
<FadeIn
key={listItem.title}
onClick={() => {
loglib.track("sidebar-link-click", {
title: listItem.title,
href: listItem.href,
});
}}
<MotionConfig transition={{ duration: 0.4, type: "spring", bounce: 0 }}>
<div className="flex flex-col">
{cts.map((item, index) => (
<div key={item.title}>
<button
className="border-b w-full hover:underline border-lines text-sm px-5 py-2.5 text-left flex items-center gap-2"
onClick={() => {
if (currentOpen === index) {
setCurrentOpen(-1);
} else {
setCurrentOpen(index);
}
}}
>
<item.Icon className="w-5 h-5" />
<span className="grow">{item.title}</span>
<motion.div
animate={{ rotate: currentOpen === index ? 180 : 0 }}
>
<ChevronDownIcon
className={cn(
"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200",
)}
/>
</motion.div>
</button>
<AnimatePresence initial={false}>
{currentOpen === index && (
<motion.div
initial={{ opacity: 0, height: 0 }}
animate={{ opacity: 1, height: "auto" }}
exit={{ opacity: 0, height: 0 }}
className="relative overflow-hidden"
>
<Suspense fallback={<>Loading...</>}>
{listItem.group ? (
<div className="flex flex-row gap-2 items-center mx-5 my-1 ">
<p className="text-sm bg-gradient-to-tr dark:from-gray-100 dark:to-stone-200 bg-clip-text text-transparent from-gray-900 to-stone-900">
{listItem.title}
</p>
<line className="flex-grow h-px bg-gradient-to-r from-stone-800/90 to-stone-800/60" />
</div>
) : (
<AsideLink
href={listItem.href}
startWith="/docs"
title={listItem.title}
className="break-words w-[--fd-sidebar-width]"
<motion.div
// initial={{ opacity: 0, y: -20 }}
// animate={{ opacity: 1, y: 0 }}
className="text-sm"
>
{item.list.map((listItem, j) => (
<div
key={listItem.title}
onClick={() => {
loglib.track("sidebar-link-click", {
title: listItem.title,
href: listItem.href,
});
}}
>
<listItem.icon className="w-4 h-4 text-stone-950 dark:text-white" />
{listItem.title}
</AsideLink>
)}
</Suspense>
</FadeIn>
))}
</FadeInStagger>
</AccordionContent>
</AccordionItem>
))}
</Accordion>
<Suspense fallback={<>Loading...</>}>
{listItem.group ? (
<div className="flex flex-row gap-2 items-center mx-5 my-1 ">
<p className="text-sm bg-gradient-to-tr dark:from-gray-100 dark:to-stone-200 bg-clip-text text-transparent from-gray-900 to-stone-900">
{listItem.title}
</p>
<line className="flex-grow h-px bg-gradient-to-r from-stone-800/90 to-stone-800/60" />
</div>
) : (
<AsideLink
href={listItem.href}
startWith="/docs"
title={listItem.title}
className="break-words w-[--fd-sidebar-width]"
>
<listItem.icon className="w-4 h-4 text-stone-950 dark:text-white" />
{listItem.title}
</AsideLink>
)}
</Suspense>
</div>
))}
</motion.div>
</motion.div>
)}
</AnimatePresence>
</div>
))}
</div>
</MotionConfig>
</aside>
);
}
+61
View File
@@ -0,0 +1,61 @@
---
title: Basic Usage
description: Getting started with Better Auth
---
## v0.3.0 (Latest)
Database Schema Generation, Phone Number Plugin, Anonymous Plugin, Better type Inference, Custom table names, and many more.
### Features & Changes
- Database Schema Generation
- Phone Number Plugin
- Anonymous Plugin
- Better type Inference
- User Delete API
- Custom table/model names
- Removed flat db config
- New core table for verification use cases
- Moved passkey challenge keys to be stored on db
- Many bug fixes and improvements
See [release notes](https://github.com/better-auth/better-auth/releases/tag/v0.3.0) for full list of changes.
<Badge>
🚧 We are still in beta and we don't recommend using better-auth in production just yet.
</Badge>
## v0.2.0
We have added support for database adapters including Prisma, Drizzle, and MongoDB, along with other changes.
### Changes
- Database adapters support including Prisma, Drizzle, and MongoDB
- Database hooks
- Cross-domain cookies
- onRequest and onResponse plugin hooks
- Init interface for plugins
See [Changelog](https://github.com/better-auth/better-auth/releases/tag/v0.2.0) for full list of changes.
<Badge>
🚧 We are still in beta and we don't recommend using better-auth in production just yet.
</Badge>
## Beta Release
The first beta release of better-auth is now available!
### Features
- Multiple framework support
- Email & Password Authentication
- OAuth Authentication
- Account & Session Management
- Rate Limiting
- Multiple Plugins
- Migration CLI
- And more...