+ {/* Logo */}
+
+
+
+ {/* Switch organization */}
+
+
+
+ {renderMenu}
+
+
+ {/* Bottom navigation */}
+
+
+ {/* // TODO: use proper link buttons */}
+
+ }
+ value=""
+ className="hidden lg:flex"
+ >
+
+ Log Out
+
+
+ } value="">
+ Documentation
+
+ } value="">
+ Support
+
+
+
-
- {/* Switch organization */}
-
-
-
-
- {[
- { title: 'Projects', url: `/${orgSlug}/`, icon: },
- {
- title: 'Settings',
- url: `/${orgSlug}/settings`,
- icon: ,
- },
- ].map(({ title, icon, url }, index) => (
-
-
- {title}
-
-
- ))}
-
-
- {/* Bottom navigation */}
-
-
- {/* // TODO: use proper link buttons */}
-
- } value="">
-
- Log Out
-
-
- } value="">
- Documentation
-
- } value="">
- Support
-
-
-
+ {/* Only shows when on mobile */}
+
+ {user?.name && (
+
+
+
+ {formatAddress(user.name)}
+
+
+ )}
+
-
+
);
};
diff --git a/packages/frontend/src/components/shared/Sidebar/constants.tsx b/packages/frontend/src/components/shared/Sidebar/constants.tsx
new file mode 100644
index 00000000..6c303105
--- /dev/null
+++ b/packages/frontend/src/components/shared/Sidebar/constants.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { FolderIcon, SettingsSlidersIcon } from 'components/shared/CustomIcon';
+
+export const SIDEBAR_MENU = (orgSlug?: string) => [
+ {
+ title: 'Projects',
+ url: `/${orgSlug}/`,
+ icon:
,
+ },
+ {
+ title: 'Settings',
+ url: `/${orgSlug}/settings`,
+ icon:
,
+ },
+];
diff --git a/packages/frontend/src/layouts/ProjectSearch.tsx b/packages/frontend/src/layouts/ProjectSearch.tsx
index 5805ba37..5a71356d 100644
--- a/packages/frontend/src/layouts/ProjectSearch.tsx
+++ b/packages/frontend/src/layouts/ProjectSearch.tsx
@@ -2,14 +2,14 @@ import React, { useCallback, useEffect, useState } from 'react';
import { Outlet, useNavigate } from 'react-router-dom';
import { User } from 'gql-client';
-// import { Tooltip } from '@material-tailwind/react';
-
-import HorizontalLine from '../components/HorizontalLine';
-import ProjectSearchBar from '../components/projects/ProjectSearchBar';
-import { useGQLClient } from '../context/GQLClientContext';
-import { formatAddress } from '../utils/format';
+import HorizontalLine from 'components/HorizontalLine';
+import { useGQLClient } from 'context/GQLClientContext';
import { NotificationBellIcon, PlusIcon } from 'components/shared/CustomIcon';
import { Button } from 'components/shared/Button';
+import { Avatar } from 'components/shared/Avatar';
+import { getInitials } from 'utils/geInitials';
+import { formatAddress } from 'utils/format';
+import { ProjectSearchBar } from 'components/projects/ProjectSearchBar';
const ProjectSearch = () => {
const navigate = useNavigate();
@@ -32,10 +32,11 @@ const ProjectSearch = () => {
}, []);
return (
-
-
-
-
+
+ {/* Header */}
+
+
+
{
navigate(
@@ -44,30 +45,37 @@ const ProjectSearch = () => {
}}
/>
-
-
- {user?.name ? (
-
- ) : null}
+
+
+
+ {user?.name && (
+
+ )}
+
-
+
+ {/* Content */}
+
-
+
+
);
};
diff --git a/packages/frontend/src/pages/org-slug/index.tsx b/packages/frontend/src/pages/org-slug/index.tsx
index 036193cf..e0e5af06 100644
--- a/packages/frontend/src/pages/org-slug/index.tsx
+++ b/packages/frontend/src/pages/org-slug/index.tsx
@@ -26,7 +26,7 @@ const Projects = () => {
}, [orgSlug]);
return (
-
+
{/* Header */}
@@ -44,7 +44,7 @@ const Projects = () => {
{/* List of projects */}
-
+
{projects.length > 0 &&
projects.map((project, key) => {
return
;
diff --git a/packages/frontend/src/pages/org-slug/layout.tsx b/packages/frontend/src/pages/org-slug/layout.tsx
index c1be6b8c..62ec1aa1 100644
--- a/packages/frontend/src/pages/org-slug/layout.tsx
+++ b/packages/frontend/src/pages/org-slug/layout.tsx
@@ -1,31 +1,130 @@
+import { Logo } from 'components/Logo';
+import { Button } from 'components/shared/Button';
+import {
+ CrossIcon,
+ MenuIcon,
+ NotificationBellIcon,
+ SearchIcon,
+} from 'components/shared/CustomIcon';
import { Sidebar } from 'components/shared/Sidebar';
import { OctokitProvider } from 'context/OctokitContext';
-import React, { ComponentPropsWithoutRef } from 'react';
-import { Outlet } from 'react-router-dom';
+import React, { ComponentPropsWithoutRef, useEffect, useState } from 'react';
+import { Outlet, useParams } from 'react-router-dom';
+import { AnimatePresence, motion } from 'framer-motion';
import { cn } from 'utils/classnames';
+import { useMediaQuery } from 'usehooks-ts';
+import { ProjectSearchBarDialog } from 'components/projects/ProjectSearchBar';
export interface DashboardLayoutProps
extends ComponentPropsWithoutRef<'section'> {}
export const DashboardLayout = ({
className,
- children,
...props
}: DashboardLayoutProps) => {
+ const { orgSlug } = useParams();
+ const isDesktop = useMediaQuery('(min-width: 960px)');
+
+ const [isSidebarOpen, setIsSidebarOpen] = useState(false);
+ const [isSearchOpen, setIsSearchOpen] = useState(false);
+
+ useEffect(() => {
+ if (isDesktop) {
+ setIsSidebarOpen(false);
+ }
+ }, [isDesktop]);
+
return (
-
-
-
-
-
-
-
+ <>
+
+ {/* Header on mobile */}
+
+
+
+
+ {isSidebarOpen ? (
+
+
+
+ ) : (
+
+ <>
+
+
+
+ >
+
+ )}
+
+
-
- {children}
-
+
+
+
setIsSearchOpen(false)}
+ onClose={() => setIsSearchOpen(false)}
+ />
+ >
);
};
diff --git a/yarn.lock b/yarn.lock
index 40284615..f0ed8b79 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10172,6 +10172,15 @@ framer-motion@6.5.1:
optionalDependencies:
"@emotion/is-prop-valid" "^0.8.2"
+framer-motion@^11.0.8:
+ version "11.0.8"
+ resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-11.0.8.tgz#8f97a18cbad5858d85b53bc325c40a03d0a5c203"
+ integrity sha512-1KSGNuqe1qZkS/SWQlDnqK2VCVzRVEoval379j0FiUBJAZoqgwyvqFkfvJbgW2IPFo4wX16K+M0k5jO23lCIjA==
+ dependencies:
+ tslib "^2.4.0"
+ optionalDependencies:
+ "@emotion/is-prop-valid" "^0.8.2"
+
framesync@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20"