docs: normalize docs topbar and toc row heights (#8566)

This commit is contained in:
Taesu
2026-03-13 23:46:35 -07:00
committed by Alex Yang
parent bc6bbddd8e
commit a7016d3f84
3 changed files with 71 additions and 48 deletions
+12 -6
View File
@@ -386,6 +386,7 @@
--scrollbar-thumb-hover: var(--ring);
--scrollbar-track: transparent;
--radius: 0.2rem;
--landing-topbar-height: 48px;
--fd-nav-height: 56px;
--fd-banner-height: 0px;
--fd-tocnav-height: 0px;
@@ -409,6 +410,12 @@
--spacing: 0.25rem;
}
@media (min-width: 64rem) {
:root {
--landing-topbar-height: 44px;
}
}
.dark {
--background: hsl(0 0% 0%);
--foreground: oklch(0.985 0.001 106.423);
@@ -629,10 +636,10 @@ html:not([data-anchor-scrolling]) {
--fd-layout-width: 100vw;
--fd-layout-offset: 0px;
--fd-page-width: 900px;
--fd-banner-height: 44px;
--fd-banner-height: var(--landing-topbar-height);
--landing-left-pane-width: min(22vw, 300px);
--staggered-nav-cta-width: 128px;
padding-top: 44px;
padding-top: var(--landing-topbar-height);
}
@media (min-width: 64rem) {
@@ -641,7 +648,6 @@ html:not([data-anchor-scrolling]) {
calc(100vw - var(--landing-left-pane-width)),
1200px
);
--fd-header-height: -1px;
padding-inline-start: var(--landing-left-pane-width);
}
@@ -649,7 +655,7 @@ html:not([data-anchor-scrolling]) {
content: "";
position: fixed;
inset-block-start: 0;
height: 44px;
height: var(--landing-topbar-height);
inset-inline-start: calc(var(--landing-left-pane-width) - 1px);
width: 1px;
background: var(--color-border);
@@ -698,7 +704,7 @@ html:not([data-anchor-scrolling]) {
/* Blog layout: matches docs pattern with narrow left pane + TOC sidebar */
.blog-layout {
padding-top: 44px;
padding-top: var(--landing-topbar-height);
}
@media (min-width: 64rem) {
@@ -710,7 +716,7 @@ html:not([data-anchor-scrolling]) {
content: "";
position: fixed;
inset-block-start: 0;
height: 44px;
height: var(--landing-topbar-height);
inset-inline-start: calc(var(--landing-left-pane-width) - 1px);
width: 1px;
background: var(--color-border);
+46 -29
View File
@@ -1,14 +1,15 @@
"use client";
import { AnimatePresence, MotionConfig, motion } from "framer-motion";
import { ChevronDownIcon, GitBranch, Search, Sparkles } from "lucide-react";
import { useSearchContext } from "fumadocs-ui/contexts/search";
import { ChevronDownIcon, GitBranch, Search } from "lucide-react";
import Link from "next/link";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import type { ReactNode } from "react";
import { useEffect, useRef, useState } from "react";
import { useCommandMenu } from "@/components/command-menu";
import type { ListItem } from "@/components/sidebar-content";
import { contents } from "@/components/sidebar-content";
import { ThemeToggle } from "@/components/theme-toggle";
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
@@ -18,7 +19,7 @@ export function DocsSidebar() {
const pathname = usePathname();
const searchParams = useSearchParams();
const branch = searchParams.get("branch");
const { setOpen, openAI } = useCommandMenu();
const { setOpenSearch } = useSearchContext();
const [currentOpen, setCurrentOpen] = useState(0);
const navRef = useRef<HTMLElement>(null);
@@ -70,37 +71,31 @@ export function DocsSidebar() {
initial={{ x: -24, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ duration: 0.28, ease: "easeOut" }}
className="fixed left-0 top-[44px] bottom-0 w-[22vw] max-w-[300px] hidden lg:flex flex-col z-30 bg-background border-r border-foreground/5 transition-[width] duration-300 ease-out"
className="fixed left-0 top-(--landing-topbar-height) bottom-0 w-[22vw] max-w-[300px] hidden lg:flex flex-col z-30 bg-background border-r border-foreground/5 transition-[width] duration-300 ease-out"
>
{/* Branch switcher */}
<BranchSwitcher />
<button
type="button"
className="flex w-full items-center gap-2 px-4 lg:px-7 py-2.5 border-b border-foreground/5 text-[12px] uppercase tracking-wider text-foreground/55 hover:text-foreground/80 transition-colors"
onClick={() => setOpen(true)}
className="flex w-full items-center gap-2 px-4 py-2.5 border-b border-foreground/5 text-sm text-foreground/55 hover:text-foreground/80 hover:bg-foreground/3 transition-colors"
onClick={() => setOpenSearch(true)}
>
<Search className="size-3.5 shrink-0" />
<Search className="size-4 shrink-0" />
<span className="truncate">Search</span>
<span
className="ml-auto flex items-center gap-1 shrink-0 text-foreground/55 hover:text-foreground/70 transition-colors"
onClick={(e) => {
e.stopPropagation();
openAI();
}}
onKeyDown={() => {}}
role="button"
tabIndex={-1}
>
<Sparkles className="size-3" />
<span className="text-[10px] normal-case tracking-normal">AI</span>
</span>
<kbd className="ml-auto inline-flex items-center gap-0.5 shrink-0 text-[10px] font-mono text-foreground/40 border border-foreground/10 rounded-md px-1.5 py-0.5">
<span className="text-[11px]">&#8984;</span>K
</kbd>
</button>
{/* Scrollable navigation area */}
<nav
ref={navRef}
className="flex-1 overflow-y-auto overflow-x-hidden pb-3 sidebar-scroll"
style={{
maskImage:
"linear-gradient(to bottom, transparent, white 1rem, white calc(100% - 2rem), transparent 100%)",
}}
>
<MotionConfig
transition={{ duration: 0.35, type: "spring", bounce: 0 }}
@@ -112,7 +107,6 @@ export function DocsSidebar() {
type="button"
className={cn(
"border-b border-foreground/6 w-full text-left flex gap-2 items-center px-4 py-2.5 transition-colors",
"lg:px-7",
"font-medium text-sm tracking-wider",
currentOpen === index
? "text-foreground bg-foreground/3"
@@ -123,7 +117,7 @@ export function DocsSidebar() {
}}
>
<section.Icon className="size-4.5" />
<span className="grow">{section.title}</span>
<span className="grow tracking-normal">{section.title}</span>
<ChevronDownIcon
className={cn(
"h-4 w-4 shrink-0 text-muted-foreground transition-transform duration-200",
@@ -154,6 +148,29 @@ export function DocsSidebar() {
</div>
</MotionConfig>
</nav>
{/* Footer: GitHub + Theme Toggle */}
<div className="flex items-center gap-1 p-2 border-t border-foreground/5 text-foreground/40">
<a
href="https://github.com/better-auth/better-auth"
target="_blank"
rel="noreferrer noopener"
className="inline-flex items-center justify-center size-8 hover:text-foreground/70 hover:bg-foreground/5 transition-colors"
aria-label="GitHub"
>
<svg
role="img"
viewBox="0 0 24 24"
fill="currentColor"
className="size-4"
>
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
</a>
<div className="ms-auto [&_button]:text-foreground/40 [&_button:hover]:text-foreground/70">
<ThemeToggle />
</div>
</div>
</motion.aside>
);
}
@@ -192,15 +209,15 @@ function BranchSwitcher() {
};
return (
<div ref={ref} className="relative border-b border-foreground/10">
<div ref={ref} className="relative border-b border-foreground/5">
<button
type="button"
className="flex w-full items-center gap-2 px-4 lg:px-7 py-3 hover:bg-foreground/[0.02] transition-colors"
className="flex h-10 w-full items-center gap-2 px-4 text-left hover:bg-foreground/2 transition-colors"
onClick={() => setOpen((v) => !v)}
>
<GitBranch className="size-3.5 text-foreground/60 shrink-0" />
<div className="grow text-left min-w-0">
<p className="text-[12px] uppercase tracking-wider text-foreground/60 block">
<p className="block text-[12px] leading-none uppercase tracking-wider text-foreground/60">
{branch}{" "}
<span className="text-[9px] text-foreground/40 ">
{branch === "main" ? "" : "pre-release"}
@@ -376,13 +393,13 @@ function SidebarItemWithSubpages({
transition={{ duration: 0.35, type: "spring", bounce: 0 }}
className="overflow-hidden"
>
<div className="relative before:absolute before:left-[calc(1.75rem+0.75rem)] lg:before:left-[calc(2.75rem+0.75rem)] before:top-0 before:bottom-0 before:w-px before:bg-foreground/20">
<div className="relative before:absolute before:left-[calc(1.75rem+0.75rem)] before:top-0 before:bottom-0 before:w-px before:bg-foreground/20">
{item.subpages.map((subpage, i) => {
if (subpage.group) {
return (
<div
key={`subgroup-${subpage.title}-${i}`}
className="flex flex-row items-center gap-2 pl-[calc(1.75rem+0.75rem+0.75rem)] lg:pl-[calc(2.75rem+0.75rem+0.75rem)] pr-4 lg:pr-7 py-1.5 mt-1 first:mt-0"
className="flex flex-row items-center gap-2 pl-[calc(1.75rem+0.75rem+0.75rem)] pr-4 py-1.5 mt-1 first:mt-0"
>
<p className="text-[10px] text-foreground/45 uppercase tracking-wider">
{subpage.title}
@@ -433,7 +450,7 @@ function SubpageLink({
href={href}
data-active={active || undefined}
className={cn(
"relative flex items-center gap-1 pl-[calc(1.75rem+0.75rem+0.75rem)] lg:pl-[calc(2.75rem+0.75rem+0.75rem)] pr-4 lg:pr-7 py-1 text-[13px] transition-all duration-150",
"relative flex items-center gap-1 pl-[calc(1.75rem+0.75rem+0.75rem)] pr-4 py-1 text-[13px] transition-all duration-150",
active
? "text-foreground bg-foreground/6"
: "text-foreground/55 hover:text-foreground/80 hover:bg-foreground/3",
@@ -474,7 +491,7 @@ function SidebarLink({
href={href}
data-active={active || undefined}
className={`
relative flex items-center gap-2.5 px-4 lg:px-7 py-1 text-[14px] transition-all duration-150
relative flex items-center gap-2.5 px-4 py-1 text-[14px] transition-all duration-150
${
active
? "text-foreground bg-foreground/6"
@@ -198,18 +198,18 @@ export function StaggeredNavFiles() {
initial={{ x: -20, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ duration: 0.28, ease: "easeOut" }}
className={`${leftPaneWidthClass} hidden ${isKnownPage ? "lg:flex" : "lg:hidden"} items-stretch shrink-0 pointer-events-auto transition-[width] duration-300 ease-out`}
className={`${leftPaneWidthClass} hidden ${isKnownPage ? "lg:flex" : "lg:hidden"} h-(--landing-topbar-height) items-stretch shrink-0 pointer-events-auto transition-[width] duration-300 ease-out`}
>
<Link
href="/"
className="flex items-center gap-1 px-4 py-3 transition-colors duration-150"
className="flex h-full items-center gap-1 px-4 py-3 transition-colors duration-150"
>
<div className="flex flex-col gap-2 w-full">
<LogoContextMenu
logo={
<div className="flex items-center gap-1">
<Logo />
<p className="select-none font-mono md:text-lg text-sm uppercase">
<Logo className="h-4 w-auto shrink-0" />
<p className="select-none font-mono text-lg uppercase leading-none">
BETTER-AUTH.
</p>
</div>
@@ -225,14 +225,14 @@ export function StaggeredNavFiles() {
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.28, ease: "easeOut" }}
className="lg:hidden flex items-center justify-between w-full h-[52px] pointer-events-auto bg-background border-b border-foreground/[0.06]"
className="lg:hidden flex items-center justify-between w-full h-(--landing-topbar-height) pointer-events-auto bg-background border-b border-foreground/[0.06]"
>
<Link
href="/"
className="flex items-center gap-1 px-4 py-3 transition-colors duration-150"
className="flex h-full items-center gap-1 px-4 transition-colors duration-150"
>
<Logo />
<p className="select-none font-mono text-base uppercase">
<Logo className="h-3.5 w-auto shrink-0" />
<p className="select-none font-mono text-base uppercase leading-none">
BETTER-AUTH.
</p>
</Link>
@@ -314,19 +314,19 @@ export function StaggeredNavFiles() {
initial={{ y: -10, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.28, delay: 0.04, ease: "easeOut" }}
className={`flex-1 hidden lg:flex items-stretch border-b bg-background pointer-events-auto min-w-0 ${navBottomBorderClass}`}
className={`flex-1 hidden lg:flex h-(--landing-topbar-height) items-stretch border-b bg-background pointer-events-auto min-w-0 ${navBottomBorderClass}`}
>
{/* Inline logo when left pane is hidden */}
{!isKnownPage && (
<Link
href="/"
className={`flex items-center gap-1 shrink-0 px-4 lg:px-7 py-3 border-r ${tabDividerClass} transition-colors duration-150`}
className={`flex h-full items-center gap-1 shrink-0 px-4 lg:px-7 py-3 border-r ${tabDividerClass} transition-colors duration-150`}
>
<LogoContextMenu
logo={
<div className="flex items-center gap-1">
<Logo />
<p className="select-none font-mono md:text-lg text-sm uppercase">
<Logo className="h-4 w-auto shrink-0" />
<p className="select-none font-mono text-lg uppercase leading-none">
BETTER-AUTH.
</p>
</div>
@@ -697,7 +697,7 @@ export function StaggeredNavFiles() {
transition={{ duration: 0.15 }}
className="lg:hidden fixed inset-0 z-[98] w-full bg-background/95 backdrop-blur-sm pointer-events-auto"
>
<div className="pt-[52px] flex flex-col h-full">
<div className="flex h-full flex-col pt-(--landing-topbar-height)">
<div className="flex-1 min-h-0 overflow-y-auto">
{isDocs && mobileView === "docs" ? (
<>