docs: added show/hide sidebar button (#4150)

* docs: added show/hide sidebar button

* added check for browser

* fix build error

* solve build errors
This commit is contained in:
Shahed Nasser
2023-05-22 19:44:50 +03:00
committed by GitHub
parent 0476f52519
commit 87444488b5
29 changed files with 589 additions and 188 deletions
+2 -2
View File
@@ -69,7 +69,7 @@ Medusa provides the essential building blocks that developers can put together t
label: 'Medusa Backend', label: 'Medusa Backend',
customProps: { customProps: {
icon: Icons['circle-stack-solid'], icon: Icons['circle-stack-solid'],
html: 'A Medusa Backend is any Node.js project with @medusajs/medusa installed. The core Medusa package orchestrates Medusa\'s Commerce Modules to expose a powerful and customizable REST API.', html: 'A Medusa Backend is any Node.js project with @medusajs/medusa installed. The core Medusa package orchestrates Medusa\'s Commerce Modules to expose powerful and customizable REST APIs.',
} }
}, },
{ {
@@ -78,7 +78,7 @@ Medusa provides the essential building blocks that developers can put together t
label: 'Admin Dashboard', label: 'Admin Dashboard',
customProps: { customProps: {
icon: Icons['computer-desktop-solid'], icon: Icons['computer-desktop-solid'],
description: 'An intuitive admin dashboard along with the Medusa backend and commerce modules. Merchants can use it to perform data management and processes such as manage orders, products, customers, and much more.' description: 'An admin dashboard used along with the Medusa backend and commerce modules. Merchants can use it to manage orders, products, customers, and much more.'
} }
}, },
]} /> ]} />
+38 -35
View File
@@ -22,7 +22,7 @@ This section gives an overview of the features available in Medusa. You can lear
Medusa provides the necessary features to build a customizable shopping experience for your customers. Medusa also offers features optimized for business operations to manage their orders effeciently. Medusa provides the necessary features to build a customizable shopping experience for your customers. Medusa also offers features optimized for business operations to manage their orders effeciently.
<LargeCardList> <LargeCardList colSize={6}>
<LargeCard <LargeCard
Icon={Icons['check-circle-solid']} Icon={Icons['check-circle-solid']}
title='Orders' title='Orders'
@@ -92,7 +92,7 @@ Medusa provides the necessary features to build a customizable shopping experien
Medusa's products configuration allows managing products of different types including products with options and gift cards. Medusa also includes advanced features related to pricing and discounts. Medusa's products configuration allows managing products of different types including products with options and gift cards. Medusa also includes advanced features related to pricing and discounts.
<LargeCardList> <LargeCardList colSize={6}>
<LargeCard <LargeCard
Icon={Icons['tag-solid']} Icon={Icons['tag-solid']}
title='Products' title='Products'
@@ -125,30 +125,32 @@ Medusa's products configuration allows managing products of different types incl
- Manage a custom gift card's balance amount. - Manage a custom gift card's balance amount.
</LargeCard>
<LargeCard
Icon={Icons['currency-dollar-solid']}
title='Price Lists and Discounts'
action={{
label: 'Learn more',
href: '/modules/price-lists/overview'
}}
>
- Create discounts and deals with advanced conditions and rules such as minimum cart quantity or specific products.
- Offer free shipping, fixed discount, or percentage discount.
- Override product prices using price lists and set special conditions such as specific customer groups.
- Import prices into a price list from a CSV file.
</LargeCard> </LargeCard>
</LargeCardList> </LargeCardList>
<LargeCard
Icon={Icons['currency-dollar-solid']}
title='Price Lists and Discounts'
action={{
label: 'Learn more',
href: '/modules/price-lists/overview'
}}
>
- Create discounts and deals with advanced conditions and rules such as minimum cart quantity or specific products.
- Offer free shipping, fixed discount, or percentage discount.
- Override product prices using price lists and set special conditions such as specific customer groups.
- Import prices into a price list from a CSV file.
</LargeCard>
### Ready Configurations for International Selling ### Ready Configurations for International Selling
Medusa's multi-region setup and sales channels allow businesses to sell internationally and sell across platforms. Medusa allows configuring regions differently to cater for different markets across the globe. Medusa's multi-region setup and sales channels allow businesses to sell internationally and sell across platforms. Medusa allows configuring regions differently to cater for different markets across the globe.
<LargeCardList> <LargeCardList colSize={6}>
<LargeCard <LargeCard
Icon={Icons['globe-europe-solid']} Icon={Icons['globe-europe-solid']}
title='Multi-Region' title='Multi-Region'
@@ -179,25 +181,26 @@ Medusa's multi-region setup and sales channels allow businesses to sell internat
- Enable tax-inclusive pricing for automatic tax-rate calculations during checkout. - Enable tax-inclusive pricing for automatic tax-rate calculations during checkout.
</LargeCard>
<LargeCard
Icon={Icons['channels-solid']}
title='Sales Channels'
action={{
label: 'Learn more',
href: '/modules/sales-channels/overview'
}}
>
- Create sales channels for your different platforms such as web, mobile, or marketplaces.
- Specify the availability of products for each sales channel.
- Associate orders with each sales channel for better handling and logistics.
- Associate API keys with sales channels for easier development.
</LargeCard> </LargeCard>
</LargeCardList> </LargeCardList>
<LargeCard
Icon={Icons['channels-solid']}
title='Sales Channels'
action={{
label: 'Learn more',
href: '/modules/sales-channels/overview'
}}
>
- Create sales channels for your different platforms such as web, mobile, or marketplaces.
- Specify the availability of products for each sales channel.
- Associate orders with each sales channel for better handling and logistics.
- Associate API keys with sales channels for easier development.
</LargeCard>
## Get Additional Help ## Get Additional Help
If you have any questions about Medusa, its features, and development with it, feel free to reach out to the core team and the community behind Medusa on [Discord](https://discord.gg/medusajs). If you have any questions about Medusa, its features, and development with it, feel free to reach out to the core team and the community behind Medusa on [Discord](https://discord.gg/medusajs).
+1
View File
@@ -141,6 +141,7 @@ const config = {
}, },
docs: { docs: {
sidebar: { sidebar: {
hideable: true,
autoCollapseCategories: true, autoCollapseCategories: true,
}, },
}, },
+8 -12
View File
@@ -15,6 +15,7 @@ type LargeCardProps = {
href: string href: string
} }
isSoon?: boolean isSoon?: boolean
className?: string
} & React.HTMLAttributes<HTMLDivElement> } & React.HTMLAttributes<HTMLDivElement>
const LargeCard: React.FC<LargeCardProps> = ({ const LargeCard: React.FC<LargeCardProps> = ({
@@ -23,26 +24,21 @@ const LargeCard: React.FC<LargeCardProps> = ({
title, title,
action: { href }, action: { href },
isSoon = false, isSoon = false,
className = "",
children, children,
}) => { }) => {
return ( return (
<article <article
className={clsx( className={clsx(
"tw-group tw-bg-docs-bg-surface dark:tw-bg-docs-bg-surface-dark", "tw-group tw-bg-docs-bg-surface dark:tw-bg-docs-bg-surface-dark",
"tw-border tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark tw-rounded", "tw-rounded",
"tw-pt-6 tw-pb-1 tw-px-1 tw-mb-2", "tw-p-1 !tw-pb-1.5 tw-shadow-card-rest dark:tw-shadow-card-rest-dark",
"tw-flex tw-flex-col tw-justify-between tw-relative", "tw-flex tw-flex-col tw-justify-between tw-relative",
"before:tw-content-[''] before:tw-absolute before:tw-left-0 before:tw-w-full before:tw-rounded before:tw-z-[1] before:tw-h-8 before:tw-top-0",
"before:tw-bg-large-card dark:before:tw-bg-large-card-dark before:tw-bg-docs-bg-surface dark:before:tw-bg-docs-bg-surface-dark",
"[&:nth-child(3n+1):before]:tw-bg-[2%_52%] [&:nth-child(3n+2):before]:tw-bg-[19%_16%] [&:nth-child(3n+3):before]:tw-bg-[17%_50%]", "[&:nth-child(3n+1):before]:tw-bg-[2%_52%] [&:nth-child(3n+2):before]:tw-bg-[19%_16%] [&:nth-child(3n+3):before]:tw-bg-[17%_50%]",
"after:tw-content-[''] after:tw-absolute after:tw-left-0 after:tw-w-full after:tw-rounded",
"after:tw-z-[2] after:tw-left-0 after:tw-top-4 after:tw-height-4 after:tw-bg-large-card-fade dark:after:tw-bg-large-card-fade-dark",
!isSoon && !isSoon &&
"hover:after:tw-bg-large-card-fade-hover dark:hover:after:tw-bg-large-card-fade-hover", "hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark hover:tw-shadow-card-hover dark:hover:tw-shadow-card-hover-dark",
!isSoon && "large-card",
"hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark", className
!isSoon &&
"hover:before:tw-bg-medusa-bg-subtle-hover dark:hover:before:tw-bg-medusa-bg-base-hover-dark"
)} )}
> >
<div className={clsx("tw-z-[3]")}> <div className={clsx("tw-z-[3]")}>
@@ -60,7 +56,7 @@ const LargeCard: React.FC<LargeCardProps> = ({
iconWrapperClassName="tw-p-[6px]" iconWrapperClassName="tw-p-[6px]"
/> />
)} )}
<div className="tw-mb-0.5"> <div className="tw-mb-[4px]">
<span <span
className={clsx( className={clsx(
isSoon && isSoon &&
@@ -12,7 +12,16 @@ const LargeCardList: React.FC<LargeCardListProps> = ({
children, children,
}) => { }) => {
return ( return (
<section className={clsx("cards-grid", `grid-${colSize}`, className)}> <section
className={clsx(
"cards-grid",
`grid-${colSize}`,
"tw-gap-1",
"[&+*:not(.large-card)]:tw-mt-2",
"[&+.large-card]:tw-mt-1",
className
)}
>
{children} {children}
</section> </section>
) )
@@ -6,27 +6,32 @@ import clsx from "clsx"
type NavbarActionsProps = { type NavbarActionsProps = {
items: NavbarAction[] items: NavbarAction[]
className?: string
} & React.HTMLAttributes<HTMLDivElement> } & React.HTMLAttributes<HTMLDivElement>
const NavbarActions: React.FC<NavbarActionsProps> = ({ items = [] }) => { const NavbarActions: React.FC<NavbarActionsProps> = ({
items = [],
className = "",
}) => {
return ( return (
<div className="lg:tw-block tw-hidden"> <div className={clsx("lg:tw-block tw-hidden", className)}>
{items.map((item, index) => { {items.map((item, index) => {
// eslint-disable-next-line no-case-declarations
const ItemIcon = item.icon ? Icon[item.icon] : null
switch (item.type) { switch (item.type) {
case "link": case "link":
// eslint-disable-next-line no-case-declarations
const ItemIcon = item.icon ? Icon[item.icon] : null
return ( return (
<Tooltip text={item.title} key={index}> <Tooltip
text={item.title}
html={item.html}
key={index}
tooltipClassName="!tw-text-label-x-small-plus"
>
<a <a
href={item.href} href={item.href}
title={item.title} title={item.title}
// className={`${ItemIcon ? "navbar-link-icon" : ""} ${
// item.className || ""
// }`}
className={clsx( className={clsx(
ItemIcon && ItemIcon && "navbar-action-icon-item",
"tw-bg-medusa-button-secondary dark:tw-bg-medusa-button-secondary-dark tw-border tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark tw-rounded tw-w-2 tw-h-2 tw-flex tw-justify-center tw-items-center hover:tw-bg-medusa-button-secondary-hover dark:hover:tw-bg-medusa-button-secondary-hover-dark",
item.className item.className
)} )}
> >
@@ -35,6 +40,26 @@ const NavbarActions: React.FC<NavbarActionsProps> = ({ items = [] }) => {
</a> </a>
</Tooltip> </Tooltip>
) )
case "button":
return (
<Tooltip
text={item.title}
html={item.html}
key={index}
tooltipClassName="!tw-text-label-x-small-plus"
>
<button
className={clsx(
ItemIcon && "navbar-action-icon-item",
item.className
)}
{...item.events}
>
{item.label}
{ItemIcon && <ItemIcon />}
</button>
</Tooltip>
)
default: default:
return <></> return <></>
} }
+5 -3
View File
@@ -5,15 +5,17 @@ import uuid from "react-uuid"
import "react-tooltip/dist/react-tooltip.css" import "react-tooltip/dist/react-tooltip.css"
type TooltipProps = { type TooltipProps = {
text: string text?: string
tooltipClassName?: string tooltipClassName?: string
html?: string
} & React.HTMLAttributes<HTMLSpanElement> & } & React.HTMLAttributes<HTMLSpanElement> &
ITooltip ITooltip
const Tooltip: React.FC<TooltipProps> = ({ const Tooltip: React.FC<TooltipProps> = ({
text, text = "",
tooltipClassName = "", tooltipClassName = "",
children, children,
html = "",
}) => { }) => {
const [elementId, setElementId] = useState(null) const [elementId, setElementId] = useState(null)
@@ -25,7 +27,7 @@ const Tooltip: React.FC<TooltipProps> = ({
return ( return (
<> <>
<span id={elementId} data-tooltip-content={text}> <span id={elementId} data-tooltip-content={text} data-tooltip-html={html}>
{children} {children}
</span> </span>
<ReactTooltip <ReactTooltip
+13
View File
@@ -0,0 +1,13 @@
import { createContext } from "react"
type SidebarContextType = {
hiddenSidebar: boolean
setHiddenSidebar: (value: boolean) => void
hiddenSidebarContainer: boolean
setHiddenSidebarContainer: (value: boolean) => void
floatingSidebar: boolean
setFloatingSidebar: (value: boolean) => void
onCollapse: () => void
}
export const SidebarContext = createContext<SidebarContextType | null>(null)
+2 -2
View File
@@ -170,7 +170,7 @@ details summary {
} }
.container { .container {
@apply !tw-pt-[38px] !tw-max-w-full; @apply !tw-pt-3 !tw-max-w-full;
} }
.pagination-nav { .pagination-nav {
@@ -234,7 +234,7 @@ html:not(.plugin-redoc) .navbar:not(.navbar-sidebar--show) {
} }
.navbar__brand { .navbar__brand {
@apply tw-mr-2; @apply tw-mr-1.5;
} }
.navbar__logo { .navbar__logo {
-2
View File
@@ -1,7 +1,5 @@
.theme-doc-sidebar-container { .theme-doc-sidebar-container {
--animate-duration: 0.2s; --animate-duration: 0.2s;
clip-path: inset(0);
} }
.sidebar-desktop nav { .sidebar-desktop nav {
+20 -4
View File
@@ -115,12 +115,28 @@
.btn-primary { .btn-primary {
@apply tw-inline-flex tw-flex-row tw-justify-center tw-items-center; @apply tw-inline-flex tw-flex-row tw-justify-center tw-items-center;
@apply tw-py-[6px] tw-px-[12px] tw-rounded tw-cursor-pointer; @apply tw-py-[6px] tw-px-[12px] tw-rounded tw-cursor-pointer;
@apply tw-bg-medusa-button-secondary dark:tw-bg-medusa-button-secondary-dark; @apply tw-bg-button-neutral dark:tw-bg-button-neutral-dark;
@apply hover:tw-bg-medusa-button-secondary-hover dark:hover:tw-bg-medusa-button-secondary-hover-dark hover:tw-no-underline; @apply hover:!tw-bg-no-image hover:tw-bg-medusa-button-neutral-hover dark:hover:tw-bg-medusa-button-neutral-hover-dark hover:tw-no-underline;
@apply tw-border tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark; @apply active:!tw-bg-no-image active:tw-bg-medusa-button-neutral-pressed dark:active:tw-bg-medusa-button-neutral-pressed;
@apply focus:tw-shadow-neutral-button-focused dark:focus:tw-shadow-neutral-button-focused-dark;
@apply disabled:!tw-bg-no-image disabled:tw-bg-medusa-button-disabled dark:disabled:tw-bg-medusa-button-disabled-dark;
@apply tw-border tw-border-solid tw-border-medusa-border-neutral-buttons dark:tw-border-medusa-border-neutral-buttons-dark;
@apply tw-text-label-small-plus tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark; @apply tw-text-label-small-plus tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark;
@apply hover:tw-text-medusa-text-base dark:hover:tw-text-medusa-text-base-dark; @apply hover:tw-text-medusa-text-base dark:hover:tw-text-medusa-text-base-dark;
@apply focus:tw-shadow-button-focused dark:focus:tw-shadow-button-focused-dark; }
.navbar-action-icon-item {
@apply tw-bg-button-neutral dark:tw-bg-button-neutral-dark hover:!tw-bg-no-image active:!tw-bg-no-image hover:tw-bg-medusa-button-neutral-hover dark:hover:tw-bg-medusa-button-neutral-hover-dark;
@apply active:tw-bg-medusa-button-neutral-pressed dark:active:tw-bg-medusa-button-neutral-pressed-dark;
@apply focus:tw-shadow-neutral-button-focused dark:focus:tw-shadow-neutral-button-focused-dark;
@apply tw-border tw-border-solid tw-border-medusa-border-neutral-buttons dark:tw-border-medusa-border-neutral-buttons-dark tw-rounded;
@apply tw-w-2 tw-h-2 tw-flex tw-justify-center tw-items-center tw-cursor-pointer;
}
}
@layer utilities {
.clip {
clip-path: inset(0);
} }
} }
+3 -3
View File
@@ -19,7 +19,7 @@ export default function AnnouncementBar(): JSX.Element | null {
<div <div
className={clsx( className={clsx(
"tw-relative tw-flex tw-items-center tw-h-auto tw-bg-medusa-bg-subtle dark:tw-bg-medusa-bg-base-dark tw-p-[12px]", "tw-relative tw-flex tw-items-center tw-h-auto tw-bg-medusa-bg-subtle dark:tw-bg-medusa-bg-base-dark tw-p-[12px]",
"tw-border tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark tw-rounded tw-mx-1.5 tw-mb-1", "tw-rounded tw-mx-1.5 tw-mb-1 tw-shadow-card-rest dark:tw-shadow-card-rest-dark",
"tw-transition-all tw-duration-200 tw-ease-ease", "tw-transition-all tw-duration-200 tw-ease-ease",
"hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark", "hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark",
"print:tw-hidden" "print:tw-hidden"
@@ -29,10 +29,10 @@ export default function AnnouncementBar(): JSX.Element | null {
<div <div
className={clsx( className={clsx(
"tw-p-[6px] tw-flex tw-justify-center tw-items-center", "tw-p-[6px] tw-flex tw-justify-center tw-items-center",
"tw-bg-announcement-bg tw-bg-cover tw-rounded-sm" "tw-rounded-sm tw-bg-medusa-bg-component dark:tw-bg-medusa-bg-component-dark"
)} )}
> >
<IconBell iconColorClassName="tw-fill-medusa-icon-on-color dark:tw-fill-medusa-icon-on-color-dark" /> <IconBell iconColorClassName="tw-fill-medusa-icon-subtle dark:tw-fill-medusa-icon-subtle-dark" />
</div> </div>
</Bordered> </Bordered>
<AnnouncementBarContent className={clsx("tw-flex-1")} /> <AnnouncementBarContent className={clsx("tw-flex-1")} />
+22 -59
View File
@@ -8,16 +8,17 @@ import {
import isInternalUrl from "@docusaurus/isInternalUrl" import isInternalUrl from "@docusaurus/isInternalUrl"
import { translate } from "@docusaurus/Translate" import { translate } from "@docusaurus/Translate"
import BorderedIcon from "@site/src/components/BorderedIcon" import BorderedIcon from "@site/src/components/BorderedIcon"
import Badge, { BadgeProps } from "@site/src/components/Badge" import Badge from "@site/src/components/Badge"
import Icons from "@site/src/theme/Icon" import Icons from "@site/src/theme/Icon"
import { import {
ModifiedPropSidebarItemCategory, ModifiedDocCard,
ModifiedPropSidebarItemLink, ModifiedDocCardItemCategory,
ModifiedDocCardItemLink,
ModifiedSidebarItem, ModifiedSidebarItem,
} from "@medusajs/docs" } from "@medusajs/docs"
type ModifiedProps = { type ModifiedProps = {
item: ModifiedSidebarItem item: ModifiedDocCard
} }
function CardContainer({ function CardContainer({
@@ -36,9 +37,9 @@ function CardContainer({
className={clsx( className={clsx(
"card", "card",
"tw-bg-medusa-bg-subtle dark:tw-bg-medusa-bg-base-dark", "tw-bg-medusa-bg-subtle dark:tw-bg-medusa-bg-base-dark",
"tw-rounded tw-border tw-border-solid tw-border-medusa-bg-subtle-hover dark:tw-border-medusa-bg-base-hover-dark", "tw-rounded tw-shadow-card-rest dark:tw-shadow-card-rest-dark",
"tw-shadow-none tw-transition-all tw-duration-200 tw-ease-ease", "tw-transition-all tw-duration-200 tw-ease-ease",
"tw-flex tw-p-1 tw-h-full", "tw-flex tw-p-1 !tw-pb-1.5 tw-h-full",
className className
)} )}
> >
@@ -57,16 +58,7 @@ function CardLayout({
containerClassName, containerClassName,
isSoon = false, isSoon = false,
badge, badge,
}: { }: ModifiedDocCard): JSX.Element {
href: string
icon: ReactNode
title: string
description?: string
html?: string
containerClassName?: string
isSoon?: boolean
badge?: BadgeProps
}): JSX.Element {
const isHighlighted = containerClassName?.includes("card-highlighted") const isHighlighted = containerClassName?.includes("card-highlighted")
return ( return (
<CardContainer <CardContainer
@@ -77,7 +69,9 @@ function CardLayout({
"hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark", "hover:tw-bg-medusa-bg-subtle-hover dark:hover:tw-bg-medusa-bg-base-hover-dark",
isSoon && "tw-pointer-events-none", isSoon && "tw-pointer-events-none",
isHighlighted && isHighlighted &&
"md:before:tw-content-[''] md:before:tw-absolute md:before:tw-top-0 before:tw-right-0 md:before:tw-w-1/2 md:before:tw-h-full md:before:tw-bg-no-repeat md:before:tw-bg-cover md:before:tw-bg-card-highlighted dark:md:before:tw-bg-card-highlighted-dark" "md:before:tw-content-[''] md:before:tw-absolute md:before:tw-top-0 before:tw-right-0 md:before:tw-w-1/2 md:before:tw-h-full md:before:tw-bg-no-repeat md:before:tw-bg-cover md:before:tw-bg-card-highlighted dark:md:before:tw-bg-card-highlighted-dark",
!isSoon &&
"hover:tw-shadow-card-hover dark:hover:tw-shadow-card-hover-dark"
)} )}
> >
<div <div
@@ -91,7 +85,7 @@ function CardLayout({
<span <span
className={clsx( className={clsx(
"tw-text-label-regular-plus tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark", "tw-text-label-regular-plus tw-text-medusa-text-base dark:tw-text-medusa-text-base-dark",
"tw-mb-0.5 tw-block", "tw-mb-[4px] tw-block",
"tw-transition-all tw-duration-200 tw-ease-ease", "tw-transition-all tw-duration-200 tw-ease-ease",
isSoon && isSoon &&
"group-hover:tw-text-medusa-text-disabled dark:group-hover:tw-text-medusa-text-disabled-dark" "group-hover:tw-text-medusa-text-disabled dark:group-hover:tw-text-medusa-text-disabled-dark"
@@ -103,7 +97,7 @@ function CardLayout({
{description && ( {description && (
<p <p
className={clsx( className={clsx(
"tw-text-label-regular tw-text-medusa-text-subtle dark:tw-text-medusa-text-subtle-dark", "tw-text-body-regular tw-text-medusa-text-subtle dark:tw-text-medusa-text-subtle-dark",
"tw-transition-all tw-duration-200 tw-ease-ease", "tw-transition-all tw-duration-200 tw-ease-ease",
isSoon && isSoon &&
"group-hover:tw-text-medusa-text-disabled dark:group-hover:tw-text-medusa-text-disabled-dark", "group-hover:tw-text-medusa-text-disabled dark:group-hover:tw-text-medusa-text-disabled-dark",
@@ -141,14 +135,7 @@ function getCardIcon(item: ModifiedSidebarItem): JSX.Element {
light: item.customProps.themedImage.light, light: item.customProps.themedImage.light,
dark: item.customProps.themedImage.dark, dark: item.customProps.themedImage.dark,
}} }}
wrapperClassName={ iconWrapperClassName={clsx("tw-p-[6px]")}
clsx()
// "card-icon-wrapper",
}
iconWrapperClassName={clsx(
item.customProps?.className?.includes("card-highlighted") &&
"tw-p-[6px]"
)}
iconClassName={clsx("tw-h-[20px] tw-w-[20px]")} iconClassName={clsx("tw-h-[20px] tw-w-[20px]")}
/> />
) )
@@ -158,14 +145,7 @@ function getCardIcon(item: ModifiedSidebarItem): JSX.Element {
icon={{ icon={{
light: item.customProps.image, light: item.customProps.image,
}} }}
wrapperClassName={ iconWrapperClassName={clsx("tw-p-[6px]")}
clsx()
// "card-icon-wrapper",
}
iconWrapperClassName={clsx(
item.customProps?.className?.includes("card-highlighted") &&
"tw-p-[6px]"
)}
iconClassName={clsx("tw-h-[20px] tw-w-[20px]")} iconClassName={clsx("tw-h-[20px] tw-w-[20px]")}
/> />
) )
@@ -173,14 +153,7 @@ function getCardIcon(item: ModifiedSidebarItem): JSX.Element {
return ( return (
<BorderedIcon <BorderedIcon
IconComponent={item.customProps.icon} IconComponent={item.customProps.icon}
wrapperClassName={ iconWrapperClassName={clsx("tw-p-[6px]")}
clsx()
// "card-icon-wrapper",
}
iconWrapperClassName={clsx(
item.customProps?.className?.includes("card-highlighted") &&
"tw-p-[6px]"
)}
iconClassName={clsx("tw-h-[20px] tw-w-[20px]")} iconClassName={clsx("tw-h-[20px] tw-w-[20px]")}
/> />
) )
@@ -191,14 +164,7 @@ function getCardIcon(item: ModifiedSidebarItem): JSX.Element {
return ( return (
<BorderedIcon <BorderedIcon
IconComponent={Icons[item.customProps?.iconName]} IconComponent={Icons[item.customProps?.iconName]}
wrapperClassName={ iconWrapperClassName={clsx("tw-p-[6px]")}
clsx()
// "card-icon-wrapper",
}
iconWrapperClassName={clsx(
item.customProps?.className?.includes("card-highlighted") &&
"tw-p-[6px]"
)}
iconClassName={clsx("tw-h-[20px] tw-w-[20px]")} iconClassName={clsx("tw-h-[20px] tw-w-[20px]")}
/> />
) )
@@ -223,7 +189,7 @@ function getCardIcon(item: ModifiedSidebarItem): JSX.Element {
function CardCategory({ function CardCategory({
item, item,
}: { }: {
item: ModifiedPropSidebarItemCategory item: ModifiedDocCardItemCategory
}): JSX.Element | null { }): JSX.Element | null {
const href = findFirstCategoryLink(item) const href = findFirstCategoryLink(item)
const icon = getCardIcon(item) const icon = getCardIcon(item)
@@ -233,6 +199,7 @@ function CardCategory({
} }
return ( return (
<CardLayout <CardLayout
{...item}
href={href} href={href}
icon={icon} icon={icon}
title={item.label} title={item.label}
@@ -253,17 +220,13 @@ function CardCategory({
) )
} }
function CardLink({ function CardLink({ item }: { item: ModifiedDocCardItemLink }): JSX.Element {
item,
}: {
item: ModifiedPropSidebarItemLink
}): JSX.Element {
const icon = getCardIcon(item) const icon = getCardIcon(item)
const doc = useDocById(item.docId ?? undefined) const doc = useDocById(item.docId ?? undefined)
return ( return (
<CardLayout <CardLayout
href={item.href} {...item}
icon={icon} icon={icon}
title={item.label} title={item.label}
description={item.customProps?.description || doc?.description} description={item.customProps?.description || doc?.description}
+6 -3
View File
@@ -1,4 +1,4 @@
import React from "react" import React, { useContext } from "react"
import clsx from "clsx" import clsx from "clsx"
import { useWindowSize } from "@docusaurus/theme-common" import { useWindowSize } from "@docusaurus/theme-common"
import { useDoc } from "@docusaurus/theme-common/internal" import { useDoc } from "@docusaurus/theme-common/internal"
@@ -12,6 +12,7 @@ import DocItemContent from "@theme/DocItem/Content"
import DocBreadcrumbs from "@theme/DocBreadcrumbs" import DocBreadcrumbs from "@theme/DocBreadcrumbs"
import type { Props } from "@theme/DocItem/Layout" import type { Props } from "@theme/DocItem/Layout"
import Footer from "@theme/Footer" import Footer from "@theme/Footer"
import { SidebarContext } from "@site/src/context/sidebar"
/** /**
* Decide if the toc should be rendered, on mobile or desktop viewports * Decide if the toc should be rendered, on mobile or desktop viewports
@@ -39,13 +40,15 @@ function useDocTOC() {
export default function DocItemLayout({ children }: Props): JSX.Element { export default function DocItemLayout({ children }: Props): JSX.Element {
const docTOC = useDocTOC() const docTOC = useDocTOC()
const sidebarContext = useContext(SidebarContext)
return ( return (
<div className="row tw-m-0"> <div className="row tw-m-0">
<div <div
className={clsx( className={clsx(
"col", "col",
"tw-my-0 tw-mx-auto tw-max-w-main-content tw-w-full tw-ml-auto lg:tw-py-0 lg:tw-px-4 tw-py-0 tw-px-1", "tw-my-0 tw-mx-auto tw-max-w-main-content tw-w-full tw-ml-auto lg:tw-py-0 tw-py-0 tw-px-1",
!docTOC.hidden && "xxl:tw-w-10/12 tw-w-9/12" !docTOC.hidden && "tw-w-9/12",
!sidebarContext?.hiddenSidebarContainer && "!tw-max-w-[720px]"
)} )}
> >
<DocVersionBanner /> <DocVersionBanner />
@@ -1,24 +1,27 @@
import React from "react" import React, { useContext } from "react"
import clsx from "clsx" import clsx from "clsx"
import { useDocsSidebar } from "@docusaurus/theme-common/internal" import { useDocsSidebar } from "@docusaurus/theme-common/internal"
import type { Props } from "@theme/DocPage/Layout/Main" import type { Props } from "@theme/DocPage/Layout/Main"
import { SidebarContext } from "@site/src/context/sidebar"
export default function DocPageLayoutMain({ export default function DocPageLayoutMain({ children }: Props): JSX.Element {
hiddenSidebarContainer,
children,
}: Props): JSX.Element {
const sidebar = useDocsSidebar() const sidebar = useDocsSidebar()
const sidebarContext = useContext(SidebarContext)
return ( return (
<main <main
className={clsx( className={clsx(
"tw-flex tw-flex-col tw-w-full lg:tw-flex-grow lg:tw-max-w-[calc(100%-320px)]", "tw-flex tw-flex-col tw-w-full lg:tw-flex-grow",
(hiddenSidebarContainer || !sidebar) && "lg:tw-max-w-[calc(100%-30px)]" (sidebarContext?.hiddenSidebarContainer || !sidebar) &&
"lg:tw-max-w-[calc(100%-30px)]",
!sidebarContext?.hiddenSidebarContainer &&
"xxl:tw-max-w-[1119px] lg:tw-max-w-[calc(100%-321px)]"
)} )}
> >
<div <div
className={clsx( className={clsx(
"container padding-top--md tw-px-0", "container padding-top--md tw-px-0",
hiddenSidebarContainer && "lg:tw-max-w-main-content-hidden-sidebar" sidebarContext?.hiddenSidebarContainer &&
"lg:tw-max-w-main-content-hidden-sidebar"
)} )}
> >
{children} {children}
@@ -1,12 +1,12 @@
import React, { type ReactNode, useState, useCallback, useRef } from "react" import React, { type ReactNode, useRef, useContext } from "react"
import clsx from "clsx" import clsx from "clsx"
import { ThemeClassNames } from "@docusaurus/theme-common" import { ThemeClassNames } from "@docusaurus/theme-common"
import { useDocsSidebar } from "@docusaurus/theme-common/internal" import { useDocsSidebar } from "@docusaurus/theme-common/internal"
import { useLocation } from "@docusaurus/router" import { useLocation } from "@docusaurus/router"
import DocSidebar from "@theme/DocSidebar" import DocSidebar from "@theme/DocSidebar"
import ExpandButton from "@theme/DocPage/Layout/Sidebar/ExpandButton"
import type { Props } from "@theme/DocPage/Layout/Sidebar" import type { Props } from "@theme/DocPage/Layout/Sidebar"
import { SwitchTransition, CSSTransition } from "react-transition-group" import { SwitchTransition, CSSTransition } from "react-transition-group"
import { SidebarContext } from "@site/src/context/sidebar"
// Reset sidebar state when sidebar changes // Reset sidebar state when sidebar changes
// Use React key to unmount/remount the children // Use React key to unmount/remount the children
@@ -23,18 +23,9 @@ function ResetOnSidebarChange({ children }: { children: ReactNode }) {
export default function DocPageLayoutSidebar({ export default function DocPageLayoutSidebar({
sidebar, sidebar,
hiddenSidebarContainer, hiddenSidebarContainer,
setHiddenSidebarContainer,
}: Props): JSX.Element { }: Props): JSX.Element {
const { pathname } = useLocation() const { pathname } = useLocation()
const sidebarContext = useContext(SidebarContext)
const [hiddenSidebar, setHiddenSidebar] = useState(false)
const toggleSidebar = useCallback(() => {
if (hiddenSidebar) {
setHiddenSidebar(false)
}
setHiddenSidebarContainer((value) => !value)
}, [setHiddenSidebarContainer, hiddenSidebar])
const { name } = useDocsSidebar() const { name } = useDocsSidebar()
const sidebarRef = useRef(null) const sidebarRef = useRef(null)
@@ -42,8 +33,13 @@ export default function DocPageLayoutSidebar({
<aside <aside
className={clsx( className={clsx(
ThemeClassNames.docs.docSidebarContainer, ThemeClassNames.docs.docSidebarContainer,
"lg:tw-block lg:tw-w-sidebar lg:tw-will-change-[width] lg:tw-transition-[width] lg:tw-ease-ease tw-clip tw-hidden tw-duration-200", "lg:tw-block lg:tw-w-sidebar lg:tw-transition-[left] lg:tw-ease-ease lg:tw-duration-200 lg:tw-left-0 tw-hidden",
hiddenSidebarContainer && "lg:tw-w-sidebar-hidden lg:tw-cursor-pointer" !hiddenSidebarContainer && "clip",
hiddenSidebarContainer &&
"lg:tw-fixed lg:tw-left-[-100%] lg:tw-rounded lg:tw-border-0 lg:tw-border-medusa-border-strong lg:dark:tw-border-medusa-border-strong-dark",
hiddenSidebarContainer &&
sidebarContext?.floatingSidebar &&
"lg:!tw-left-0.5 lg:tw-top-[65px] lg:tw-z-20 lg:tw-bg-docs-bg lg:dark:tw-bg-docs-bg-dark lg:tw-shadow-flyout lg:dark:tw-shadow-flyout-dark"
)} )}
onTransitionEnd={(e) => { onTransitionEnd={(e) => {
if ( if (
@@ -55,7 +51,24 @@ export default function DocPageLayoutSidebar({
} }
if (hiddenSidebarContainer) { if (hiddenSidebarContainer) {
setHiddenSidebar(true) sidebarContext?.setHiddenSidebar(true)
}
}}
onMouseLeave={() => {
setTimeout(() => {
if (!document.querySelector(".sidebar-toggler:hover")) {
sidebarContext?.setFloatingSidebar(false)
}
}, 100)
}}
onMouseUp={(e) => {
const target = e.target as Element
console.log("here", target.classList)
if (
target.classList.contains("menu__list-item") ||
target.parentElement.classList.contains("menu__list-item")
) {
sidebarContext?.setFloatingSidebar(false)
} }
}} }}
> >
@@ -80,12 +93,9 @@ export default function DocPageLayoutSidebar({
<DocSidebar <DocSidebar
sidebar={sidebar} sidebar={sidebar}
path={pathname} path={pathname}
onCollapse={toggleSidebar} onCollapse={sidebarContext?.onCollapse}
isHidden={hiddenSidebar} isHidden={sidebarContext?.hiddenSidebar}
/> />
{hiddenSidebar && (
<ExpandButton toggleSidebar={toggleSidebar} />
)}
</div> </div>
</ResetOnSidebarChange> </ResetOnSidebarChange>
</div> </div>
@@ -0,0 +1,35 @@
import React, { useContext } from "react"
import { useDocsSidebar } from "@docusaurus/theme-common/internal"
import Layout from "@theme/Layout"
import BackToTopButton from "@theme/BackToTopButton"
import DocPageLayoutSidebar from "@theme/DocPage/Layout/Sidebar"
import DocPageLayoutMain from "@theme/DocPage/Layout/Main"
import type { Props } from "@theme/DocPage/Layout"
import { SidebarContext } from "@site/src/context/sidebar"
import clsx from "clsx"
export default function DocPageLayout({ children }: Props): JSX.Element {
const sidebar = useDocsSidebar()
const sidebarContext = useContext(SidebarContext)
return (
<Layout wrapperClassName={clsx("tw-flex tw-flex-[1_0_auto]")}>
<BackToTopButton />
<div className={clsx("tw-flex tw-w-full tw-flex-[1_0]")}>
{sidebar && (
<DocPageLayoutSidebar
sidebar={sidebar.items}
hiddenSidebarContainer={sidebarContext?.hiddenSidebarContainer}
setHiddenSidebarContainer={
sidebarContext?.setHiddenSidebarContainer
}
/>
)}
<DocPageLayoutMain
hiddenSidebarContainer={sidebarContext?.hiddenSidebarContainer}
>
{children}
</DocPageLayoutMain>
</div>
</Layout>
)
}
+62 -2
View File
@@ -1,9 +1,10 @@
import React from "react" import React, { useCallback, useEffect, useState } from "react"
import clsx from "clsx" import clsx from "clsx"
import { import {
HtmlClassNameProvider, HtmlClassNameProvider,
ThemeClassNames, ThemeClassNames,
PageMetadata, PageMetadata,
prefersReducedMotion,
} from "@docusaurus/theme-common" } from "@docusaurus/theme-common"
import { import {
docVersionSearchTag, docVersionSearchTag,
@@ -15,6 +16,7 @@ import DocPageLayout from "@theme/DocPage/Layout"
import NotFound from "@theme/NotFound" import NotFound from "@theme/NotFound"
import SearchMetadata from "@theme/SearchMetadata" import SearchMetadata from "@theme/SearchMetadata"
import type { Props } from "@theme/DocPage" import type { Props } from "@theme/DocPage"
import { SidebarContext } from "@site/src/context/sidebar"
function DocPageMetadata(props: Props): JSX.Element { function DocPageMetadata(props: Props): JSX.Element {
const { versionMetadata } = props const { versionMetadata } = props
@@ -43,6 +45,52 @@ export default function DocPage(props: Props): JSX.Element {
return <NotFound /> return <NotFound />
} }
const { docElement, sidebarName, sidebarItems } = currentDocRouteMetadata const { docElement, sidebarName, sidebarItems } = currentDocRouteMetadata
const [hiddenSidebar, setHiddenSidebar] = useState(false)
const [hiddenSidebarContainer, setHiddenSidebarContainer] = useState(false)
const [floatingSidebar, setFloatingSidebar] = useState(false)
const toggleSidebar = useCallback(() => {
if (hiddenSidebar) {
setHiddenSidebar(false)
}
// onTransitionEnd won't fire when sidebar animation is disabled
// fixes https://github.com/facebook/docusaurus/issues/8918
if (!hiddenSidebar && prefersReducedMotion()) {
setHiddenSidebar(true)
}
setHiddenSidebarContainer((value) => !value)
}, [setHiddenSidebarContainer, hiddenSidebar])
useEffect(() => {
function isEditingContent(event: KeyboardEvent) {
const element = event.target as HTMLElement
const tagName = element.tagName
return (
element.isContentEditable ||
tagName === "INPUT" ||
tagName === "SELECT" ||
tagName === "TEXTAREA"
)
}
function sidebarShortcut(e: KeyboardEvent) {
if (
(e.metaKey || e.ctrlKey) &&
e.key.toLowerCase() === "i" &&
!isEditingContent(e)
) {
e.preventDefault()
toggleSidebar()
}
}
window.addEventListener("keydown", sidebarShortcut)
return () => {
window.removeEventListener("keydown", sidebarShortcut)
}
})
return ( return (
<> <>
<DocPageMetadata {...props} /> <DocPageMetadata {...props} />
@@ -57,7 +105,19 @@ export default function DocPage(props: Props): JSX.Element {
> >
<DocsVersionProvider version={versionMetadata}> <DocsVersionProvider version={versionMetadata}>
<DocsSidebarProvider name={sidebarName} items={sidebarItems}> <DocsSidebarProvider name={sidebarName} items={sidebarItems}>
<DocPageLayout>{docElement}</DocPageLayout> <SidebarContext.Provider
value={{
hiddenSidebar,
setHiddenSidebar,
hiddenSidebarContainer,
setHiddenSidebarContainer,
floatingSidebar,
setFloatingSidebar,
onCollapse: toggleSidebar,
}}
>
<DocPageLayout>{docElement}</DocPageLayout>
</SidebarContext.Provider>
</DocsSidebarProvider> </DocsSidebarProvider>
</DocsVersionProvider> </DocsVersionProvider>
</HtmlClassNameProvider> </HtmlClassNameProvider>
@@ -1,19 +1,15 @@
import React, { useEffect, useRef } from "react" import React, { useEffect, useRef } from "react"
import clsx from "clsx" import clsx from "clsx"
import { useThemeConfig } from "@docusaurus/theme-common" import { useThemeConfig } from "@docusaurus/theme-common"
import CollapseButton from "@theme/DocSidebar/Desktop/CollapseButton"
import Content from "@theme/DocSidebar/Desktop/Content" import Content from "@theme/DocSidebar/Desktop/Content"
import type { Props } from "@theme/DocSidebar/Desktop" import type { Props } from "@theme/DocSidebar/Desktop"
import useIsBrowser from "@docusaurus/useIsBrowser" import useIsBrowser from "@docusaurus/useIsBrowser"
import { useLocation } from "@docusaurus/router" import { useLocation } from "@docusaurus/router"
import AnnouncementBar from "../../AnnouncementBar/index" import AnnouncementBar from "../../AnnouncementBar/index"
function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) { function DocSidebarDesktop({ path, sidebar, isHidden }: Props) {
const { const {
navbar: { hideOnScroll }, navbar: { hideOnScroll },
docs: {
sidebar: { hideable },
},
} = useThemeConfig() } = useThemeConfig()
const isBrowser = useIsBrowser() const isBrowser = useIsBrowser()
const sidebarRef = useRef(null) const sidebarRef = useRef(null)
@@ -82,9 +78,7 @@ function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) {
className={clsx( className={clsx(
"lg:tw-flex lg:tw-flex-col lg:tw-max-h-screen lg:tw-h-full lg:tw-sticky lg:tw-top-0 lg:tw-transition-opacity lg:tw-duration-[50ms] lg:tw-ease-ease lg:tw-pt-1.5", "lg:tw-flex lg:tw-flex-col lg:tw-max-h-screen lg:tw-h-full lg:tw-sticky lg:tw-top-0 lg:tw-transition-opacity lg:tw-duration-[50ms] lg:tw-ease-ease lg:tw-pt-1.5",
"sidebar-desktop", "sidebar-desktop",
hideOnScroll && "lg:tw-pt-0", hideOnScroll && "lg:tw-pt-0"
isHidden &&
"lg:tw-opacity-0 lg:tw-h-0 lg:tw-overflow-hidden lg:tw-invisible"
)} )}
ref={sidebarRef} ref={sidebarRef}
> >
@@ -97,7 +91,6 @@ function DocSidebarDesktop({ path, sidebar, onCollapse, isHidden }: Props) {
"!tw-mt-0 !tw-pt-0 !tw-px-1.5 !tw-pb-4" "!tw-mt-0 !tw-pt-0 !tw-px-1.5 !tw-pb-4"
)} )}
/> />
{hideable && <CollapseButton onClick={onCollapse} />}
</div> </div>
) )
} }
@@ -165,7 +165,7 @@ export default function DocSidebarItemCategory({
"[&_.sidebar-item-icon]:tw-w-[20px] [&_.sidebar-item-icon]:tw-h-[20px]", "[&_.sidebar-item-icon]:tw-w-[20px] [&_.sidebar-item-icon]:tw-h-[20px]",
!customProps?.sidebar_is_title && !customProps?.sidebar_is_title &&
!customProps?.sidebar_is_back_link && !customProps?.sidebar_is_back_link &&
"[&_.sidebar-item-icon]:tw-mr-1" "[&_.sidebar-item-icon]:tw-mr-[12px]"
)} )}
> >
<div <div
@@ -36,7 +36,7 @@ export default function DocSidebarItemHtml({
"[&_.sidebar-item-icon]:tw-w-[20px] [&_.sidebar-item-icon]:tw-h-[20px]", "[&_.sidebar-item-icon]:tw-w-[20px] [&_.sidebar-item-icon]:tw-h-[20px]",
!customProps?.sidebar_is_title && !customProps?.sidebar_is_title &&
!customProps?.sidebar_is_back_link && !customProps?.sidebar_is_back_link &&
"[&_.sidebar-item-icon]:tw-mr-1" "[&_.sidebar-item-icon]:tw-mr-[12px]"
)} )}
key={index} key={index}
> >
@@ -42,7 +42,7 @@ export default function DocSidebarItemLink({
"[&_.sidebar-item-icon]:tw-w-[20px] [&_.sidebar-item-icon]:tw-h-[20px]", "[&_.sidebar-item-icon]:tw-w-[20px] [&_.sidebar-item-icon]:tw-h-[20px]",
!customProps?.sidebar_is_title && !customProps?.sidebar_is_title &&
!customProps?.sidebar_is_back_link && !customProps?.sidebar_is_back_link &&
"[&_.sidebar-item-icon]:tw-mr-1" "[&_.sidebar-item-icon]:tw-mr-[12px]"
)} )}
key={label} key={label}
> >
@@ -0,0 +1,31 @@
import React from "react"
import { IconProps } from ".."
const IconBarsThree: React.FC<IconProps> = ({
iconColorClassName,
...props
}) => {
return (
<svg
width={props.width || 20}
height={props.height || 20}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M3.125 5.00006H16.875M3.125 10H16.875M3.125 15.0001H16.875"
className={
iconColorClassName ||
"tw-stroke-medusa-icon-secondary dark:tw-stroke-medusa-icon-secondary"
}
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
}
export default IconBarsThree
@@ -0,0 +1,30 @@
import React from "react"
import { IconProps } from ".."
const IconChevronDoubleLeftMiniSolid: React.FC<IconProps> = ({
iconColorClassName,
...props
}) => {
return (
<svg
width={props.width || 20}
height={props.height || 20}
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M15.79 14.77C15.6521 14.9131 15.4629 14.9957 15.2641 14.9994C15.0654 15.0032 14.8733 14.9278 14.73 14.79L10.23 10.54C10.1574 10.47 10.0997 10.3862 10.0602 10.2934C10.0208 10.2006 10.0005 10.1008 10.0005 10C10.0005 9.89919 10.0208 9.79941 10.0602 9.70663C10.0997 9.61385 10.1574 9.52997 10.23 9.46001L14.73 5.21001C14.8002 5.13826 14.8841 5.08133 14.9767 5.0426C15.0693 5.00386 15.1687 4.98411 15.2691 4.9845C15.3695 4.9849 15.4687 5.00544 15.561 5.04491C15.6533 5.08437 15.7367 5.14196 15.8064 5.21427C15.876 5.28657 15.9304 5.37211 15.9663 5.46582C16.0023 5.55953 16.0191 5.65951 16.0157 5.75982C16.0123 5.86014 15.9888 5.95875 15.9466 6.04983C15.9044 6.1409 15.8444 6.22257 15.77 6.29001L11.832 10L15.77 13.71C15.9131 13.848 15.9957 14.0371 15.9994 14.2359C16.0032 14.4346 15.9278 14.6267 15.79 14.77ZM9.79001 14.77C9.65205 14.9131 9.46291 14.9957 9.26415 14.9994C9.06539 15.0032 8.87327 14.9278 8.73001 14.79L4.23001 10.54C4.15742 10.47 4.09968 10.3862 4.06025 10.2934C4.02081 10.2006 4.00049 10.1008 4.00049 10C4.00049 9.89919 4.02081 9.79941 4.06025 9.70663C4.09968 9.61385 4.15742 9.52997 4.23001 9.46001L8.73001 5.21001C8.8002 5.13826 8.88408 5.08133 8.97668 5.0426C9.06928 5.00386 9.16871 4.98411 9.26908 4.9845C9.36945 4.9849 9.46873 5.00544 9.56102 5.04491C9.6533 5.08437 9.73673 5.14196 9.80635 5.21427C9.87598 5.28657 9.93038 5.37211 9.96634 5.46582C10.0023 5.55953 10.0191 5.65951 10.0157 5.75982C10.0123 5.86014 9.98881 5.95875 9.9466 6.04983C9.9044 6.1409 9.84435 6.22257 9.77001 6.29001L5.83201 10L9.77001 13.71C9.91314 13.848 9.99565 14.0371 9.9994 14.2359C10.0032 14.4346 9.92784 14.6267 9.79001 14.77Z"
className={
iconColorClassName ||
"tw-fill-medusa-icon-secondary dark:tw-fill-medusa-icon-secondary-dark"
}
/>
</svg>
)
}
export default IconChevronDoubleLeftMiniSolid
+4
View File
@@ -3,6 +3,7 @@ import IconAdjustments from "./Adjustments"
import IconAlert from "./Alert" import IconAlert from "./Alert"
import IconArrowDownTray from "./ArrowDownTray" import IconArrowDownTray from "./ArrowDownTray"
import IconBackArrow from "./BackArrow" import IconBackArrow from "./BackArrow"
import IconBarsThree from "./BarsThree"
import IconBell from "./Bell" import IconBell from "./Bell"
import IconBellAlertSolid from "./BellAlertSolid" import IconBellAlertSolid from "./BellAlertSolid"
import IconBolt from "./Bolt" import IconBolt from "./Bolt"
@@ -18,6 +19,7 @@ import IconCashSolid from "./CashSolid"
import IconChannels from "./Channels" import IconChannels from "./Channels"
import IconChannelsSolid from "./ChannelsSolid" import IconChannelsSolid from "./ChannelsSolid"
import IconCheckCircleSolid from "./CheckCircleSolid" import IconCheckCircleSolid from "./CheckCircleSolid"
import IconChevronDoubleLeftMiniSolid from "./ChevronDoubleLeftMiniSolid"
import IconCircleStack from "./CircleStack" import IconCircleStack from "./CircleStack"
import IconCircleStackSolid from "./CircleStackSolid" import IconCircleStackSolid from "./CircleStackSolid"
import IconClockSolidMini from "./ClockSolidMini" import IconClockSolidMini from "./ClockSolidMini"
@@ -95,6 +97,7 @@ export default {
alert: IconAlert, alert: IconAlert,
"arrow-down-tray": IconArrowDownTray, "arrow-down-tray": IconArrowDownTray,
"back-arrow": IconBackArrow, "back-arrow": IconBackArrow,
"bars-three": IconBarsThree,
bell: IconBell, bell: IconBell,
"bell-alert-solid": IconBellAlertSolid, "bell-alert-solid": IconBellAlertSolid,
bolt: IconBolt, bolt: IconBolt,
@@ -110,6 +113,7 @@ export default {
"channels-solid": IconChannelsSolid, "channels-solid": IconChannelsSolid,
channels: IconChannels, channels: IconChannels,
"check-circle-solid": IconCheckCircleSolid, "check-circle-solid": IconCheckCircleSolid,
"chevron-double-left-mini-solid": IconChevronDoubleLeftMiniSolid,
"circle-stack": IconCircleStack, "circle-stack": IconCircleStack,
"circle-stack-solid": IconCircleStackSolid, "circle-stack-solid": IconCircleStackSolid,
"clock-solid-mini": IconClockSolidMini, "clock-solid-mini": IconClockSolidMini,
@@ -0,0 +1,26 @@
import React from "react"
import { useColorMode, useThemeConfig } from "@docusaurus/theme-common"
import ColorModeToggle from "@theme/ColorModeToggle"
import type { Props } from "@theme/Navbar/ColorModeToggle"
export default function NavbarColorModeToggle({
className,
}: Props): JSX.Element | null {
const disabled = useThemeConfig().colorMode.disableSwitch
const { colorMode, setColorMode } = useColorMode()
if (disabled) {
return null
}
return (
<ColorModeToggle
className={className}
buttonClassName={
"hover:!tw-bg-medusa-button-neutral-hover dark:hover:!tw-bg-medusa-button-neutral-hover-dark"
}
value={colorMode}
onChange={setColorMode}
/>
)
}
+75 -5
View File
@@ -1,4 +1,4 @@
import React, { type ReactNode } from "react" import React, { useContext, type ReactNode } from "react"
import { useThemeConfig } from "@docusaurus/theme-common" import { useThemeConfig } from "@docusaurus/theme-common"
import { import {
splitNavbarItems, splitNavbarItems,
@@ -11,7 +11,9 @@ import NavbarLogo from "@theme/Navbar/Logo"
import NavbarActions from "@site/src/components/Navbar/Actions" import NavbarActions from "@site/src/components/Navbar/Actions"
import Tooltip from "@site/src/components/Tooltip" import Tooltip from "@site/src/components/Tooltip"
import { ThemeConfig } from "@medusajs/docs" import { ThemeConfig } from "@medusajs/docs"
import useIsBrowser from "@docusaurus/useIsBrowser"
import clsx from "clsx" import clsx from "clsx"
import { SidebarContext } from "@site/src/context/sidebar"
function useNavbarItems() { function useNavbarItems() {
// TODO temporary casting until ThemeConfig type is improved // TODO temporary casting until ThemeConfig type is improved
@@ -62,7 +64,18 @@ export default function NavbarContent(): JSX.Element {
const items = useNavbarItems() const items = useNavbarItems()
const [leftItems, rightItems] = splitNavbarItems(items) const [leftItems, rightItems] = splitNavbarItems(items)
const { navbarActions } = useThemeConfig() as ThemeConfig const {
navbarActions,
docs: {
sidebar: { hideable },
},
} = useThemeConfig() as ThemeConfig
const sidebarContext = useContext(SidebarContext)
const isBrowser = useIsBrowser()
const isApple = isBrowser
? navigator.userAgent.toLowerCase().indexOf("mac") !== 0
: true
return ( return (
<NavbarContentLayout <NavbarContentLayout
@@ -71,6 +84,65 @@ export default function NavbarContent(): JSX.Element {
<> <>
{!mobileSidebar.disabled && <NavbarMobileSidebarToggle />} {!mobileSidebar.disabled && <NavbarMobileSidebarToggle />}
<NavbarLogo /> <NavbarLogo />
{hideable && (
<NavbarActions
items={[
{
type: "button",
html: !sidebarContext?.hiddenSidebarContainer
? `<span class="tw-text-label-x-small-plus">Close sidebar <kbd class="${clsx(
"tw-bg-medusa-tag-neutral-bg dark:tw-bg-medusa-tag-neutral-bg-dark",
"tw-border tw-border-solid tw-rounded tw-border-medusa-tag-neutral-border dark:tw-border-medusa-tag-neutral-border-dark",
"tw-text-medusa-tag-neutral-text dark:tw-text-medusa-tag-neutral-text tw-font-base tw-text-label-x-small-plus",
"tw-inline-flex tw-w-[22px] tw-h-[22px] !tw-p-0 tw-justify-center tw-items-center tw-shadow-none tw-ml-0.5"
)}">${isApple ? "⌘" : "Ctrl"}</kbd>
<kbd class="${clsx(
"tw-bg-medusa-tag-neutral-bg dark:tw-bg-medusa-tag-neutral-bg-dark",
"tw-border tw-border-solid tw-rounded tw-border-medusa-tag-neutral-border dark:tw-border-medusa-tag-neutral-border-dark",
"tw-text-medusa-tag-neutral-text dark:tw-text-medusa-tag-neutral-text tw-font-base tw-text-label-x-small-plus",
"tw-inline-flex tw-w-[22px] tw-h-[22px] !tw-p-0 tw-justify-center tw-items-center tw-shadow-none"
)}">I</kbd></span>`
: `<span class="tw-text-label-x-small-plus">Lock sidebar open <kbd class="${clsx(
"tw-bg-medusa-tag-neutral-bg dark:tw-bg-medusa-tag-neutral-bg-dark",
"tw-border tw-border-solid tw-rounded tw-border-medusa-tag-neutral-border dark:tw-border-medusa-tag-neutral-border-dark",
"tw-text-medusa-tag-neutral-text dark:tw-text-medusa-tag-neutral-text tw-font-base tw-text-label-x-small-plus",
"tw-inline-flex tw-w-[22px] tw-h-[22px] !tw-p-0 tw-justify-center tw-items-center tw-shadow-none tw-ml-0.5"
)}">${isApple ? "⌘" : "Ctrl"}</kbd>
<kbd class="${clsx(
"tw-bg-medusa-tag-neutral-bg dark:tw-bg-medusa-tag-neutral-bg-dark",
"tw-border tw-border-solid tw-rounded tw-border-medusa-tag-neutral-border dark:tw-border-medusa-tag-neutral-border-dark",
"tw-text-medusa-tag-neutral-text dark:tw-text-medusa-tag-neutral-text tw-font-base tw-text-label-x-small-plus",
"tw-inline-flex tw-w-[22px] tw-h-[22px] !tw-p-0 tw-justify-center tw-items-center tw-shadow-none"
)}">I</kbd></span>`,
events: {
onClick: sidebarContext?.onCollapse,
onMouseEnter: () => {
if (!sidebarContext?.hiddenSidebarContainer) {
sidebarContext?.setFloatingSidebar(false)
} else {
sidebarContext?.setFloatingSidebar(true)
}
},
onMouseLeave: () => {
setTimeout(() => {
if (
!document.querySelector(
".theme-doc-sidebar-container:hover"
)
) {
sidebarContext?.setFloatingSidebar(false)
}
}, 100)
},
},
icon: !sidebarContext?.hiddenSidebarContainer
? "bars-three"
: "chevron-double-left-mini-solid",
},
]}
className="tw-mr-0.5 sidebar-toggler"
/>
)}
<NavbarItems items={leftItems} /> <NavbarItems items={leftItems} />
</> </>
} }
@@ -88,9 +160,7 @@ export default function NavbarContent(): JSX.Element {
<NavbarColorModeToggle <NavbarColorModeToggle
className={clsx( className={clsx(
"lg:tw-block tw-hidden", "lg:tw-block tw-hidden",
"tw-bg-medusa-button-secondary dark:tw-bg-medusa-button-secondary-dark", "navbar-action-icon-item !tw-w-2 !tw-h-2 tw-ml-1 tw-mr-[12px] [&>button]:!tw-rounded"
"tw-border tw-border-solid tw-border-medusa-border-base dark:tw-border-medusa-border-base-dark",
"tw-rounded !tw-w-2 !tw-h-2 tw-ml-1 tw-mr-[12px] [&>button]:!tw-rounded"
)} )}
/> />
</Tooltip> </Tooltip>
+48 -3
View File
@@ -30,6 +30,7 @@ declare module "@medusajs/docs" {
import { BadgeProps } from "../components/Badge/index" import { BadgeProps } from "../components/Badge/index"
import { IconProps } from "../theme/Icon/index" import { IconProps } from "../theme/Icon/index"
import { DocContextValue as DocusaurusDocContextValue } from "@docusaurus/theme-common/internal" import { DocContextValue as DocusaurusDocContextValue } from "@docusaurus/theme-common/internal"
import { ReactNode } from "react"
type ItemCustomProps = { type ItemCustomProps = {
customProps?: { customProps?: {
@@ -69,20 +70,64 @@ declare module "@medusajs/docs" {
| ModifiedPropSidebarItemLink | ModifiedPropSidebarItemLink
| ModifiedPropSidebarItemHtml | ModifiedPropSidebarItemHtml
export declare type ModifiedDocCardBase = {
type: string
href: string
icon: ReactNode | string
title: string
description?: string
html?: string
containerClassName?: string
isSoon?: boolean
badge?: BadgeProps
children?: React.ReactNode
}
export declare type ModifiedDocCardItemLink = {
type: "link"
} & ModifiedDocCardBase &
ModifiedPropSidebarItemLink
export declare type ModifiedDocCardItemCategory = {
type: "category"
} & ModifiedDocCardBase &
ModifiedPropSidebarItemCategory
export declare type ModifiedDocCard =
| ModifiedDocCardItemLink
| ModifiedDocCardItemCategory
export declare type SocialLink = { export declare type SocialLink = {
href: string href: string
type: string type: string
} }
export declare type NavbarAction = { export declare type NavbarActionBase = {
type: "link" type: string
href: string
title?: string title?: string
icon?: string icon?: string
className?: string className?: string
label?: string label?: string
html?: string
} }
export declare type NavbarActionLink = NavbarActionBase & {
type: "link"
href: string
}
export declare type NavbarActionButton = NavbarActionBase & {
type: "button"
events?: {
onClick?: (e: any) => any
onMouseEnter?: (e: any) => any
onMouseLeave?: (e: any) => any
onMouseOver?: (e: any) => any
}
}
export declare type NavbarAction = NavbarActionLink | NavbarActionButton
export declare type ThemeConfig = { export declare type ThemeConfig = {
reportCodeLinkPrefix?: string reportCodeLinkPrefix?: string
footerFeedback: { footerFeedback: {
+67 -2
View File
@@ -179,6 +179,10 @@ module.exports = {
DEFAULT: "#6E56CF", DEFAULT: "#6E56CF",
dark: "#6E56CF", dark: "#6E56CF",
}, },
"neutral-buttons": {
DEFAULT: "#11181C1A",
dark: "#FFFFFF1F",
},
}, },
text: { text: {
base: { base: {
@@ -255,6 +259,20 @@ module.exports = {
DEFAULT: "#30A46C", DEFAULT: "#30A46C",
dark: "#30A46C", dark: "#30A46C",
}, },
neutral: {
hover: {
DEFAULT: "#F8F9FA",
dark: "#2E2E32",
},
pressed: {
DEFAULT: "#F1F3F5",
dark: "#34343A",
},
},
disabled: {
DEFAULT: "#ECEEF0",
dark: "#28282C",
},
}, },
icon: { icon: {
primary: { primary: {
@@ -289,6 +307,10 @@ module.exports = {
DEFAULT: "#E5484D", DEFAULT: "#E5484D",
dark: "#E5484D", dark: "#E5484D",
}, },
subtle: {
DEFAULT: "#687076",
dark: "#7E7D86",
},
}, },
support: { support: {
error: { error: {
@@ -418,6 +440,28 @@ module.exports = {
dark: "#0D3868", dark: "#0D3868",
}, },
}, },
neutral: {
bg: {
DEFAULT: "#F1F3F5",
dark: "#28282C",
hover: {
DEFAULT: "#ECEEF0",
dark: "#2E2E32",
},
},
text: {
DEFAULT: "#687076",
dark: "#A09FA6",
},
icon: {
DEFAULT: "#889096",
dark: "#706F78",
},
border: {
DEFAULT: "#DFE3E6",
dark: "#3E3E44",
},
},
}, },
}, },
/* docs defaults */ /* docs defaults */
@@ -442,6 +486,22 @@ module.exports = {
"0px 0px 0px 2px #1C1C1F, 0px 0px 0px 4px #6E56CF", "0px 0px 0px 2px #1C1C1F, 0px 0px 0px 4px #6E56CF",
navbar: "0px 1px 0px 0px #E6E8EB", navbar: "0px 1px 0px 0px #E6E8EB",
"navbar-dark": "0px 1px 0px 0px #2E2E32", "navbar-dark": "0px 1px 0px 0px #2E2E32",
flyout:
"0px 0px 0px 1px rgba(17, 24, 28, 0.08), 0px 8px 16px rgba(17, 24, 28, 0.08)",
"flyout-dark":
"0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 8px 16px rgba(0, 0, 0, 0.32)",
"neutral-button-focused":
"0px 0px 0px 2px #FFFFFF, 0px 0px 0px 4px #6E56CF",
"neutral-button-focused-dark":
"0px 0px 0px 2px #1C1C1F, 0px 0px 0px 4px #6E56CF",
"card-rest":
"0px 0px 0px 1px rgba(17, 24, 28, 0.08), 0px 1px 2px -1px rgba(17, 24, 28, 0.08), 0px 2px 4px rgba(17, 24, 28, 0.04)",
"card-rest-dark":
"0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 1px 2px -1px rgba(255, 255, 255, 0.16), 0px 2px 4px rgba(0, 0, 0, 0.32)",
"card-hover":
"0px 0px 0px 1px rgba(17, 24, 28, 0.08), 0px 1px 2px -1px rgba(17, 24, 28, 0.08), 0px 2px 8px rgba(17, 24, 28, 0.1)",
"card-hover-dark":
"0px 0px 0px 1px rgba(255, 255, 255, 0.1), 0px 1px 2px -1px rgba(255, 255, 255, 0.16), 0px 2px 8px rgba(0, 0, 0, 0.32)",
}, },
borderRadius: { borderRadius: {
DEFAULT: "8px", DEFAULT: "8px",
@@ -454,6 +514,11 @@ module.exports = {
"primary-gradient": "primary-gradient":
"linear-gradient(90deg, rgba(146, 144, 254, 0) 0%, rgba(163, 219, 254, 0.4) 26.04%, #9290FE 53.65%, rgba(197, 145, 255, 0.4) 78.65%, rgba(201, 138, 255, 0) 100%)", "linear-gradient(90deg, rgba(146, 144, 254, 0) 0%, rgba(163, 219, 254, 0.4) 26.04%, #9290FE 53.65%, rgba(197, 145, 255, 0.4) 78.65%, rgba(201, 138, 255, 0) 100%)",
"code-fade": "linear-gradient(90deg, #1C1C1F00, #1C1C1F 24px)", "code-fade": "linear-gradient(90deg, #1C1C1F00, #1C1C1F 24px)",
"button-neutral":
"linear-gradient(180deg, #FFFFFF 30.1%, #F8F9FA 100%)",
"button-neutral-dark":
"linear-gradient(180deg, #2E2E32 0%, #28282C 32.67%)",
"no-image": "none",
}, },
screens: { screens: {
xs: "576px", xs: "576px",
@@ -465,8 +530,8 @@ module.exports = {
ease: "ease", ease: "ease",
}, },
width: { width: {
sidebar: "320px", sidebar: "321px",
"sidebar-hidden": "30px", "sidebar-hidden": "0px",
"main-content": "1140px", "main-content": "1140px",
"main-content-hidden-sidebar": "1440px", "main-content-hidden-sidebar": "1440px",
}, },