diff --git a/www/apps/docs/src/components/LearningPath/Steps/Actions/index.tsx b/www/apps/docs/src/components/LearningPath/Steps/Actions/index.tsx index 49f0fb2cdb..0460c5fde5 100644 --- a/www/apps/docs/src/components/LearningPath/Steps/Actions/index.tsx +++ b/www/apps/docs/src/components/LearningPath/Steps/Actions/index.tsx @@ -1,15 +1,18 @@ import React from "react" import { useLearningPath } from "../../../../providers/LearningPath" import { Button } from "docs-ui" +import { ArrowDownLeftMini, ArrowDownMini } from "@medusajs/icons" type LearningPathStepActionsType = { onFinish?: () => void onClose?: () => void + setCollapsed: React.Dispatch> } & React.AllHTMLAttributes const LearningPathStepActions: React.FC = ({ onFinish, onClose, + setCollapsed, }) => { const { hasNextStep, nextStep, endPath } = useLearningPath() @@ -22,18 +25,34 @@ const LearningPathStepActions: React.FC = ({ } return ( -
- - {hasNextStep() && ( - - )} - {!hasNextStep() && ( - - )} +
+
+ {hasNextStep() && ( + <> + + + + )} + {!hasNextStep() && ( + + )} +
) } diff --git a/www/apps/docs/src/components/LearningPath/Steps/index.tsx b/www/apps/docs/src/components/LearningPath/Steps/index.tsx index 812623e61e..60f45c1d3e 100644 --- a/www/apps/docs/src/components/LearningPath/Steps/index.tsx +++ b/www/apps/docs/src/components/LearningPath/Steps/index.tsx @@ -1,10 +1,12 @@ import { useLearningPath } from "@site/src/providers/LearningPath" -import React from "react" +import React, { useCallback, useEffect, useRef, useState } from "react" import LearningPathStepActions from "./Actions" import clsx from "clsx" import IconCircleDottedLine from "@site/src/theme/Icon/CircleDottedLine" import Link from "@docusaurus/Link" -import { CheckCircleSolid, CircleMiniSolid } from "@medusajs/icons" +import { CheckCircleSolid, CircleMiniSolid, ListBullet } from "@medusajs/icons" +import { Badge, Button } from "docs-ui" +import { CSSTransition, SwitchTransition } from "react-transition-group" type LearningPathStepsProps = { onFinish?: () => void @@ -13,66 +15,140 @@ type LearningPathStepsProps = { const LearningPathSteps: React.FC = ({ ...rest }) => { const { path, currentStep, goToStep } = useLearningPath() + const [collapsed, setCollapsed] = useState(false) + const stepsRef = useRef(null) + const buttonRef = useRef(null) + const nodeRef: React.RefObject = collapsed ? buttonRef : stepsRef + + const handleScroll = useCallback(() => { + if (window.scrollY > 100 && !collapsed) { + // automatically collapse steps + setCollapsed(true) + } else if ( + (window.scrollY === 0 || + window.scrollY + window.innerHeight >= document.body.scrollHeight) && + collapsed + ) { + // automatically open steps + setCollapsed(false) + } + }, [collapsed]) + + useEffect(() => { + window.addEventListener("scroll", handleScroll) + + return () => { + window.removeEventListener("scroll", handleScroll) + } + }, [handleScroll]) if (!path) { return <> } return ( - <> -
- {path.steps.map((step, index) => ( -
-
-
- {index === currentStep && ( - + { + nodeRef.current?.addEventListener("transitionend", done, false) + }} + classNames={{ + enter: "animate-maximize animate-fast", + exit: "animate-minimize animate-fast", + }} + > + <> + {!collapsed && ( +
+
+ {path.steps.map((step, index) => ( +
- )} - {index < currentStep && ( - - )} - {index > currentStep && ( - - )} + key={index} + > +
+
+ {index === currentStep && ( + + )} + {index < currentStep && ( + + )} + {index > currentStep && ( + + )} +
+ + {step.title} + +
+ {index === currentStep && ( +
+
+
+ {step.descriptionJSX ?? step.description} +
+
+ )} + { + e.preventDefault() + goToStep(index) + }} + /> +
+ ))}
- - {step.title} - +
- {index === currentStep && ( -
-
-
- {step.descriptionJSX ?? step.description} -
-
- )} - { - e.preventDefault() - goToStep(index) - }} - /> -
- ))} -
- - + )} + {collapsed && ( + + )} + + + ) } diff --git a/www/apps/docs/src/hooks/use-select.tsx b/www/apps/docs/src/hooks/use-select.tsx deleted file mode 100644 index d685d80db2..0000000000 --- a/www/apps/docs/src/hooks/use-select.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useCallback, useMemo } from "react" - -export type OptionType = { - value: string - label: string - index?: string - isAllOption?: boolean -} - -export type SelectOptions = { - value: string | string[] - multiple?: boolean - options: OptionType[] - setSelected?: (value: string | string[]) => void - addSelected?: (value: string) => void - removeSelected?: (value: string) => void - handleAddAll?: (isAllSelected: boolean) => void -} - -const useSelect = ({ - value, - options, - multiple = false, - setSelected, - addSelected, - removeSelected, - handleAddAll, -}: SelectOptions) => { - const isValueSelected = useCallback( - (val: string) => { - return ( - (typeof value === "string" && val === value) || - (Array.isArray(value) && value.includes(val)) - ) - }, - [value] - ) - - // checks if there are multiple selected values - const hasSelectedValues = useMemo(() => { - return multiple && Array.isArray(value) && value.length > 0 - }, [value, multiple]) - - // checks if there are any selected values, - // whether multiple or one - const hasSelectedValue = useMemo(() => { - return hasSelectedValues || (typeof value === "string" && value.length) - }, [hasSelectedValues, value]) - - const selectedValues: OptionType[] = useMemo(() => { - if (typeof value === "string") { - const selectedValue = options.find((option) => option.value === value) - return selectedValue ? [selectedValue] : [] - } else if (Array.isArray(value)) { - return options.filter((option) => value.includes(option.value)) - } - return [] - }, [options, value]) - - const isAllSelected = useMemo(() => { - return Array.isArray(value) && value.length === options.length - }, [options, value]) - - const handleChange = (selectedValue: string, wasSelected: boolean) => { - if (multiple) { - wasSelected - ? removeSelected?.(selectedValue) - : addSelected?.(selectedValue) - } else { - setSelected?.(selectedValue) - } - } - - const handleSelectAll = () => { - if (handleAddAll) { - handleAddAll(isAllSelected) - } else { - setSelected?.(options.map((option) => option.value)) - } - } - - return { - isValueSelected, - hasSelectedValue, - hasSelectedValues, - selectedValues, - isAllSelected, - handleChange, - handleSelectAll, - } -} - -export default useSelect diff --git a/www/apps/docs/src/providers/DocsProviders/index.tsx b/www/apps/docs/src/providers/DocsProviders/index.tsx index 34a263bb46..64ab048320 100644 --- a/www/apps/docs/src/providers/DocsProviders/index.tsx +++ b/www/apps/docs/src/providers/DocsProviders/index.tsx @@ -9,6 +9,7 @@ import { useThemeConfig } from "@docusaurus/theme-common" import { ThemeConfig } from "@medusajs/docs" import SearchProvider from "../Search" import LearningPathProvider from "../LearningPath" +import SkipToContent from "@theme/SkipToContent" type DocsProvidersProps = { children?: React.ReactNode @@ -25,7 +26,10 @@ const DocsProviders = ({ children }: DocsProvidersProps) => { - {children} + + + {children} + diff --git a/www/apps/docs/src/theme/BackToTopButton/index.tsx b/www/apps/docs/src/theme/BackToTopButton/index.tsx new file mode 100644 index 0000000000..97fca7c712 --- /dev/null +++ b/www/apps/docs/src/theme/BackToTopButton/index.tsx @@ -0,0 +1,33 @@ +import React from "react" +import clsx from "clsx" +import { translate } from "@docusaurus/Translate" +import { useBackToTopButton } from "@docusaurus/theme-common/internal" +import { Button, useNotifications } from "docs-ui" +import { ArrowUpMini } from "@medusajs/icons" + +export default function BackToTopButton(): JSX.Element { + const { shown, scrollToTop } = useBackToTopButton({ threshold: 300 }) + const { notifications } = useNotifications() + + return ( + + ) +} diff --git a/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx b/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx index 5824975acc..f9dad395f9 100644 --- a/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx +++ b/www/packages/docs-ui/src/components/Notification/Item/Layout/Default/index.tsx @@ -27,7 +27,7 @@ export const NotificationItemLayoutDefault: React.FC< closeButtonText = "Close", }) => { return ( - <> +
{type !== "none" && (
{closeButtonText}
)} - +
) } diff --git a/www/packages/docs-ui/src/components/Notification/Item/index.tsx b/www/packages/docs-ui/src/components/Notification/Item/index.tsx index f416d1bbb0..65aac402a5 100644 --- a/www/packages/docs-ui/src/components/Notification/Item/index.tsx +++ b/www/packages/docs-ui/src/components/Notification/Item/index.tsx @@ -36,8 +36,7 @@ export const NotificationItem = ({ return (
{ className?: string ) => { return ( - + {notifications.filter(condition).map((notification) => ( { <> {renderFilteredNotifications( (notification) => notification.placement === "top", - "flex fixed flex-col gap-docs_0.5 right-0 top-0 md:w-auto w-full max-h-[calc(100vh-57px)] overflow-y-auto" + "top-0" )} {renderFilteredNotifications( (notification) => notification.placement !== "top", - "flex flex-col gap-docs_0.5 fixed right-0 bottom-0 md:w-auto w-full max-h-[calc(100vh-57px)] overflow-y-auto" + "bottom-0" )} ) diff --git a/www/packages/tailwind/base.tailwind.config.js b/www/packages/tailwind/base.tailwind.config.js index 4a1326a33a..edc2fe4161 100644 --- a/www/packages/tailwind/base.tailwind.config.js +++ b/www/packages/tailwind/base.tailwind.config.js @@ -560,6 +560,22 @@ module.exports = { opacity: 0.3, }, }, + minimize: { + from: { + transform: "scale(1)", + }, + to: { + transform: "scale(0)", + }, + }, + maximize: { + from: { + transform: "scale(0)", + }, + to: { + transform: "scale(1)", + }, + }, }), animation: { fadeIn: "fadeIn 500ms", @@ -576,6 +592,8 @@ module.exports = { slideInLeft: "slideInLeft 500ms", slideOutLeft: "slideOutLeft 500ms", pulsingDots: "pulsingDots 1s alternate infinite", + minimize: "minimize 500ms", + maximize: "maximize 500ms", }, }, fontFamily: { @@ -686,6 +704,9 @@ module.exports = { display: "none", }, }, + ".flip-y": { + transform: "rotateY(180deg)", + }, }) addComponents({ ".btn-secondary-icon": {