{name}
{links.length > 0 && (
diff --git a/src/components/Links/links.module.scss b/src/components/Links/links.module.scss
index ca0cd18..be78665 100644
--- a/src/components/Links/links.module.scss
+++ b/src/components/Links/links.module.scss
@@ -31,9 +31,13 @@
& h2 {
color: $blue;
- margin-bottom: 0.25em;
+ margin-bottom: 0.5em;
font-weight: 500;
+ & svg {
+ display: flex;
+ }
+
& .links-count {
color: $grey;
font-weight: 300;
@@ -44,7 +48,7 @@
.category-header {
display: flex;
- gap: 0.25em;
+ gap: 0.4em;
align-items: center;
justify-content: space-between;
@@ -188,3 +192,9 @@
animation: rotate 1s both reverse infinite linear;
}
}
+
+@media (max-width: 768px) {
+ .links-wrapper {
+ padding: 0;
+ }
+}
diff --git a/src/components/MobileCategoriesModal.tsx b/src/components/MobileCategoriesModal.tsx
deleted file mode 100644
index 62d198a..0000000
--- a/src/components/MobileCategoriesModal.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import PATHS from 'constants/paths';
-import { AnimatePresence } from 'framer-motion';
-import useModal from 'hooks/useModal';
-import { useTranslation } from 'next-i18next';
-import { RxHamburgerMenu } from 'react-icons/rx';
-import BlockWrapper from './BlockWrapper/BlockWrapper';
-import ButtonLink from './ButtonLink';
-import Modal from './Modal/Modal';
-import Categories from './SideMenu/Categories/Categories';
-
-export default function MobileCategoriesModal() {
- const { t } = useTranslation();
- const mobileModal = useModal();
-
- return (
- <>
-
-
-
-
- {mobileModal.isShowing && (
-
-
-
- {t('common:category.create')}
-
-
-
-
- )}
-
- >
- );
-}
diff --git a/src/components/SideMenu/SideMenu.tsx b/src/components/SideMenu/SideMenu.tsx
index cbdbfcb..a861056 100644
--- a/src/components/SideMenu/SideMenu.tsx
+++ b/src/components/SideMenu/SideMenu.tsx
@@ -1,25 +1,44 @@
-import BlockWrapper from 'components/BlockWrapper/BlockWrapper';
-import Categories from './Categories/Categories';
-import Favorites from './Favorites/Favorites';
-import NavigationLinks from './NavigationLinks';
-import UserCard from './UserCard/UserCard';
-import styles from './sidemenu.module.scss';
+import { motion } from 'framer-motion';
+import { ReactNode } from 'react';
+import { createPortal } from 'react-dom';
+import { useSwipeable } from 'react-swipeable';
+import styles from './side-menu.module.scss';
-export default function SideMenu() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+interface SideMenuProps {
+ close?: (...args: any) => void;
+ children: ReactNode;
+}
+
+export default function SideMenu({ close, children }: Readonly) {
+ const handlers = useSwipeable({
+ trackMouse: true,
+ onSwipedLeft: close,
+ });
+
+ const handleWrapperClick = (event) =>
+ event.target.classList?.[0] === styles['side-menu-wrapper'] &&
+ close &&
+ close();
+
+ return createPortal(
+
+
+ {children}
+
+ ,
+ document.body,
);
}
diff --git a/src/components/SideMenu/side-menu.module.scss b/src/components/SideMenu/side-menu.module.scss
new file mode 100644
index 0000000..113e6ba
--- /dev/null
+++ b/src/components/SideMenu/side-menu.module.scss
@@ -0,0 +1,20 @@
+@import 'styles/colors.scss';
+
+.side-menu-wrapper {
+ z-index: 9999;
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ background-color: $black-blur;
+ box-shadow: 0 0 1em 0 $black-blur;
+}
+
+.side-menu-container {
+ height: 100%;
+ width: fit-content;
+ max-width: 100%;
+ background: $light-grey;
+ padding: 0.75em;
+}
diff --git a/src/components/SideMenu/Categories/Categories.tsx b/src/components/SideNavigation/Categories/Categories.tsx
similarity index 100%
rename from src/components/SideMenu/Categories/Categories.tsx
rename to src/components/SideNavigation/Categories/Categories.tsx
diff --git a/src/components/SideMenu/Categories/CategoryItem.tsx b/src/components/SideNavigation/Categories/CategoryItem.tsx
similarity index 100%
rename from src/components/SideMenu/Categories/CategoryItem.tsx
rename to src/components/SideNavigation/Categories/CategoryItem.tsx
diff --git a/src/components/SideMenu/Categories/categories.module.scss b/src/components/SideNavigation/Categories/categories.module.scss
similarity index 100%
rename from src/components/SideMenu/Categories/categories.module.scss
rename to src/components/SideNavigation/Categories/categories.module.scss
diff --git a/src/components/SideMenu/Favorites/FavoriteItem.tsx b/src/components/SideNavigation/Favorites/FavoriteItem.tsx
similarity index 100%
rename from src/components/SideMenu/Favorites/FavoriteItem.tsx
rename to src/components/SideNavigation/Favorites/FavoriteItem.tsx
diff --git a/src/components/SideMenu/Favorites/Favorites.tsx b/src/components/SideNavigation/Favorites/Favorites.tsx
similarity index 100%
rename from src/components/SideMenu/Favorites/Favorites.tsx
rename to src/components/SideNavigation/Favorites/Favorites.tsx
diff --git a/src/components/SideMenu/Favorites/favorites.module.scss b/src/components/SideNavigation/Favorites/favorites.module.scss
similarity index 100%
rename from src/components/SideMenu/Favorites/favorites.module.scss
rename to src/components/SideNavigation/Favorites/favorites.module.scss
diff --git a/src/components/SideMenu/NavigationLinks.tsx b/src/components/SideNavigation/NavigationLinks.tsx
similarity index 95%
rename from src/components/SideMenu/NavigationLinks.tsx
rename to src/components/SideNavigation/NavigationLinks.tsx
index a8a67bd..3830300 100644
--- a/src/components/SideMenu/NavigationLinks.tsx
+++ b/src/components/SideNavigation/NavigationLinks.tsx
@@ -3,7 +3,7 @@ import SearchModal from 'components/SearchModal/SearchModal';
import PATHS from 'constants/paths';
import useActiveCategory from 'hooks/useActiveCategory';
import { useTranslation } from 'next-i18next';
-import styles from './sidemenu.module.scss';
+import styles from './side-nav.module.scss';
export default function NavigationLinks() {
const { t } = useTranslation();
diff --git a/src/components/SideNavigation/SideNavigation.tsx b/src/components/SideNavigation/SideNavigation.tsx
new file mode 100644
index 0000000..28877db
--- /dev/null
+++ b/src/components/SideNavigation/SideNavigation.tsx
@@ -0,0 +1,25 @@
+import BlockWrapper from 'components/BlockWrapper/BlockWrapper';
+import Categories from './Categories/Categories';
+import Favorites from './Favorites/Favorites';
+import NavigationLinks from './NavigationLinks';
+import UserCard from './UserCard/UserCard';
+import styles from './side-nav.module.scss';
+
+export default function SideNavigation() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/SideMenu/UserCard/UserCard.tsx b/src/components/SideNavigation/UserCard/UserCard.tsx
similarity index 100%
rename from src/components/SideMenu/UserCard/UserCard.tsx
rename to src/components/SideNavigation/UserCard/UserCard.tsx
diff --git a/src/components/SideMenu/UserCard/user-card.module.scss b/src/components/SideNavigation/UserCard/user-card.module.scss
similarity index 100%
rename from src/components/SideMenu/UserCard/user-card.module.scss
rename to src/components/SideNavigation/UserCard/user-card.module.scss
diff --git a/src/components/SideMenu/sidemenu.module.scss b/src/components/SideNavigation/side-nav.module.scss
similarity index 81%
rename from src/components/SideMenu/sidemenu.module.scss
rename to src/components/SideNavigation/side-nav.module.scss
index e715108..ca4c3a1 100644
--- a/src/components/SideMenu/sidemenu.module.scss
+++ b/src/components/SideNavigation/side-nav.module.scss
@@ -3,9 +3,6 @@
.side-menu {
height: 100%;
width: 325px;
- padding: 0 25px 0 10px;
- border-right: 1px solid $lightest-grey;
- margin-right: 15px;
display: flex;
align-items: center;
flex-direction: column;
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 225a621..baef7c9 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -2,20 +2,24 @@ import clsx from 'clsx';
import Links from 'components/Links/Links';
import PageTransition from 'components/PageTransition';
import SideMenu from 'components/SideMenu/SideMenu';
-import UserCard from 'components/SideMenu/UserCard/UserCard';
+import SideNavigation from 'components/SideNavigation/SideNavigation';
import * as Keys from 'constants/keys';
import PATHS from 'constants/paths';
import ActiveCategoryContext from 'contexts/activeCategoryContext';
import CategoriesContext from 'contexts/categoriesContext';
import FavoritesContext from 'contexts/favoritesContext';
import GlobalHotkeysContext from 'contexts/globalHotkeysContext';
+import { AnimatePresence } from 'framer-motion';
import { useMediaQuery } from 'hooks/useMediaQuery';
+import useModal from 'hooks/useModal';
import { getServerSideTranslation } from 'i18n';
import getUserCategories from 'lib/category/getUserCategories';
import sortCategoriesByNextId from 'lib/category/sortCategoriesByNextId';
import { useRouter } from 'next/router';
-import { useMemo, useState } from 'react';
+import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
+import { useSwipeable } from 'react-swipeable';
+import styles from 'styles/home.module.scss';
import { CategoryWithLinks, LinkWithCategory } from 'types/types';
import { withAuthentication } from 'utils/session';
@@ -25,10 +29,63 @@ interface HomePageProps {
}
export default function HomePage(props: Readonly) {
- const router = useRouter();
const isMobile = useMediaQuery('(max-width: 768px)');
+ const { isShowing, open, close } = useModal();
+ const handlers = useSwipeable({
+ trackMouse: true,
+ onSwipedRight: open,
+ });
- const [globalHotkeysEnable, setGlobalHotkeysEnabled] =
+ useEffect(() => {
+ if (!isMobile && isShowing) {
+ close();
+ }
+ }, [close, isMobile, isShowing]);
+
+ return (
+
+
+
+ {!isMobile && (
+
+
+
+ )}
+
+ {isShowing && (
+
+
+
+ )}
+
+
+
+
+
+ );
+}
+
+function HomeProviders(
+ props: Readonly<{
+ children: ReactNode;
+ categories: CategoryWithLinks[];
+ activeCategory: CategoryWithLinks;
+ }>,
+) {
+ const router = useRouter();
+ const [globalHotkeysEnabled, setGlobalHotkeysEnabled] =
useState(true);
const [categories, setCategories] = useState(
props.categories,
@@ -36,10 +93,13 @@ export default function HomePage(props: Readonly) {
const [activeCategory, setActiveCategory] =
useState(props.activeCategory || categories?.[0]);
- const handleChangeCategory = (category: CategoryWithLinks) => {
- setActiveCategory(category);
- router.push(`${PATHS.HOME}?categoryId=${category.id}`);
- };
+ const handleChangeCategory = useCallback(
+ (category: CategoryWithLinks) => {
+ setActiveCategory(category);
+ router.push(`${PATHS.HOME}?categoryId=${category.id}`);
+ },
+ [router],
+ );
const favorites = useMemo(
() =>
@@ -52,44 +112,47 @@ export default function HomePage(props: Readonly) {
[categories],
);
+ const categoriesContextValue = useMemo(
+ () => ({ categories, setCategories }),
+ [categories],
+ );
+ const activeCategoryContextValue = useMemo(
+ () => ({ activeCategory, setActiveCategory: handleChangeCategory }),
+ [activeCategory, handleChangeCategory],
+ );
+ const favoritesContextValue = useMemo(() => ({ favorites }), [favorites]);
+ const globalHotkeysContextValue = useMemo(
+ () => ({
+ globalHotkeysEnabled: globalHotkeysEnabled,
+ setGlobalHotkeysEnabled,
+ }),
+ [globalHotkeysEnabled],
+ );
+
useHotkeys(
Keys.OPEN_CREATE_LINK_KEY,
() => {
router.push(`${PATHS.LINK.CREATE}?categoryId=${activeCategory.id}`);
},
- { enabled: globalHotkeysEnable },
+ { enabled: globalHotkeysEnabled },
);
useHotkeys(
Keys.OPEN_CREATE_CATEGORY_KEY,
() => {
router.push(PATHS.CATEGORY.CREATE);
},
- { enabled: globalHotkeysEnable },
+ { enabled: globalHotkeysEnabled },
);
-
return (
-
-
-
-
-
- {isMobile ? : }
-
-
-
-
-
-
+
+
+
+
+ {props.children}
+
+
+
+
);
}
diff --git a/src/styles/form.module.scss b/src/styles/form.module.scss
index 823e18f..75b8e88 100644
--- a/src/styles/form.module.scss
+++ b/src/styles/form.module.scss
@@ -30,7 +30,7 @@
@media (max-width: 768px) {
.form-container {
width: 100%;
- margin-top: 5em;
+ margin-top: 1em;
padding: 0 1em;
}
}
diff --git a/src/styles/globals.scss b/src/styles/globals.scss
index 48141ba..d305a93 100644
--- a/src/styles/globals.scss
+++ b/src/styles/globals.scss
@@ -214,6 +214,7 @@ kbd {
@media (max-width: 768px) {
.App {
+ padding: 0.75em;
flex-direction: column;
}
diff --git a/src/styles/home.module.scss b/src/styles/home.module.scss
new file mode 100644
index 0000000..abd233d
--- /dev/null
+++ b/src/styles/home.module.scss
@@ -0,0 +1,23 @@
+@import 'colors.scss';
+
+.swipe-handler {
+ height: 100%;
+ width: 100%;
+ display: flex;
+ transition: background-color 0.15s;
+}
+
+.side-menu {
+ position: absolute;
+ top: 0;
+ height: 100%;
+ background-color: $light-grey;
+ box-shadow: 0 0 1em 0 $black-blur;
+ padding: 0.75em;
+}
+
+.side-bar {
+ padding-right: 0.75em;
+ border-right: 1px solid $lightest-grey;
+ margin-right: 5px;
+}