mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-11-30 04:12:15 +03:00
feat: refact workspace modal
This commit is contained in:
parent
056c657721
commit
2dba0927ef
56
packages/app/src/components/workspace-modal/Footer.tsx
Normal file
56
packages/app/src/components/workspace-modal/Footer.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { CloudInsyncIcon, LogOutIcon } from '@blocksuite/icons';
|
||||
import { Wrapper } from '@/ui/layout';
|
||||
import { WorkspaceAvatar } from '@/components/workspace-avatar';
|
||||
import { IconButton } from '@/ui/button';
|
||||
import { useAppState } from '@/providers/app-state-provider';
|
||||
import { StyledFooter, StyleUserInfo, StyleSignIn } from './styles';
|
||||
|
||||
export const Footer = ({
|
||||
onLogin,
|
||||
onLogout,
|
||||
}: {
|
||||
onLogin: () => void;
|
||||
onLogout: () => void;
|
||||
}) => {
|
||||
const { user } = useAppState();
|
||||
|
||||
return (
|
||||
<StyledFooter>
|
||||
{user && (
|
||||
<>
|
||||
<Wrapper>
|
||||
<WorkspaceAvatar
|
||||
size={40}
|
||||
name={user.name}
|
||||
avatar={user.avatar}
|
||||
></WorkspaceAvatar>
|
||||
<StyleUserInfo>
|
||||
<p>{user.name}</p>
|
||||
<p>{user.email}</p>
|
||||
</StyleUserInfo>
|
||||
</Wrapper>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
onLogout();
|
||||
}}
|
||||
>
|
||||
<LogOutIcon />
|
||||
</IconButton>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!user && (
|
||||
<StyleSignIn
|
||||
onClick={async () => {
|
||||
onLogin();
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<CloudInsyncIcon fontSize={16} />
|
||||
</span>
|
||||
Sign in to sync with AFFINE Cloud
|
||||
</StyleSignIn>
|
||||
)}
|
||||
</StyledFooter>
|
||||
);
|
||||
};
|
61
packages/app/src/components/workspace-modal/LanguageMenu.tsx
Normal file
61
packages/app/src/components/workspace-modal/LanguageMenu.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import { LOCALES } from '@affine/i18n';
|
||||
import { styled } from '@/styles';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { ArrowDownIcon } from '@blocksuite/icons';
|
||||
import { Button } from '@/ui/button';
|
||||
import { Menu, MenuItem } from '@/ui/menu';
|
||||
|
||||
const LanguageMenuContent = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const changeLanguage = (event: string) => {
|
||||
i18n.changeLanguage(event);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
{LOCALES.map(option => {
|
||||
return (
|
||||
<ListItem
|
||||
key={option.name}
|
||||
title={option.name}
|
||||
onClick={() => {
|
||||
changeLanguage(option.tag);
|
||||
}}
|
||||
>
|
||||
{option.originalName}
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const LanguageMenu = () => {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const currentLanguage = LOCALES.find(item => item.tag === i18n.language);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
content={<LanguageMenuContent />}
|
||||
placement="bottom"
|
||||
trigger="click"
|
||||
disablePortal={true}
|
||||
>
|
||||
<Button
|
||||
icon={<ArrowDownIcon />}
|
||||
iconPosition="end"
|
||||
noBorder={true}
|
||||
style={{ textTransform: 'capitalize' }}
|
||||
>
|
||||
{currentLanguage?.originalName}
|
||||
</Button>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const ListItem = styled(MenuItem)(({ theme }) => ({
|
||||
height: '38px',
|
||||
color: theme.colors.popoverColor,
|
||||
fontSize: theme.font.sm,
|
||||
textTransform: 'capitalize',
|
||||
padding: '0 24px',
|
||||
}));
|
@ -0,0 +1,69 @@
|
||||
import { WorkspaceUnitAvatar } from '@/components/workspace-avatar';
|
||||
import {
|
||||
CloudIcon,
|
||||
LocalIcon,
|
||||
OfflineIcon,
|
||||
} from '@/components/workspace-modal/icons';
|
||||
import { PublishIcon, UsersIcon } from '@blocksuite/icons';
|
||||
import { WorkspaceUnit } from '@affine/datacenter';
|
||||
import { useAppState } from '@/providers/app-state-provider';
|
||||
import { StyleWorkspaceInfo, StyleWorkspaceTitle, StyledCard } from './styles';
|
||||
import { Wrapper } from '@/ui/layout';
|
||||
|
||||
export const WorkspaceCard = ({
|
||||
workspaceData,
|
||||
onClick,
|
||||
}: {
|
||||
workspaceData: WorkspaceUnit;
|
||||
onClick: (data: WorkspaceUnit) => void;
|
||||
}) => {
|
||||
const { currentWorkspace, isOwner } = useAppState();
|
||||
|
||||
return (
|
||||
<StyledCard
|
||||
onClick={() => {
|
||||
onClick(workspaceData);
|
||||
}}
|
||||
active={workspaceData.id === currentWorkspace?.id}
|
||||
>
|
||||
<Wrapper>
|
||||
<WorkspaceUnitAvatar size={58} workspaceUnit={workspaceData} />
|
||||
</Wrapper>
|
||||
|
||||
<StyleWorkspaceInfo>
|
||||
<StyleWorkspaceTitle>
|
||||
{workspaceData.name || 'AFFiNE'}
|
||||
</StyleWorkspaceTitle>
|
||||
{isOwner ? (
|
||||
workspaceData.provider === 'local' ? (
|
||||
<p>
|
||||
<LocalIcon />
|
||||
Local Workspace
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
<CloudIcon />
|
||||
Cloud Workspace
|
||||
</p>
|
||||
)
|
||||
) : (
|
||||
<p>
|
||||
<UsersIcon fontSize={20} color={'#FF646B'} />
|
||||
Joined Workspace
|
||||
</p>
|
||||
)}
|
||||
{workspaceData.provider === 'local' && (
|
||||
<p>
|
||||
<OfflineIcon />
|
||||
All data can be accessed offline
|
||||
</p>
|
||||
)}
|
||||
{workspaceData.published && (
|
||||
<p>
|
||||
<PublishIcon fontSize={16} /> Published to Web
|
||||
</p>
|
||||
)}
|
||||
</StyleWorkspaceInfo>
|
||||
</StyledCard>
|
||||
);
|
||||
};
|
@ -1,28 +1,35 @@
|
||||
import { styled } from '@/styles';
|
||||
import { Modal, ModalWrapper } from '@/ui/modal';
|
||||
import { Button, IconButton } from '@/ui/button';
|
||||
import { Modal, ModalWrapper, ModalCloseButton } from '@/ui/modal';
|
||||
import { Wrapper } from '@/ui/layout';
|
||||
import { useState } from 'react';
|
||||
import { CreateWorkspaceModal } from '../create-workspace';
|
||||
import {
|
||||
UsersIcon,
|
||||
AddIcon,
|
||||
LogOutIcon,
|
||||
CloudInsyncIcon,
|
||||
PublishIcon,
|
||||
CloseIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import {
|
||||
WorkspaceAvatar,
|
||||
WorkspaceUnitAvatar,
|
||||
} from '@/components/workspace-avatar';
|
||||
import { Tooltip } from '@/ui/tooltip';
|
||||
import { toast } from '@/ui/toast';
|
||||
|
||||
import { AddIcon, HelpCenterIcon } from '@blocksuite/icons';
|
||||
|
||||
import { useAppState } from '@/providers/app-state-provider';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { LanguageMenu } from './languageMenu';
|
||||
import { LanguageMenu } from './LanguageMenu';
|
||||
|
||||
import { CloudIcon, LineIcon, LocalIcon, OfflineIcon } from './icons';
|
||||
import { LoginModal } from '../login-modal';
|
||||
import { LogoutModal } from '../logout-modal';
|
||||
import {
|
||||
StyledCard,
|
||||
StyledSplitLine,
|
||||
StyleWorkspaceInfo,
|
||||
StyleWorkspaceTitle,
|
||||
StyledModalHeaderLeft,
|
||||
StyledModalTitle,
|
||||
StyledHelperContainer,
|
||||
StyledModalContent,
|
||||
StyledOperationWrapper,
|
||||
StyleWorkspaceAdd,
|
||||
StyledModalHeader,
|
||||
} from './styles';
|
||||
import { WorkspaceCard } from './WorkspaceCard';
|
||||
import { Footer } from './Footer';
|
||||
import { useConfirm } from '@/providers/ConfirmProvider';
|
||||
interface WorkspaceModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@ -30,337 +37,128 @@ interface WorkspaceModalProps {
|
||||
|
||||
export const WorkspaceModal = ({ open, onClose }: WorkspaceModalProps) => {
|
||||
const [createWorkspaceOpen, setCreateWorkspaceOpen] = useState(false);
|
||||
const { workspaceList, currentWorkspace, user, logout, isOwner } =
|
||||
useAppState();
|
||||
const { workspaceList, logout } = useAppState();
|
||||
const router = useRouter();
|
||||
const { t } = useTranslation();
|
||||
const [loginOpen, setLoginOpen] = useState(false);
|
||||
const [logoutOpen, setLogoutOpen] = useState(false);
|
||||
const { confirm } = useConfirm();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
<Modal open={open} onClose={onClose}>
|
||||
<ModalWrapper
|
||||
width={720}
|
||||
height={690}
|
||||
style={{
|
||||
padding: '24px 40px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<Header>
|
||||
<ContentTitle>{t('My Workspaces')}</ContentTitle>
|
||||
<HeaderOption>
|
||||
<LanguageMenu />
|
||||
<div
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
border: 'none',
|
||||
margin: '2px 16px',
|
||||
height: '24px',
|
||||
position: 'relative',
|
||||
top: '4px',
|
||||
}}
|
||||
<StyledModalHeader>
|
||||
<StyledModalHeaderLeft>
|
||||
<StyledModalTitle>{t('My Workspaces')}</StyledModalTitle>
|
||||
<Tooltip
|
||||
content={t(
|
||||
'A workspace is your virtual space to capture, create and plan as just one person or together as a team.'
|
||||
)}
|
||||
placement="top-start"
|
||||
disablePortal={true}
|
||||
>
|
||||
<LineIcon></LineIcon>
|
||||
</div>
|
||||
<StyledHelperContainer>
|
||||
<HelpCenterIcon />
|
||||
</StyledHelperContainer>
|
||||
</Tooltip>
|
||||
</StyledModalHeaderLeft>
|
||||
|
||||
<Button
|
||||
style={{ border: 'none', padding: 0 }}
|
||||
<StyledOperationWrapper>
|
||||
<LanguageMenu />
|
||||
<StyledSplitLine />
|
||||
<ModalCloseButton
|
||||
onClick={() => {
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<CloseIcon></CloseIcon>
|
||||
</Button>
|
||||
</HeaderOption>
|
||||
</Header>
|
||||
<Content>
|
||||
<WorkspaceList>
|
||||
{workspaceList.map((item, index) => {
|
||||
return (
|
||||
<WorkspaceItem
|
||||
onClick={() => {
|
||||
router.replace(`/workspace/${item.id}`);
|
||||
onClose();
|
||||
}}
|
||||
active={item.id === currentWorkspace?.id}
|
||||
key={index}
|
||||
>
|
||||
<div>
|
||||
<WorkspaceUnitAvatar size={58} workspaceUnit={item} />
|
||||
</div>
|
||||
absolute={false}
|
||||
/>
|
||||
</StyledOperationWrapper>
|
||||
</StyledModalHeader>
|
||||
|
||||
<StyleWorkspaceInfo>
|
||||
<StyleWorkspaceTitle>
|
||||
{item.name || 'AFFiNE'}
|
||||
</StyleWorkspaceTitle>
|
||||
{isOwner ? (
|
||||
item.provider === 'local' ? (
|
||||
<p>
|
||||
<LocalIcon />
|
||||
Local Workspace
|
||||
</p>
|
||||
) : (
|
||||
<p>
|
||||
<CloudIcon />
|
||||
Cloud Workspace
|
||||
</p>
|
||||
)
|
||||
) : (
|
||||
<p>
|
||||
<UsersIcon fontSize={20} color={'#FF646B'} />
|
||||
Joined Workspace
|
||||
</p>
|
||||
)}
|
||||
{item.provider === 'local' && (
|
||||
<p>
|
||||
<OfflineIcon />
|
||||
All data can be accessed offline
|
||||
</p>
|
||||
)}
|
||||
{item.published && (
|
||||
<p>
|
||||
<PublishIcon fontSize={16} /> Published to Web
|
||||
</p>
|
||||
)}
|
||||
</StyleWorkspaceInfo>
|
||||
</WorkspaceItem>
|
||||
);
|
||||
})}
|
||||
<WorkspaceItem
|
||||
onClick={() => {
|
||||
setCreateWorkspaceOpen(true);
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<StyleWorkspaceAdd className="add-icon">
|
||||
<AddIcon fontSize={18} />
|
||||
</StyleWorkspaceAdd>
|
||||
</div>
|
||||
<StyledModalContent>
|
||||
{workspaceList.map((item, index) => {
|
||||
return (
|
||||
<WorkspaceCard
|
||||
workspaceData={item}
|
||||
onClick={workspaceData => {
|
||||
router.replace(`/workspace/${workspaceData.id}`);
|
||||
onClose();
|
||||
}}
|
||||
key={index}
|
||||
></WorkspaceCard>
|
||||
);
|
||||
})}
|
||||
<StyledCard
|
||||
onClick={() => {
|
||||
setCreateWorkspaceOpen(true);
|
||||
}}
|
||||
>
|
||||
<Wrapper>
|
||||
<StyleWorkspaceAdd className="add-icon">
|
||||
<AddIcon fontSize={18} />
|
||||
</StyleWorkspaceAdd>
|
||||
</Wrapper>
|
||||
|
||||
<StyleWorkspaceInfo>
|
||||
<StyleWorkspaceTitle>New workspace</StyleWorkspaceTitle>
|
||||
<p>Crete or import</p>
|
||||
</StyleWorkspaceInfo>
|
||||
</WorkspaceItem>
|
||||
</WorkspaceList>
|
||||
{/* <p style={{ fontSize: '14px', color: '#ccc', margin: '12px 0' }}>
|
||||
{t('Tips')}
|
||||
{t('Workspace description')}
|
||||
</p> */}
|
||||
</Content>
|
||||
<LoginModal
|
||||
open={loginOpen}
|
||||
onClose={() => {
|
||||
setLoginOpen(false);
|
||||
<StyleWorkspaceInfo>
|
||||
<StyleWorkspaceTitle>New workspace</StyleWorkspaceTitle>
|
||||
<p>Crete or import</p>
|
||||
</StyleWorkspaceInfo>
|
||||
</StyledCard>
|
||||
</StyledModalContent>
|
||||
|
||||
<Footer
|
||||
onLogin={() => {
|
||||
setLoginOpen(true);
|
||||
}}
|
||||
></LoginModal>
|
||||
<Footer>
|
||||
{!user ? (
|
||||
<StyleSignIn
|
||||
onClick={async () => {
|
||||
setLoginOpen(true);
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<CloudInsyncIcon fontSize={16} />
|
||||
</span>
|
||||
Sign in to sync with AFFINE Cloud
|
||||
</StyleSignIn>
|
||||
) : (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div style={{ paddingTop: '20px' }}>
|
||||
<WorkspaceAvatar
|
||||
size={40}
|
||||
name={user.name}
|
||||
avatar={user.avatar}
|
||||
></WorkspaceAvatar>
|
||||
</div>
|
||||
<StyleUserInfo style={{}}>
|
||||
<p>{user.name}</p>
|
||||
<p>{user.email}</p>
|
||||
</StyleUserInfo>
|
||||
<div style={{ paddingTop: '25px' }}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setLogoutOpen(true);
|
||||
// confirm({
|
||||
// title: 'Sign out?',
|
||||
// content: `All data has been stored in the cloud. `,
|
||||
// confirmText: 'Sign out',
|
||||
// cancelText: 'Cancel',
|
||||
// }).then(async confirm => {
|
||||
// // if (confirm) {
|
||||
// // if (user) {
|
||||
// // await logout();
|
||||
// // router.replace(`/workspace`);
|
||||
// // toast('Enabled success');
|
||||
// // }
|
||||
// // }
|
||||
// });
|
||||
}}
|
||||
>
|
||||
<LogOutIcon></LogOutIcon>
|
||||
</IconButton>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Footer>
|
||||
<CreateWorkspaceModal
|
||||
open={createWorkspaceOpen}
|
||||
onClose={() => {
|
||||
setCreateWorkspaceOpen(false);
|
||||
onLogout={() => {
|
||||
setLoginOpen(true);
|
||||
confirm({
|
||||
title: 'Sign out?',
|
||||
content: `All data has been stored in the cloud. `,
|
||||
confirmText: 'Sign out',
|
||||
cancelText: 'Cancel',
|
||||
}).then(async confirm => {
|
||||
if (confirm) {
|
||||
await logout();
|
||||
await router.replace(`/workspace`);
|
||||
toast('Enabled success');
|
||||
}
|
||||
});
|
||||
}}
|
||||
></CreateWorkspaceModal>
|
||||
<LogoutModal
|
||||
open={logoutOpen}
|
||||
onClose={async wait => {
|
||||
if (!wait) {
|
||||
await logout();
|
||||
router.replace(`/workspace`);
|
||||
}
|
||||
setLogoutOpen(false);
|
||||
}}
|
||||
></LogoutModal>
|
||||
/>
|
||||
</ModalWrapper>
|
||||
</Modal>
|
||||
</div>
|
||||
|
||||
<LoginModal
|
||||
open={loginOpen}
|
||||
onClose={() => {
|
||||
setLoginOpen(false);
|
||||
}}
|
||||
/>
|
||||
<LogoutModal
|
||||
open={logoutOpen}
|
||||
onClose={async wait => {
|
||||
if (!wait) {
|
||||
await logout();
|
||||
router.replace(`/workspace`);
|
||||
}
|
||||
setLogoutOpen(false);
|
||||
}}
|
||||
/>
|
||||
<CreateWorkspaceModal
|
||||
open={createWorkspaceOpen}
|
||||
onClose={() => {
|
||||
setCreateWorkspaceOpen(false);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Header = styled('div')({
|
||||
display: 'flex',
|
||||
});
|
||||
|
||||
const Content = styled('div')({
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: '16px',
|
||||
flex: 1,
|
||||
});
|
||||
const HeaderOption = styled.div(() => {
|
||||
return {
|
||||
marginLeft: '16px',
|
||||
};
|
||||
});
|
||||
const ContentTitle = styled('div')({
|
||||
fontSize: '20px',
|
||||
lineHeight: '24px',
|
||||
fontWeight: 600,
|
||||
textAlign: 'left',
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
const WorkspaceList = styled('div')({
|
||||
maxHeight: '500px',
|
||||
overflow: 'auto',
|
||||
display: 'grid',
|
||||
gridRowGap: '24px',
|
||||
gridColumnGap: '24px',
|
||||
fontSize: '16px',
|
||||
marginTop: '36px',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
});
|
||||
|
||||
export const WorkspaceItem = styled.div<{
|
||||
active?: boolean;
|
||||
}>(({ theme, active }) => {
|
||||
const borderColor = active ? theme.colors.primaryColor : 'transparent';
|
||||
return {
|
||||
cursor: 'pointer',
|
||||
padding: '16px',
|
||||
height: '124px',
|
||||
boxShadow: theme.shadow.modal,
|
||||
display: 'flex',
|
||||
borderRadius: '12px',
|
||||
border: `1px solid ${borderColor}`,
|
||||
':hover': {
|
||||
background: theme.colors.hoverBackground,
|
||||
'.add-icon': {
|
||||
border: `1.5px dashed ${theme.colors.primaryColor}`,
|
||||
svg: {
|
||||
fill: theme.colors.primaryColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const StyleWorkspaceInfo = styled.div(({ theme }) => {
|
||||
return {
|
||||
marginLeft: '16px',
|
||||
p: {
|
||||
fontSize: theme.font.xs,
|
||||
lineHeight: '16px',
|
||||
},
|
||||
svg: {
|
||||
verticalAlign: 'text-bottom',
|
||||
marginRight: '8px',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const StyleWorkspaceTitle = styled.div(({ theme }) => {
|
||||
return {
|
||||
fontSize: theme.font.base,
|
||||
fontWeight: 600,
|
||||
lineHeight: '24px',
|
||||
marginBottom: '8px',
|
||||
};
|
||||
});
|
||||
|
||||
const StyleWorkspaceAdd = styled.div(() => {
|
||||
return {
|
||||
width: '58px',
|
||||
height: '58px',
|
||||
borderRadius: '100%',
|
||||
textAlign: 'center',
|
||||
background: '#f4f5fa',
|
||||
border: '1.5px dashed #f4f5fa',
|
||||
lineHeight: '58px',
|
||||
marginTop: '2px',
|
||||
};
|
||||
});
|
||||
|
||||
const Footer = styled('div')({
|
||||
paddingTop: '16px',
|
||||
});
|
||||
|
||||
const StyleUserInfo = styled.div(({ theme }) => {
|
||||
return {
|
||||
textAlign: 'left',
|
||||
marginLeft: '16px',
|
||||
marginTop: '16px',
|
||||
flex: 1,
|
||||
p: {
|
||||
lineHeight: '24px',
|
||||
color: theme.colors.iconColor,
|
||||
},
|
||||
'p:nth-child(1)': {
|
||||
color: theme.colors.textColor,
|
||||
fontWeight: 600,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const StyleSignIn = styled.div(({ theme }) => {
|
||||
return {
|
||||
cursor: 'pointer',
|
||||
fontSize: '16px',
|
||||
fontWeight: 700,
|
||||
color: theme.colors.iconColor,
|
||||
span: {
|
||||
display: 'inline-block',
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
borderRadius: '40px',
|
||||
backgroundColor: theme.colors.innerHoverBackground,
|
||||
textAlign: 'center',
|
||||
lineHeight: '44px',
|
||||
marginRight: '16px',
|
||||
svg: {
|
||||
fill: theme.colors.primaryColor,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -1,93 +1,61 @@
|
||||
import { LOCALES } from '@affine/i18n';
|
||||
import { TooltipProps } from '@mui/material';
|
||||
import { styled } from '@/styles';
|
||||
import { Tooltip } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from '@affine/i18n';
|
||||
import { ArrowDownIcon } from '@blocksuite/icons';
|
||||
import { Button } from '@/ui/button';
|
||||
import { Menu, MenuItem } from '@/ui/menu';
|
||||
|
||||
export const LanguageMenu = () => {
|
||||
const LanguageMenuContent = () => {
|
||||
const { i18n } = useTranslation();
|
||||
const changeLanguage = (event: string) => {
|
||||
i18n.changeLanguage(event);
|
||||
};
|
||||
const [show, setShow] = useState(false);
|
||||
const currentLanguage = LOCALES.find(item => item.tag === i18n.language);
|
||||
const [languageName, setLanguageName] = useState(
|
||||
currentLanguage?.originalName
|
||||
);
|
||||
return (
|
||||
<StyledTooltip
|
||||
title={
|
||||
<>
|
||||
{LOCALES.map(option => {
|
||||
return (
|
||||
<ListItem
|
||||
style={{ border: 'none' }}
|
||||
key={option.name}
|
||||
title={option.name}
|
||||
onClick={() => {
|
||||
changeLanguage(option.tag);
|
||||
setShow(false);
|
||||
setLanguageName(option.originalName);
|
||||
}}
|
||||
>
|
||||
{option.originalName}
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
}
|
||||
open={show}
|
||||
<>
|
||||
{LOCALES.map(option => {
|
||||
return (
|
||||
<ListItem
|
||||
key={option.name}
|
||||
title={option.name}
|
||||
onClick={() => {
|
||||
changeLanguage(option.tag);
|
||||
}}
|
||||
>
|
||||
{option.originalName}
|
||||
</ListItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export const LanguageMenu = () => {
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const currentLanguage = LOCALES.find(item => item.tag === i18n.language);
|
||||
|
||||
return (
|
||||
<Menu
|
||||
content={<LanguageMenuContent />}
|
||||
placement="bottom"
|
||||
trigger="click"
|
||||
disablePortal={true}
|
||||
>
|
||||
<StyledTitleButton
|
||||
style={{ border: 'none', padding: '0px' }}
|
||||
onClick={() => {
|
||||
setShow(!show);
|
||||
}}
|
||||
<Button
|
||||
icon={<ArrowDownIcon />}
|
||||
iconPosition="end"
|
||||
noBorder={true}
|
||||
style={{ textTransform: 'capitalize' }}
|
||||
>
|
||||
<StyledContainer>
|
||||
<StyledText>{languageName}</StyledText>
|
||||
<ArrowDownIcon fontSize={18} />
|
||||
</StyledContainer>
|
||||
</StyledTitleButton>
|
||||
</StyledTooltip>
|
||||
{currentLanguage?.originalName}
|
||||
</Button>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
const StyledContainer = styled('div')(() => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}));
|
||||
|
||||
const StyledText = styled('span')(({ theme }) => ({
|
||||
marginRight: '4px',
|
||||
marginLeft: '16px',
|
||||
fontSize: theme.font.sm,
|
||||
fontWeight: '500',
|
||||
textTransform: 'capitalize',
|
||||
}));
|
||||
const StyledTooltip = styled(({ className, ...props }: TooltipProps) => (
|
||||
<Tooltip {...props} classes={{ popper: className }} />
|
||||
))(({ theme }) => ({
|
||||
zIndex: theme.zIndex.modal,
|
||||
'& .MuiTooltip-tooltip': {
|
||||
backgroundColor: theme.colors.popoverBackground,
|
||||
boxShadow: theme.shadow.modal,
|
||||
color: theme.colors.popoverColor,
|
||||
},
|
||||
}));
|
||||
|
||||
const ListItem = styled(Button)(({ theme }) => ({
|
||||
display: 'block',
|
||||
width: '100%',
|
||||
const ListItem = styled(MenuItem)(({ theme }) => ({
|
||||
height: '38px',
|
||||
color: theme.colors.popoverColor,
|
||||
fontSize: theme.font.sm,
|
||||
textTransform: 'capitalize',
|
||||
}));
|
||||
|
||||
const StyledTitleButton = styled(Button)(({ theme }) => ({
|
||||
color: theme.colors.popoverColor,
|
||||
fontSize: theme.font.sm,
|
||||
padding: '0 24px',
|
||||
}));
|
||||
|
@ -1,38 +1,161 @@
|
||||
import { displayFlex, styled } from '@/styles';
|
||||
|
||||
export const StyledTitle = styled.div(() => {
|
||||
export const StyledSplitLine = styled.div(({ theme }) => {
|
||||
return {
|
||||
...displayFlex('center', 'center'),
|
||||
fontSize: '20px',
|
||||
fontWeight: 500,
|
||||
marginTop: '60px',
|
||||
lineHeight: 1,
|
||||
width: '1px',
|
||||
height: '20px',
|
||||
background: theme.colors.iconColor,
|
||||
marginRight: '24px',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledContent = styled.div(() => {
|
||||
export const StyleWorkspaceInfo = styled.div(({ theme }) => {
|
||||
return {
|
||||
padding: '0 40px',
|
||||
marginTop: '32px',
|
||||
fontSize: '18px',
|
||||
lineHeight: '25px',
|
||||
'p:not(last-of-type)': {
|
||||
marginBottom: '10px',
|
||||
marginLeft: '15px',
|
||||
p: {
|
||||
height: '20px',
|
||||
fontSize: theme.font.xs,
|
||||
...displayFlex('flex-start', 'center'),
|
||||
},
|
||||
svg: {
|
||||
marginRight: '10px',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledButton = styled.div(({ theme }) => {
|
||||
export const StyleWorkspaceTitle = styled.div(({ theme }) => {
|
||||
return {
|
||||
width: '146px',
|
||||
height: '42px',
|
||||
background: theme.colors.primaryColor,
|
||||
color: '#FFFFFF',
|
||||
fontSize: '18px',
|
||||
fontWeight: 500,
|
||||
borderRadius: '21px',
|
||||
margin: '52px auto 0',
|
||||
fontSize: theme.font.base,
|
||||
fontWeight: 600,
|
||||
lineHeight: '24px',
|
||||
marginBottom: '10px',
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledCard = styled.div<{
|
||||
active?: boolean;
|
||||
}>(({ theme, active }) => {
|
||||
const borderColor = active ? theme.colors.primaryColor : 'transparent';
|
||||
return {
|
||||
width: '310px',
|
||||
height: '124px',
|
||||
cursor: 'pointer',
|
||||
padding: '16px',
|
||||
boxShadow: '0px 0px 8px rgba(0, 0, 0, 0.1)',
|
||||
borderRadius: '12px',
|
||||
border: `1px solid ${borderColor}`,
|
||||
...displayFlex('flex-start', 'flex-start'),
|
||||
':hover': {
|
||||
background: theme.colors.hoverBackground,
|
||||
'.add-icon': {
|
||||
border: `1.5px dashed ${theme.colors.primaryColor}`,
|
||||
svg: {
|
||||
fill: theme.colors.primaryColor,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledFooter = styled('div')({
|
||||
height: '84px',
|
||||
padding: '0 40px',
|
||||
...displayFlex('space-between', 'center'),
|
||||
});
|
||||
|
||||
export const StyleUserInfo = styled.div(({ theme }) => {
|
||||
return {
|
||||
textAlign: 'left',
|
||||
marginLeft: '16px',
|
||||
flex: 1,
|
||||
p: {
|
||||
lineHeight: '24px',
|
||||
color: theme.colors.iconColor,
|
||||
},
|
||||
'p:nth-child(1)': {
|
||||
color: theme.colors.textColor,
|
||||
fontWeight: 600,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyleSignIn = styled.div(({ theme }) => {
|
||||
return {
|
||||
cursor: 'pointer',
|
||||
fontSize: '16px',
|
||||
fontWeight: 700,
|
||||
color: theme.colors.iconColor,
|
||||
span: {
|
||||
display: 'inline-block',
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
borderRadius: '40px',
|
||||
backgroundColor: theme.colors.innerHoverBackground,
|
||||
textAlign: 'center',
|
||||
lineHeight: '44px',
|
||||
marginRight: '16px',
|
||||
svg: {
|
||||
fill: theme.colors.primaryColor,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledModalHeaderLeft = styled.div(() => {
|
||||
return { ...displayFlex('flex-start', 'center') };
|
||||
});
|
||||
export const StyledModalTitle = styled.div(({ theme }) => {
|
||||
return {
|
||||
fontWeight: 600,
|
||||
fontSize: theme.font.h6,
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledHelperContainer = styled.div(({ theme }) => {
|
||||
return {
|
||||
color: theme.colors.iconColor,
|
||||
marginLeft: '15px',
|
||||
fontWeight: 400,
|
||||
...displayFlex('center', 'center'),
|
||||
};
|
||||
});
|
||||
|
||||
export const StyledModalContent = styled('div')({
|
||||
height: '534px',
|
||||
padding: '8px 40px',
|
||||
marginTop: '72px',
|
||||
overflow: 'auto',
|
||||
...displayFlex('space-between', 'flex-start', 'column'),
|
||||
flexWrap: 'wrap',
|
||||
});
|
||||
export const StyledOperationWrapper = styled.div(() => {
|
||||
return {
|
||||
...displayFlex('flex-end', 'center'),
|
||||
};
|
||||
});
|
||||
|
||||
export const StyleWorkspaceAdd = styled.div(() => {
|
||||
return {
|
||||
width: '58px',
|
||||
height: '58px',
|
||||
borderRadius: '100%',
|
||||
textAlign: 'center',
|
||||
background: '#f4f5fa',
|
||||
border: '1.5px dashed #f4f5fa',
|
||||
lineHeight: '58px',
|
||||
marginTop: '2px',
|
||||
};
|
||||
});
|
||||
export const StyledModalHeader = styled('div')(({ theme }) => {
|
||||
return {
|
||||
width: '100%',
|
||||
height: '72px',
|
||||
position: 'absolute',
|
||||
left: 0,
|
||||
top: 0,
|
||||
background: theme.colors.pageBackground,
|
||||
borderRadius: '24px 24px 0 0',
|
||||
padding: '0 40px',
|
||||
...displayFlex('space-between', 'center'),
|
||||
};
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user