refactor: 群组侧边栏header

pull/13/head
moonrailgun 4 years ago
parent a56dc48660
commit 83a73f9c21

@ -1,8 +1,9 @@
import React from 'react';
import React, { useCallback } from 'react';
import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom';
import { TcProvider, useStorage } from 'tailchat-shared';
import clsx from 'clsx';
import { Loadable } from './components/Loadable';
import { ConfigProvider as AntdProvider } from 'antd';
const MainRoute = Loadable(() =>
import('./routes/Main').then((module) => module.MainRoute)
@ -13,9 +14,25 @@ const EntryRoute = Loadable(() =>
);
const AppProvider: React.FC = React.memo((props) => {
const getPopupContainer = useCallback(
(triggerNode: HTMLElement): HTMLElement => {
const appRoot = document.querySelector<HTMLElement>('#tailchat-app');
if (appRoot) {
return appRoot;
}
return document.body;
},
[]
);
return (
<BrowserRouter>
<TcProvider>{props.children}</TcProvider>
<TcProvider>
<AntdProvider getPopupContainer={getPopupContainer}>
{props.children}
</AntdProvider>
</TcProvider>
</BrowserRouter>
);
});
@ -26,6 +43,7 @@ export const App: React.FC = React.memo(() => {
return (
<div
id="tailchat-app"
className={clsx('h-screen w-screen min-h-screen select-none', {
dark: darkMode,
})}

@ -0,0 +1,36 @@
import React, { useState } from 'react';
import { Dropdown } from 'antd';
import { Icon } from '@iconify/react';
interface SectionHeaderProps {
menu?: React.ReactElement;
}
export const SectionHeader: React.FC<SectionHeaderProps> = React.memo(
(props) => {
const [visible, setVisible] = useState(false);
return (
<div className="h-12 relative flex items-center px-4 py-0 text-base font-bold flex-shrink-0 thin-line-bottom">
{React.isValidElement(props.menu) ? (
<Dropdown
visible={visible}
onVisibleChange={setVisible}
overlay={props.menu}
placement="topRight"
trigger={['click']}
>
<div className="cursor-pointer flex flex-1">
<header className="flex-1 truncate">{props.children}</header>
<Icon className="text-2xl" icon="mdi-chevron-down">
&#xe60f;
</Icon>
</div>
</Dropdown>
) : (
<header className="flex-1 truncate">{props.children}</header>
)}
</div>
);
}
);
SectionHeader.displayName = 'SectionHeader';

@ -0,0 +1,48 @@
import React from 'react';
import { Menu } from 'antd';
import _isNil from 'lodash/isNil';
// import { useGroupHeaderAction } from './useGroupHeaderAction';
import { useGroupInfo, useTranslation } from 'tailchat-shared';
import { SectionHeader } from '@/components/SectionHeader';
interface GroupHeaderProps {
groupId: string;
}
export const GroupHeader: React.FC<GroupHeaderProps> = React.memo((props) => {
const { groupId } = props;
const groupInfo = useGroupInfo(groupId);
const { t } = useTranslation();
// const {
// handleShowGroupInfo,
// handleShowInvite,
// handleCreateGroupPanel,
// handleQuitGroup,
// } = useGroupHeaderAction(groupInfo!);
if (_isNil(groupInfo)) {
return null;
}
const menu = (
<Menu>
{/* TODO */}
<Menu.Item key="0" onClick={() => console.log('查看详情')}>
{t('查看详情')}
</Menu.Item>
{/* <Menu.Item onClick={handleShowGroupInfo}>{t('查看详情')}</Menu.Item> */}
{/* {isGroupManager && (
<Menu.Item onClick={handleShowInvite}>{t('邀请成员')}</Menu.Item>
)}
{isGroupManager && (
<Menu.Item onClick={handleCreateGroupPanel}>{t('创建面板')}</Menu.Item>
)}
<Menu.Item danger={true} onClick={handleQuitGroup}>
{currentUserUUID === groupInfo.owner_uuid ? t('解散团') : t('退出团')}
</Menu.Item> */}
</Menu>
);
return <SectionHeader menu={menu}>{groupInfo?.name}</SectionHeader>;
});
GroupHeader.displayName = 'GroupHeader';

@ -5,6 +5,7 @@ import { useLocation, useParams } from 'react-router';
import { Badge, Typography } from 'antd';
import { Link } from 'react-router-dom';
import clsx from 'clsx';
import { GroupHeader } from './GroupHeader';
interface GroupParams {
groupId: string;
@ -91,6 +92,9 @@ export const Sidebar: React.FC = React.memo(() => {
return (
<div>
<GroupHeader groupId={groupId} />
<div className="p-2">
{groupPanels
.filter((panel) => panel.type === GroupPanelType.GROUP)
.map((group) => (
@ -108,6 +112,7 @@ export const Sidebar: React.FC = React.memo(() => {
</GroupSection>
))}
</div>
</div>
);
});
Sidebar.displayName = 'Sidebar';

@ -77,7 +77,7 @@ export const PageContent: React.FC<PageContentProps> = React.memo((props) => {
const sidebarEl = _isNil(sidebar) ? null : (
<div
className={clsx('bg-gray-800 p-2 flex-shrink-0', {
className={clsx('bg-gray-800 flex-shrink-0', {
'w-60': showSidebar,
})}
>

@ -26,4 +26,22 @@
.ant-carousel {
color: rgba(255,255,255,0.65);
}
// 下拉菜单
.ant-dropdown {
color: rgba(255,255,255,0.65);
.ant-dropdown-menu {
background-color: #1f1f1f;
.ant-dropdown-menu-item, .ant-dropdown-menu-submenu-title {
color: rgba(255,255,255,0.65);
&:hover {
background-color: rgba(255,255,255,0.08);
}
}
}
}
}

@ -1,5 +1,41 @@
// tailwind.config.js
// Reference: https://www.tailwindcss.cn/docs/configuration
// 默认配置文件: https://unpkg.com/browse/tailwindcss@2.2.7/stubs/defaultConfig.stub.js
const plugin = require('tailwindcss/plugin');
const customTheme = {
boxShadow: {
normal: 'rgba(0, 0, 0, 0.15) 0 0 8px',
elevationStroke: '0 0 0 1px rgba(4,4,5,0.15)',
elevationLow:
'0 1px 0 rgba(4,4,5,0.2),0 1.5px 0 rgba(6,6,7,0.05),0 2px 0 rgba(4,4,5,0.05)',
elevationMedium: '0 4px 4px rgba(0,0,0,0.16)',
elevationHigh: '0 8px 16px rgba(0,0,0,0.24)',
},
};
const tailchat = plugin(({ addUtilities }) => {
// Reference: https://www.tailwindcss.cn/docs/plugins#adding-utilities
const newUtilities = {
'.thin-line-bottom': {
'&::after': {
content: '" "',
position: 'absolute',
display: 'block',
bottom: '1px',
left: 0,
right: 0,
height: '1px',
boxShadow: customTheme.boxShadow.elevationLow,
zIndex: 1,
pointerEvents: 'none',
},
},
};
addUtilities(newUtilities);
});
module.exports = {
purge: {
@ -25,6 +61,9 @@ module.exports = {
lineHeight: {
13: '3.25rem',
},
boxShadow: {
...customTheme.boxShadow,
},
},
},
variants: {
@ -34,5 +73,5 @@ module.exports = {
borderRadius: ['hover'],
},
},
plugins: [],
plugins: [tailchat],
};

Loading…
Cancel
Save