docs: redesigned navigation (#9525)
Redesign navigation bar to reflect new design and allow for dropdowns Closes DX-943
This commit is contained in:
@@ -34,6 +34,7 @@ export default function RootLayout({
|
||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||
showToc={false}
|
||||
showBanner={false}
|
||||
showBreadcrumbs={false}
|
||||
>
|
||||
{children}
|
||||
</WideLayout>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { DocsConfig } from "types"
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"
|
||||
|
||||
@@ -16,9 +15,10 @@ export const config: DocsConfig = {
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
}),
|
||||
mobile: [],
|
||||
},
|
||||
project: {
|
||||
title: "API Reference",
|
||||
key: "api-reference",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import {
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { usePathname } from "next/navigation"
|
||||
import basePathUrl from "../utils/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -17,15 +15,12 @@ type MainNavProviderProps = {
|
||||
|
||||
export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
const { isBrowser } = useIsBrowser()
|
||||
const pathname = usePathname()
|
||||
const navigationDropdownItems = useMemo(
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(pathname),
|
||||
version: "v2",
|
||||
}),
|
||||
[pathname]
|
||||
[]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import {
|
||||
usePageLoading,
|
||||
SearchProvider as UiSearchProvider,
|
||||
searchFiltersV2,
|
||||
searchFilters,
|
||||
AiAssistantIcon,
|
||||
AiAssistantProvider,
|
||||
} from "docs-ui"
|
||||
@@ -51,7 +51,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
||||
checkInternalPattern: new RegExp(
|
||||
`^${config.baseUrl}${basePathUrl(`/(admin|store)`)}`
|
||||
),
|
||||
filterOptions: searchFiltersV2,
|
||||
filterOptions: searchFilters,
|
||||
}}
|
||||
commands={[
|
||||
{
|
||||
|
||||
@@ -7,5 +7,12 @@ export const config: DocsConfig = {
|
||||
titleSuffix: "Medusa v2 Docs",
|
||||
baseUrl,
|
||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||
sidebar: sidebarConfig(baseUrl),
|
||||
sidebar: sidebarConfig,
|
||||
project: {
|
||||
title: "Documentation",
|
||||
key: "book",
|
||||
},
|
||||
breadcrumbOptions: {
|
||||
showCategories: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Badge, getMobileSidebarItems } from "docs-ui"
|
||||
import { Badge } from "docs-ui"
|
||||
import type { SidebarConfig, SidebarItem } from "@/types"
|
||||
import { sidebar } from "../sidebar.mjs"
|
||||
|
||||
@@ -20,12 +20,7 @@ const normalizeSidebarItems = (items: SidebarItem[]) =>
|
||||
return item
|
||||
})
|
||||
|
||||
export const sidebarConfig = (baseUrl: string): SidebarConfig => {
|
||||
return {
|
||||
default: normalizeSidebarItems(sidebar),
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
}),
|
||||
}
|
||||
export const sidebarConfig: SidebarConfig = {
|
||||
default: normalizeSidebarItems(sidebar),
|
||||
mobile: [],
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { basePathUrl } from "../utils/base-path-url"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { generatedEditDates } from "../generated/edit-dates.mjs"
|
||||
|
||||
@@ -23,8 +22,6 @@ export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
@@ -51,9 +48,6 @@ export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
navItems={navigationDropdownItems}
|
||||
reportIssueLink={reportLink}
|
||||
editDate={editDate}
|
||||
breadcrumbOptions={{
|
||||
showCategories: false,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UiMainNavProvider>
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
AiAssistantIcon,
|
||||
AiAssistantProvider,
|
||||
SearchProvider as UiSearchProvider,
|
||||
searchFiltersV2,
|
||||
searchFilters,
|
||||
} from "docs-ui"
|
||||
import { config } from "../config"
|
||||
|
||||
@@ -50,7 +50,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
||||
checkInternalPattern: new RegExp(
|
||||
`^${config.baseUrl}/v2/([^(resources)])*`
|
||||
),
|
||||
filterOptions: searchFiltersV2,
|
||||
filterOptions: searchFilters,
|
||||
}}
|
||||
commands={[
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { DocsConfig, SidebarItem } from "types"
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
import { generatedSidebar } from "../generated/sidebar.mjs"
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"
|
||||
@@ -10,9 +9,13 @@ export const config: DocsConfig = {
|
||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||
sidebar: {
|
||||
default: generatedSidebar as SidebarItem[],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
}),
|
||||
mobile: [],
|
||||
},
|
||||
project: {
|
||||
title: "Development Resources",
|
||||
key: "resources",
|
||||
},
|
||||
breadcrumbOptions: {
|
||||
showCategories: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { basePathUrl } from "../utils/base-path-url"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { generatedEditDates } from "../generated/edit-dates.mjs"
|
||||
|
||||
@@ -23,14 +22,8 @@ export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(
|
||||
pathname.startsWith("/commerce-modules")
|
||||
? "/commerce-modules"
|
||||
: undefined
|
||||
),
|
||||
version: "v2",
|
||||
}),
|
||||
[pathname]
|
||||
[]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
AiAssistantIcon,
|
||||
AiAssistantProvider,
|
||||
SearchProvider as UiSearchProvider,
|
||||
searchFiltersV2,
|
||||
searchFilters,
|
||||
} from "docs-ui"
|
||||
import { config } from "../config"
|
||||
|
||||
@@ -39,7 +39,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
||||
},
|
||||
],
|
||||
checkInternalPattern: new RegExp(`^${config.baseUrl}/v2/resources/.*`),
|
||||
filterOptions: searchFiltersV2,
|
||||
filterOptions: searchFilters,
|
||||
}}
|
||||
commands={[
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
import { SidebarSectionItems } from "types"
|
||||
import { siteConfig } from "./site"
|
||||
|
||||
type DocsConfig = {
|
||||
sidebar: SidebarSectionItems
|
||||
@@ -359,9 +357,6 @@ export const docsConfig: DocsConfig = {
|
||||
],
|
||||
},
|
||||
],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl: siteConfig.baseUrl,
|
||||
version: "v1",
|
||||
}),
|
||||
mobile: [],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -19,4 +19,11 @@ export const siteConfig: SiteConfig = {
|
||||
default: [],
|
||||
mobile: [],
|
||||
},
|
||||
project: {
|
||||
title: "Medusa UI",
|
||||
key: "ui",
|
||||
},
|
||||
breadcrumbOptions: {
|
||||
showCategories: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { siteConfig } from "../config/site"
|
||||
import { basePathUrl } from "../lib/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -20,8 +19,6 @@ export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: siteConfig.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v1",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
AiAssistantIcon,
|
||||
AiAssistantProvider,
|
||||
SearchProvider as UiSearchProvider,
|
||||
searchFiltersV1,
|
||||
searchFilters,
|
||||
} from "docs-ui"
|
||||
import { absoluteUrl } from "../lib/absolute-url"
|
||||
|
||||
@@ -34,7 +34,7 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
||||
},
|
||||
],
|
||||
checkInternalPattern: new RegExp(`^${absoluteUrl()}/ui`),
|
||||
filterOptions: searchFiltersV1,
|
||||
filterOptions: searchFilters,
|
||||
}}
|
||||
initialDefaultFilters={["ui"]}
|
||||
commands={[
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
@apply text-ui-fg-subtle;
|
||||
}
|
||||
|
||||
/* Hack to hide navbar / toc when some components like prompt are opened. */
|
||||
body[data-scroll-locked] .z-20,
|
||||
body[data-scroll-locked] .z-10 {
|
||||
z-index: 0 !important;
|
||||
}
|
||||
|
||||
body[data-modal="opened"] {
|
||||
@apply !overflow-hidden text-ui-fg-base;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { DocsConfig, SidebarItem } from "types"
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs"
|
||||
|
||||
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || "http://localhost:3000"
|
||||
@@ -10,9 +9,13 @@ export const config: DocsConfig = {
|
||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||
sidebar: {
|
||||
default: sidebar as SidebarItem[],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
}),
|
||||
mobile: [],
|
||||
},
|
||||
project: {
|
||||
title: "User Guide",
|
||||
key: "user-guide",
|
||||
},
|
||||
breadcrumbOptions: {
|
||||
showCategories: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { basePathUrl } from "../utils/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -20,8 +19,6 @@ export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
SearchProvider as UiSearchProvider,
|
||||
AiAssistantIcon,
|
||||
AiAssistantProvider,
|
||||
searchFiltersV1,
|
||||
searchFilters,
|
||||
} from "docs-ui"
|
||||
import { config } from "../config"
|
||||
|
||||
@@ -42,9 +42,10 @@ const SearchProvider = ({ children }: SearchProviderProps) => {
|
||||
},
|
||||
],
|
||||
checkInternalPattern: new RegExp(`^${config.baseUrl}/user-guide`),
|
||||
filterOptions: searchFiltersV1,
|
||||
filterOptions: searchFilters,
|
||||
}}
|
||||
initialDefaultFilters={["user-guide"]}
|
||||
// TODO change later when we have a user guide filter
|
||||
initialDefaultFilters={["guides"]}
|
||||
commands={[
|
||||
{
|
||||
name: "ai-assistant",
|
||||
|
||||
@@ -1,29 +1,55 @@
|
||||
"use client"
|
||||
|
||||
import React, { useMemo } from "react"
|
||||
import { CurrentItemsState, useSidebar } from "@/providers"
|
||||
import { TriangleRightMini } from "@medusajs/icons"
|
||||
import Link from "next/link"
|
||||
import clsx from "clsx"
|
||||
|
||||
type BreadcrumbItem = Map<string, string>
|
||||
import Link from "next/link"
|
||||
import { SidebarItemLink } from "types"
|
||||
import { CurrentItemsState, useSidebar, useSiteConfig } from "../../providers"
|
||||
import { Button } from "../Button"
|
||||
import { TriangleRightMini } from "@medusajs/icons"
|
||||
|
||||
export const Breadcrumbs = () => {
|
||||
const { currentItems } = useSidebar()
|
||||
const { currentItems, activeItem: sidebarActiveItem } = useSidebar()
|
||||
const {
|
||||
config: { breadcrumbOptions, project, baseUrl, basePath },
|
||||
} = useSiteConfig()
|
||||
|
||||
const getBreadcrumbsOfItem = (item: CurrentItemsState): BreadcrumbItem => {
|
||||
let tempBreadcrumbItems: BreadcrumbItem = new Map()
|
||||
const getLinkPath = (item?: SidebarItemLink): string | undefined => {
|
||||
if (!item) {
|
||||
return
|
||||
}
|
||||
return item.isPathHref ? item.path : `#${item.path}`
|
||||
}
|
||||
|
||||
const getBreadcrumbsOfItem = (
|
||||
item: CurrentItemsState
|
||||
): Map<string, string> => {
|
||||
let tempBreadcrumbItems: Map<string, string> = new Map()
|
||||
if (item.previousSidebar) {
|
||||
tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar)
|
||||
}
|
||||
|
||||
const parentPath =
|
||||
item.parentItem?.type === "link" ? item.parentItem.path : undefined
|
||||
item.parentItem?.type === "link"
|
||||
? getLinkPath(item.parentItem)
|
||||
: (item.parentItem?.type === "category" &&
|
||||
breadcrumbOptions?.showCategories) ||
|
||||
item.parentItem?.type === "sub-category"
|
||||
? "#"
|
||||
: undefined
|
||||
const firstItemPath =
|
||||
item.default[0].type === "link" ? item.default[0].path : undefined
|
||||
item.default[0].type === "link"
|
||||
? getLinkPath(item.default[0])
|
||||
: (item.default[0].type === "category" &&
|
||||
breadcrumbOptions?.showCategories) ||
|
||||
item.default[0].type === "sub-category"
|
||||
? "#"
|
||||
: undefined
|
||||
|
||||
const breadcrumbPath = parentPath || firstItemPath || "/"
|
||||
|
||||
tempBreadcrumbItems.set(
|
||||
parentPath || firstItemPath || "/",
|
||||
breadcrumbPath,
|
||||
item.parentItem?.childSidebarTitle || item.parentItem?.title || ""
|
||||
)
|
||||
|
||||
@@ -31,51 +57,65 @@ export const Breadcrumbs = () => {
|
||||
}
|
||||
|
||||
const breadcrumbItems = useMemo(() => {
|
||||
const tempBreadcrumbItems: BreadcrumbItem = new Map()
|
||||
if (!currentItems) {
|
||||
return tempBreadcrumbItems
|
||||
const tempBreadcrumbItems: Map<string, string> = new Map()
|
||||
tempBreadcrumbItems.set(`${baseUrl}${basePath}`, project.title)
|
||||
|
||||
if (currentItems) {
|
||||
getBreadcrumbsOfItem(currentItems).forEach((value, key) =>
|
||||
tempBreadcrumbItems.set(key, value)
|
||||
)
|
||||
}
|
||||
|
||||
tempBreadcrumbItems.set("/", "Home")
|
||||
|
||||
getBreadcrumbsOfItem(currentItems).forEach((value, key) =>
|
||||
tempBreadcrumbItems.set(key, value)
|
||||
)
|
||||
if (sidebarActiveItem) {
|
||||
if (
|
||||
sidebarActiveItem.parentItem &&
|
||||
(sidebarActiveItem.parentItem.type !== "category" ||
|
||||
breadcrumbOptions?.showCategories)
|
||||
) {
|
||||
tempBreadcrumbItems.set(
|
||||
sidebarActiveItem.parentItem.type === "link"
|
||||
? getLinkPath(sidebarActiveItem.parentItem) || "#"
|
||||
: "#",
|
||||
sidebarActiveItem.parentItem.title || ""
|
||||
)
|
||||
}
|
||||
tempBreadcrumbItems.set(
|
||||
getLinkPath(sidebarActiveItem) || "/",
|
||||
sidebarActiveItem.title || ""
|
||||
)
|
||||
}
|
||||
|
||||
return tempBreadcrumbItems
|
||||
}, [currentItems])
|
||||
|
||||
const getBreadcrumbItemElms = (): React.ReactNode[] => {
|
||||
const elms: React.ReactNode[] = []
|
||||
breadcrumbItems.forEach((title, path) => {
|
||||
elms.push(
|
||||
<React.Fragment key={path}>
|
||||
{elms.length !== 0 && (
|
||||
<TriangleRightMini className={clsx("text-medusa-fg-muted")} />
|
||||
)}
|
||||
<Link
|
||||
href={path}
|
||||
className={clsx(
|
||||
"text-compact-x-small-plus text-medusa-fg-muted",
|
||||
"hover:text-medusa-fg-subtle transition-colors"
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</Link>
|
||||
</React.Fragment>
|
||||
)
|
||||
})
|
||||
|
||||
return elms
|
||||
}
|
||||
}, [currentItems, sidebarActiveItem, breadcrumbOptions])
|
||||
|
||||
return (
|
||||
<>
|
||||
{breadcrumbItems.size > 0 && (
|
||||
<div className="flex gap-docs_0.25 items-center mb-docs_1">
|
||||
{...getBreadcrumbItemElms()}
|
||||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center gap-docs_0.25",
|
||||
"text-medusa-fg-muted text-compact-small",
|
||||
"mb-docs_1"
|
||||
)}
|
||||
</>
|
||||
>
|
||||
{Array.from(breadcrumbItems).map(([link, title], index) => (
|
||||
<React.Fragment key={link}>
|
||||
{index > 0 && <TriangleRightMini />}
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className={clsx(
|
||||
"px-docs_0.5 py-docs_0.25",
|
||||
link === "#" && "hover:cursor-default",
|
||||
"!p-0 hover:!bg-transparent hover:!text-medusa-fg-subtle"
|
||||
)}
|
||||
>
|
||||
<Link
|
||||
href={link}
|
||||
className={clsx(link === "#" && "hover:cursor-default")}
|
||||
>
|
||||
{title}
|
||||
</Link>
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React, { useMemo } from "react"
|
||||
import { Button, CurrentItemsState, useMainNav, useSidebar } from "../../.."
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import { SidebarItemLink } from "types"
|
||||
|
||||
export const MainNavBreadcrumbs = () => {
|
||||
const { currentItems, activeItem } = useSidebar()
|
||||
const {
|
||||
activeItem: mainNavActiveItem,
|
||||
breadcrumbOptions: { showCategories },
|
||||
} = useMainNav()
|
||||
|
||||
const getLinkPath = (item?: SidebarItemLink): string | undefined => {
|
||||
if (!item) {
|
||||
return
|
||||
}
|
||||
return item.isPathHref ? item.path : `#${item.path}`
|
||||
}
|
||||
|
||||
const getBreadcrumbsOfItem = (
|
||||
item: CurrentItemsState
|
||||
): Map<string, string> => {
|
||||
let tempBreadcrumbItems: Map<string, string> = new Map()
|
||||
if (item.previousSidebar) {
|
||||
tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar)
|
||||
}
|
||||
|
||||
const parentPath =
|
||||
item.parentItem?.type === "link"
|
||||
? getLinkPath(item.parentItem)
|
||||
: (item.parentItem?.type === "category" && showCategories) ||
|
||||
item.parentItem?.type === "sub-category"
|
||||
? "#"
|
||||
: undefined
|
||||
const firstItemPath =
|
||||
item.default[0].type === "link"
|
||||
? getLinkPath(item.default[0])
|
||||
: (item.default[0].type === "category" && showCategories) ||
|
||||
item.default[0].type === "sub-category"
|
||||
? "#"
|
||||
: undefined
|
||||
|
||||
const breadcrumbPath = parentPath || firstItemPath || "/"
|
||||
|
||||
if (!mainNavActiveItem?.path.endsWith(breadcrumbPath)) {
|
||||
tempBreadcrumbItems.set(
|
||||
breadcrumbPath,
|
||||
item.parentItem?.childSidebarTitle || item.parentItem?.title || ""
|
||||
)
|
||||
}
|
||||
|
||||
return tempBreadcrumbItems
|
||||
}
|
||||
|
||||
const breadcrumbItems = useMemo(() => {
|
||||
const tempBreadcrumbItems: Map<string, string> = new Map()
|
||||
if (currentItems) {
|
||||
getBreadcrumbsOfItem(currentItems).forEach((value, key) =>
|
||||
tempBreadcrumbItems.set(key, value)
|
||||
)
|
||||
}
|
||||
|
||||
if (activeItem && !mainNavActiveItem?.path.endsWith(activeItem.path)) {
|
||||
if (
|
||||
activeItem.parentItem &&
|
||||
(activeItem.parentItem.type !== "category" || showCategories)
|
||||
) {
|
||||
tempBreadcrumbItems.set(
|
||||
activeItem.parentItem.type === "link"
|
||||
? getLinkPath(activeItem.parentItem) || "#"
|
||||
: "#",
|
||||
activeItem.parentItem.title || ""
|
||||
)
|
||||
}
|
||||
tempBreadcrumbItems.set(
|
||||
getLinkPath(activeItem) || "/",
|
||||
activeItem.title || ""
|
||||
)
|
||||
}
|
||||
|
||||
return tempBreadcrumbItems
|
||||
}, [currentItems, activeItem])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center gap-docs_0.25",
|
||||
"text-medusa-fg-muted text-compact-small"
|
||||
)}
|
||||
>
|
||||
{Array.from(breadcrumbItems).map(([link, title]) => (
|
||||
<React.Fragment key={link}>
|
||||
<span>/</span>
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className={clsx(
|
||||
"px-docs_0.5 py-docs_0.25",
|
||||
link === "#" && "hover:!bg-transparent hover:cursor-default"
|
||||
)}
|
||||
>
|
||||
<Link
|
||||
href={link}
|
||||
className={clsx(link === "#" && "hover:cursor-default")}
|
||||
>
|
||||
{title}
|
||||
</Link>
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { useColorMode } from "../../../providers"
|
||||
import { Button, Tooltip } from "../../.."
|
||||
import { Moon, Sun } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
|
||||
export const MainNavColorMode = () => {
|
||||
const { colorMode, toggleColorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<Tooltip place="bottom" tooltipChildren="Change Theme">
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className={clsx("!p-[6.5px] text-medusa-fg-muted")}
|
||||
onClick={toggleColorMode}
|
||||
>
|
||||
{colorMode === "light" && <Sun />}
|
||||
{colorMode === "dark" && <Moon />}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { useColorMode } from "../../../../providers"
|
||||
import clsx from "clsx"
|
||||
import { EllipseMiniSolid } from "@medusajs/icons"
|
||||
|
||||
export const MainNavThemeMenu = () => {
|
||||
const { colorMode, setColorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center gap-docs_0.5",
|
||||
"py-docs_0.25 px-docs_0.5",
|
||||
"rounded-docs_xs text-compact-x-small-plus",
|
||||
"text-medusa-fg-subtle"
|
||||
)}
|
||||
>
|
||||
Theme
|
||||
</div>
|
||||
<div className="px-docs_0.25">
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center gap-docs_0.5",
|
||||
"py-docs_0.25 px-docs_0.5 cursor-pointer",
|
||||
"rounded-docs_xs text-medusa-fg-base",
|
||||
"hover:bg-medusa-bg-component-hover"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={() => setColorMode("light")}
|
||||
>
|
||||
<EllipseMiniSolid
|
||||
className={clsx(colorMode !== "light" && "invisible")}
|
||||
/>
|
||||
<span
|
||||
className={clsx(
|
||||
colorMode !== "light" && "text-compact-small",
|
||||
colorMode === "light" && "text-compact-small-plus"
|
||||
)}
|
||||
>
|
||||
Light
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-docs_0.25">
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center gap-docs_0.5",
|
||||
"py-docs_0.25 px-docs_0.5 cursor-pointer",
|
||||
"rounded-docs_xs text-medusa-fg-base",
|
||||
"hover:bg-medusa-bg-component-hover"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={() => setColorMode("dark")}
|
||||
>
|
||||
<EllipseMiniSolid
|
||||
className={clsx(colorMode !== "dark" && "invisible")}
|
||||
/>
|
||||
<span
|
||||
className={clsx(
|
||||
colorMode !== "dark" && "text-compact-small",
|
||||
colorMode === "dark" && "text-compact-small-plus"
|
||||
)}
|
||||
>
|
||||
Dark
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
BarsThree,
|
||||
QuestionMarkCircle,
|
||||
SidebarLeft,
|
||||
TimelineVertical,
|
||||
} from "@medusajs/icons"
|
||||
import React, { useRef, useState } from "react"
|
||||
import {
|
||||
Button,
|
||||
getOsShortcut,
|
||||
Menu,
|
||||
useClickOutside,
|
||||
useSidebar,
|
||||
} from "../../.."
|
||||
import clsx from "clsx"
|
||||
import { HouseIcon } from "../../Icons/House"
|
||||
import { MainNavThemeMenu } from "./ThemeMenu"
|
||||
|
||||
export const MainNavDesktopMenu = () => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const { setDesktopSidebarOpen } = useSidebar()
|
||||
const ref = useRef(null)
|
||||
|
||||
useClickOutside({
|
||||
elmRef: ref,
|
||||
onClickOutside: () => setIsOpen(false),
|
||||
})
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative hidden lg:flex justify-center items-center"
|
||||
ref={ref}
|
||||
>
|
||||
<Button
|
||||
variant="transparent"
|
||||
onClick={() => setIsOpen((prev) => !prev)}
|
||||
className="!p-[6.5px]"
|
||||
>
|
||||
<BarsThree className="text-medusa-fg-subtle" />
|
||||
</Button>
|
||||
<Menu
|
||||
className={clsx(
|
||||
"absolute top-[calc(100%+8px)] right-0 min-w-[200px]",
|
||||
!isOpen && "hidden"
|
||||
)}
|
||||
items={[
|
||||
{
|
||||
type: "link",
|
||||
icon: <HouseIcon />,
|
||||
title: "Homepage",
|
||||
link: "https://medusajs.com",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
icon: <TimelineVertical />,
|
||||
title: "Changelog",
|
||||
link: "https://medusajs.com/changelog",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
icon: <QuestionMarkCircle />,
|
||||
title: "Troubleshooting",
|
||||
link: "https://docs.medusajs.com/v2/resources/troubleshooting",
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "action",
|
||||
title: "Hide Sidebar",
|
||||
icon: <SidebarLeft />,
|
||||
shortcut: `${getOsShortcut()}\\`,
|
||||
action: () => {
|
||||
setDesktopSidebarOpen((prev) => !prev)
|
||||
setIsOpen(false)
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "custom",
|
||||
content: <MainNavThemeMenu />,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
|
||||
export const MainNavDivider = () => {
|
||||
return (
|
||||
<span
|
||||
className={clsx("h-docs_0.75 w-px block bg-medusa-border-base")}
|
||||
></span>
|
||||
)
|
||||
}
|
||||
@@ -18,7 +18,7 @@ export const MainNavEditDate = ({ date }: MainNavEditDateProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className="text-compact-small">
|
||||
<span className="text-compact-small-plus">
|
||||
Edited {dateMatch.groups.month} {dateObj.getDate()}
|
||||
{dateObj.getFullYear() !== today.getFullYear()
|
||||
? `, ${dateObj.getFullYear()}`
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React, { useRef, useState } from "react"
|
||||
import { Button, Kbd, Tooltip } from "@/components"
|
||||
import { Bug, Discord, QuestionMark } from "@medusajs/icons"
|
||||
import { Menu, useClickOutside } from "../../.."
|
||||
import { MenuItem } from "types"
|
||||
import clsx from "clsx"
|
||||
import { GithubIcon } from "../../Icons/Github"
|
||||
|
||||
export const MainNavHelpButton = () => {
|
||||
const [showMenu, setShowMenu] = useState(false)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
useClickOutside({
|
||||
elmRef: ref,
|
||||
onClickOutside: () => {
|
||||
setShowMenu(false)
|
||||
},
|
||||
})
|
||||
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
title: "Create a GitHub Issue",
|
||||
link: "https://github.com/medusajs/medusa/issues/new/choose",
|
||||
icon: <GithubIcon className="text-medusa-fg-base" />,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Get Support on Discord",
|
||||
link: "https://discord.gg/medusajs",
|
||||
icon: <Discord />,
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Troubleshooting Guides",
|
||||
link: "https://docs.medusajs.com/v2/resources/troubleshooting",
|
||||
icon: <Bug />,
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="relative" ref={ref}>
|
||||
<Tooltip
|
||||
tooltipChildren={
|
||||
<span className="flex gap-[6px] items-center">
|
||||
<span>Need help?</span>
|
||||
<Kbd className="w-docs_1 h-docs_1">?</Kbd>
|
||||
</span>
|
||||
}
|
||||
place="bottom"
|
||||
hidden={showMenu}
|
||||
>
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className="text-medusa-fg-muted !px-[6.5px] !py-[6.5px]"
|
||||
onClick={() => setShowMenu((prev) => !prev)}
|
||||
>
|
||||
<QuestionMark />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<div
|
||||
className={clsx(
|
||||
"absolute bottom-0 left-0",
|
||||
"z-50 -translate-x-[40%] translate-y-[calc(100%+8px)]",
|
||||
!showMenu && "hidden"
|
||||
)}
|
||||
>
|
||||
<Menu items={menuItems} className="w-[200px]" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
"use client"
|
||||
|
||||
import { TriangleDownMini } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
import React, { useRef, useState } from "react"
|
||||
import { NavigationItemDropdown } from "types"
|
||||
import { Menu, useClickOutside } from "../../../.."
|
||||
|
||||
type MainNavItemDropdownProps = {
|
||||
item: NavigationItemDropdown
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
export const MainNavItemDropdown = ({
|
||||
item,
|
||||
isActive,
|
||||
}: MainNavItemDropdownProps) => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const ref = useRef(null)
|
||||
|
||||
useClickOutside({
|
||||
elmRef: ref,
|
||||
onClickOutside: () => setIsOpen(false),
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={clsx("relative")} ref={ref}>
|
||||
<div
|
||||
className={clsx(
|
||||
"cursor-pointer flex gap-docs_0.25 items-center",
|
||||
isActive && "text-medusa-fg-base",
|
||||
!isActive && [
|
||||
"text-medusa-fg-muted hover:text-medusa-fg-subtle",
|
||||
isOpen && "text-medusa-fg-subtle",
|
||||
]
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={() => setIsOpen((prev) => !prev)}
|
||||
>
|
||||
<span className="text-compact-small-plus">{item.title}</span>
|
||||
<TriangleDownMini
|
||||
className={clsx("transition-transform", isOpen && "rotate-180")}
|
||||
/>
|
||||
</div>
|
||||
<Menu
|
||||
className={clsx(
|
||||
"absolute top-[calc(100%+4px)] -left-docs_0.75 min-w-[190px]",
|
||||
!isOpen && "hidden"
|
||||
)}
|
||||
items={item.children}
|
||||
itemsOnClick={() => setIsOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { NavigationItemLink } from "types"
|
||||
import { LinkButton } from "../../../.."
|
||||
import clsx from "clsx"
|
||||
|
||||
type MainNavItemLinkProps = {
|
||||
item: NavigationItemLink
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
export const MainNavItemLink = ({ item, isActive }: MainNavItemLinkProps) => {
|
||||
return (
|
||||
<LinkButton
|
||||
href={item.path}
|
||||
className={clsx(
|
||||
isActive && "text-medusa-fg-base",
|
||||
!isActive && "text-medusa-fg-muted hover:text-medusa-fg-subtle"
|
||||
)}
|
||||
>
|
||||
{item.title}
|
||||
</LinkButton>
|
||||
)
|
||||
}
|
||||
35
www/packages/docs-ui/src/components/MainNav/Items/index.tsx
Normal file
35
www/packages/docs-ui/src/components/MainNav/Items/index.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { useMainNav } from "../../.."
|
||||
import clsx from "clsx"
|
||||
import { MainNavItemLink } from "./Link"
|
||||
import { MainNavItemDropdown } from "./Dropdown"
|
||||
|
||||
export const MainNavItems = () => {
|
||||
const { navItems, activeItemIndex } = useMainNav()
|
||||
|
||||
return (
|
||||
<ul
|
||||
className={clsx(
|
||||
"hidden lg:flex justify-start gap-docs_1 items-center",
|
||||
"my-docs_0.75"
|
||||
)}
|
||||
>
|
||||
{navItems.map((item, index) => {
|
||||
const isActive = index === activeItemIndex
|
||||
|
||||
return (
|
||||
<li className={clsx("flex items-center group")} key={index}>
|
||||
{item.type === "link" && (
|
||||
<MainNavItemLink item={item} isActive={isActive} />
|
||||
)}
|
||||
{item.type === "dropdown" && (
|
||||
<MainNavItemDropdown item={item} isActive={isActive} />
|
||||
)}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { useMainNav } from "../../../../providers"
|
||||
import Link from "next/link"
|
||||
import { TriangleRightMini } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
import { SelectedMenu } from ".."
|
||||
|
||||
type MainNavMobileMainMenu = {
|
||||
setSelectedMenu: (menu: SelectedMenu) => void
|
||||
}
|
||||
|
||||
export const MainNavMobileMainMenu = ({
|
||||
setSelectedMenu,
|
||||
}: MainNavMobileMainMenu) => {
|
||||
const { navItems } = useMainNav()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-[23px]">
|
||||
<span className="text-compact-small-plus text-medusa-fg-muted uppercase">
|
||||
Menu
|
||||
</span>
|
||||
<ul className="flex flex-col gap-[18px]">
|
||||
{navItems.map((item, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={clsx(
|
||||
"text-h1 text-medusa-fg-base cursor-pointer",
|
||||
"flex justify-between gap-docs_1"
|
||||
)}
|
||||
onClick={() => {
|
||||
if (item.type !== "dropdown") {
|
||||
return
|
||||
}
|
||||
|
||||
setSelectedMenu({
|
||||
title: item.title,
|
||||
menu: item.children,
|
||||
})
|
||||
}}
|
||||
>
|
||||
{item.type === "link" && (
|
||||
<Link href={item.path} className="block w-full">
|
||||
{item.title}
|
||||
</Link>
|
||||
)}
|
||||
{item.type === "dropdown" && (
|
||||
<>
|
||||
<span>{item.title}</span>
|
||||
<TriangleRightMini />
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import React, { useMemo } from "react"
|
||||
import { MenuItem, MenuItemLink } from "types"
|
||||
|
||||
type MainNavMobileSubMenuProps = {
|
||||
menu: MenuItem[]
|
||||
title: string
|
||||
}
|
||||
|
||||
export const MainNavMobileSubMenu = ({
|
||||
menu,
|
||||
title,
|
||||
}: MainNavMobileSubMenuProps) => {
|
||||
const filteredItems: MenuItemLink[] = useMemo(() => {
|
||||
return menu.filter((item) => item.type === "link") as MenuItemLink[]
|
||||
}, [menu])
|
||||
return (
|
||||
<div className="flex flex-col gap-[23px]">
|
||||
<span className="text-compact-small-plus text-medusa-fg-muted uppercase">
|
||||
{title}
|
||||
</span>
|
||||
<ul className="flex flex-col gap-[18px]">
|
||||
{filteredItems.map((item, index) => (
|
||||
<li
|
||||
key={index}
|
||||
className={clsx(
|
||||
"text-h1 text-medusa-fg-base cursor-pointer",
|
||||
"flex justify-between gap-docs_1"
|
||||
)}
|
||||
>
|
||||
<Link href={item.link} className="block w-full">
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
"use client"
|
||||
|
||||
import React, { useRef, useState } from "react"
|
||||
import { Button } from "../../Button"
|
||||
import { ArrowUturnLeft, BarsThree, XMark } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
import { MenuItem } from "types"
|
||||
import { CSSTransition, SwitchTransition } from "react-transition-group"
|
||||
import { MainNavMobileMainMenu } from "./Main"
|
||||
import { MainNavMobileSubMenu } from "./SubMenu"
|
||||
|
||||
export type SelectedMenu = {
|
||||
title: string
|
||||
menu: MenuItem[]
|
||||
}
|
||||
|
||||
export const MainNavMobileMenu = () => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [selectedMenu, setSelectedMenu] = useState<SelectedMenu>()
|
||||
const ref = useRef(null)
|
||||
|
||||
return (
|
||||
<div className="flex lg:hidden justify-center items-center">
|
||||
<Button
|
||||
variant="transparent"
|
||||
onClick={() => setIsOpen((prev) => !prev)}
|
||||
className="text-medusa-fg-subtle !p-[6.5px]"
|
||||
>
|
||||
{!isOpen && <BarsThree />}
|
||||
{isOpen && <XMark />}
|
||||
</Button>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center justify-center fixed w-full h-[calc(100vh-52px)]",
|
||||
"top-[52px] transition-[left] bg-medusa-bg-subtle z-50",
|
||||
!isOpen && "-left-full",
|
||||
isOpen && "left-0"
|
||||
)}
|
||||
>
|
||||
<SwitchTransition>
|
||||
<CSSTransition
|
||||
key={!selectedMenu ? "main" : "sub"}
|
||||
classNames={{
|
||||
enter: "animate-fadeInLeft animate-fast",
|
||||
exit: "animate-fadeOutRight animate-fast",
|
||||
}}
|
||||
nodeRef={ref}
|
||||
timeout={250}
|
||||
>
|
||||
<div ref={ref} className="w-full px-docs_1.5">
|
||||
{!selectedMenu && (
|
||||
<MainNavMobileMainMenu setSelectedMenu={setSelectedMenu} />
|
||||
)}
|
||||
{selectedMenu && (
|
||||
<>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center gap-docs_0.5",
|
||||
"text-medusa-fg-base my-[14px]",
|
||||
"cursor-pointer"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={() => setSelectedMenu(undefined)}
|
||||
>
|
||||
<ArrowUturnLeft />
|
||||
<span className="text-h1">Back</span>
|
||||
</div>
|
||||
<MainNavMobileSubMenu {...selectedMenu} />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</CSSTransition>
|
||||
</SwitchTransition>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import React from "react"
|
||||
import { BorderedIcon } from "@/components"
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
|
||||
export type MainNavigationDropdownIconProps = {
|
||||
icon: React.FC<IconProps>
|
||||
inDropdown?: boolean
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownIcon = ({
|
||||
icon,
|
||||
inDropdown = false,
|
||||
}: MainNavigationDropdownIconProps) => {
|
||||
return (
|
||||
<BorderedIcon
|
||||
IconComponent={icon}
|
||||
iconClassName={inDropdown ? "w-docs_1 h-docs_1" : ""}
|
||||
iconWrapperClassName="rounded-docs_xs"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import Link from "next/link"
|
||||
import clsx from "clsx"
|
||||
import { EllipseMiniSolid } from "@medusajs/icons"
|
||||
import { MainNavigationDropdownIcon } from "../../Icon"
|
||||
import { DottedSeparator } from "../../../.."
|
||||
|
||||
export type MainNavigationDropdownMenuItemProps = {
|
||||
item: NavigationDropdownItem
|
||||
onSelect: () => void
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownMenuItem = ({
|
||||
item,
|
||||
onSelect,
|
||||
}: MainNavigationDropdownMenuItemProps) => {
|
||||
switch (item.type) {
|
||||
case "divider":
|
||||
return <DottedSeparator className="my-docs_0.25" />
|
||||
case "link":
|
||||
return (
|
||||
<Link
|
||||
href={item.path}
|
||||
className={clsx(
|
||||
"hover:bg-medusa-bg-component-hover",
|
||||
"block rounded-docs_xs"
|
||||
)}
|
||||
prefetch={false}
|
||||
onClick={onSelect}
|
||||
>
|
||||
<li
|
||||
className={clsx(
|
||||
"px-docs_0.5 py-docs_0.25",
|
||||
"rounded-docs_xs text-medusa-fg-base",
|
||||
"flex gap-docs_0.5 justify-start items-center"
|
||||
)}
|
||||
>
|
||||
<span className={clsx(!item.isActive && "invisible")}>
|
||||
<EllipseMiniSolid />
|
||||
</span>
|
||||
<MainNavigationDropdownIcon icon={item.icon} inDropdown={true} />
|
||||
<span className="whitespace-nowrap">{item.title}</span>
|
||||
</li>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import { MainNavigationDropdownMenuItem } from "./Item"
|
||||
|
||||
export type MainNavigationDropdownMenuProps = {
|
||||
items: NavigationDropdownItem[]
|
||||
open: boolean
|
||||
onSelect: () => void
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownMenu = ({
|
||||
items,
|
||||
open,
|
||||
onSelect,
|
||||
}: MainNavigationDropdownMenuProps) => {
|
||||
return (
|
||||
<ul
|
||||
className={clsx(
|
||||
"absolute top-[calc(100%+4px)] p-docs_0.25 z-50 lg:-left-docs_0.25",
|
||||
"bg-medusa-bg-component rounded shadow-elevation-flyout",
|
||||
!open && "hidden"
|
||||
)}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<MainNavigationDropdownMenuItem
|
||||
item={item}
|
||||
key={index}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import { TrianglesMini } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
import { MainNavigationDropdownIcon } from "../Icon"
|
||||
|
||||
export type MainNavigationDropdownSelectedProps = {
|
||||
item: NavigationDropdownItem
|
||||
onClick: () => void
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownSelected = ({
|
||||
item,
|
||||
onClick,
|
||||
isActive,
|
||||
}: MainNavigationDropdownSelectedProps) => {
|
||||
if (item.type === "divider") {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex justify-between items-center gap-docs_0.25",
|
||||
"cursor-pointer rounded-docs_sm group"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={onClick}
|
||||
>
|
||||
<MainNavigationDropdownIcon icon={item.icon} />
|
||||
<div
|
||||
className={clsx(
|
||||
"flex gap-[6px] py-docs_0.25 px-docs_0.5",
|
||||
"items-center group-hover:bg-medusa-button-transparent-hover",
|
||||
"rounded-docs_sm",
|
||||
isActive && "bg-medusa-button-transparent-hover"
|
||||
)}
|
||||
>
|
||||
<span className="text-medusa-fg-base whitespace-nowrap flex-1 text-compact-small-plus">
|
||||
{item.title}
|
||||
</span>
|
||||
<TrianglesMini className="text-medusa-fg-muted" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React, { useMemo, useRef, useState } from "react"
|
||||
import { MainNavigationDropdownSelected } from "./Selected"
|
||||
import { MainNavigationDropdownMenu } from "./Menu"
|
||||
import { useAnalytics, useClickOutside, useMainNav } from "../../.."
|
||||
|
||||
export const MainNavigationDropdown = () => {
|
||||
const { navItems: items } = useMainNav()
|
||||
const navigationRef = useRef<HTMLDivElement>(null)
|
||||
const [menuOpen, setMenuOpen] = useState(false)
|
||||
const { track } = useAnalytics()
|
||||
useClickOutside({
|
||||
elmRef: navigationRef,
|
||||
onClickOutside: () => {
|
||||
setMenuOpen(false)
|
||||
},
|
||||
})
|
||||
|
||||
const selectedItem = useMemo(() => {
|
||||
const activeItem = items.find(
|
||||
(item) => item.type === "link" && item.isActive
|
||||
)
|
||||
|
||||
if (!activeItem) {
|
||||
return items.length ? items[0] : undefined
|
||||
}
|
||||
|
||||
return activeItem
|
||||
}, [items])
|
||||
return (
|
||||
<div className={clsx("relative z-50")} ref={navigationRef}>
|
||||
{selectedItem && (
|
||||
<MainNavigationDropdownSelected
|
||||
item={selectedItem}
|
||||
onClick={() => {
|
||||
setMenuOpen((prev) => !prev)
|
||||
if (!menuOpen) {
|
||||
track("nav_main_open", {
|
||||
url: window.location.href,
|
||||
})
|
||||
}
|
||||
}}
|
||||
isActive={menuOpen}
|
||||
/>
|
||||
)}
|
||||
<MainNavigationDropdownMenu
|
||||
items={items}
|
||||
open={menuOpen}
|
||||
onSelect={() => setMenuOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { Button, useSidebar } from "../../.."
|
||||
import clsx from "clsx"
|
||||
import { SidebarLeft } from "@medusajs/icons"
|
||||
|
||||
export const MainNavSidebarOpener = () => {
|
||||
const { desktopSidebarOpen, setDesktopSidebarOpen } = useSidebar()
|
||||
|
||||
if (desktopSidebarOpen) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className={clsx("!p-[6.5px] text-medusa-fg-muted", "mr-docs_0.5")}
|
||||
onClick={() => setDesktopSidebarOpen(true)}
|
||||
>
|
||||
<SidebarLeft />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -2,57 +2,65 @@
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { MainNavigationDropdown } from "./NavigationDropdown"
|
||||
import { MainNavBreadcrumbs } from "./Breadcrumb"
|
||||
import {
|
||||
BorderedIcon,
|
||||
Button,
|
||||
LinkButton,
|
||||
SearchModalOpener,
|
||||
useMainNav,
|
||||
useSidebar,
|
||||
} from "../.."
|
||||
import { MainNavColorMode } from "./ColorMode"
|
||||
import { MainNavDivider } from "./Divider"
|
||||
import { MainNavSidebarOpener } from "./SidebarOpener"
|
||||
import { MainNavHelpButton } from "./HelpButton"
|
||||
import { SidebarLeftIcon } from "../Icons/SidebarLeft"
|
||||
import { MainNavEditDate } from "./EditDate"
|
||||
import { MainNavItems } from "./Items"
|
||||
import { MedusaIcon } from "../Icons/MedusaLogo"
|
||||
import { MainNavDesktopMenu } from "./DesktopMenu"
|
||||
import { SidebarLeftIcon } from "../Icons/SidebarLeft"
|
||||
import { MainNavMobileMenu } from "./MobileMenu"
|
||||
|
||||
export const MainNav = () => {
|
||||
const { reportIssueLink, editDate } = useMainNav()
|
||||
const { setMobileSidebarOpen } = useSidebar()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"hidden sm:flex justify-between items-center",
|
||||
"px-docs_1 py-docs_0.75 w-full z-20",
|
||||
"flex justify-between items-center",
|
||||
"px-docs_1 w-full z-20",
|
||||
"sticky top-0 bg-medusa-bg-base"
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-docs_0.25">
|
||||
<Button
|
||||
className="lg:hidden"
|
||||
variant="transparent-clear"
|
||||
onClick={() => setMobileSidebarOpen(true)}
|
||||
>
|
||||
<SidebarLeftIcon />
|
||||
</Button>
|
||||
<MainNavSidebarOpener />
|
||||
<MainNavigationDropdown />
|
||||
<MainNavBreadcrumbs />
|
||||
<div className="flex items-center gap-docs_1">
|
||||
<div className="flex items-center gap-[10px]">
|
||||
<Button
|
||||
className="lg:hidden my-docs_0.75 !p-[6.5px]"
|
||||
variant="transparent-clear"
|
||||
onClick={() => setMobileSidebarOpen(true)}
|
||||
>
|
||||
<SidebarLeftIcon />
|
||||
</Button>
|
||||
<BorderedIcon
|
||||
IconComponent={MedusaIcon}
|
||||
iconWrapperClassName="my-[14px]"
|
||||
/>
|
||||
</div>
|
||||
<MainNavItems />
|
||||
</div>
|
||||
<div className="flex items-center gap-docs_0.75">
|
||||
<div className="flex items-center gap-[6px] text-medusa-fg-muted">
|
||||
<div className="flex items-center gap-docs_0.75 my-docs_0.75">
|
||||
<div className="lg:flex items-center gap-docs_0.5 text-medusa-fg-subtle hidden">
|
||||
{editDate && <MainNavEditDate date={editDate} />}
|
||||
<LinkButton href={reportIssueLink} variant="muted" target="_blank">
|
||||
<LinkButton
|
||||
href={reportIssueLink}
|
||||
variant="subtle"
|
||||
target="_blank"
|
||||
className="text-compact-small-plus"
|
||||
>
|
||||
Report Issue
|
||||
</LinkButton>
|
||||
</div>
|
||||
<MainNavDivider />
|
||||
<div className="flex items-center gap-docs_0.25">
|
||||
<MainNavHelpButton />
|
||||
<MainNavColorMode />
|
||||
<SearchModalOpener />
|
||||
<MainNavDesktopMenu />
|
||||
<MainNavMobileMenu />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,13 +2,14 @@
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { MenuItemAction } from "types"
|
||||
import { MenuItem, MenuItemAction } from "types"
|
||||
|
||||
export type MenuActionProps = {
|
||||
item: MenuItemAction
|
||||
onClick?: (item: MenuItem) => void
|
||||
}
|
||||
|
||||
export const MenuAction = ({ item }: MenuActionProps) => {
|
||||
export const MenuAction = ({ item, onClick }: MenuActionProps) => {
|
||||
return (
|
||||
<div className="px-docs_0.25">
|
||||
<span
|
||||
@@ -19,7 +20,10 @@ export const MenuAction = ({ item }: MenuActionProps) => {
|
||||
"text-medusa-fg-base cursor-pointer"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={item.action}
|
||||
onClick={() => {
|
||||
item.action()
|
||||
onClick?.(item)
|
||||
}}
|
||||
>
|
||||
<span className="text-medusa-fg-subtle mt-[2.5px] block">
|
||||
{item.icon}
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import React from "react"
|
||||
import { MenuItemLink } from "types"
|
||||
import { MenuItem as MenuItemType, MenuItemLink } from "types"
|
||||
|
||||
export type MenuItemProps = {
|
||||
item: MenuItemLink
|
||||
onClick?: (item: MenuItemType) => void
|
||||
}
|
||||
|
||||
export const MenuItem = ({ item }: MenuItemProps) => {
|
||||
export const MenuItem = ({ item, onClick }: MenuItemProps) => {
|
||||
return (
|
||||
<div className="px-docs_0.25">
|
||||
<Link
|
||||
@@ -20,10 +21,13 @@ export const MenuItem = ({ item }: MenuItemProps) => {
|
||||
"text-medusa-fg-base"
|
||||
)}
|
||||
href={item.link}
|
||||
onClick={() => onClick?.(item)}
|
||||
>
|
||||
<span className="text-medusa-fg-subtle mt-[2.5px] block">
|
||||
{item.icon}
|
||||
</span>
|
||||
{item.icon && (
|
||||
<span className="text-medusa-fg-subtle mt-[2.5px] block">
|
||||
{item.icon}
|
||||
</span>
|
||||
)}
|
||||
<span className="text-compact-small">{item.title}</span>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -8,9 +8,10 @@ import { MenuAction } from "./Action"
|
||||
export type MenuProps = {
|
||||
items: MenuItemType[]
|
||||
className?: string
|
||||
itemsOnClick?: (item: MenuItemType) => void
|
||||
}
|
||||
|
||||
export const Menu = ({ items, className }: MenuProps) => {
|
||||
export const Menu = ({ items, className, itemsOnClick }: MenuProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
@@ -21,9 +22,14 @@ export const Menu = ({ items, className }: MenuProps) => {
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<React.Fragment key={index}>
|
||||
{item.type === "link" && <MenuItem item={item} />}
|
||||
{item.type === "action" && <MenuAction item={item} />}
|
||||
{item.type === "link" && (
|
||||
<MenuItem item={item} onClick={itemsOnClick} />
|
||||
)}
|
||||
{item.type === "action" && (
|
||||
<MenuAction item={item} onClick={itemsOnClick} />
|
||||
)}
|
||||
{item.type === "divider" && <MenuDivider />}
|
||||
{item.type === "custom" && item.content}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { SidebarLeftIcon } from "../Icons/SidebarLeft"
|
||||
import { Button, SearchModalOpener, useSidebar } from "../.."
|
||||
import { MainNavigationDropdown } from "../MainNav/NavigationDropdown"
|
||||
|
||||
export const MobileNavigation = () => {
|
||||
const { setMobileSidebarOpen } = useSidebar()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"sm:hidden bg-medusa-bg-base",
|
||||
"sticky top-0 w-full z-40 h-min",
|
||||
"px-docs_0.75 py-docs_0.5",
|
||||
"flex justify-between items-center",
|
||||
"border-b border-medusa-border-base"
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
onClick={() => setMobileSidebarOpen(true)}
|
||||
>
|
||||
<SidebarLeftIcon />
|
||||
</Button>
|
||||
<MainNavigationDropdown />
|
||||
<SearchModalOpener />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import React, { MouseEvent, useMemo } from "react"
|
||||
import clsx from "clsx"
|
||||
import { useMobile, useSearch } from "@/providers"
|
||||
import { Button, Tooltip } from "@/components"
|
||||
import React, { MouseEvent } from "react"
|
||||
import { useSearch } from "@/providers"
|
||||
import { Button } from "@/components"
|
||||
import { MagnifyingGlass } from "@medusajs/icons"
|
||||
import { useKeyboardShortcut } from "@/hooks"
|
||||
|
||||
@@ -14,15 +13,8 @@ export type SearchModalOpenerProps = {
|
||||
|
||||
export const SearchModalOpener = ({
|
||||
isLoading = false,
|
||||
className,
|
||||
}: SearchModalOpenerProps) => {
|
||||
const { isMobile } = useMobile()
|
||||
const { setIsOpen } = useSearch()
|
||||
const isApple = useMemo(() => {
|
||||
return typeof navigator !== "undefined"
|
||||
? navigator.userAgent.toLowerCase().indexOf("mac") !== 0
|
||||
: true
|
||||
}, [])
|
||||
useKeyboardShortcut({
|
||||
shortcutKeys: ["k"],
|
||||
action: () => setIsOpen((prev) => !prev),
|
||||
@@ -46,29 +38,12 @@ export const SearchModalOpener = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isMobile && (
|
||||
<Button variant="transparent" onClick={handleOpen}>
|
||||
<MagnifyingGlass className="text-medusa-fg-muted" />
|
||||
</Button>
|
||||
)}
|
||||
{!isMobile && (
|
||||
<Tooltip place="bottom" tooltipChildren="Ask or search">
|
||||
<Button
|
||||
className={clsx(
|
||||
"relative hover:cursor-pointer group",
|
||||
"flex gap-[6px] !py-docs_0.25 !px-docs_0.5",
|
||||
"justify-between items-center text-medusa-fg-muted",
|
||||
className
|
||||
)}
|
||||
variant="transparent-clear"
|
||||
onClick={handleOpen}
|
||||
>
|
||||
<MagnifyingGlass />
|
||||
<span>{isApple ? "⌘" : "Ctrl"}K</span>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</>
|
||||
<Button
|
||||
variant="transparent"
|
||||
onClick={handleOpen}
|
||||
className="hidden sm:flex !p-[6.5px]"
|
||||
>
|
||||
<MagnifyingGlass className="text-medusa-fg-subtle" />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import React from "react"
|
||||
import { SidebarChild } from "../Child"
|
||||
import { InteractiveSidebarItem } from "types"
|
||||
import { SidebarTopMobileClose } from "./MobileClose"
|
||||
import { SidebarTopMedusaMenu } from "./MedusaMenu"
|
||||
import { DottedSeparator } from "../../.."
|
||||
|
||||
export type SidebarTopProps = {
|
||||
@@ -17,14 +16,12 @@ export const SidebarTop = React.forwardRef<HTMLDivElement, SidebarTopProps>(
|
||||
<div className="pt-docs_0.25">
|
||||
<SidebarTopMobileClose />
|
||||
<div ref={ref}>
|
||||
<SidebarTopMedusaMenu />
|
||||
{parentItem && (
|
||||
<>
|
||||
<DottedSeparator />
|
||||
<SidebarChild item={parentItem} />
|
||||
<DottedSeparator wrapperClassName="!my-0" />
|
||||
</>
|
||||
)}
|
||||
<DottedSeparator wrapperClassName="!my-0" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -118,8 +118,8 @@ export const Sidebar = ({
|
||||
}}
|
||||
id="sidebar"
|
||||
>
|
||||
{/* MOBILE SIDEBAR */}
|
||||
<div className={clsx("lg:hidden")}>
|
||||
{/* MOBILE SIDEBAR - keeping this in case we need it in the future */}
|
||||
{/* <div className={clsx("lg:hidden")}>
|
||||
{!sidebarItems.mobile.length && !staticSidebarItems && (
|
||||
<Loading className="px-0" />
|
||||
)}
|
||||
@@ -131,8 +131,8 @@ export const Sidebar = ({
|
||||
hasNextItems={index !== sidebarItems.default.length - 1}
|
||||
/>
|
||||
))}
|
||||
<DottedSeparator />
|
||||
</div>
|
||||
{sidebarItems.mobile.length > 0 && <DottedSeparator />}
|
||||
</div> */}
|
||||
{/* DESKTOP SIDEBAR */}
|
||||
<div className="mt-docs_0.75 lg:mt-0">
|
||||
{!sidebarItems.default.length && !staticSidebarItems && (
|
||||
|
||||
@@ -1,195 +1,118 @@
|
||||
import React from "react"
|
||||
import { Badge } from "@/components"
|
||||
import { OptionType } from "@/hooks"
|
||||
import { NavigationDropdownItem, SidebarItem } from "types"
|
||||
import { NavigationDropdownDocIcon } from "./components/Icons/NavigationDropdown/Doc"
|
||||
import { NavigationDropdownStoreIcon } from "./components/Icons/NavigationDropdown/Store"
|
||||
import { NavigationDropdownAdminIcon } from "./components/Icons/NavigationDropdown/Admin"
|
||||
import { NavigationDropdownUiIcon } from "./components/Icons/NavigationDropdown/Ui"
|
||||
import { NavigationDropdownDocV1Icon } from "./components/Icons/NavigationDropdown/DocV1"
|
||||
import { NavigationDropdownUserIcon } from "./components/Icons/NavigationDropdown/User"
|
||||
import { NavigationDropdownResourcesIcon } from "./components/Icons/NavigationDropdown/Resources"
|
||||
import { NavigationDropdownModulesIcon } from "./components/Icons/NavigationDropdown/Modules"
|
||||
import { NavigationItem } from "types"
|
||||
|
||||
export const GITHUB_ISSUES_PREFIX = `https://github.com/medusajs/medusa/issues/new?assignees=&labels=type%3A+docs&template=docs.yml`
|
||||
export const GITHUB_UI_ISSUES_PREFIX = `https://github.com/medusajs/ui/issues/new?labels=documentation`
|
||||
|
||||
export const navDropdownItemsV2: NavigationDropdownItem[] = [
|
||||
export const navDropdownItems: NavigationItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
path: `/v2`,
|
||||
icon: NavigationDropdownDocIcon,
|
||||
title: "Documentation",
|
||||
title: "Get Started",
|
||||
project: "book",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/v2/resources/commerce-modules`,
|
||||
icon: NavigationDropdownModulesIcon,
|
||||
title: "Commerce Modules",
|
||||
type: "dropdown",
|
||||
title: "Product",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Commerce Modules",
|
||||
link: "/v2/resources/commerce-modules",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Architectural Modules",
|
||||
link: "/v2/resources/architectural-modules",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/v2/resources`,
|
||||
icon: NavigationDropdownResourcesIcon,
|
||||
title: "Development Resources",
|
||||
type: "dropdown",
|
||||
title: "Resources",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Guides",
|
||||
link: "/v2/resources",
|
||||
useAsFallback: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Recipes",
|
||||
link: "/v2/resources/recipes",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "UI Library",
|
||||
link: "/ui",
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Storefront Development",
|
||||
link: "/v2/resources/storefront-development",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/v2/api/store`,
|
||||
icon: NavigationDropdownStoreIcon,
|
||||
title: "Store API",
|
||||
type: "dropdown",
|
||||
title: "Tools & SDKs",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Medusa CLI",
|
||||
link: "/v2/resources/medusa-cli",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Next.js Starter",
|
||||
link: "/v2/resources/nextjs-starter",
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Integrations",
|
||||
link: "/v2/resources/integrations",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/v2/api/admin`,
|
||||
icon: NavigationDropdownAdminIcon,
|
||||
title: "Admin API",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/ui`,
|
||||
icon: NavigationDropdownUiIcon,
|
||||
title: "UI",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/`,
|
||||
icon: NavigationDropdownDocV1Icon,
|
||||
title: "Medusa v1",
|
||||
type: "dropdown",
|
||||
title: "Reference",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Admin API",
|
||||
link: "/v2/api/admin",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Store API",
|
||||
link: "/v2/api/store",
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Workflows",
|
||||
link: "/v2/resources/medusa-workflows-reference",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Data Model API",
|
||||
link: "/v2/resources/references/data-model",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
export const navDropdownItemsV1: NavigationDropdownItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
path: `/`,
|
||||
icon: NavigationDropdownDocV1Icon,
|
||||
title: "Documentation",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/user-guide`,
|
||||
icon: NavigationDropdownUserIcon,
|
||||
title: "User Guide",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/api/store`,
|
||||
icon: NavigationDropdownStoreIcon,
|
||||
title: "Store API",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/api/admin`,
|
||||
icon: NavigationDropdownAdminIcon,
|
||||
title: "Admin API",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/ui`,
|
||||
icon: NavigationDropdownUiIcon,
|
||||
title: "UI",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: `/v2`,
|
||||
icon: NavigationDropdownDocIcon,
|
||||
title: "Medusa v2",
|
||||
},
|
||||
]
|
||||
|
||||
export const mobileSidebarItemsV1: SidebarItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
title: "Docs",
|
||||
path: `/`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "User Guide",
|
||||
path: `/user-guide`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Store API",
|
||||
path: `/api/store`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Admin API",
|
||||
path: `/api/admin`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "UI",
|
||||
path: `/ui`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Learn Medusa V2",
|
||||
path: `/v2`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
additionalElms: <Badge variant="blue">v2</Badge>,
|
||||
},
|
||||
]
|
||||
|
||||
export const mobileSidebarItemsV2: SidebarItem[] = [
|
||||
{
|
||||
type: "link",
|
||||
title: "Docs",
|
||||
path: `/v2`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Learning Resources",
|
||||
path: `/v2/resources`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Store API",
|
||||
path: `/v2/api/store`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Admin API",
|
||||
path: `/v2/api/admin`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "UI",
|
||||
path: `/ui`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Medusa v1",
|
||||
path: `/`,
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
]
|
||||
|
||||
export const searchFiltersV2: OptionType[] = [
|
||||
export const searchFilters: OptionType[] = [
|
||||
{
|
||||
value: "guides",
|
||||
label: "Guides",
|
||||
@@ -206,36 +129,9 @@ export const searchFiltersV2: OptionType[] = [
|
||||
value: "store-v2",
|
||||
label: "Store API (v2)",
|
||||
},
|
||||
// TODO add more filters
|
||||
]
|
||||
|
||||
export const searchFiltersV1: OptionType[] = [
|
||||
{
|
||||
value: "admin",
|
||||
label: "Admin API",
|
||||
},
|
||||
{
|
||||
value: "store",
|
||||
label: "Store API",
|
||||
},
|
||||
{
|
||||
value: "docs",
|
||||
label: "Docs",
|
||||
},
|
||||
{
|
||||
value: "user-guide",
|
||||
label: "User Guide",
|
||||
},
|
||||
{
|
||||
value: "plugins",
|
||||
label: "Plugins",
|
||||
},
|
||||
{
|
||||
value: "reference",
|
||||
label: "References",
|
||||
},
|
||||
{
|
||||
value: "ui",
|
||||
label: "UI",
|
||||
label: "Medusa UI",
|
||||
},
|
||||
// TODO add more filters
|
||||
]
|
||||
|
||||
@@ -50,7 +50,8 @@ export const MainContentLayout = ({
|
||||
"flex-col items-center",
|
||||
"h-full w-full",
|
||||
"overflow-y-scroll overflow-x-hidden",
|
||||
"md:rounded-t-docs_DEFAULT shadow-elevation-card-rest",
|
||||
"md:rounded-t-docs_DEFAULT",
|
||||
"shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
|
||||
mainWrapperClasses
|
||||
)}
|
||||
id="main"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from "react"
|
||||
import clsx from "clsx"
|
||||
import { RootProviders, Sidebar, SidebarProps } from "@/components"
|
||||
import { MobileNavigation } from "../components/MobileNavigation"
|
||||
import { Toc } from "../components/Toc"
|
||||
import { MainContentLayout, MainContentLayoutProps } from "./main-content"
|
||||
|
||||
@@ -14,6 +13,7 @@ export type RootLayoutProps = {
|
||||
showPagination?: boolean
|
||||
feedbackComponent?: React.ReactNode
|
||||
editComponent?: React.ReactNode
|
||||
showBreadcrumbs?: boolean
|
||||
} & MainContentLayoutProps
|
||||
|
||||
export const RootLayout = ({
|
||||
@@ -38,7 +38,6 @@ export const RootLayout = ({
|
||||
>
|
||||
<RootProviders>
|
||||
<ProvidersComponent>
|
||||
<MobileNavigation />
|
||||
<Sidebar {...sidebarProps} />
|
||||
<div className={clsx("relative", "h-screen", "flex")}>
|
||||
<MainContentLayout {...mainProps} />
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from "react"
|
||||
import { RootLayout, RootLayoutProps } from "./root"
|
||||
import clsx from "clsx"
|
||||
import { Pagination } from ".."
|
||||
import { Breadcrumbs, Pagination } from ".."
|
||||
|
||||
export const TightLayout = ({
|
||||
children,
|
||||
showPagination,
|
||||
feedbackComponent,
|
||||
editComponent,
|
||||
showBreadcrumbs = true,
|
||||
...props
|
||||
}: RootLayoutProps) => {
|
||||
return (
|
||||
@@ -21,6 +22,7 @@ export const TightLayout = ({
|
||||
"px-docs_1 md:px-docs_4 lg:px-0"
|
||||
)}
|
||||
>
|
||||
{showBreadcrumbs && <Breadcrumbs />}
|
||||
{children}
|
||||
{feedbackComponent}
|
||||
{showPagination && <Pagination />}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React from "react"
|
||||
import { RootLayout, RootLayoutProps } from "./root"
|
||||
import clsx from "clsx"
|
||||
import { Pagination } from ".."
|
||||
import { Breadcrumbs, Pagination } from ".."
|
||||
|
||||
export const WideLayout = ({
|
||||
children,
|
||||
showPagination,
|
||||
feedbackComponent,
|
||||
editComponent,
|
||||
showBreadcrumbs = true,
|
||||
...props
|
||||
}: RootLayoutProps) => {
|
||||
return (
|
||||
@@ -22,6 +23,7 @@ export const WideLayout = ({
|
||||
"lg:max-w-lg-wide-content xl:max-w-xl-wide-content relative mt-4 w-full flex-1 lg:mt-7"
|
||||
)}
|
||||
>
|
||||
{showBreadcrumbs && <Breadcrumbs />}
|
||||
{children}
|
||||
{feedbackComponent}
|
||||
{showPagination && <Pagination />}
|
||||
|
||||
@@ -1,27 +1,24 @@
|
||||
"use client"
|
||||
|
||||
import { usePathname } from "next/navigation"
|
||||
import React, { createContext, useContext, useMemo } from "react"
|
||||
import {
|
||||
BreadcrumbOptions,
|
||||
NavigationDropdownItem,
|
||||
NavigationDropdownItemLink,
|
||||
} from "types"
|
||||
import { NavigationItem } from "types"
|
||||
import { useSiteConfig } from "../SiteConifg"
|
||||
|
||||
export type MainNavContext = {
|
||||
navItems: NavigationDropdownItem[]
|
||||
activeItem?: NavigationDropdownItemLink
|
||||
navItems: NavigationItem[]
|
||||
activeItemIndex?: number
|
||||
activeItem?: NavigationItem
|
||||
reportIssueLink: string
|
||||
editDate?: string
|
||||
breadcrumbOptions: BreadcrumbOptions
|
||||
}
|
||||
|
||||
const MainNavContext = createContext<MainNavContext | null>(null)
|
||||
|
||||
export type MainNavProviderProps = {
|
||||
navItems: NavigationDropdownItem[]
|
||||
navItems: NavigationItem[]
|
||||
reportIssueLink: string
|
||||
editDate?: string
|
||||
breadcrumbOptions?: BreadcrumbOptions
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
@@ -30,26 +27,72 @@ export const MainNavProvider = ({
|
||||
reportIssueLink,
|
||||
children,
|
||||
editDate,
|
||||
breadcrumbOptions = {
|
||||
showCategories: true,
|
||||
},
|
||||
}: MainNavProviderProps) => {
|
||||
const activeItem = useMemo(
|
||||
() =>
|
||||
navItems.find(
|
||||
(item) => item.type === "link" && item.isActive
|
||||
) as NavigationDropdownItemLink,
|
||||
[navItems]
|
||||
)
|
||||
const pathname = usePathname()
|
||||
const { config } = useSiteConfig()
|
||||
|
||||
const baseUrl = `${config.baseUrl}${config.basePath}`
|
||||
|
||||
const activeItemIndex = useMemo(() => {
|
||||
const currentUrl = `${baseUrl}${pathname}`.replace(/\/$/, "")
|
||||
|
||||
let fallbackIndex: number | undefined
|
||||
|
||||
const index = navItems.findIndex((item, index) => {
|
||||
if (item.type === "dropdown") {
|
||||
return item.children.some((childItem) => {
|
||||
if (childItem.type !== "link") {
|
||||
return
|
||||
}
|
||||
|
||||
const isItemActive = currentUrl.startsWith(childItem.link)
|
||||
|
||||
if (
|
||||
isItemActive &&
|
||||
childItem.useAsFallback &&
|
||||
fallbackIndex === undefined
|
||||
) {
|
||||
fallbackIndex = index
|
||||
return false
|
||||
}
|
||||
|
||||
return isItemActive
|
||||
})
|
||||
}
|
||||
|
||||
if (item.project && item.project !== config.project.key) {
|
||||
return false
|
||||
}
|
||||
|
||||
const isItemActive = currentUrl.startsWith(item.path)
|
||||
|
||||
if (isItemActive && item.useAsFallback && fallbackIndex === undefined) {
|
||||
fallbackIndex = index
|
||||
return false
|
||||
}
|
||||
|
||||
return isItemActive
|
||||
})
|
||||
|
||||
return index !== -1 ? index : fallbackIndex
|
||||
}, [navItems, pathname, baseUrl, config])
|
||||
|
||||
const activeItem = useMemo(() => {
|
||||
if (activeItemIndex === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
return navItems[activeItemIndex]
|
||||
}, [navItems, activeItemIndex])
|
||||
|
||||
return (
|
||||
<MainNavContext.Provider
|
||||
value={{
|
||||
navItems,
|
||||
activeItem,
|
||||
activeItemIndex,
|
||||
reportIssueLink,
|
||||
editDate,
|
||||
breadcrumbOptions,
|
||||
activeItem,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -26,6 +26,13 @@ export const SiteConfigProvider = ({
|
||||
default: [],
|
||||
mobile: [],
|
||||
},
|
||||
project: {
|
||||
title: "",
|
||||
key: "",
|
||||
},
|
||||
breadcrumbOptions: {
|
||||
showCategories: true,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { SidebarItem } from "types"
|
||||
import { mobileSidebarItemsV1, mobileSidebarItemsV2 } from ".."
|
||||
|
||||
type Options = {
|
||||
baseUrl: string
|
||||
version?: "v1" | "v2"
|
||||
}
|
||||
|
||||
export function getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version = "v1",
|
||||
}: Options): SidebarItem[] {
|
||||
const mobileItems =
|
||||
version === "v2" ? mobileSidebarItemsV2 : mobileSidebarItemsV1
|
||||
return mobileItems.map((item) => {
|
||||
if (item.type !== "link") {
|
||||
return item
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
path: `${baseUrl}${item.path}`,
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -1,27 +1,31 @@
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import { navDropdownItemsV1, navDropdownItemsV2 } from ".."
|
||||
import { NavigationItem } from "types"
|
||||
import { navDropdownItems } from ".."
|
||||
|
||||
type Options = {
|
||||
basePath: string
|
||||
activePath: string
|
||||
version?: "v1" | "v2"
|
||||
}
|
||||
|
||||
export function getNavDropdownItems({
|
||||
basePath,
|
||||
activePath,
|
||||
version = "v1",
|
||||
}: Options): NavigationDropdownItem[] {
|
||||
const items = version === "v2" ? navDropdownItemsV2 : navDropdownItemsV1
|
||||
return items.map((item) => {
|
||||
if (item.type === "divider") {
|
||||
return item
|
||||
export function getNavDropdownItems({ basePath }: Options): NavigationItem[] {
|
||||
return navDropdownItems.map((item) => {
|
||||
const newItem = {
|
||||
...item,
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
isActive: activePath === item.path,
|
||||
path: `${basePath}${item.path}`,
|
||||
if (newItem.type === "link") {
|
||||
newItem.path = `${basePath}${newItem.path}`
|
||||
} else {
|
||||
newItem.children = newItem.children.map((childItem) => {
|
||||
if (childItem.type !== "link") {
|
||||
return childItem
|
||||
}
|
||||
|
||||
return {
|
||||
...childItem,
|
||||
link: `${basePath}${childItem.link}`,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return newItem
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ export * from "./decode-str"
|
||||
export * from "./dom-utils"
|
||||
export * from "./format-report-link"
|
||||
export * from "./get-link-with-base-path"
|
||||
export * from "./get-mobile-sidebar-items"
|
||||
export * from "./get-navbar-items"
|
||||
export * from "./get-os-shortcut"
|
||||
export * from "./get-scrolled-top"
|
||||
|
||||
@@ -191,23 +191,23 @@ module.exports = {
|
||||
"elevation-card-rest":
|
||||
"0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), 0px 2px 4px 0px rgba(0, 0, 0, 0.04)",
|
||||
"elevation-card-rest-dark":
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 1px 2px 0px rgba(0, 0, 0, 0.32), 0px 2px 4px 0px rgba(0, 0, 0, 0.32)",
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px #27272A, 0px 1px 2px 0px rgba(0, 0, 0, 0.32), 0px 2px 4px 0px rgba(0, 0, 0, 0.32)",
|
||||
"elevation-card-hover":
|
||||
"0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), 0px 2px 8px 0px rgba(0, 0, 0, 0.1)",
|
||||
"0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 1px 2px -1px rgba(0, 0, 0, 0.08), 0px 2px 8px 0px rgba(0, 0, 0, 0.10)",
|
||||
"elevation-card-hover-dark":
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(39, 39, 42, 1), 0px 1px 4px 0px rgba(0, 0, 0, 0.48), 0px 2px 8px 0px rgba(0, 0, 0, 0.48)",
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px #27272A, 0px 1px 4px 0px rgba(0, 0, 0, 0.48), 0px 2px 8px 0px rgba(0, 0, 0, 0.48)",
|
||||
"elevation-tooltip":
|
||||
"0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 2px 4px 0px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px rgba(0, 0, 0, 0.08)",
|
||||
"elevation-tooltip-dark":
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 2px 4px 0px rgba(0, 0, 0, 0.32), 0px 4px 8px 0px rgba(0, 0, 0, 0.32)",
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.10), 0px 2px 4px 0px rgba(0, 0, 0, 0.32), 0px 4px 8px 0px rgba(0, 0, 0, 0.32)",
|
||||
"elevation-flyout":
|
||||
"0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 4px 8px 0px rgba(0, 0, 0, 0.08), 0px 8px 16px 0px rgba(0, 0, 0, 0.08)",
|
||||
"elevation-flyout-dark":
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32)",
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.10), 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32)",
|
||||
"elevation-modal":
|
||||
"0px 0px 0px 1px rgba(255, 255, 255, 1) inset, 0px 0px 0px 1.5px rgba(228, 228, 231, 0.6) inset, 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 8px 16px 0px rgba(0, 0, 0, 0.08), 0px 16px 32px 0px rgba(0, 0, 0, 0.08)",
|
||||
"0px 0px 0px 1px #FFF inset, 0px 0px 0px 1.5px rgba(228, 228, 231, 0.60) inset, 0px 0px 0px 1px rgba(0, 0, 0, 0.08), 0px 8px 16px 0px rgba(0, 0, 0, 0.08), 0px 16px 32px 0px rgba(0, 0, 0, 0.08)",
|
||||
"elevation-modal-dark":
|
||||
"0px 0px 0px 1px rgba(24, 24, 27, 1) inset, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.06) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32)",
|
||||
"0px 0px 0px 1px #18181B inset, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.06) inset, 0px -1px 0px 0px rgba(255, 255, 255, 0.04), 0px 0px 0px 1px rgba(255, 255, 255, 0.10), 0px 4px 8px 0px rgba(0, 0, 0, 0.32), 0px 8px 16px 0px rgba(0, 0, 0, 0.32)",
|
||||
"button-neutral":
|
||||
"0px 1px 2px 0px rgba(0, 0, 0, 0.12), 0px 0px 0px 1px rgba(0, 0, 0, 0.08)",
|
||||
"button-neutral-dark":
|
||||
@@ -234,7 +234,7 @@ module.exports = {
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(255, 255, 255, 0.12), 0px 0px 0px 1px rgba(82, 82, 91, 1), 0px 0px 0px 2px rgba(24, 24, 27, 1), 0px 0px 0px 4px rgba(96, 165, 250, 0.8)",
|
||||
|
||||
"elevation-code-block":
|
||||
"0px 0px 0px 1px #18181B, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.20)",
|
||||
"0px 0px 0px 1px #18181B inset, 0px 0px 0px 1.5px rgba(255, 255, 255, 0.20) inset",
|
||||
"elevation-code-block-dark":
|
||||
"0px -1px 0px 0px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px rgba(255, 255, 255, 0.06), 0px 0px 0px 1px #27272A, 0px 1px 2px 0px rgba(0, 0, 0, 0.32), 0px 2px 4px 0px rgba(0, 0, 0, 0.32)",
|
||||
active: "0px 0px 0px 3px #E1F0FF",
|
||||
@@ -326,7 +326,7 @@ module.exports = {
|
||||
h1: [
|
||||
"24px",
|
||||
{
|
||||
lineHeight: "36px",
|
||||
lineHeight: "125%",
|
||||
fontWeight: "500",
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { SidebarSectionItems } from "./sidebar.js"
|
||||
|
||||
export type BreadcrumbOptions = {
|
||||
showCategories?: boolean
|
||||
}
|
||||
|
||||
export declare type DocsConfig = {
|
||||
titleSuffix?: string
|
||||
baseUrl: string
|
||||
@@ -7,4 +11,9 @@ export declare type DocsConfig = {
|
||||
sidebar: SidebarSectionItems
|
||||
filesBasePath?: string
|
||||
useNextLinks?: boolean
|
||||
project: {
|
||||
title: string
|
||||
key: string
|
||||
}
|
||||
breadcrumbOptions?: BreadcrumbOptions
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ export * from "./api-testing.js"
|
||||
export * from "./config.js"
|
||||
export * from "./general.js"
|
||||
export * from "./menu.js"
|
||||
export * from "./navigation.js"
|
||||
export * from "./navigation-dropdown.js"
|
||||
export * from "./sidebar.js"
|
||||
export * from "./toc.js"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export type MenuItemLink = {
|
||||
type: "link"
|
||||
icon: React.ReactNode
|
||||
icon?: React.ReactNode
|
||||
title: string
|
||||
link: string
|
||||
}
|
||||
@@ -17,4 +17,13 @@ export type MenuItemAction = {
|
||||
action: () => void
|
||||
}
|
||||
|
||||
export type MenuItem = MenuItemLink | MenuItemDivider | MenuItemAction
|
||||
export type MenuItemCustom = {
|
||||
type: "custom"
|
||||
content: React.ReactNode
|
||||
}
|
||||
|
||||
export type MenuItem =
|
||||
| MenuItemLink
|
||||
| MenuItemDivider
|
||||
| MenuItemAction
|
||||
| MenuItemCustom
|
||||
|
||||
@@ -14,7 +14,3 @@ export type NavigationDropdownItem =
|
||||
| {
|
||||
type: "divider"
|
||||
}
|
||||
|
||||
export type BreadcrumbOptions = {
|
||||
showCategories?: boolean
|
||||
}
|
||||
|
||||
20
www/packages/types/src/navigation.ts
Normal file
20
www/packages/types/src/navigation.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { MenuItem } from "./menu.js"
|
||||
|
||||
export type NavigationItemDropdown = {
|
||||
type: "dropdown"
|
||||
title: string
|
||||
children: (MenuItem & {
|
||||
useAsFallback?: boolean
|
||||
})[]
|
||||
project?: string
|
||||
}
|
||||
|
||||
export type NavigationItemLink = {
|
||||
type: "link"
|
||||
path: string
|
||||
title: string
|
||||
project?: string
|
||||
useAsFallback?: boolean
|
||||
}
|
||||
|
||||
export type NavigationItem = NavigationItemLink | NavigationItemDropdown
|
||||
Reference in New Issue
Block a user