diff --git a/front/src/App.tsx b/front/src/App.tsx
index 378bd06e3..8cb19a087 100644
--- a/front/src/App.tsx
+++ b/front/src/App.tsx
@@ -24,7 +24,7 @@ function App() {
}, [data]);
return (
-
+ <>
{
@@ -65,7 +65,7 @@ function App() {
}
-
+ >
);
}
diff --git a/front/src/components/comments/RightDrawerComments.tsx b/front/src/components/comments/RightDrawerComments.tsx
new file mode 100644
index 000000000..13372bc79
--- /dev/null
+++ b/front/src/components/comments/RightDrawerComments.tsx
@@ -0,0 +1,9 @@
+import { RightDrawerTopBar } from '../../layout/right-drawer/RightDrawerTopBar';
+
+export function RightDrawerComments() {
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/front/src/components/table/action-bar/EntityTableActionBar.tsx b/front/src/components/table/action-bar/EntityTableActionBar.tsx
index 70b322bdf..b9747af8a 100644
--- a/front/src/components/table/action-bar/EntityTableActionBar.tsx
+++ b/front/src/components/table/action-bar/EntityTableActionBar.tsx
@@ -17,7 +17,6 @@ const StyledContainer = styled.div`
align-items: center;
padding-left: ${(props) => props.theme.spacing(2)};
padding-right: ${(props) => props.theme.spacing(2)};
- color: ${(props) => props.theme.red};
left: 50%;
transform: translateX(-50%);
diff --git a/front/src/components/table/action-bar/EntityTableActionBarButton.tsx b/front/src/components/table/action-bar/EntityTableActionBarButton.tsx
index dbd1386af..d7923b1c0 100644
--- a/front/src/components/table/action-bar/EntityTableActionBarButton.tsx
+++ b/front/src/components/table/action-bar/EntityTableActionBarButton.tsx
@@ -4,14 +4,20 @@ import { ReactNode } from 'react';
type OwnProps = {
icon: ReactNode;
label: string;
+ type?: 'standard' | 'warning';
onClick: () => void;
};
-const StyledButton = styled.div`
+type StyledButtonProps = {
+ type: 'standard' | 'warning';
+};
+
+const StyledButton = styled.div`
display: flex;
cursor: pointer;
user-select: none;
-
+ color: ${(props) =>
+ props.type === 'warning' ? props.theme.red : props.theme.text60};
justify-content: center;
padding: ${(props) => props.theme.spacing(2)};
@@ -28,9 +34,14 @@ const StyledButtonLabel = styled.div`
font-weight: 500;
`;
-export function EntityTableActionBarButton({ label, icon, onClick }: OwnProps) {
+export function EntityTableActionBarButton({
+ label,
+ icon,
+ type = 'standard',
+ onClick,
+}: OwnProps) {
return (
-
+
{icon}
{label}
diff --git a/front/src/components/table/action-bar/TableActionBarButtonOpenComments.tsx b/front/src/components/table/action-bar/TableActionBarButtonOpenComments.tsx
new file mode 100644
index 000000000..50d100775
--- /dev/null
+++ b/front/src/components/table/action-bar/TableActionBarButtonOpenComments.tsx
@@ -0,0 +1,19 @@
+import { FaRegComment } from 'react-icons/fa';
+import { EntityTableActionBarButton } from './EntityTableActionBarButton';
+import { useOpenRightDrawer } from '../../../modules/ui/layout/right-drawer/hooks/useOpenRightDrawer';
+
+export function TableActionBarButtonToggleComments() {
+ const openRightDrawer = useOpenRightDrawer();
+
+ async function handleButtonClick() {
+ openRightDrawer('comments');
+ }
+
+ return (
+ }
+ onClick={handleButtonClick}
+ />
+ );
+}
diff --git a/front/src/layout/AppLayout.tsx b/front/src/layout/AppLayout.tsx
index 2bf7c7b39..29a507c7b 100644
--- a/front/src/layout/AppLayout.tsx
+++ b/front/src/layout/AppLayout.tsx
@@ -1,4 +1,4 @@
-import Navbar from './navbar/Navbar';
+import { Navbar } from './navbar/Navbar';
import styled from '@emotion/styled';
import { ThemeProvider } from '@emotion/react';
import { User } from '../interfaces/entities/user.interface';
@@ -9,13 +9,15 @@ const StyledLayout = styled.div`
flex-direction: row;
width: 100vw;
height: 100vh;
+ background: ${(props) => props.theme.noisyBackground};
+ overflow: hidden;
`;
-const StyledRightContainer = styled.div`
+const MainContainer = styled.div`
display: flex;
flex-direction: row;
- flex: 1;
overflow: hidden;
+ widht: calc(100% - 220px);
`;
type OwnProps = {
@@ -28,7 +30,7 @@ function AppLayout({ children, user }: OwnProps) {
- {children}
+ {children}
);
diff --git a/front/src/layout/Panel.tsx b/front/src/layout/Panel.tsx
new file mode 100644
index 000000000..c0deaa998
--- /dev/null
+++ b/front/src/layout/Panel.tsx
@@ -0,0 +1,14 @@
+import styled from '@emotion/styled';
+import React from 'react';
+
+const StyledPanel = styled.div`
+ display: flex;
+ background: ${(props) => props.theme.primaryBackground};
+ border-radius: 8px;
+ border: 1px solid ${(props) => props.theme.primaryBorder};
+ width: 100%;
+`;
+
+export function Panel({ children }: { children: React.ReactNode }) {
+ return {children};
+}
diff --git a/front/src/layout/containers/MainContainer.tsx b/front/src/layout/containers/MainContainer.tsx
new file mode 100644
index 000000000..30ca40390
--- /dev/null
+++ b/front/src/layout/containers/MainContainer.tsx
@@ -0,0 +1,12 @@
+import styled from '@emotion/styled';
+import React from 'react';
+
+const StyledMainContainer = styled.div`
+ display: flex;
+ flex-direction: row;
+ overflow: hidden;
+`;
+
+export function MainContainer({ children }: { children: React.ReactNode }) {
+ return {children};
+}
diff --git a/front/src/layout/containers/WithTopBarContainer.tsx b/front/src/layout/containers/WithTopBarContainer.tsx
index 6dcf001b9..f3696a701 100644
--- a/front/src/layout/containers/WithTopBarContainer.tsx
+++ b/front/src/layout/containers/WithTopBarContainer.tsx
@@ -1,6 +1,10 @@
import styled from '@emotion/styled';
import TopBar from '../top-bar/TopBar';
import { ReactNode } from 'react';
+import { RightDrawer } from '../right-drawer/RightDrawer';
+import { Panel } from '../Panel';
+import { isRightDrawerOpenState } from '../../modules/ui/layout/right-drawer/states/isRightDrawerOpenState';
+import { useRecoilState } from 'recoil';
type OwnProps = {
children: JSX.Element;
@@ -11,30 +15,32 @@ type OwnProps = {
const StyledContainer = styled.div`
display: flex;
- flex: 1;
flex-direction: column;
- overflow: hidden;
+ width: 100%;
`;
-const ContentContainer = styled.div`
+const MainContainer = styled.div`
display: flex;
- position: relative;
- flex-direction: column;
- background: ${(props) => props.theme.noisyBackground};
- flex: 1;
- padding-right: ${(props) => props.theme.spacing(3)};
- padding-bottom: ${(props) => props.theme.spacing(3)};
- width: calc(100% - ${(props) => props.theme.spacing(3)});
- height: calc(100% - 54px);
-`;
-
-const ContentSubContainer = styled.div`
- display: flex;
- background: ${(props) => props.theme.primaryBackground};
- border-radius: 8px;
+ flex-direction: row;
height: 100%;
- flex: 1;
- border: 1px solid ${(props) => props.theme.primaryBorder};
+ width: calc(100% - 16px);
+ margin-right: 8px;
+ margin-bottom: 8px;
+ gap: 8px;
+ padding: 4px;
+`;
+
+const RIGHT_DRAWER_WIDTH = '300px';
+
+type LeftContainerProps = {
+ isRightDrawerOpen?: boolean;
+};
+
+const LeftContainer = styled.div`
+ display: flex;
+ width: calc(
+ 100% - ${(props) => (props.isRightDrawerOpen ? RIGHT_DRAWER_WIDTH : '0px')}
+ );
`;
function FullWidthContainer({
@@ -43,12 +49,17 @@ function FullWidthContainer({
icon,
onAddButtonClick,
}: OwnProps) {
+ const [isRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
+
return (
-
- {children}
-
+
+
+ {children}
+
+
+
);
}
diff --git a/front/src/layout/navbar/Navbar.tsx b/front/src/layout/navbar/Navbar.tsx
index 1173700fc..2223153b7 100644
--- a/front/src/layout/navbar/Navbar.tsx
+++ b/front/src/layout/navbar/Navbar.tsx
@@ -10,9 +10,9 @@ import { TbBuilding, TbUser } from 'react-icons/tb';
const NavbarContainer = styled.div`
display: flex;
flex-direction: column;
- background: ${(props) => props.theme.noisyBackground};
- min-width: 220px;
+ width: 220px;
padding: ${(props) => props.theme.spacing(2)};
+ flex-shrink: 0;
`;
const NavItemsContainer = styled.div`
@@ -26,7 +26,7 @@ type OwnProps = {
workspace?: Workspace;
};
-function Navbar({ workspace }: OwnProps) {
+export function Navbar({ workspace }: OwnProps) {
return (
<>
@@ -60,5 +60,3 @@ function Navbar({ workspace }: OwnProps) {
>
);
}
-
-export default Navbar;
diff --git a/front/src/layout/right-drawer/RightDrawer.tsx b/front/src/layout/right-drawer/RightDrawer.tsx
new file mode 100644
index 000000000..7a97bc5f1
--- /dev/null
+++ b/front/src/layout/right-drawer/RightDrawer.tsx
@@ -0,0 +1,30 @@
+import styled from '@emotion/styled';
+import { useRecoilState } from 'recoil';
+import { isRightDrawerOpenState } from '../../modules/ui/layout/right-drawer/states/isRightDrawerOpenState';
+import { RightDrawerRouter } from './RightDrawerRouter';
+import { rightDrawerPageState } from '../../modules/ui/layout/right-drawer/states/rightDrawerPageState';
+import { isDefined } from '../../modules/utils/type-guards/isDefined';
+import { Panel } from '../Panel';
+
+const StyledRightDrawer = styled.div`
+ display: flex;
+ flex-direction: row;
+ width: 300px;
+`;
+
+export function RightDrawer() {
+ const [isRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
+ const [rightDrawerPage] = useRecoilState(rightDrawerPageState);
+
+ if (!isRightDrawerOpen || !isDefined(rightDrawerPage)) {
+ return <>>;
+ }
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/front/src/layout/right-drawer/RightDrawerRouter.tsx b/front/src/layout/right-drawer/RightDrawerRouter.tsx
new file mode 100644
index 000000000..843dbe470
--- /dev/null
+++ b/front/src/layout/right-drawer/RightDrawerRouter.tsx
@@ -0,0 +1,14 @@
+import { useRecoilState } from 'recoil';
+import { rightDrawerPageState } from '../../modules/ui/layout/right-drawer/states/rightDrawerPageState';
+import { isDefined } from '../../modules/utils/type-guards/isDefined';
+import { RightDrawerComments } from '../../components/comments/RightDrawerComments';
+
+export function RightDrawerRouter() {
+ const [rightDrawerPage] = useRecoilState(rightDrawerPageState);
+
+ if (!isDefined(rightDrawerPage)) {
+ return <>>;
+ }
+
+ return rightDrawerPage === 'comments' ? : <>>;
+}
diff --git a/front/src/layout/right-drawer/RightDrawerTopBar.tsx b/front/src/layout/right-drawer/RightDrawerTopBar.tsx
new file mode 100644
index 000000000..fcb0ba7ff
--- /dev/null
+++ b/front/src/layout/right-drawer/RightDrawerTopBar.tsx
@@ -0,0 +1,34 @@
+import styled from '@emotion/styled';
+import { RightDrawerTopBarCloseButton } from './RightDrawerTopBarCloseButton';
+
+const StyledRightDrawerTopBar = styled.div`
+ display: flex;
+ flex-direction: row;
+ height: 40px;
+ align-items: center;
+ justify-content: space-between;
+ padding-left: 8px;
+ padding-right: 8px;
+ font-size: 13px;
+ color: ${(props) => props.theme.text60};
+ border-bottom: 1px solid ${(props) => props.theme.lightBorder};
+ width: 100%;
+`;
+
+const StyledTopBarTitle = styled.div`
+ align-items: center;
+ font-weight: 500;
+`;
+
+export function RightDrawerTopBar({
+ title,
+}: {
+ title: string | null | undefined;
+}) {
+ return (
+
+ {title}
+
+
+ );
+}
diff --git a/front/src/layout/right-drawer/RightDrawerTopBarCloseButton.tsx b/front/src/layout/right-drawer/RightDrawerTopBarCloseButton.tsx
new file mode 100644
index 000000000..4f507dec7
--- /dev/null
+++ b/front/src/layout/right-drawer/RightDrawerTopBarCloseButton.tsx
@@ -0,0 +1,37 @@
+import styled from '@emotion/styled';
+import { FaTimes } from 'react-icons/fa';
+import { useRecoilState } from 'recoil';
+import { isRightDrawerOpenState } from '../../modules/ui/layout/right-drawer/states/isRightDrawerOpenState';
+
+const StyledButton = styled.button`
+ height: 24px;
+ width: 24px;
+ border: 1px solid ${(props) => props.theme.lightBorder};
+ background: none;
+ cursor: pointer;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ padding: 8px;
+
+ border-radius: 4px;
+
+ transition: ${(props) => props.theme.clickableElementBackgroundTransition};
+ &:hover {
+ background: ${(props) => props.theme.clickableElementBackgroundHover};
+ }
+`;
+
+export function RightDrawerTopBarCloseButton() {
+ const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
+
+ function handleButtonClick() {
+ setIsRightDrawerOpen(false);
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/front/src/layout/styles/themes.ts b/front/src/layout/styles/themes.ts
index bbe14b601..7e3486f12 100644
--- a/front/src/layout/styles/themes.ts
+++ b/front/src/layout/styles/themes.ts
@@ -30,6 +30,10 @@ const lightThemeSpecific = {
secondaryBackgroundSmallTransparency: 'rgba(252, 252, 252, 0.97)',
primaryBorder: 'rgba(0, 0, 0, 0.08)',
+ lightBorder: '#f5f5f5',
+
+ clickableElementBackgroundHover: 'rgba(0, 0, 0, 0.04)',
+ clickableElementBackgroundTransition: 'background 0.1s ease',
text100: '#000',
text80: '#333333',
@@ -62,7 +66,11 @@ const darkThemeSpecific: typeof lightThemeSpecific = {
secondaryBackgroundSmallTransparency: 'rgba(23, 23, 23, 0.97)',
+ clickableElementBackgroundHover: 'rgba(0, 0, 0, 0.04)',
+ clickableElementBackgroundTransition: 'background 0.1s ease',
+
primaryBorder: 'rgba(255, 255, 255, 0.08)',
+ lightBorder: '#222222',
text100: '#ffffff',
text80: '#cccccc',
diff --git a/front/src/layout/top-bar/TopBar.tsx b/front/src/layout/top-bar/TopBar.tsx
index eb790c21d..9d3eda056 100644
--- a/front/src/layout/top-bar/TopBar.tsx
+++ b/front/src/layout/top-bar/TopBar.tsx
@@ -11,7 +11,6 @@ const TopBarContainer = styled.div`
padding: 8px;
font-size: 14px;
color: ${(props) => props.theme.text80};
- flex-shrink: 0;
`;
const TitleContainer = styled.div`
diff --git a/front/src/modules/ui/layout/right-drawer/hooks/useOpenRightDrawer.ts b/front/src/modules/ui/layout/right-drawer/hooks/useOpenRightDrawer.ts
new file mode 100644
index 000000000..dbce2d034
--- /dev/null
+++ b/front/src/modules/ui/layout/right-drawer/hooks/useOpenRightDrawer.ts
@@ -0,0 +1,14 @@
+import { useRecoilState } from 'recoil';
+import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState';
+import { rightDrawerPageState } from '../states/rightDrawerPageState';
+import { RightDrawerPage } from '../types/RightDrawerPage';
+
+export function useOpenRightDrawer() {
+ const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
+ const [, setRightDrawerPage] = useRecoilState(rightDrawerPageState);
+
+ return function openRightDrawer(rightDrawerPage: RightDrawerPage) {
+ setRightDrawerPage(rightDrawerPage);
+ setIsRightDrawerOpen(true);
+ };
+}
diff --git a/front/src/modules/ui/layout/right-drawer/states/isRightDrawerOpenState.ts b/front/src/modules/ui/layout/right-drawer/states/isRightDrawerOpenState.ts
new file mode 100644
index 000000000..fcfd62975
--- /dev/null
+++ b/front/src/modules/ui/layout/right-drawer/states/isRightDrawerOpenState.ts
@@ -0,0 +1,6 @@
+import { atom } from 'recoil';
+
+export const isRightDrawerOpenState = atom({
+ key: 'ui/layout/is-right-drawer-open',
+ default: false,
+});
diff --git a/front/src/modules/ui/layout/right-drawer/states/rightDrawerPageState.ts b/front/src/modules/ui/layout/right-drawer/states/rightDrawerPageState.ts
new file mode 100644
index 000000000..12641d91a
--- /dev/null
+++ b/front/src/modules/ui/layout/right-drawer/states/rightDrawerPageState.ts
@@ -0,0 +1,7 @@
+import { atom } from 'recoil';
+import { RightDrawerPage } from '../types/RightDrawerPage';
+
+export const rightDrawerPageState = atom({
+ key: 'ui/layout/right-drawer-page',
+ default: 'comments',
+});
diff --git a/front/src/modules/ui/layout/right-drawer/types/RightDrawerPage.ts b/front/src/modules/ui/layout/right-drawer/types/RightDrawerPage.ts
new file mode 100644
index 000000000..8fc92dbce
--- /dev/null
+++ b/front/src/modules/ui/layout/right-drawer/types/RightDrawerPage.ts
@@ -0,0 +1 @@
+export type RightDrawerPage = 'comments';
diff --git a/front/src/pages/companies/Companies.tsx b/front/src/pages/companies/Companies.tsx
index a27c9925e..306697e90 100644
--- a/front/src/pages/companies/Companies.tsx
+++ b/front/src/pages/companies/Companies.tsx
@@ -28,6 +28,7 @@ import { availableFilters } from './companies-filters';
import { TbBuilding } from 'react-icons/tb';
import { EntityTableActionBar } from '../../components/table/action-bar/EntityTableActionBar';
import { TableActionBarButtonDeleteCompanies } from './table/TableActionBarButtonDeleteCompanies';
+import { TableActionBarButtonToggleComments } from '../../components/table/action-bar/TableActionBarButtonOpenComments';
const StyledCompaniesContainer = styled.div`
display: flex;
@@ -91,6 +92,7 @@ function Companies() {
/>
+
>
diff --git a/front/src/pages/companies/table/TableActionBarButtonDeleteCompanies.tsx b/front/src/pages/companies/table/TableActionBarButtonDeleteCompanies.tsx
index fb8fa0f3a..4b4375bd4 100644
--- a/front/src/pages/companies/table/TableActionBarButtonDeleteCompanies.tsx
+++ b/front/src/pages/companies/table/TableActionBarButtonDeleteCompanies.tsx
@@ -4,9 +4,11 @@ import { useDeleteCompaniesMutation } from '../../../generated/graphql';
import { selectedRowIdsState } from '../../../modules/ui/tables/states/selectedRowIdsState';
import { useRecoilValue } from 'recoil';
import { useResetTableRowSelection } from '../../../modules/ui/tables/hooks/useResetTableRowSelection';
+import { useTheme } from '@emotion/react';
export function TableActionBarButtonDeleteCompanies() {
const selectedRowIds = useRecoilValue(selectedRowIdsState);
+ const theme = useTheme();
const resetRowSelection = useResetTableRowSelection();
@@ -28,6 +30,7 @@ export function TableActionBarButtonDeleteCompanies() {
}
+ type="warning"
onClick={handleDeleteClick}
/>
);
diff --git a/front/src/pages/people/People.tsx b/front/src/pages/people/People.tsx
index 8610ec0ee..eb49371d7 100644
--- a/front/src/pages/people/People.tsx
+++ b/front/src/pages/people/People.tsx
@@ -28,6 +28,7 @@ import { availableFilters } from './people-filters';
import { TbUser } from 'react-icons/tb';
import { EntityTableActionBar } from '../../components/table/action-bar/EntityTableActionBar';
import { TableActionBarButtonDeletePeople } from './table/TableActionBarButtonDeletePeople';
+import { TableActionBarButtonToggleComments } from '../../components/table/action-bar/TableActionBarButtonOpenComments';
const StyledPeopleContainer = styled.div`
display: flex;
@@ -93,6 +94,7 @@ function People() {
/>
+
>
diff --git a/front/src/pages/people/table/TableActionBarButtonDeletePeople.tsx b/front/src/pages/people/table/TableActionBarButtonDeletePeople.tsx
index 0d5c73ca0..8d0740469 100644
--- a/front/src/pages/people/table/TableActionBarButtonDeletePeople.tsx
+++ b/front/src/pages/people/table/TableActionBarButtonDeletePeople.tsx
@@ -28,6 +28,7 @@ export function TableActionBarButtonDeletePeople() {
}
+ type="warning"
onClick={handleDeleteClick}
/>
);