diff --git a/front/src/AppNavbar.tsx b/front/src/AppNavbar.tsx
index eae338d8c..218d941da 100644
--- a/front/src/AppNavbar.tsx
+++ b/front/src/AppNavbar.tsx
@@ -10,24 +10,23 @@ import {
IconTargetArrow,
IconUser,
} from '@/ui/icons/index';
-import NavItemsContainer from '@/ui/layout/navbar/NavItemsContainer';
+import { useIsSubNavbarDisplayed } from '@/ui/layout/hooks/useIsSubNavbarDisplayed';
+import MainNavbar from '@/ui/layout/navbar/MainNavbar';
import NavItem from './modules/ui/layout/navbar/NavItem';
import NavTitle from './modules/ui/layout/navbar/NavTitle';
-import NavWorkspaceButton from './modules/ui/layout/navbar/NavWorkspaceButton';
export function AppNavbar() {
const theme = useTheme();
const currentPath = useLocation().pathname;
- const shouldDiplaySubNavBar = currentPath.match(/\/settings\//g) !== null;
+ const isSubNavbarDisplayed = useIsSubNavbarDisplayed();
return (
<>
- {!shouldDiplaySubNavBar ? (
- <>
-
-
+ {!isSubNavbarDisplayed ? (
+
+ <>
}
active={currentPath === '/opportunities'}
/>
-
- >
+ >
+
) : (
)}
diff --git a/front/src/modules/comments/components/timeline/Timeline.tsx b/front/src/modules/comments/components/timeline/Timeline.tsx
index 67bf9276a..146529dd4 100644
--- a/front/src/modules/comments/components/timeline/Timeline.tsx
+++ b/front/src/modules/comments/components/timeline/Timeline.tsx
@@ -6,7 +6,7 @@ import { useOpenCommentThreadRightDrawer } from '@/comments/hooks/useOpenComment
import { useOpenCreateCommentThreadDrawer } from '@/comments/hooks/useOpenCreateCommentThreadDrawer';
import { CommentableEntity } from '@/comments/types/CommentableEntity';
import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer';
-import { IconCirclePlus, IconNotes } from '@/ui/icons/index';
+import { IconNotes } from '@/ui/icons/index';
import {
beautifyExactDate,
beautifyPastDateRelativeToNow,
@@ -221,10 +221,6 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
-
-
-
-
openCreateCommandThread(entity)}
/>
diff --git a/front/src/modules/settings/components/SettingsNavbar.tsx b/front/src/modules/settings/components/SettingsNavbar.tsx
index bcf87bb99..0fb34152a 100644
--- a/front/src/modules/settings/components/SettingsNavbar.tsx
+++ b/front/src/modules/settings/components/SettingsNavbar.tsx
@@ -11,9 +11,8 @@ import {
IconUsers,
} from '@/ui/icons/index';
import NavItem from '@/ui/layout/navbar/NavItem';
-import NavItemsContainer from '@/ui/layout/navbar/NavItemsContainer';
import NavTitle from '@/ui/layout/navbar/NavTitle';
-import SubNavbarContainer from '@/ui/layout/navbar/sub-navbar/SubNavBarContainer';
+import SubNavbar from '@/ui/layout/navbar/sub-navbar/SubNavbar';
export function SettingsNavbar() {
const theme = useTheme();
@@ -25,8 +24,8 @@ export function SettingsNavbar() {
}, [logout]);
return (
-
-
+
+ <>
}
danger={true}
/>
-
-
+ >
+
);
}
diff --git a/front/src/modules/ui/components/buttons/IconButton.tsx b/front/src/modules/ui/components/buttons/IconButton.tsx
index 70b79c90d..334187c28 100644
--- a/front/src/modules/ui/components/buttons/IconButton.tsx
+++ b/front/src/modules/ui/components/buttons/IconButton.tsx
@@ -1,33 +1,118 @@
+import React from 'react';
import styled from '@emotion/styled';
-const StyledIconButton = styled.button`
+export type IconButtonVariant = 'transparent' | 'border' | 'shadow' | 'white';
+
+export type IconButtonSize = 'large' | 'medium' | 'small';
+
+export type ButtonProps = {
+ icon?: React.ReactNode;
+ variant?: IconButtonVariant;
+ size?: IconButtonSize;
+} & React.ComponentProps<'button'>;
+
+const StyledIconButton = styled.button>`
align-items: center;
- background: ${({ theme }) => theme.color.blue};
- border: none;
+ background: ${({ theme, variant, disabled }) => {
+ switch (variant) {
+ case 'shadow':
+ case 'white':
+ return theme.background.transparent.lighter;
+ case 'transparent':
+ case 'border':
+ default:
+ return 'transparent';
+ }
+ }};
+ border-color: ${({ theme, variant }) => {
+ switch (variant) {
+ case 'border':
+ return theme.border.color.medium;
+ case 'shadow':
+ case 'white':
+ case 'transparent':
+ default:
+ return 'none';
+ }
+ }};
+ transition: background 0.1s ease;
+ border-radius: ${({ theme }) => {
+ return theme.border.radius.sm;
+ }};
+ border-width: ${({ variant }) => {
+ switch (variant) {
+ case 'border':
+ return '1px';
+ case 'shadow':
+ case 'white':
+ case 'transparent':
+ default:
+ return 0;
+ }
+ }};
+ color: ${({ theme, disabled }) => {
+ if (disabled) {
+ return theme.font.color.extraLight;
+ }
- border-radius: 50%;
- color: ${({ theme }) => theme.font.color.inverted};
-
- cursor: pointer;
+ return theme.font.color.tertiary;
+ }};
+ border-style: solid;
+ cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
+ height: ${({ size }) => {
+ switch (size) {
+ case 'large':
+ return '32px';
+ case 'medium':
+ return '24px';
+ case 'small':
+ default:
+ return '20px';
+ }
+ }};
display: flex;
- height: 20px;
-
justify-content: center;
-
padding: 0;
- transition: color 0.1s ease-in-out, background 0.1s ease-in-out;
- width: 20px;
-
- &:disabled {
- background: ${({ theme }) => theme.background.quaternary};
- color: ${({ theme }) => theme.font.color.tertiary};
- cursor: default;
+ width: ${({ size }) => {
+ switch (size) {
+ case 'large':
+ return '32px';
+ case 'medium':
+ return '24px';
+ case 'small':
+ default:
+ return '20px';
+ }
+ }};
+ flex-shrink: 0;
+ &:hover {
+ background: ${({ theme, disabled }) => {
+ return disabled ? 'auto' : theme.background.transparent.light;
+ }};
}
+ user-select: none;
+ &:active {
+ background: ${({ theme, disabled }) => {
+ return disabled ? 'auto' : theme.background.transparent.medium;
+ }};
`;
export function IconButton({
icon,
+ title,
+ variant = 'transparent',
+ size = 'medium',
+ disabled = false,
...props
-}: { icon: React.ReactNode } & React.ButtonHTMLAttributes) {
- return {icon};
+}: ButtonProps) {
+ return (
+
+ {icon}
+
+ );
}
diff --git a/front/src/modules/ui/components/buttons/RoundedIconButton.tsx b/front/src/modules/ui/components/buttons/RoundedIconButton.tsx
new file mode 100644
index 000000000..ae49fffd7
--- /dev/null
+++ b/front/src/modules/ui/components/buttons/RoundedIconButton.tsx
@@ -0,0 +1,33 @@
+import styled from '@emotion/styled';
+
+const StyledIconButton = styled.button`
+ align-items: center;
+ background: ${({ theme }) => theme.color.blue};
+ border: none;
+
+ border-radius: 50%;
+ color: ${({ theme }) => theme.font.color.inverted};
+
+ cursor: pointer;
+ display: flex;
+ height: 20px;
+
+ justify-content: center;
+
+ padding: 0;
+ transition: color 0.1s ease-in-out, background 0.1s ease-in-out;
+ width: 20px;
+
+ &:disabled {
+ background: ${({ theme }) => theme.background.quaternary};
+ color: ${({ theme }) => theme.font.color.tertiary};
+ cursor: default;
+ }
+`;
+
+export function RoundedIconButton({
+ icon,
+ ...props
+}: { icon: React.ReactNode } & React.ButtonHTMLAttributes) {
+ return {icon};
+}
diff --git a/front/src/modules/ui/components/buttons/__stories__/IconButton.stories.tsx b/front/src/modules/ui/components/buttons/__stories__/IconButton.stories.tsx
index b875f901e..4a96c6f1e 100644
--- a/front/src/modules/ui/components/buttons/__stories__/IconButton.stories.tsx
+++ b/front/src/modules/ui/components/buttons/__stories__/IconButton.stories.tsx
@@ -1,33 +1,153 @@
+import React from 'react';
+import styled from '@emotion/styled';
+import { withKnobs } from '@storybook/addon-knobs';
import { expect, jest } from '@storybook/jest';
import type { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
-import { IconArrowRight } from '@/ui/icons';
+import { IconUser } from '@/ui/icons';
import { getRenderWrapperForComponent } from '~/testing/renderWrappers';
import { IconButton } from '../IconButton';
+type IconButtonProps = React.ComponentProps;
+
+const StyledContainer = styled.div`
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ width: 800px;
+ > * + * {
+ margin-top: ${({ theme }) => theme.spacing(4)};
+ }
+`;
+
+const StyledTitle = styled.h1`
+ font-size: ${({ theme }) => theme.font.size.lg};
+ font-weight: ${({ theme }) => theme.font.weight.semiBold};
+ margin-bottom: ${({ theme }) => theme.spacing(2)};
+ margin-top: ${({ theme }) => theme.spacing(3)};
+`;
+
+const StyledDescription = styled.span`
+ color: ${({ theme }) => theme.font.color.light};
+ font-size: ${({ theme }) => theme.font.size.xs};
+ font-weight: ${({ theme }) => theme.font.weight.semiBold};
+ margin-bottom: ${({ theme }) => theme.spacing(1)};
+ text-align: center;
+ text-transform: uppercase;
+`;
+
+const StyledLine = styled.div`
+ display: flex;
+ flex: 1;
+ flex-direction: row;
+`;
+
+const StyledIconButtonContainer = styled.div`
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ padding: ${({ theme }) => theme.spacing(2)};
+ width: 50px;
+`;
+
const meta: Meta = {
title: 'UI/Buttons/IconButton',
component: IconButton,
+ decorators: [withKnobs],
};
export default meta;
type Story = StoryObj;
+const variants: IconButtonProps['variant'][] = [
+ 'transparent',
+ 'border',
+ 'shadow',
+ 'white',
+];
+
const clickJestFn = jest.fn();
-export const Default: Story = {
+const states = {
+ default: {
+ description: 'Default',
+ extraProps: (variant: string) => ({
+ 'data-testid': `${variant}-button-default`,
+ onClick: clickJestFn,
+ }),
+ },
+ hover: {
+ description: 'Hover',
+ extraProps: (variant: string) => ({
+ id: `${variant}-button-hover`,
+ 'data-testid': `${variant}-button-hover`,
+ }),
+ },
+ pressed: {
+ description: 'Pressed',
+ extraProps: (variant: string) => ({
+ id: `${variant}-button-pressed`,
+ 'data-testid': `${variant}-button-pressed`,
+ }),
+ },
+ disabled: {
+ description: 'Disabled',
+ extraProps: (variant: string) => ({
+ 'data-testid': `${variant}-button-disabled`,
+ disabled: true,
+ }),
+ },
+};
+
+function IconButtonRow({ variant, size, ...props }: IconButtonProps) {
+ const iconSize = size === 'small' ? 14 : 16;
+ return (
+ <>
+ {Object.entries(states).map(([state, { description, extraProps }]) => (
+
+ {description}
+ }
+ />
+
+ ))}
+ >
+ );
+}
+
+const generateStory = (
+ size: IconButtonProps['size'],
+ LineComponent: React.ComponentType,
+): Story => ({
render: getRenderWrapperForComponent(
- } />,
+
+ {variants.map((variant) => (
+
+ {variant}
+
+
+
+
+ ))}
+ ,
),
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
- expect(clickJestFn).toHaveBeenCalledTimes(0);
- const button = canvas.getByRole('button');
- await userEvent.click(button);
+ const button = canvas.getByTestId(`transparent-button-default`);
- expect(clickJestFn).toHaveBeenCalledTimes(1);
+ const numberOfClicks = clickJestFn.mock.calls.length;
+ await userEvent.click(button);
+ expect(clickJestFn).toHaveBeenCalledTimes(numberOfClicks + 1);
},
-};
+});
+
+export const LargeSize = generateStory('large', IconButtonRow);
+export const MediumSize = generateStory('medium', IconButtonRow);
+export const SmallSize = generateStory('small', IconButtonRow);
diff --git a/front/src/modules/ui/components/buttons/__stories__/RoundedIconButton.stories.tsx b/front/src/modules/ui/components/buttons/__stories__/RoundedIconButton.stories.tsx
new file mode 100644
index 000000000..647282852
--- /dev/null
+++ b/front/src/modules/ui/components/buttons/__stories__/RoundedIconButton.stories.tsx
@@ -0,0 +1,36 @@
+import { expect, jest } from '@storybook/jest';
+import type { Meta, StoryObj } from '@storybook/react';
+import { userEvent, within } from '@storybook/testing-library';
+
+import { IconArrowRight } from '@/ui/icons';
+import { getRenderWrapperForComponent } from '~/testing/renderWrappers';
+
+import { RoundedIconButton } from '../RoundedIconButton';
+
+const meta: Meta = {
+ title: 'UI/Buttons/RoundedIconButton',
+ component: RoundedIconButton,
+};
+
+export default meta;
+type Story = StoryObj;
+
+const clickJestFn = jest.fn();
+
+export const Default: Story = {
+ render: getRenderWrapperForComponent(
+ }
+ />,
+ ),
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+
+ expect(clickJestFn).toHaveBeenCalledTimes(0);
+ const button = canvas.getByRole('button');
+ await userEvent.click(button);
+
+ expect(clickJestFn).toHaveBeenCalledTimes(1);
+ },
+};
diff --git a/front/src/modules/ui/components/inputs/AutosizeTextInput.tsx b/front/src/modules/ui/components/inputs/AutosizeTextInput.tsx
index 7ce375878..28c5d48d0 100644
--- a/front/src/modules/ui/components/inputs/AutosizeTextInput.tsx
+++ b/front/src/modules/ui/components/inputs/AutosizeTextInput.tsx
@@ -4,7 +4,7 @@ import { HotkeysEvent } from 'react-hotkeys-hook/dist/types';
import TextareaAutosize from 'react-textarea-autosize';
import styled from '@emotion/styled';
-import { IconButton } from '@/ui/components/buttons/IconButton';
+import { RoundedIconButton } from '@/ui/components/buttons/RoundedIconButton';
import { IconArrowRight } from '@/ui/icons/index';
const MAX_ROWS = 5;
@@ -47,7 +47,7 @@ const StyledTextArea = styled(TextareaAutosize)`
`;
// TODO: this messes with the layout, fix it
-const StyledBottomRightIconButton = styled.div`
+const StyledBottomRightRoundedIconButton = styled.div`
height: 0;
position: relative;
right: 26px;
@@ -129,13 +129,13 @@ export function AutosizeTextInput({
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
-
-
+ }
disabled={isSendButtonDisabled}
/>
-
+
>
);
diff --git a/front/src/modules/ui/components/table/EntityTableBody.tsx b/front/src/modules/ui/components/table/EntityTableBody.tsx
index 2f749007b..b4e88a135 100644
--- a/front/src/modules/ui/components/table/EntityTableBody.tsx
+++ b/front/src/modules/ui/components/table/EntityTableBody.tsx
@@ -2,6 +2,7 @@ import { useRecoilValue } from 'recoil';
import { TableColumn } from '@/people/table/components/peopleColumns';
import { RecoilScope } from '@/recoil-scope/components/RecoilScope';
+import { isNavbarSwitchingSizeState } from '@/ui/layout/states/isNavbarSwitchingSizeState';
import { isFetchingEntityTableDataState } from '@/ui/tables/states/isFetchingEntityTableDataState';
import { RowContext } from '@/ui/tables/states/RowContext';
import { tableRowIdsState } from '@/ui/tables/states/tableRowIdsState';
@@ -11,13 +12,15 @@ import { EntityTableRow } from './EntityTableRow';
export function EntityTableBody({ columns }: { columns: Array }) {
const rowIds = useRecoilValue(tableRowIdsState);
+ const isNavbarSwitchingSize = useRecoilValue(isNavbarSwitchingSizeState);
+
const isFetchingEntityTableData = useRecoilValue(
isFetchingEntityTableDataState,
);
return (
- {!isFetchingEntityTableData
+ {!isFetchingEntityTableData && !isNavbarSwitchingSize
? rowIds.map((rowId, index) => (
diff --git a/front/src/modules/ui/layout/DefaultLayout.tsx b/front/src/modules/ui/layout/DefaultLayout.tsx
index db490dca8..57d58ba64 100644
--- a/front/src/modules/ui/layout/DefaultLayout.tsx
+++ b/front/src/modules/ui/layout/DefaultLayout.tsx
@@ -7,7 +7,7 @@ import { AppNavbar } from '~/AppNavbar';
import { MOBILE_VIEWPORT } from '../themes/themes';
-import { NavbarContainer } from './navbar/NavbarContainer';
+import { NavbarAnimatedContainer } from './navbar/NavbarAnimatedContainer';
import { isNavbarOpenedState } from './states/isNavbarOpenedState';
const StyledLayout = styled.div`
@@ -47,9 +47,9 @@ export function DefaultLayout({ children }: OwnProps) {
{userIsAuthenticated ? (
<>
-
+
-
+
{children}
>
) : (
diff --git a/front/src/modules/ui/layout/hooks/useIsSubNavbarDisplayed.ts b/front/src/modules/ui/layout/hooks/useIsSubNavbarDisplayed.ts
new file mode 100644
index 000000000..fbc9bff39
--- /dev/null
+++ b/front/src/modules/ui/layout/hooks/useIsSubNavbarDisplayed.ts
@@ -0,0 +1,6 @@
+import { useLocation } from 'react-router-dom';
+
+export function useIsSubNavbarDisplayed() {
+ const currentPath = useLocation().pathname;
+ return currentPath.match(/\/settings\//g) !== null;
+}
diff --git a/front/src/modules/ui/layout/navbar/MainNavbar.tsx b/front/src/modules/ui/layout/navbar/MainNavbar.tsx
new file mode 100644
index 000000000..3eef39791
--- /dev/null
+++ b/front/src/modules/ui/layout/navbar/MainNavbar.tsx
@@ -0,0 +1,21 @@
+import styled from '@emotion/styled';
+
+import NavItemsContainer from './NavItemsContainer';
+import NavWorkspaceButton from './NavWorkspaceButton';
+
+type OwnProps = {
+ children: JSX.Element;
+};
+
+const StyledContainer = styled.div`
+ width: 220px;
+`;
+
+export default function MainNavbar({ children }: OwnProps) {
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/front/src/modules/ui/layout/navbar/NavItemsContainer.tsx b/front/src/modules/ui/layout/navbar/NavItemsContainer.tsx
index 56e1356ac..452ec3b28 100644
--- a/front/src/modules/ui/layout/navbar/NavItemsContainer.tsx
+++ b/front/src/modules/ui/layout/navbar/NavItemsContainer.tsx
@@ -8,7 +8,6 @@ const StyledNavItemsContainer = styled.div`
display: flex;
flex-direction: column;
margin-top: 40px;
- min-width: 220px;
`;
function NavItemsContainer({ children }: OwnProps) {
diff --git a/front/src/modules/ui/layout/navbar/NavbarAnimatedContainer.tsx b/front/src/modules/ui/layout/navbar/NavbarAnimatedContainer.tsx
new file mode 100644
index 000000000..4ac742e53
--- /dev/null
+++ b/front/src/modules/ui/layout/navbar/NavbarAnimatedContainer.tsx
@@ -0,0 +1,57 @@
+import { useTheme } from '@emotion/react';
+import styled from '@emotion/styled';
+import { motion } from 'framer-motion';
+import { useRecoilState, useRecoilValue } from 'recoil';
+
+import { MOBILE_VIEWPORT } from '@/ui/themes/themes';
+
+import { useIsSubNavbarDisplayed } from '../hooks/useIsSubNavbarDisplayed';
+import { isNavbarOpenedState } from '../states/isNavbarOpenedState';
+import { isNavbarSwitchingSizeState } from '../states/isNavbarSwitchingSizeState';
+
+const StyledNavbarContainer = styled(motion.div)`
+ align-items: end;
+ display: flex;
+ flex-direction: column;
+ flex-shrink: 0;
+ overflow: hidden;
+ padding: ${({ theme }) => theme.spacing(2)};
+
+ @media (max-width: ${MOBILE_VIEWPORT}px) {
+ width: ${(props) =>
+ useRecoilValue(isNavbarOpenedState)
+ ? `calc(100% - ` + props.theme.spacing(4) + `)`
+ : '0'};
+ }
+`;
+
+type NavbarProps = {
+ children: React.ReactNode;
+ layout?: string;
+};
+
+export function NavbarAnimatedContainer({ children, layout }: NavbarProps) {
+ const isMenuOpened = useRecoilValue(isNavbarOpenedState);
+ const [, setIsNavbarSwitchingSize] = useRecoilState(
+ isNavbarSwitchingSizeState,
+ );
+ const isSubNavbarDisplayed = useIsSubNavbarDisplayed();
+ const theme = useTheme();
+
+ return (
+ {
+ setIsNavbarSwitchingSize(false);
+ }}
+ animate={{
+ width: isMenuOpened ? (isSubNavbarDisplayed ? '520px' : '220px') : '0',
+ opacity: isMenuOpened ? 1 : 0,
+ }}
+ transition={{
+ duration: theme.animation.duration.visible,
+ }}
+ >
+ {children}
+
+ );
+}
diff --git a/front/src/modules/ui/layout/navbar/NavbarContainer.tsx b/front/src/modules/ui/layout/navbar/NavbarContainer.tsx
deleted file mode 100644
index 81b1d20c1..000000000
--- a/front/src/modules/ui/layout/navbar/NavbarContainer.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import styled from '@emotion/styled';
-import { useRecoilValue } from 'recoil';
-
-import { MOBILE_VIEWPORT } from '@/ui/themes/themes';
-
-import { isNavbarOpenedState } from '../states/isNavbarOpenedState';
-
-const StyledNavbarContainer = styled.div`
- flex-direction: column;
- flex-shrink: 0;
- overflow: hidden;
- padding: ${({ theme }) => theme.spacing(2)};
- width: ${(props) => (useRecoilValue(isNavbarOpenedState) ? 'auto' : '0')};
-
- @media (max-width: ${MOBILE_VIEWPORT}px) {
- width: ${(props) =>
- useRecoilValue(isNavbarOpenedState)
- ? `calc(100% - ` + props.theme.spacing(4) + `)`
- : '0'};
- }
-`;
-
-const NavbarContent = styled.div`
- display: ${() => (useRecoilValue(isNavbarOpenedState) ? 'block' : 'none')};
-`;
-
-type NavbarProps = {
- children: React.ReactNode;
- layout?: string;
-};
-
-export function NavbarContainer({ children, layout }: NavbarProps) {
- return (
-
- {children}
-
- );
-}
diff --git a/front/src/modules/ui/layout/navbar/sub-navbar/NavBackButton.tsx b/front/src/modules/ui/layout/navbar/sub-navbar/NavBackButton.tsx
index da97abcbb..177baa16c 100644
--- a/front/src/modules/ui/layout/navbar/sub-navbar/NavBackButton.tsx
+++ b/front/src/modules/ui/layout/navbar/sub-navbar/NavBackButton.tsx
@@ -1,8 +1,10 @@
import { useNavigate } from 'react-router-dom';
import styled from '@emotion/styled';
+import { useRecoilState } from 'recoil';
import { IconChevronLeft } from '@/ui/icons/index';
+import { isNavbarSwitchingSizeState } from '../../states/isNavbarSwitchingSizeState';
import NavCollapseButton from '../NavCollapseButton';
type OwnProps = {
@@ -32,12 +34,18 @@ const StyledContainer = styled.div`
export default function NavBackButton({ title }: OwnProps) {
const navigate = useNavigate();
+ const [, setIsNavbarSwitchingSize] = useRecoilState(
+ isNavbarSwitchingSizeState,
+ );
return (
<>
navigate('/', { replace: true })}
+ onClick={() => {
+ setIsNavbarSwitchingSize(true);
+ navigate('/', { replace: true });
+ }}
>
{title}
diff --git a/front/src/modules/ui/layout/navbar/sub-navbar/SubNavBarContainer.tsx b/front/src/modules/ui/layout/navbar/sub-navbar/SubNavbar.tsx
similarity index 59%
rename from front/src/modules/ui/layout/navbar/sub-navbar/SubNavBarContainer.tsx
rename to front/src/modules/ui/layout/navbar/sub-navbar/SubNavbar.tsx
index 9f7e19e94..9a7585170 100644
--- a/front/src/modules/ui/layout/navbar/sub-navbar/SubNavBarContainer.tsx
+++ b/front/src/modules/ui/layout/navbar/sub-navbar/SubNavbar.tsx
@@ -1,5 +1,7 @@
import styled from '@emotion/styled';
+import NavItemsContainer from '../NavItemsContainer';
+
import NavBackButton from './NavBackButton';
type OwnProps = {
@@ -10,23 +12,15 @@ type OwnProps = {
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
- padding-left: 300px;
padding-top: ${({ theme }) => theme.spacing(6)};
+ width: 220px;
`;
-const StyledNavItemsContainer = styled.div`
- display: flex;
- flex-direction: column;
-`;
-
-export default function SubNavbarContainer({
- children,
- backButtonTitle,
-}: OwnProps) {
+export default function SubNavbar({ children, backButtonTitle }: OwnProps) {
return (
- {children}
+ {children}
);
}
diff --git a/front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx
index 77443ad5b..c43d8ddec 100644
--- a/front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx
+++ b/front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx
@@ -1,5 +1,7 @@
import { useRef } from 'react';
+import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
+import { motion } from 'framer-motion';
import { useRecoilState } from 'recoil';
import {
@@ -13,16 +15,15 @@ import { rightDrawerPageState } from '../states/rightDrawerPageState';
import { RightDrawerRouter } from './RightDrawerRouter';
-const StyledContainer = styled.div`
+const StyledContainer = styled(motion.div)`
background: ${({ theme }) => theme.background.primary};
box-shadow: ${({ theme }) => theme.boxShadow.strong};
height: 100%;
overflow-x: hidden;
position: fixed;
+
right: 0;
top: 0;
- transition: width 0.5s;
- width: ${({ theme }) => theme.rightDrawerWidth};
z-index: 2;
`;
@@ -45,17 +46,23 @@ export function RightDrawer() {
callback: () => setIsRightDrawerOpen(false),
mode: OutsideClickAlerterMode.absolute,
});
- if (!isRightDrawerOpen || !isDefined(rightDrawerPage)) {
+ const theme = useTheme();
+ if (!isDefined(rightDrawerPage)) {
return <>>;
}
return (
- <>
-
-
-
-
-
- >
+
+
+
+
+
);
}
diff --git a/front/src/modules/ui/layout/states/isNavbarSwitchingSizeState.ts b/front/src/modules/ui/layout/states/isNavbarSwitchingSizeState.ts
new file mode 100644
index 000000000..c9a524484
--- /dev/null
+++ b/front/src/modules/ui/layout/states/isNavbarSwitchingSizeState.ts
@@ -0,0 +1,6 @@
+import { atom } from 'recoil';
+
+export const isNavbarSwitchingSizeState = atom({
+ key: 'ui/isNavbarSwitchingSizeState',
+ default: true,
+});
diff --git a/front/src/modules/ui/layout/top-bar/TopBar.tsx b/front/src/modules/ui/layout/top-bar/TopBar.tsx
index 3b3fd85db..deb625c45 100644
--- a/front/src/modules/ui/layout/top-bar/TopBar.tsx
+++ b/front/src/modules/ui/layout/top-bar/TopBar.tsx
@@ -1,6 +1,7 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
+import { IconButton } from '@/ui/components/buttons/IconButton';
import { IconPlus } from '@/ui/icons/index';
import NavCollapseButton from '../navbar/NavCollapseButton';
@@ -16,6 +17,7 @@ const TopBarContainer = styled.div`
font-size: 14px;
min-height: ${TOP_BAR_MIN_HEIGHT}px;
padding: ${({ theme }) => theme.spacing(2)};
+ padding-right: ${({ theme }) => theme.spacing(3)};
`;
const TitleContainer = styled.div`
@@ -26,22 +28,6 @@ const TitleContainer = styled.div`
width: 100%;
`;
-const AddButtonContainer = styled.div`
- align-items: center;
- border: 1px solid ${({ theme }) => theme.border.color.medium};
- border-radius: ${({ theme }) => theme.border.radius.sm};
- color: ${({ theme }) => theme.font.color.tertiary};
- cursor: pointer;
- display: flex;
- flex-shrink: 0;
- height: 28px;
- justify-content: center;
- justify-self: flex-end;
- margin-right: ${({ theme }) => theme.spacing(1)};
- user-select: none;
- width: 28px;
-`;
-
type OwnProps = {
title: string;
icon: ReactNode;
@@ -56,12 +42,13 @@ export function TopBar({ title, icon, onAddButtonClick }: OwnProps) {
{icon}
{title}
{onAddButtonClick && (
- }
+ size="large"
data-testid="add-button"
onClick={onAddButtonClick}
- >
-
-
+ variant="border"
+ />
)}
>
diff --git a/front/src/modules/ui/themes/animation.ts b/front/src/modules/ui/themes/animation.ts
new file mode 100644
index 000000000..422a1ad91
--- /dev/null
+++ b/front/src/modules/ui/themes/animation.ts
@@ -0,0 +1,6 @@
+export const animation = {
+ duration: {
+ instant: 0.1,
+ visible: 0.3,
+ },
+};
diff --git a/front/src/modules/ui/themes/themes.ts b/front/src/modules/ui/themes/themes.ts
index 85bff0f12..3bfd0ad31 100644
--- a/front/src/modules/ui/themes/themes.ts
+++ b/front/src/modules/ui/themes/themes.ts
@@ -1,3 +1,4 @@
+import { animation } from './animation';
import { backgroundDark, backgroundLight } from './background';
import { blur } from './blur';
import { borderDark, borderLight } from './border';
@@ -13,6 +14,7 @@ const common = {
icon: icon,
text: text,
blur: blur,
+ animation: animation,
snackBar: {
success: {
background: '#16A26B',