Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/components/CopyPageDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import {
DropdownContent,
DropdownItem,
} from './Dropdown'
import {
getPackageManager,
PACKAGE_MANAGERS,
} from '~/utils/markdown/installCommand'
import { getPackageManager } from '~/utils/markdown/installCommand'

// Markdown icon component matching the screenshot
function MarkdownIcon({ className }: { className?: string }) {
Expand Down
97 changes: 77 additions & 20 deletions src/components/DocsLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -534,28 +534,59 @@ export function DocsLayout({
d.status === 'active' && d.name !== 'Nozzle.io' && d.id !== 'fireship',
)

const menuItems = menuConfig.map((group, i) => {
const WrapperComp = group.collapsible ? 'details' : 'div'
const LabelComp = group.collapsible ? 'summary' : 'div'
const groupInitialOpenState = React.useMemo(() => {
return menuConfig.reduce<Record<string, boolean>>((acc, group, index) => {
const isChildActive = group.children.some((child) => child.to === _splat)
const key = `${index}:${String(group.label)}`

const isChildActive = group.children.some((d) => d.to === _splat)
const configGroupOpenState =
typeof group.defaultCollapsed !== 'undefined'
? !group.defaultCollapsed // defaultCollapsed is true means the group is closed
: undefined
const isOpen = isChildActive ? true : (configGroupOpenState ?? false)
acc[key] = isChildActive
? true
: typeof group.defaultCollapsed !== 'undefined'
? !group.defaultCollapsed
: false

const detailsProps = group.collapsible ? { open: isOpen } : {}
return acc
}, {})
}, [menuConfig, _splat])

return (
<WrapperComp
key={`group-${i}`}
className="[&>summary]:before:mr-1 [&>summary]:marker:text-[0.8em] [&>summary]:marker:leading-4 relative select-none"
{...detailsProps}
>
<LabelComp className="text-[.8em] font-bold leading-4 px-2 ts-sidebar-label">
{group?.label}
</LabelComp>
const [openGroups, setOpenGroups] = React.useState(groupInitialOpenState)

React.useEffect(() => {
setOpenGroups((prev) => {
let hasChanged = false
const next = { ...prev }

Object.entries(groupInitialOpenState).forEach(([key, isOpen]) => {
if (!(key in next)) {
next[key] = isOpen
hasChanged = true
return
}

if (isOpen && !next[key]) {
next[key] = true
hasChanged = true
}
})

return hasChanged ? next : prev
})
}, [groupInitialOpenState])

const menuItems = menuConfig.map((group, i) => {
const groupKey = `${i}:${String(group.label)}`

const groupContent = (
<>
{group.collapsible ? (
<summary className="text-[.8em] font-bold leading-4 px-2 ts-sidebar-label">
{group.label}
</summary>
) : (
<div className="text-[.8em] font-bold leading-4 px-2 ts-sidebar-label">
{group.label}
</div>
)}
<div className="h-2" />
<ul className="text-[.85em] leading-snug list-none">
{group?.children?.map((child, i) => {
Expand All @@ -580,6 +611,7 @@ export function DocsLayout({
onClick={() => {
detailsRef.current.removeAttribute('open')
}}
preload={false}
activeOptions={{
exact: true,
includeHash: false,
Expand Down Expand Up @@ -614,7 +646,32 @@ export function DocsLayout({
)
})}
</ul>
</WrapperComp>
</>
)

return group.collapsible ? (
<details
key={`group-${i}`}
className="[&>summary]:before:mr-1 [&>summary]:marker:text-[0.8em] [&>summary]:marker:leading-4 relative select-none"
open={openGroups[groupKey] ?? false}
onToggle={(event) => {
const nextOpen = event.currentTarget.open
setOpenGroups((prev) =>
prev[groupKey] === nextOpen
? prev
: { ...prev, [groupKey]: nextOpen },
)
}}
>
{groupContent}
</details>
) : (
<div
key={`group-${i}`}
className="[&>summary]:before:mr-1 [&>summary]:marker:text-[0.8em] [&>summary]:marker:leading-4 relative select-none"
>
{groupContent}
</div>
)
})

Expand Down
18 changes: 12 additions & 6 deletions src/components/SearchModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -565,9 +565,12 @@ function LibraryRefinement() {
const currentLibrary = libraries.find((l) => l.id === selectedLibrary)

return (
<Dropdown>
<DropdownTrigger asChild={false}>
<button className="flex items-center gap-1 text-sm focus:outline-none cursor-pointer font-bold">
<Dropdown modal={false}>
<DropdownTrigger>
<button
type="button"
className="flex items-center gap-1 text-sm focus:outline-none cursor-pointer font-bold"
>
{currentLibrary ? (
<span className="uppercase font-black [letter-spacing:-.05em]">
<span className="opacity-50">TanStack</span>{' '}
Expand Down Expand Up @@ -637,9 +640,12 @@ function FrameworkRefinement() {
)

return (
<Dropdown>
<DropdownTrigger asChild={false}>
<button className="flex items-center gap-1 text-sm font-bold focus:outline-none cursor-pointer">
<Dropdown modal={false}>
<DropdownTrigger>
<button
type="button"
className="flex items-center gap-1 text-sm font-bold focus:outline-none cursor-pointer"
>
{currentFramework && (
<img
src={currentFramework.logo}
Expand Down
21 changes: 17 additions & 4 deletions src/routes/$libraryId/$version.docs.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { Outlet, useMatch, createFileRoute } from '@tanstack/react-router'
import {
Outlet,
useMatch,
notFound,
createFileRoute,
} from '@tanstack/react-router'
import { DocsLayout } from '~/components/DocsLayout'
import { getLibrary } from '~/libraries'
import { findLibrary } from '~/libraries'
import { seo } from '~/utils/seo'
import type { ConfigSchema } from '~/utils/config'

export const Route = createFileRoute('/$libraryId/$version/docs')({
head: (ctx) => {
const { libraryId } = ctx.params
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}

return {
meta: seo({
Expand All @@ -27,7 +36,11 @@ export const Route = createFileRoute('/$libraryId/$version/docs')({

function DocsRoute() {
const { libraryId, version } = Route.useParams()
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}
const versionMatch = useMatch({ from: '/$libraryId/$version' })
const { config } = versionMatch.loaderData as { config: ConfigSchema }

Expand Down
15 changes: 12 additions & 3 deletions src/routes/$libraryId/$version.index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import {
useMatch,
redirect,
Link,
notFound,
createFileRoute,
} from '@tanstack/react-router'
import { DocsLayout } from '~/components/DocsLayout'
import { getLibrary } from '~/libraries'
import { findLibrary } from '~/libraries'
import type { LibraryId } from '~/libraries'
import { seo } from '~/utils/seo'

Expand Down Expand Up @@ -52,7 +53,11 @@ const landingComponents: Partial<Record<LibraryId, ComponentType>> = {
export const Route = createFileRoute('/$libraryId/$version/')({
head: (ctx) => {
const { libraryId } = ctx.params
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}

return {
meta: seo({
Expand All @@ -79,7 +84,11 @@ export const Route = createFileRoute('/$libraryId/$version/')({

function LibraryVersionIndex() {
const { libraryId, version } = Route.useParams()
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}
const versionMatch = useMatch({ from: '/$libraryId/$version' })
const { config } = versionMatch.loaderData as { config: ConfigSchema }

Expand Down
28 changes: 23 additions & 5 deletions src/routes/$libraryId/$version.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import { Outlet, redirect, createFileRoute } from '@tanstack/react-router'
import {
Outlet,
redirect,
notFound,
createFileRoute,
} from '@tanstack/react-router'
import { RedirectVersionBanner } from '~/components/RedirectVersionBanner'
import { getBranch, getLibrary } from '~/libraries'
import { findLibrary, getBranch } from '~/libraries'
import { getTanstackDocsConfig } from '~/utils/config'

export const Route = createFileRoute('/$libraryId/$version')({
staleTime: 1000 * 60 * 5,
beforeLoad: (ctx) => {
const { libraryId, version } = ctx.params
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}

library.handleRedirects?.(ctx.location.href)

Expand All @@ -19,7 +28,12 @@ export const Route = createFileRoute('/$libraryId/$version')({
},
loader: async (ctx) => {
const { libraryId, version } = ctx.params
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}

const branch = getBranch(library, version)
const config = await getTanstackDocsConfig({
data: {
Expand All @@ -36,7 +50,11 @@ export const Route = createFileRoute('/$libraryId/$version')({

function RouteForm() {
const { libraryId, version } = Route.useParams()
const library = getLibrary(libraryId)
const library = findLibrary(libraryId)

if (!library) {
throw notFound()
}

return (
<>
Expand Down
1 change: 1 addition & 0 deletions src/routes/admin/audit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ function AuditPage() {
[],
)

// eslint-disable-next-line react-hooks/incompatible-library
const table = useReactTable({
data: (auditQuery?.data?.page || []) as AuditLogEntry[],
columns,
Expand Down
1 change: 1 addition & 0 deletions src/routes/admin/github-stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ function GitHubStatsAdmin() {
[refreshingKey, refreshAllMutation, refreshMutation],
)

// eslint-disable-next-line react-hooks/incompatible-library
const table = useReactTable({
data: cacheEntries ?? [],
columns,
Expand Down
1 change: 1 addition & 0 deletions src/routes/admin/logins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ function LoginsPage() {
[],
)

// eslint-disable-next-line react-hooks/incompatible-library
const table = useReactTable({
data: (loginsQuery?.data?.page || []) as LoginHistoryEntry[],
columns,
Expand Down
1 change: 1 addition & 0 deletions src/routes/admin/npm-stats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ function NpmStatsAdmin() {
[refreshPackageMutation],
)

// eslint-disable-next-line react-hooks/incompatible-library
const libraryTable = useReactTable({
data: libraryStats ?? [],
columns: libraryColumns,
Expand Down
1 change: 1 addition & 0 deletions src/routes/admin/roles.$roleId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ function RoleDetailPage() {
[selectedUserIds, usersWithRole, toggleAllSelection, toggleUserSelection],
)

// eslint-disable-next-line react-hooks/incompatible-library
const table = useReactTable({
data: usersWithRole || [],
columns,
Expand Down
Loading