-
-
Notifications
You must be signed in to change notification settings - Fork 163
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ feat(chat): add ChatItem and ChatList components
This commit updates the `packages/dumi-theme-lobehub/package.json` file by removing unused dependencies, updating the version of some packages, and adding a dependency on `"@floating-ui/react": "^0"`. In addition, it adds two new demo files in the `src/ChatItem/demos` folder. The first demo file is `Alert.tsx`, which creates an alert message using the `ChatItem` component with props passed via `useControls` hook, while the second is `index.tsx` which exports the `ChatItem` component used in the previous demo file.
- Loading branch information
1 parent
9c6a8db
commit e3bacd8
Showing
17 changed files
with
413 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { ChatItem, ChatItemProps, StroyBook, useControls, useCreateStore } from '@lobehub/ui'; | ||
|
||
export default () => { | ||
const store = useCreateStore(); | ||
const control: ChatItemProps['alert'] | any = useControls( | ||
{ | ||
message: 'Error', | ||
description: '', | ||
type: { | ||
value: 'error', | ||
options: ['success', 'info', 'warning', 'error'], | ||
}, | ||
}, | ||
{ store }, | ||
); | ||
|
||
return ( | ||
<StroyBook levaStore={store}> | ||
<ChatItem alert={control} avatar="😅" /> | ||
</StroyBook> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { ChatItem, ChatItemProps, StroyBook, useControls, useCreateStore } from '@lobehub/ui'; | ||
|
||
export default () => { | ||
const store = useCreateStore(); | ||
const control: ChatItemProps | any = useControls( | ||
{ | ||
avatar: '😅', | ||
name: '', | ||
message: { | ||
value: | ||
"要使用 dayjs 的 fromNow 函数,需要先安装 dayjs 库并在代码中引入它。然后,可以使用以下语法来获取当前时间与给定时间之间的相对时间:\n\n```javascript\ndayjs().fromNow();\ndayjs('2021-05-01').fromNow();\n```", | ||
rows: true, | ||
}, | ||
primary: false, | ||
placement: { | ||
value: 'left', | ||
options: ['left', 'right'], | ||
}, | ||
type: { | ||
value: 'block', | ||
options: ['block', 'pure'], | ||
}, | ||
borderSpacing: true, | ||
loading: false, | ||
}, | ||
{ store }, | ||
); | ||
|
||
return ( | ||
<StroyBook levaStore={store}> | ||
<ChatItem {...control} /> | ||
</StroyBook> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
--- | ||
nav: Components | ||
group: Chat | ||
title: ChatItem | ||
description: ChatItem is a React component that represents a single item in a chat conversation. It displays the user's avatar, name, and message. It can also display a loading indicator if the message is still being sent. | ||
--- | ||
|
||
## Default | ||
|
||
<code src="./demos/index.tsx" nopadding></code> | ||
|
||
## Alert | ||
|
||
<code src="./demos/Alert.tsx" nopadding></code> | ||
|
||
## APIs | ||
|
||
<API></API> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { Alert, type AlertProps } from 'antd'; | ||
import { Loader2 } from 'lucide-react'; | ||
import { memo } from 'react'; | ||
|
||
import { Avatar, Icon, Markdown } from '@/index'; | ||
import type { DivProps } from '@/types'; | ||
|
||
import { useStyles } from './style'; | ||
|
||
const AVATAR_SIZE = 40; | ||
|
||
export interface ChatItemProps extends DivProps { | ||
/** | ||
* @description Weather to show alert and alert config | ||
*/ | ||
alert?: AlertProps; | ||
/** | ||
* @description URL of the avatar image | ||
*/ | ||
avatar?: string; | ||
/** | ||
* @description Whether to add spacing between chat items | ||
* @default true | ||
*/ | ||
borderSpacing?: boolean; | ||
/** | ||
* @description Whether to show a loading spinner | ||
* @default false | ||
*/ | ||
loading?: boolean; | ||
/** | ||
* @description The message to be displayed | ||
*/ | ||
message?: string; | ||
/** | ||
* @description The name of the chat item | ||
*/ | ||
name?: string; | ||
/** | ||
* @description The placement of the chat item | ||
* @default 'left' | ||
*/ | ||
placement?: 'left' | 'right'; | ||
/** | ||
* @description Whether the chat item is primary | ||
* @default false | ||
*/ | ||
primary?: boolean; | ||
/** | ||
* @description The type of chat item | ||
* @default 'block' | ||
*/ | ||
type?: 'block' | 'pure'; | ||
} | ||
|
||
const ChatItem = memo<ChatItemProps>( | ||
({ | ||
className, | ||
name, | ||
primary, | ||
borderSpacing = true, | ||
loading, | ||
message, | ||
placement = 'left', | ||
type = 'block', | ||
avatar, | ||
alert, | ||
...props | ||
}) => { | ||
const { cx, styles } = useStyles({ placement, type, name, primary, avatarSize: AVATAR_SIZE }); | ||
return ( | ||
<div className={cx(styles.container, className)} {...props}> | ||
<div className={styles.avatarContainer}> | ||
<Avatar avatar={avatar} size={AVATAR_SIZE} /> | ||
{loading && ( | ||
<div className={styles.loading}> | ||
<Icon icon={Loader2} size={{ fontSize: 12, strokeWidth: 3 }} spin /> | ||
</div> | ||
)} | ||
</div> | ||
<div className={styles.messageContainer}> | ||
{name && <div className={styles.name}>{name}</div>} | ||
{alert ? ( | ||
<Alert showIcon {...alert} /> | ||
) : ( | ||
<div className={styles.message}> | ||
<Markdown>{String(message || '...')}</Markdown> | ||
</div> | ||
)} | ||
</div> | ||
{borderSpacing && <div style={{ width: AVATAR_SIZE, flex: 'none' }} />} | ||
</div> | ||
); | ||
}, | ||
); | ||
|
||
export default ChatItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { createStyles } from 'antd-style'; | ||
|
||
export const useStyles = createStyles( | ||
( | ||
{ cx, css, token }, | ||
{ | ||
placement, | ||
type, | ||
name, | ||
primary, | ||
avatarSize, | ||
}: { | ||
avatarSize: number; | ||
name?: string; | ||
placement?: 'left' | 'right'; | ||
primary?: boolean; | ||
type?: 'block' | 'pure'; | ||
}, | ||
) => { | ||
const blockStylish = css` | ||
padding: 8px 12px; | ||
background-color: ${primary ? token.colorFillSecondary : token.colorFillTertiary}; | ||
border-radius: ${token.borderRadiusLG}px; | ||
transition: background-color 100ms ${token.motionEaseOut}; | ||
&:active { | ||
background-color: ${primary ? token.colorFill : token.colorFillSecondary}; | ||
} | ||
`; | ||
|
||
const pureStylish = css` | ||
padding-top: ${name ? 0 : '6px'}; | ||
`; | ||
|
||
const pureContainerStylish = css` | ||
border-radius: ${token.borderRadiusLG}px; | ||
transition: background-color 100ms ${token.motionEaseOut}; | ||
&:hover { | ||
background-color: ${token.colorFillTertiary}; | ||
} | ||
&:active { | ||
background-color: ${token.colorFillSecondary}; | ||
} | ||
`; | ||
|
||
const typeStylish = type === 'block' ? blockStylish : pureStylish; | ||
|
||
return { | ||
container: cx( | ||
type === 'pure' && pureContainerStylish, | ||
css` | ||
position: relative; | ||
display: flex; | ||
flex-direction: ${placement === 'left' ? 'row' : 'row-reverse'}; | ||
gap: 12px; | ||
align-items: flex-start; | ||
justify-content: revert; | ||
width: 100%; | ||
padding: 12px; | ||
`, | ||
), | ||
loading: css` | ||
position: absolute; | ||
right: ${placement === 'left' ? '-4px' : 'unset'}; | ||
bottom: 0; | ||
left: ${placement === 'right' ? '-4px' : 'unset'}; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
width: 16px; | ||
height: 16px; | ||
color: ${token.colorBgLayout}; | ||
background: ${token.colorPrimary}; | ||
border-radius: 50%; | ||
`, | ||
avatarContainer: css` | ||
position: relative; | ||
flex: none; | ||
width: ${avatarSize}px; | ||
height: ${avatarSize}px; | ||
`, | ||
messageContainer: css` | ||
position: relative; | ||
.ant-alert-with-description { | ||
padding-block: 12px; | ||
padding-inline: 12px; | ||
} | ||
`, | ||
name: css` | ||
margin-bottom: 6px; | ||
font-size: 12px; | ||
line-height: 1; | ||
color: ${token.colorTextDescription}; | ||
text-align: ${placement === 'left' ? 'left' : 'right'}; | ||
`, | ||
message: cx( | ||
typeStylish, | ||
css` | ||
position: relative; | ||
`, | ||
), | ||
}; | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { ChatMessage } from '@/Chat'; | ||
|
||
export const data: ChatMessage[] = [ | ||
{ | ||
role: 'user', | ||
content: 'dayjs 如何使用 fromNow', | ||
}, | ||
{ | ||
role: 'assistant', | ||
content: | ||
'要使用 dayjs 的 fromNow 函数,需要先安装 dayjs 库并在代码中引入它。然后,可以使用以下语法来获取当前时间与给定时间之间的相对时间:\n\n```javascript\ndayjs().fromNow(); // 获取当前时间的相对时间\ndayjs(\'2021-05-01\').fromNow(); // 获取给定时间的相对时间\n```\n\n第一个示例将返回类似于 "几秒前"、"一分钟前"、"2 天前" 的相对时间字符串,表示当前时间与调用 fromNow 方法时的时间差。第二个示例将返回给定时间与当前时间的相对时间字符串。', | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { ChatList, ChatListProps, StroyBook, useControls, useCreateStore } from '@lobehub/ui'; | ||
|
||
import { data } from './data'; | ||
|
||
export default () => { | ||
const store = useCreateStore(); | ||
const control: ChatListProps | any = useControls( | ||
{ | ||
type: { | ||
value: 'chat', | ||
options: ['doc', 'chat'], | ||
}, | ||
}, | ||
{ store }, | ||
); | ||
|
||
return ( | ||
<StroyBook levaStore={store}> | ||
<ChatList data={data} {...control} /> | ||
</StroyBook> | ||
); | ||
}; |
Oops, something went wrong.