feat(plugin-docs-menu): Added hamburger menu for mobile screen
MODIFY
packages/plugin-docs/client/theme-doc/Head.tsx
packages/plugin-docs/client/theme-doc/Head.tsx
+import cx from 'classnames';
import React from 'react';
import Github from './Github';
import LangSwitch from './LangSwitch';
@@ -6,7 +7,12 @@ import NavBar from './NavBar';
import Search from './Search';
import ThemeSwitch from './ThemeSwitch';
-export default () => {
+interface HeadProps {
+ isMenuOpened: boolean;
+ setMenuOpened: React.Dispatch<React.SetStateAction<boolean>>;
+}
+
+export default (props: HeadProps) => {
return (
<div
className="w-full flex flex-row items-center justify-between
@@ -15,6 +21,7 @@ export default () => {
<Logo />
<div className="flex flex-row items-center">
<Search />
+ <HamburgerButton {...props} />
<div className="hidden lg:block">
<NavBar />
</div>
@@ -31,3 +38,35 @@ export default () => {
</div>
);
};
+
+interface HamburgerButtonProps {
+ isMenuOpened: boolean;
+ setMenuOpened: React.Dispatch<React.SetStateAction<boolean>>;
+}
+
+function HamburgerButton(props: HamburgerButtonProps) {
+ const barClass =
+ 'block absolute h-0.5 w-5 bg-current transform' +
+ ' transition duration-500 ease-in-out';
+
+ return (
+ <div
+ className="relative py-3 sm:max-w-xl mx-auto mx-5 lg:hidden"
+ onClick={() => props.setMenuOpened((o) => !o)}
+ >
+ <span
+ className={cx(
+ barClass,
+ props.isMenuOpened ? 'rotate-45 ' : '-translate-y-1.5',
+ )}
+ />
+ <span className={cx(barClass, props.isMenuOpened && 'opacity-0')} />
+ <span
+ className={cx(
+ barClass,
+ props.isMenuOpened ? '-rotate-45' : 'translate-y-1.5',
+ )}
+ />
+ </div>
+ );
+}

MODIFY
packages/plugin-docs/client/theme-doc/Layout.tsx
packages/plugin-docs/client/theme-doc/Layout.tsx
-import React from 'react';
+import cx from 'classnames';
+import React, { useState } from 'react';
import { ThemeContext } from './context';
import Head from './Head';
import Sidebar from './Sidebar';
import Toc from './Toc';
export default (props: any) => {
+ const [isMenuOpened, setIsMenuOpened] = useState(false);
+
return (
<ThemeContext.Provider
value={{
@@ -20,7 +23,7 @@ export default (props: any) => {
before:backdrop-blur-md before:absolute before:block
before:w-full before:h-full before:z-[-1]"
>
- <Head />
+ <Head setMenuOpened={setIsMenuOpened} isMenuOpened={isMenuOpened} />
</div>
<div className="w-full flex flex-row justify-center overflow-x-hidden">
@@ -53,6 +56,16 @@ export default (props: any) => {
</div>
</div>
</div>
+
+ <div
+ className={cx(
+ 'fixed top-12 w-screen bg-white z-20',
+ 'overflow-hidden transition-all duration-500',
+ isMenuOpened ? 'max-h-screen' : 'max-h-0',
+ )}
+ >
+ <Sidebar setMenuOpened={setIsMenuOpened} />
+ </div>
</ThemeContext.Provider>
);
};

MODIFY
packages/plugin-docs/client/theme-doc/Search.tsx
packages/plugin-docs/client/theme-doc/Search.tsx
@@ -29,7 +29,7 @@ export default () => {
return (
<Fragment>
<div
- className="rounded-lg w-64 flex items-center pr-2 flex-row hover:bg-gray-50
+ className="rounded-lg w-40 lg:w-64 flex items-center pr-2 flex-row hover:bg-gray-50
transition duration-300 bg-gray-100 border border-white focus-within:border-gray-100
focus-within:bg-white"
>

MODIFY
packages/plugin-docs/client/theme-doc/Sidebar.tsx
packages/plugin-docs/client/theme-doc/Sidebar.tsx
+import cx from 'classnames';
import React from 'react';
import { useThemeContext } from './context';
-export default () => {
+interface SidebarProps {
+ setMenuOpened?: React.Dispatch<React.SetStateAction<boolean>>;
+}
+
+export default (props: SidebarProps) => {
const { appData, components, themeConfig, location } = useThemeContext()!;
const matchedNav = themeConfig.navs.filter((nav) =>
location.pathname.startsWith(nav.path),
@@ -25,7 +30,12 @@ export default () => {
});
return (
- <ul className="h-[calc(100vh-8rem)] overflow-y-scroll w-64 p-8 pb-12 fadeout">
+ <ul
+ className={cx(
+ 'h-screen lg:h-[calc(100vh-8rem)] overflow-y-scroll',
+ 'lg:w-64 p-8 pb-12 fadeout w-full',
+ )}
+ >
{(matchedNav.children || []).map((item) => {
return (
<li key={item.title}>
@@ -50,7 +60,12 @@ export default () => {
}
return (
- <components.Link to={`${matchedNav.path}/${child}`}>
+ <components.Link
+ to={`${matchedNav.path}/${child}`}
+ onClick={() =>
+ props.setMenuOpened && props.setMenuOpened((o) => !o)
+ }
+ >
<div
key={child}
className="text-gray-700 my-2 hover:text-blue-400 transition-all px-4 py-1"

feat(plugin-docs-menu): Added hamburger menu for mobile screen (#299)