Uniformize folder structure (#693)
* Uniformize folder structure * Fix icons * Fix icons * Fix tests * Fix tests
This commit is contained in:
68
front/src/modules/ui/right-drawer/components/RightDrawer.tsx
Normal file
68
front/src/modules/ui/right-drawer/components/RightDrawer.tsx
Normal file
@ -0,0 +1,68 @@
|
||||
import { useRef } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import {
|
||||
OutsideClickAlerterMode,
|
||||
useOutsideAlerter,
|
||||
} from '@/ui/hooks/useOutsideAlerter';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState';
|
||||
import { rightDrawerPageState } from '../states/rightDrawerPageState';
|
||||
|
||||
import { RightDrawerRouter } from './RightDrawerRouter';
|
||||
|
||||
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;
|
||||
z-index: 2;
|
||||
`;
|
||||
|
||||
const StyledRightDrawer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export function RightDrawer() {
|
||||
const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState(
|
||||
isRightDrawerOpenState,
|
||||
);
|
||||
|
||||
const [rightDrawerPage] = useRecoilState(rightDrawerPageState);
|
||||
|
||||
const rightDrawerRef = useRef(null);
|
||||
useOutsideAlerter({
|
||||
ref: rightDrawerRef,
|
||||
callback: () => setIsRightDrawerOpen(false),
|
||||
mode: OutsideClickAlerterMode.absolute,
|
||||
});
|
||||
const theme = useTheme();
|
||||
if (!isDefined(rightDrawerPage)) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledContainer
|
||||
animate={{
|
||||
width: isRightDrawerOpen ? theme.rightDrawerWidth : '0',
|
||||
}}
|
||||
transition={{
|
||||
duration: theme.animation.duration.visible,
|
||||
}}
|
||||
>
|
||||
<StyledRightDrawer ref={rightDrawerRef}>
|
||||
<RightDrawerRouter />
|
||||
</StyledRightDrawer>
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const RightDrawerBody = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: calc(
|
||||
100vh - ${({ theme }) => theme.spacing(14)} - 1px
|
||||
); // (-1 for border)
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
`;
|
||||
@ -0,0 +1,8 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
export const RightDrawerPage = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
`;
|
||||
@ -0,0 +1,28 @@
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { RightDrawerCreateCommentThread } from '@/activities/right-drawer/components/create/RightDrawerCreateCommentThread';
|
||||
import { RightDrawerEditCommentThread } from '@/activities/right-drawer/components/edit/RightDrawerEditCommentThread';
|
||||
import { RightDrawerTimeline } from '@/activities/right-drawer/components/RightDrawerTimeline';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { rightDrawerPageState } from '../states/rightDrawerPageState';
|
||||
import { RightDrawerPages } from '../types/RightDrawerPages';
|
||||
|
||||
export function RightDrawerRouter() {
|
||||
const [rightDrawerPage] = useRecoilState(rightDrawerPageState);
|
||||
|
||||
if (!isDefined(rightDrawerPage)) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
switch (rightDrawerPage) {
|
||||
case RightDrawerPages.Timeline:
|
||||
return <RightDrawerTimeline />;
|
||||
case RightDrawerPages.CreateCommentThread:
|
||||
return <RightDrawerCreateCommentThread />;
|
||||
case RightDrawerPages.EditCommentThread:
|
||||
return <RightDrawerEditCommentThread />;
|
||||
default:
|
||||
return <></>;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RightDrawerTopBarCloseButton } from './RightDrawerTopBarCloseButton';
|
||||
|
||||
const StyledRightDrawerTopBar = styled.div`
|
||||
align-items: center;
|
||||
background: ${({ theme }) => theme.background.secondary};
|
||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
color: ${({ theme }) => theme.font.color.secondary};
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: ${({ theme }) => theme.font.size.md};
|
||||
height: 56px;
|
||||
justify-content: space-between;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
title?: string | null | undefined;
|
||||
};
|
||||
|
||||
export function RightDrawerTopBar({ title }: OwnProps) {
|
||||
return (
|
||||
<StyledRightDrawerTopBar>
|
||||
<RightDrawerTopBarCloseButton />
|
||||
</StyledRightDrawerTopBar>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { IconChevronsRight } from '@/ui/icon/index';
|
||||
|
||||
import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState';
|
||||
|
||||
const StyledButton = styled.button`
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: 1px solid ${({ theme }) => theme.border.color.light};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 24px;
|
||||
padding: 3px;
|
||||
|
||||
transition: ${({ theme }) => theme.clickableElementBackgroundTransition};
|
||||
|
||||
width: 24px;
|
||||
&:hover {
|
||||
background: ${({ theme }) => theme.background.transparent.light};
|
||||
}
|
||||
svg {
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
export function RightDrawerTopBarCloseButton() {
|
||||
const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
|
||||
|
||||
function handleButtonClick() {
|
||||
setIsRightDrawerOpen(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledButton onClick={handleButtonClick}>
|
||||
<IconChevronsRight size={16} />
|
||||
</StyledButton>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { getRenderWrapperForComponent } from '~/testing/renderWrappers';
|
||||
|
||||
import { RightDrawerTopBar } from '../RightDrawerTopBar';
|
||||
|
||||
const meta: Meta<typeof RightDrawerTopBar> = {
|
||||
title: 'UI/RightDrawer/RightDrawerTopBar',
|
||||
component: RightDrawerTopBar,
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
defaultValue: 'My Title',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof RightDrawerTopBar>;
|
||||
|
||||
export const Default: Story = {
|
||||
render: getRenderWrapperForComponent(
|
||||
<div style={{ width: '500px' }}>
|
||||
<RightDrawerTopBar title={'Title'} />
|
||||
</div>,
|
||||
),
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
actions: { argTypesRegex: '^on.*' },
|
||||
},
|
||||
args: {},
|
||||
};
|
||||
@ -0,0 +1,15 @@
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState';
|
||||
import { rightDrawerPageState } from '../states/rightDrawerPageState';
|
||||
import { RightDrawerPages } from '../types/RightDrawerPages';
|
||||
|
||||
export function useOpenRightDrawer() {
|
||||
const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
|
||||
const [, setRightDrawerPage] = useRecoilState(rightDrawerPageState);
|
||||
|
||||
return function openRightDrawer(rightDrawerPage: RightDrawerPages) {
|
||||
setRightDrawerPage(rightDrawerPage);
|
||||
setIsRightDrawerOpen(true);
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const isRightDrawerOpenState = atom<boolean>({
|
||||
key: 'ui/layout/is-right-drawer-open',
|
||||
default: false,
|
||||
});
|
||||
@ -0,0 +1,8 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { RightDrawerPages } from '../types/RightDrawerPages';
|
||||
|
||||
export const rightDrawerPageState = atom<RightDrawerPages | null>({
|
||||
key: 'ui/layout/right-drawer-page',
|
||||
default: null,
|
||||
});
|
||||
@ -0,0 +1,3 @@
|
||||
export enum RightDrawerHotkeyScope {
|
||||
RightDrawer = 'right-drawer',
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
export enum RightDrawerPages {
|
||||
Timeline = 'timeline',
|
||||
CreateCommentThread = 'create-comment-thread',
|
||||
EditCommentThread = 'edit-comment-thread',
|
||||
}
|
||||
Reference in New Issue
Block a user