From 47622870a514d347a34502e43a3e56039b20488f Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 16:47:09 +0330 Subject: [PATCH 1/7] customize header layout. --- docusaurus.config.js | 6 +- src/containers/GlobalStore/GlobalStore.tsx | 4 + src/css/custom.css | 1 + src/theme/Navbar/Content/index.tsx | 87 +++++++++++++++ src/theme/Navbar/Content/styles.module.scss | 112 ++++++++++++++++++++ src/theme/Navbar/index.scss | 10 ++ src/theme/Navbar/index.tsx | 15 +++ static/icons/chevron-left.svg | 3 + static/icons/hamburger-menu.svg | 3 + static/img/logo.svg | 11 +- 10 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 src/theme/Navbar/Content/index.tsx create mode 100644 src/theme/Navbar/Content/styles.module.scss create mode 100644 src/theme/Navbar/index.scss create mode 100644 src/theme/Navbar/index.tsx create mode 100644 static/icons/chevron-left.svg create mode 100644 static/icons/hamburger-menu.svg diff --git a/docusaurus.config.js b/docusaurus.config.js index e20b400..55b2711 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -59,7 +59,7 @@ const config = { ({ docs: { sidebar: { hideable: true } }, navbar: { - title: 'My Site', + title: '', logo: { alt: 'My Site Logo', src: 'img/logo.svg', @@ -71,10 +71,8 @@ const config = { position: 'left', label: 'Tutorial', }, - { to: '/blog', label: 'Blog', position: 'left' }, { - href: 'https://github.com/facebook/docusaurus', - label: 'GitHub', + type: 'localeDropdown', position: 'right', }, ], diff --git a/src/containers/GlobalStore/GlobalStore.tsx b/src/containers/GlobalStore/GlobalStore.tsx index 1be0710..f725281 100644 --- a/src/containers/GlobalStore/GlobalStore.tsx +++ b/src/containers/GlobalStore/GlobalStore.tsx @@ -6,6 +6,7 @@ export namespace GlobalStore { } export type Actions = { + toggleSidebar: () => void setHiddenSidebar: (payload: any) => void } @@ -14,6 +15,9 @@ export namespace GlobalStore { export const globalStore = new GlobalStore.Store(() => { return { + toggleSidebar: (payload, state, setState, dispatch) => { + setState((state) => void (state.hiddenSidebar = !state.hiddenSidebar)) + }, setHiddenSidebar: (payload, state, setState, dispatch) => { setState((state) => { state.hiddenSidebar = diff --git a/src/css/custom.css b/src/css/custom.css index ca9c1f5..15aeb22 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -29,6 +29,7 @@ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); } +/* sidebar */ :root { --doc-sidebar-width: 16.66vw !important; --doc-sidebar-max-width: 320px; diff --git a/src/theme/Navbar/Content/index.tsx b/src/theme/Navbar/Content/index.tsx new file mode 100644 index 0000000..aa5940b --- /dev/null +++ b/src/theme/Navbar/Content/index.tsx @@ -0,0 +1,87 @@ +import { useThemeConfig } from '@docusaurus/theme-common' +import { useNavbarMobileSidebar } from '@docusaurus/theme-common/internal' +import { + globalStore, + selectHiddenSidebar, +} from '@site/src/containers/GlobalStore' +import ChevronIcon from '@site/static/icons/chevron-left.svg' +import HamburgerIcon from '@site/static/icons/hamburger-menu.svg' +import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle' +import NavbarLogo from '@theme/Navbar/Logo' +import NavbarSearch from '@theme/Navbar/Search' +import NavbarItem, { Props as NavbarItemConfig } from '@theme/NavbarItem' +import SearchBar from '@theme/SearchBar' +import clsx from 'clsx' +import React from 'react' +import styles from './styles.module.scss' + +function useNavbarItems() { + // TODO temporary casting until ThemeConfig type is improved + return useThemeConfig().navbar.items as NavbarItemConfig[] +} + +function NavbarItems({ items }: { items: NavbarItemConfig[] }): JSX.Element { + return ( + <> + {items.map((item, i) => ( + + ))} + + ) +} + +export default function NavbarContent(): JSX.Element { + const mobileSidebar = useNavbarMobileSidebar() + + const items = useNavbarItems() + + const dispatch = globalStore.useDispatch() + const hiddenDesktopSidebar = globalStore.useSelector(selectHiddenSidebar) + + const localeDropdown = items.find((item) => item.type === 'localeDropdown') + const links = items.filter( + (item) => item.type === 'doc' || !!(item as any).to, + ) + + return ( +
+
+ +
+ +
+
+
+ +
+
+ + + +
+
+
+ +
+
+ +
+ + {localeDropdown && } +
+
+ ) +} diff --git a/src/theme/Navbar/Content/styles.module.scss b/src/theme/Navbar/Content/styles.module.scss new file mode 100644 index 0000000..c361cbf --- /dev/null +++ b/src/theme/Navbar/Content/styles.module.scss @@ -0,0 +1,112 @@ +@use '@site/src/css/utils'; + +.root { + width: 100%; + margin: 0; + + & > div { + display: flex; + flex-direction: row; + align-items: center; + flex-grow: 0; + } + + & > div:first-child { + max-width: var(--doc-sidebar-max-width); + } + + & > .headerMiddle { + justify-content: space-between; + flex-grow: 1; + } +} + +.leftContainer { + display: flex; + flex-direction: row; + align-items: center; + + transition: 0.2s; + transform: translateX(0); + + &.shifted { + transform: translateX( + calc(-1 * min(var(--doc-sidebar-max-width), 16.66vw) + 64px) + ); + } +} + +.headerRight { + justify-content: flex-end; +} + +.navbarLogoWrapper { + & > * { + margin: 0; + } +} + +.menu { + @extend %menu-common; + + display: flex; + flex-direction: row; +} + +.sidebarButton { + border: none; + background: none; + + cursor: pointer; + + @extend %menu-common; + + width: 52px; + height: 46px; +} + +%menu-common { + padding: 6px; + background-color: var(--ifm-background-surface-color); + border-radius: 1rem; +} + +@include utils.responsive('lg', 'down') { + .root { + padding: 0 var(--ifm-spacing-horizontal); + } + + .root > * { + width: auto; + flex: 0 0 auto !important; + padding: 0; + } + + .headerLeft { + } + + .headerMiddle { + margin-left: 20px; + + .leftContainer.shifted { + transform: none; + } + + nav { + display: none; + } + } + + .headerRight { + display: none !important; + } +} + +/* +Hide color mode toggle in small viewports + */ +@media (max-width: 996px) { + .colorModeToggle { + display: none; + } +} diff --git a/src/theme/Navbar/index.scss b/src/theme/Navbar/index.scss new file mode 100644 index 0000000..2a282f6 --- /dev/null +++ b/src/theme/Navbar/index.scss @@ -0,0 +1,10 @@ +.navbar { + --ifm-navbar-height: 3.875rem; + --ifm-navbar-background-color: none; + --ifm-navbar-shadow: none; + --ifm-navbar-padding-horizontal: 0px; + --ifm-navbar-padding-vertical: 8px; +} + +:root { +} diff --git a/src/theme/Navbar/index.tsx b/src/theme/Navbar/index.tsx new file mode 100644 index 0000000..05ffc9b --- /dev/null +++ b/src/theme/Navbar/index.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import Navbar from '@theme-original/Navbar' +import type NavbarType from '@theme/Navbar' +import type { WrapperProps } from '@docusaurus/types' +import './index.scss' + +type Props = WrapperProps + +export default function NavbarWrapper(props: Props): JSX.Element { + return ( + <> + + + ) +} diff --git a/static/icons/chevron-left.svg b/static/icons/chevron-left.svg new file mode 100644 index 0000000..f1cdcbd --- /dev/null +++ b/static/icons/chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/icons/hamburger-menu.svg b/static/icons/hamburger-menu.svg new file mode 100644 index 0000000..fee9118 --- /dev/null +++ b/static/icons/hamburger-menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/img/logo.svg b/static/img/logo.svg index 9db6d0d..2263d40 100644 --- a/static/img/logo.svg +++ b/static/img/logo.svg @@ -1 +1,10 @@ - \ No newline at end of file + + + + + + + + + + From fe2856392cf05dc4a803f140af1fe7648c24cc9d Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 18:52:23 +0330 Subject: [PATCH 2/7] change locale dropdown's icon and background; adjust navbar dropdown spacing. --- src/css/custom.css | 3 + src/theme/NavbarItem/DropdownNavbarItem.scss | 24 +++ src/theme/NavbarItem/DropdownNavbarItem.tsx | 190 ++++++++++++++++++ .../LocaleDropdownNavbarItem/index.tsx | 66 ++++++ .../styles.module.css | 4 + static/icons/dropdown.svg | 3 + 6 files changed, 290 insertions(+) create mode 100644 src/theme/NavbarItem/DropdownNavbarItem.scss create mode 100644 src/theme/NavbarItem/DropdownNavbarItem.tsx create mode 100644 src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx create mode 100644 src/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css create mode 100644 static/icons/dropdown.svg diff --git a/src/css/custom.css b/src/css/custom.css index ca9c1f5..d73c340 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -32,4 +32,7 @@ :root { --doc-sidebar-width: 16.66vw !important; --doc-sidebar-max-width: 320px; + + --ifm-navbar-item-padding-vertical: 8px; + --ifm-navbar-item-padding-horizontal: 12px; } diff --git a/src/theme/NavbarItem/DropdownNavbarItem.scss b/src/theme/NavbarItem/DropdownNavbarItem.scss new file mode 100644 index 0000000..693c37a --- /dev/null +++ b/src/theme/NavbarItem/DropdownNavbarItem.scss @@ -0,0 +1,24 @@ +.navbar__item.dropdown { + background-color: #eeeef1; + border-radius: 0.5rem; + + & > .navbar__link { + &::after { + display: none; + } + + & + svg { + margin-left: 0.75rem; + } + } + + ul { + margin-top: 5px; + } +} + +[data-theme='dark'] { + .navbar__item.dropdown { + background-color: var(--ifm-background-color); + } +} diff --git a/src/theme/NavbarItem/DropdownNavbarItem.tsx b/src/theme/NavbarItem/DropdownNavbarItem.tsx new file mode 100644 index 0000000..1eb484a --- /dev/null +++ b/src/theme/NavbarItem/DropdownNavbarItem.tsx @@ -0,0 +1,190 @@ +import React, { useState, useRef, useEffect } from 'react' +import clsx from 'clsx' +import { + isRegexpStringMatch, + useCollapsible, + Collapsible, +} from '@docusaurus/theme-common' +import { isSamePath, useLocalPathname } from '@docusaurus/theme-common/internal' +import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink' +import NavbarItem, { LinkLikeNavbarItemProps } from '@theme/NavbarItem' +import type { + DesktopOrMobileNavBarItemProps, + Props, +} from '@theme/NavbarItem/DropdownNavbarItem' +import './DropdownNavbarItem.scss' +import DropdownIcon from '@site/static/icons/dropdown.svg' + +function isItemActive( + item: LinkLikeNavbarItemProps, + localPathname: string, +): boolean { + if (isSamePath(item.to, localPathname)) { + return true + } + if (isRegexpStringMatch(item.activeBaseRegex, localPathname)) { + return true + } + if (item.activeBasePath && localPathname.startsWith(item.activeBasePath)) { + return true + } + return false +} + +function containsActiveItems( + items: readonly LinkLikeNavbarItemProps[], + localPathname: string, +): boolean { + return items.some((item) => isItemActive(item, localPathname)) +} + +function DropdownNavbarItemDesktop({ + items, + position, + className, + onClick, + ...props +}: DesktopOrMobileNavBarItemProps) { + const dropdownRef = useRef(null) + const [showDropdown, setShowDropdown] = useState(false) + + useEffect(() => { + const handleClickOutside = (event: MouseEvent | TouchEvent) => { + if ( + !dropdownRef.current || + dropdownRef.current.contains(event.target as Node) + ) { + return + } + setShowDropdown(false) + } + + document.addEventListener('mousedown', handleClickOutside) + document.addEventListener('touchstart', handleClickOutside) + + return () => { + document.removeEventListener('mousedown', handleClickOutside) + document.removeEventListener('touchstart', handleClickOutside) + } + }, [dropdownRef]) + + return ( +
+ e.preventDefault()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault() + setShowDropdown(!showDropdown) + } + }} + > + {props.children ?? props.label} + + +
    + {items.map((childItemProps, i) => ( + { + if (i === items.length - 1 && e.key === 'Tab') { + e.preventDefault() + setShowDropdown(false) + const nextNavbarItem = dropdownRef.current!.nextElementSibling + if (nextNavbarItem) { + const targetItem = + nextNavbarItem instanceof HTMLAnchorElement + ? nextNavbarItem + : // Next item is another dropdown; focus on the inner + // anchor element instead so there's outline + nextNavbarItem.querySelector('a')! + targetItem.focus() + } + } + }} + activeClassName="dropdown__link--active" + {...childItemProps} + key={i} + /> + ))} +
+
+ ) +} + +function DropdownNavbarItemMobile({ + items, + className, + position, // Need to destructure position from props so that it doesn't get passed on. + onClick, + ...props +}: DesktopOrMobileNavBarItemProps) { + const localPathname = useLocalPathname() + const containsActive = containsActiveItems(items, localPathname) + + const { collapsed, toggleCollapsed, setCollapsed } = useCollapsible({ + initialState: () => !containsActive, + }) + + // Expand/collapse if any item active after a navigation + useEffect(() => { + if (containsActive) { + setCollapsed(!containsActive) + } + }, [localPathname, containsActive, setCollapsed]) + + return ( +
  • + { + e.preventDefault() + toggleCollapsed() + }} + > + {props.children ?? props.label} + + + {items.map((childItemProps, i) => ( + + ))} + +
  • + ) +} + +export default function DropdownNavbarItem({ + mobile = false, + ...props +}: Props): JSX.Element { + const Comp = mobile ? DropdownNavbarItemMobile : DropdownNavbarItemDesktop + return +} diff --git a/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx b/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx new file mode 100644 index 0000000..7d1229f --- /dev/null +++ b/src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx @@ -0,0 +1,66 @@ +import React from 'react' +import useDocusaurusContext from '@docusaurus/useDocusaurusContext' +import { useAlternatePageUtils } from '@docusaurus/theme-common/internal' +import { translate } from '@docusaurus/Translate' +import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem' +import IconLanguage from '@theme/Icon/Language' +import type { LinkLikeNavbarItemProps } from '@theme/NavbarItem' +import type { Props } from '@theme/NavbarItem/LocaleDropdownNavbarItem' + +import styles from './styles.module.css' + +export default function LocaleDropdownNavbarItem({ + mobile, + dropdownItemsBefore, + dropdownItemsAfter, + ...props +}: Props): JSX.Element { + const { + i18n: { currentLocale, locales, localeConfigs }, + } = useDocusaurusContext() + const alternatePageUtils = useAlternatePageUtils() + + const localeItems = locales.map((locale): LinkLikeNavbarItemProps => { + const to = `pathname://${alternatePageUtils.createUrl({ + locale, + fullyQualified: false, + })}` + return { + label: localeConfigs[locale]!.label, + lang: localeConfigs[locale]!.htmlLang, + to, + target: '_self', + autoAddBaseUrl: false, + className: + // eslint-disable-next-line no-nested-ternary + locale === currentLocale + ? // Similar idea as DefaultNavbarItem: select the right Infima active + // class name. This cannot be substituted with isActive, because the + // target URLs contain `pathname://` and therefore are not NavLinks! + mobile + ? 'menu__link--active' + : 'dropdown__link--active' + : '', + } + }) + + const items = [...dropdownItemsBefore, ...localeItems, ...dropdownItemsAfter] + + // Mobile is handled a bit differently + const dropdownLabel = mobile + ? translate({ + message: 'Languages', + id: 'theme.navbar.mobileLanguageDropdown.label', + description: 'The label for the mobile language switcher dropdown', + }) + : localeConfigs[currentLocale]!.label + + return ( + {dropdownLabel}} + items={items} + /> + ) +} diff --git a/src/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css b/src/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css new file mode 100644 index 0000000..8804a08 --- /dev/null +++ b/src/theme/NavbarItem/LocaleDropdownNavbarItem/styles.module.css @@ -0,0 +1,4 @@ +.iconLanguage { + vertical-align: text-bottom; + margin-right: 5px; +} diff --git a/static/icons/dropdown.svg b/static/icons/dropdown.svg new file mode 100644 index 0000000..f583120 --- /dev/null +++ b/static/icons/dropdown.svg @@ -0,0 +1,3 @@ + + + From c7196f026969c65a0350c1818ea0437709e690cf Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 19:04:09 +0330 Subject: [PATCH 3/7] add divider before locale dropdown button. --- src/theme/Navbar/Content/index.tsx | 7 ++++++- src/theme/Navbar/Content/styles.module.scss | 13 +++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/theme/Navbar/Content/index.tsx b/src/theme/Navbar/Content/index.tsx index aa5940b..5a3d9b4 100644 --- a/src/theme/Navbar/Content/index.tsx +++ b/src/theme/Navbar/Content/index.tsx @@ -80,7 +80,12 @@ export default function NavbarContent(): JSX.Element {
    - {localeDropdown && } + {localeDropdown && ( + <> +
    + + + )}
    ) diff --git a/src/theme/Navbar/Content/styles.module.scss b/src/theme/Navbar/Content/styles.module.scss index c361cbf..af32fdc 100644 --- a/src/theme/Navbar/Content/styles.module.scss +++ b/src/theme/Navbar/Content/styles.module.scss @@ -71,6 +71,19 @@ border-radius: 1rem; } +.headerRight { + & > *:not(:last-child) { + margin-right: 34px; + } +} + +.divider { + height: 11px; + width: 1px; + + background-color: #d9d9d9; // TODO: use infima variables +} + @include utils.responsive('lg', 'down') { .root { padding: 0 var(--ifm-spacing-horizontal); From 20c54a5cb55310ca080a8877df439459d51783db Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 19:48:38 +0330 Subject: [PATCH 4/7] add IconButton component (taken from theme-classic/ColorModeToggle). --- .../IconButton/IconButton.module.scss | 17 ++++++ src/components/IconButton/IconButton.tsx | 20 +++++++ src/components/IconButton/index.ts | 1 + src/theme/ColorModeToggle/index.tsx | 56 +++++++++++++++++++ src/theme/ColorModeToggle/styles.module.css | 8 +++ 5 files changed, 102 insertions(+) create mode 100644 src/components/IconButton/IconButton.module.scss create mode 100644 src/components/IconButton/IconButton.tsx create mode 100644 src/components/IconButton/index.ts create mode 100644 src/theme/ColorModeToggle/index.tsx create mode 100644 src/theme/ColorModeToggle/styles.module.css diff --git a/src/components/IconButton/IconButton.module.scss b/src/components/IconButton/IconButton.module.scss new file mode 100644 index 0000000..9ce3a4d --- /dev/null +++ b/src/components/IconButton/IconButton.module.scss @@ -0,0 +1,17 @@ +.root { + -webkit-tap-highlight-color: transparent; + align-items: center; + display: flex; + justify-content: center; + width: 100%; + height: 100%; + border-radius: 50%; + transition: background var(--ifm-transition-fast); + + width: 2rem; + height: 2rem; +} + +.root:hover { + background: var(--ifm-color-emphasis-200); +} diff --git a/src/components/IconButton/IconButton.tsx b/src/components/IconButton/IconButton.tsx new file mode 100644 index 0000000..ed96c23 --- /dev/null +++ b/src/components/IconButton/IconButton.tsx @@ -0,0 +1,20 @@ +import clsx from 'clsx' +import React from 'react' +import styles from './IconButton.module.scss' + +export const IconButton: React.FC< + React.DetailedHTMLProps< + React.ButtonHTMLAttributes, + HTMLButtonElement + > & {} +> = ({ children, className, ...props }) => { + return ( + + ) +} diff --git a/src/components/IconButton/index.ts b/src/components/IconButton/index.ts new file mode 100644 index 0000000..a37a7fc --- /dev/null +++ b/src/components/IconButton/index.ts @@ -0,0 +1 @@ +export * from './IconButton' diff --git a/src/theme/ColorModeToggle/index.tsx b/src/theme/ColorModeToggle/index.tsx new file mode 100644 index 0000000..7531f4d --- /dev/null +++ b/src/theme/ColorModeToggle/index.tsx @@ -0,0 +1,56 @@ +import { translate } from '@docusaurus/Translate' +import useIsBrowser from '@docusaurus/useIsBrowser' +import { IconButton } from '@site/src/components/IconButton' +import type { Props } from '@theme/ColorModeToggle' +import IconDarkMode from '@theme/Icon/DarkMode' +import IconLightMode from '@theme/Icon/LightMode' +import clsx from 'clsx' +import React from 'react' +import styles from './styles.module.css' + +function ColorModeToggle({ className, value, onChange }: Props): JSX.Element { + const isBrowser = useIsBrowser() + + const title = translate( + { + message: 'Switch between dark and light mode (currently {mode})', + id: 'theme.colorToggle.ariaLabel', + description: 'The ARIA label for the navbar color mode toggle', + }, + { + mode: + value === 'dark' + ? translate({ + message: 'dark mode', + id: 'theme.colorToggle.ariaLabel.mode.dark', + description: 'The name for the dark color mode', + }) + : translate({ + message: 'light mode', + id: 'theme.colorToggle.ariaLabel.mode.light', + description: 'The name for the light color mode', + }), + }, + ) + + return ( +
    + onChange(value === 'dark' ? 'light' : 'dark')} + > + + + +
    + ) +} + +export default React.memo(ColorModeToggle) diff --git a/src/theme/ColorModeToggle/styles.module.css b/src/theme/ColorModeToggle/styles.module.css new file mode 100644 index 0000000..d94cb13 --- /dev/null +++ b/src/theme/ColorModeToggle/styles.module.css @@ -0,0 +1,8 @@ +[data-theme='light'] .darkToggleIcon, +[data-theme='dark'] .lightToggleIcon { + display: none; +} + +.toggleButtonDisabled { + cursor: not-allowed; +} From 8f0869d83e4999683467846f60eeaebbd10a75ee Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 19:50:24 +0330 Subject: [PATCH 5/7] update light mode icon. --- src/theme/Icon/LightMode/index.tsx | 7 +++++++ static/icons/day.svg | 3 +++ 2 files changed, 10 insertions(+) create mode 100644 src/theme/Icon/LightMode/index.tsx create mode 100644 static/icons/day.svg diff --git a/src/theme/Icon/LightMode/index.tsx b/src/theme/Icon/LightMode/index.tsx new file mode 100644 index 0000000..da7fb65 --- /dev/null +++ b/src/theme/Icon/LightMode/index.tsx @@ -0,0 +1,7 @@ +import React from 'react' +import type { Props } from '@theme/Icon/LightMode' +import Icon from '@site/static/icons/day.svg' + +export default function IconLightMode(props: Props): JSX.Element { + return +} diff --git a/static/icons/day.svg b/static/icons/day.svg new file mode 100644 index 0000000..62fa63f --- /dev/null +++ b/static/icons/day.svg @@ -0,0 +1,3 @@ + + + From 3a21240a02dbeefded11f0d31f4509be49af573c Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 19:50:40 +0330 Subject: [PATCH 6/7] feat: add share button --- docusaurus.config.js | 2 +- package.json | 1 + src/theme/Navbar/Content/ShareButton.tsx | 21 +++++++++++++++++++++ src/theme/Navbar/Content/index.tsx | 2 ++ src/theme/Navbar/Content/styles.module.scss | 8 ++++++++ static/icons/share.svg | 3 +++ yarn.lock | 12 ++++++++++++ 7 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/theme/Navbar/Content/ShareButton.tsx create mode 100644 static/icons/share.svg diff --git a/docusaurus.config.js b/docusaurus.config.js index 55b2711..9eb1801 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -69,7 +69,7 @@ const config = { type: 'doc', docId: 'intro', position: 'left', - label: 'Tutorial', + label: 'Docs', }, { type: 'localeDropdown', diff --git a/package.json b/package.json index b696e54..575fbbc 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@docusaurus/preset-classic": "2.1.0", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", + "copy-to-clipboard": "^3.3.2", "prism-react-renderer": "^1.3.5", "react": "^17.0.2", "react-dom": "^17.0.2" diff --git a/src/theme/Navbar/Content/ShareButton.tsx b/src/theme/Navbar/Content/ShareButton.tsx new file mode 100644 index 0000000..588a7ca --- /dev/null +++ b/src/theme/Navbar/Content/ShareButton.tsx @@ -0,0 +1,21 @@ +import { IconButton } from '@site/src/components/IconButton' +import React from 'react' +import Icon from '@site/static/icons/share.svg' +import styles from './styles.module.scss' +import copy2clipboard from 'copy-to-clipboard' + +export const ShareButton: React.FC<{}> = ({}) => { + return ( + { + if (typeof navigator?.share === 'function') navigator.share() + else copy2clipboard(window.location.href) + }} + className={styles.shareButton} + > + + + ) +} diff --git a/src/theme/Navbar/Content/index.tsx b/src/theme/Navbar/Content/index.tsx index 5a3d9b4..3706fce 100644 --- a/src/theme/Navbar/Content/index.tsx +++ b/src/theme/Navbar/Content/index.tsx @@ -13,6 +13,7 @@ import NavbarItem, { Props as NavbarItemConfig } from '@theme/NavbarItem' import SearchBar from '@theme/SearchBar' import clsx from 'clsx' import React from 'react' +import { ShareButton } from './ShareButton' import styles from './styles.module.scss' function useNavbarItems() { @@ -79,6 +80,7 @@ export default function NavbarContent(): JSX.Element {
    + {localeDropdown && ( <> diff --git a/src/theme/Navbar/Content/styles.module.scss b/src/theme/Navbar/Content/styles.module.scss index af32fdc..eb3ce77 100644 --- a/src/theme/Navbar/Content/styles.module.scss +++ b/src/theme/Navbar/Content/styles.module.scss @@ -84,6 +84,14 @@ background-color: #d9d9d9; // TODO: use infima variables } +.shareButton { + svg, + svg * { + fill: currentColor; + stroke: currentColor; + } +} + @include utils.responsive('lg', 'down') { .root { padding: 0 var(--ifm-spacing-horizontal); diff --git a/static/icons/share.svg b/static/icons/share.svg new file mode 100644 index 0000000..fe0cd06 --- /dev/null +++ b/static/icons/share.svg @@ -0,0 +1,3 @@ + + + diff --git a/yarn.lock b/yarn.lock index 228afe1..436e060 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3082,6 +3082,13 @@ copy-text-to-clipboard@^3.0.1: resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== +copy-to-clipboard@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz#5b263ec2366224b100181dded7ce0579b340c107" + integrity sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg== + dependencies: + toggle-selection "^1.0.6" + copy-webpack-plugin@^11.0.0: version "11.0.0" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" @@ -7065,6 +7072,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toggle-selection@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" From d12eb1c9bf9e60e1b87960cd69d9cae122908e52 Mon Sep 17 00:00:00 2001 From: Hossein Mehrabi Date: Fri, 7 Oct 2022 21:08:07 +0330 Subject: [PATCH 7/7] dark mode sidebar button. --- src/theme/Navbar/Content/index.tsx | 5 ++++- src/theme/Navbar/Content/styles.module.scss | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/theme/Navbar/Content/index.tsx b/src/theme/Navbar/Content/index.tsx index 3706fce..0757600 100644 --- a/src/theme/Navbar/Content/index.tsx +++ b/src/theme/Navbar/Content/index.tsx @@ -49,7 +49,10 @@ export default function NavbarContent(): JSX.Element {
    diff --git a/src/theme/Navbar/Content/styles.module.scss b/src/theme/Navbar/Content/styles.module.scss index eb3ce77..13f775c 100644 --- a/src/theme/Navbar/Content/styles.module.scss +++ b/src/theme/Navbar/Content/styles.module.scss @@ -63,6 +63,20 @@ width: 52px; height: 46px; + + &.expand { + svg, + svg * { + fill: currentColor; + } + } + + &:not(.expand) { + svg, + svg * { + stroke: currentColor; + } + } } %menu-common {