From ae3829628ad0fef406ce1bcd64df204302aa0b44 Mon Sep 17 00:00:00 2001 From: moonrailgun Date: Sun, 5 Jun 2022 13:22:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=BE=A4=E7=BB=84?= =?UTF-8?q?=E6=88=90=E5=91=98popover?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/design/components/Avatar/index.tsx | 1 - .../components/AvatarWithPreview/index.tsx | 40 +++++++++++++++++++ packages/design/components/index.ts | 1 + shared/i18n/langs/en-US/translation.json | 1 + shared/i18n/langs/zh-CN/translation.json | 1 + shared/index.tsx | 1 + .../components/Panel/group/MembersPanel.tsx | 7 +++- web/src/components/UserListItem.tsx | 24 ++++++----- .../components/popover/GroupUserPopover.tsx | 29 ++++++++++++++ web/src/styles/antd/dark.less | 22 ++++++++++ 10 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 packages/design/components/AvatarWithPreview/index.tsx create mode 100644 web/src/components/popover/GroupUserPopover.tsx diff --git a/packages/design/components/Avatar/index.tsx b/packages/design/components/Avatar/index.tsx index 49a72916..4e9216bc 100644 --- a/packages/design/components/Avatar/index.tsx +++ b/packages/design/components/Avatar/index.tsx @@ -30,7 +30,6 @@ export const Avatar: React.FC = React.memo((_props) => { const style: React.CSSProperties = useMemo( () => ({ - cursor: 'inherit', userSelect: 'none', ...props.style, backgroundColor: color, diff --git a/packages/design/components/AvatarWithPreview/index.tsx b/packages/design/components/AvatarWithPreview/index.tsx new file mode 100644 index 00000000..93428be2 --- /dev/null +++ b/packages/design/components/AvatarWithPreview/index.tsx @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; +import { Avatar, AvatarProps } from '../Avatar'; +import { Image } from '../Image'; + +export const AvatarWithPreview: React.FC = React.memo((props) => { + const [visible, setVisible] = useState(false); + + const hasImage = typeof props.src === 'string'; + + return ( + <> +
setVisible(!visible)} + > + +
+ {hasImage && ( +
+ { + setVisible(value); + }, + }} + /> +
+ )} + + ); +}); +AvatarWithPreview.displayName = 'AvatarWithPreview'; diff --git a/packages/design/components/index.ts b/packages/design/components/index.ts index abff9975..c948495d 100644 --- a/packages/design/components/index.ts +++ b/packages/design/components/index.ts @@ -1,5 +1,6 @@ export { AutoFolder } from './AutoFolder'; export { Avatar } from './Avatar'; +export { AvatarWithPreview } from './AvatarWithPreview'; export { CombinedAvatar } from './Avatar/combined'; export { DelayTip } from './DelayTip'; export { Highlight } from './Highlight'; diff --git a/shared/i18n/langs/en-US/translation.json b/shared/i18n/langs/en-US/translation.json index f0e0e8c7..8ac2759a 100644 --- a/shared/i18n/langs/en-US/translation.json +++ b/shared/i18n/langs/en-US/translation.json @@ -32,6 +32,7 @@ "k2c7df74f": "Modify Group Panel", "k2d6cfb27": "Chat Channel", "k2ec4966c": "Selected {{num}} items", + "k2edb3d74": "Guest", "k3081870c": "More", "k313bda4b": "OTP", "k3172297b": "This feature is not yet open", diff --git a/shared/i18n/langs/zh-CN/translation.json b/shared/i18n/langs/zh-CN/translation.json index c73224d3..6be3c9eb 100644 --- a/shared/i18n/langs/zh-CN/translation.json +++ b/shared/i18n/langs/zh-CN/translation.json @@ -32,6 +32,7 @@ "k2c7df74f": "编辑群组面板", "k2d6cfb27": "聊天频道", "k2ec4966c": "已选择 {{num}} 项", + "k2edb3d74": "游客", "k3081870c": "更多", "k313bda4b": "OTP", "k3172297b": "该功能暂未开放", diff --git a/shared/index.tsx b/shared/index.tsx index 3b58b531..e7d693b8 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -117,6 +117,7 @@ export type { GroupInfo, GroupBasicInfo, GroupInvite, + GroupMember, } from './model/group'; export { sendMessage, diff --git a/web/src/components/Panel/group/MembersPanel.tsx b/web/src/components/Panel/group/MembersPanel.tsx index c3f27c1e..04c6551f 100644 --- a/web/src/components/Panel/group/MembersPanel.tsx +++ b/web/src/components/Panel/group/MembersPanel.tsx @@ -1,4 +1,5 @@ import { Icon } from '@/components/Icon'; +import { GroupUserPopover } from '@/components/popover/GroupUserPopover'; import { UserListItem } from '@/components/UserListItem'; import { Divider, Input, Skeleton } from 'antd'; import React, { useMemo, useState } from 'react'; @@ -55,7 +56,11 @@ export const MembersPanel: React.FC = React.memo((props) => { const isSearching = searchStr !== ''; const renderUser = (member: UserBaseInfo) => ( - + } + /> ); return ( diff --git a/web/src/components/UserListItem.tsx b/web/src/components/UserListItem.tsx index a86ab51a..d83de94d 100644 --- a/web/src/components/UserListItem.tsx +++ b/web/src/components/UserListItem.tsx @@ -1,11 +1,13 @@ -import React, { useCallback } from 'react'; +import React from 'react'; import { Avatar } from './Avatar'; import _isEmpty from 'lodash/isEmpty'; -import { Skeleton, Space } from 'antd'; +import { Popover, PopoverProps, Skeleton, Space } from 'antd'; import { useCachedUserInfo, useCachedOnlineStatus } from 'tailchat-shared'; +import clsx from 'clsx'; interface UserListItemProps { userId: string; + popover?: PopoverProps['content']; actions?: React.ReactElement[]; } export const UserListItem: React.FC = React.memo((props) => { @@ -14,11 +16,6 @@ export const UserListItem: React.FC = React.memo((props) => { const [isOnline] = useCachedOnlineStatus([props.userId]); const userName = userInfo.nickname; - const handleClick = useCallback(() => { - // TODO 点击展开用户信息卡片 - console.log('clicked avatar'); - }, []); - return (
= React.memo((props) => { title={false} active={true} > -
- +
+ + +
{userName} diff --git a/web/src/components/popover/GroupUserPopover.tsx b/web/src/components/popover/GroupUserPopover.tsx new file mode 100644 index 00000000..f1c298bc --- /dev/null +++ b/web/src/components/popover/GroupUserPopover.tsx @@ -0,0 +1,29 @@ +import { Tag } from 'antd'; +import React from 'react'; +import { AvatarWithPreview } from 'tailchat-design'; +import { t, UserBaseInfo } from 'tailchat-shared'; + +export const GroupUserPopover: React.FC<{ + userInfo: UserBaseInfo; +}> = React.memo((props) => { + const { userInfo } = props; + + return ( +
+ +
+ {userInfo.nickname} + #{userInfo.discriminator} +
+ +
+ {userInfo.temporary && {t('游客')}} +
+
+ ); +}); +GroupUserPopover.displayName = 'GroupUserPopover'; diff --git a/web/src/styles/antd/dark.less b/web/src/styles/antd/dark.less index 57125239..347b9891 100644 --- a/web/src/styles/antd/dark.less +++ b/web/src/styles/antd/dark.less @@ -350,4 +350,26 @@ border-color: #177ddc; } } + + // Popover + .ant-popover { + .ant-popover-arrow > .ant-popover-arrow-content, + .ant-popover-arrow > .ant-popover-arrow-content::before, + .ant-popover-inner { + background-color: #1f1f1f; + } + + .ant-popover-inner-content { + color: rgba(255, 255, 255, 0.85); + } + } + + // Tag + .ant-tag { + &.ant-tag-processing { + color: #177ddc; + background: #111b26; + border-color: #153450; + } + } }