style: adjust copilot chat style (#2915)

This commit is contained in:
JimmFly
2023-07-03 13:57:30 +08:00
committed by GitHub
parent 8d0edd5255
commit 6f9487deb7
5 changed files with 149 additions and 30 deletions

View File

@@ -1,4 +1,5 @@
import { Button, Input } from '@affine/component';
import { IconButton } from '@affine/component';
import { SendIcon } from '@blocksuite/icons';
import { rootStore } from '@toeverything/plugin-infra/manager';
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
import { Provider, useAtomValue, useSetAtom } from 'jotai';
@@ -12,8 +13,8 @@ import { openAIApiKeyAtom, useChatAtoms } from '../core/hooks';
import {
detailContentActionsStyle,
detailContentStyle,
inputStyle,
sendButtonStyle,
textareaStyle,
} from './index.css';
if (typeof window === 'undefined') {
@@ -71,22 +72,23 @@ const Actions = () => {
<>
<FollowingUp questions={questions} />
<div className={detailContentActionsStyle}>
<Input
className={inputStyle}
<textarea
className={textareaStyle}
value={input}
onChange={text => {
setInput(text);
placeholder="Type here ask Copilot some thing..."
onChange={e => {
setInput(e.target.value);
}}
/>
<Button
<IconButton
className={sendButtonStyle}
onClick={useCallback(async () => {
await call(input);
await generateFollowingUp();
}, [call, generateFollowingUp, input])}
>
send
</Button>
<SendIcon />
</IconButton>
</div>
</>
);

View File

@@ -13,15 +13,31 @@ export const detailContentStyle = style({
export const detailContentActionsStyle = style({
marginTop: 'auto',
alignItems: 'flex-end',
marginBottom: '10px',
fontSize: 'var(--affine-font-xs)',
display: 'flex',
width: '100%',
justifyContent: 'space-between',
});
export const inputStyle = style({
export const textareaStyle = style({
fontSize: 'var(--affine-font-xs)',
border: '1px solid var(--affine-border-color)',
width: '100%',
borderRadius: '4px',
background: 'var(--affine-hover-color)',
height: '117px',
padding: '8px 10px',
'::placeholder': {
color: 'var(--affine-text-secondary-color)',
},
});
export const sendButtonStyle = style({
marginTop: '10px',
borderRadius: '8px',
fontSize: 'var(--affine-font-xs)',
width: '16px',
height: '16px',
marginLeft: '8px',
':hover': {
cursor: 'pointer',
backgroundColor: 'transparent',
},
});

View File

@@ -3,7 +3,7 @@ import { style } from '@vanilla-extract/css';
export const conversationListStyle = style({
display: 'flex',
flexDirection: 'column',
gap: '30px',
gap: '24px',
height: 'calc(100% - 100px)',
overflow: 'auto',
});

View File

@@ -1,18 +1,80 @@
import { style } from '@vanilla-extract/css';
import { globalStyle, style } from '@vanilla-extract/css';
export const containerStyle = style({
display: 'flex',
width: '100%',
padding: '0 16px',
gap: '10px',
});
export const conversationStyle = style({
padding: '10px 18px',
border: '1px solid var(--affine-border-color)',
fontSize: 'var(--affine-font-xs)',
lineHeight: '16px',
borderRadius: '18px',
position: 'relative',
});
export const conversationContainerStyle = style({
maxWidth: '90%',
display: 'flex',
flexDirection: 'column',
position: 'relative',
});
export const insertButtonsStyle = style({
width: '100%',
marginTop: '10px',
display: 'flex',
flexWrap: 'wrap',
gap: '8px',
});
export const insertButtonStyle = style({
maxWidth: '100%',
padding: '16px 8px',
fontSize: 'var(--affine-font-xs)',
borderRadius: '8px',
border: '1px solid var(--affine-border-color)',
cursor: 'pointer',
backgroundColor: 'var(--affine-white)',
gap: '8px',
':hover': {
background: 'var(--affine-white),var(--affine-hover-color)',
borderColor: 'var(--affine-border-color)',
},
});
export const avatarRightStyle = style({
flexDirection: 'row-reverse',
});
export const aiMessageStyle = style({
backgroundColor: 'rgba(207, 252, 255, 0.3)',
borderRadius: '18px 18px 18px 2px',
});
export const humanMessageStyle = style({
borderRadius: '18px 18px 2px 18px',
backgroundColor: 'var(--affine-white-90)',
});
export const regenerateButtonStyle = style({
position: 'absolute',
display: 'none',
right: '12px',
top: '-16px',
padding: '4px 8px',
fontSize: 'var(--affine-font-xs)',
borderRadius: '8px',
border: '1px solid var(--affine-border-color)',
cursor: 'pointer',
backgroundColor: 'var(--affine-white)',
':hover': {
background:
'linear-gradient(var(--affine-white),var(--affine-white)),var(--affine-hover-color)',
backgroundBlendMode: 'overlay',
display: 'flex',
},
});
export const resetIconStyle = style({
fontSize: 'var(--affine-font-sm)',
display: 'inline-flex',
alignItems: 'center',
marginRight: '4px',
});
globalStyle(`${conversationStyle}:hover ${regenerateButtonStyle}`, {
display: 'flex',
});

View File

@@ -1,3 +1,6 @@
import { Button } from '@affine/component';
import { WorkspaceAvatar } from '@affine/component/workspace-avatar';
import { PlusIcon, ResetIcon } from '@blocksuite/icons';
import { clsx } from 'clsx';
import type { MessageType } from 'langchain/schema';
import { marked } from 'marked';
@@ -5,11 +8,7 @@ import { gfmHeadingId } from 'marked-gfm-heading-id';
import { mangle } from 'marked-mangle';
import { type ReactElement, useMemo } from 'react';
import {
aiMessageStyle,
conversationStyle,
humanMessageStyle,
} from './index.css';
import * as styles from './index.css';
marked.use(
gfmHeadingId({
@@ -28,13 +27,53 @@ export const Conversation = (props: ConversationProps): ReactElement => {
const html = useMemo(() => marked.parse(props.text), [props.text]);
return (
<div
className={clsx(conversationStyle, {
[aiMessageStyle]: props.type === 'ai',
[humanMessageStyle]: props.type === 'human',
className={clsx(styles.containerStyle, {
[styles.avatarRightStyle]: props.type === 'human',
})}
dangerouslySetInnerHTML={{
__html: html,
}}
></div>
>
<WorkspaceAvatar workspace={null} />
<div className={styles.conversationContainerStyle}>
<div
className={clsx(styles.conversationStyle, {
[styles.aiMessageStyle]: props.type === 'ai',
[styles.humanMessageStyle]: props.type === 'human',
})}
>
{props.type === 'ai' ? (
<div className={styles.regenerateButtonStyle}>
<div className={styles.resetIconStyle}>
<ResetIcon />
</div>
Regenerate
</div>
) : null}
<div
dangerouslySetInnerHTML={{
__html: html,
}}
></div>
</div>
{props.type === 'ai' ? (
<div className={styles.insertButtonsStyle}>
<Button
icon={<PlusIcon />}
size="small"
className={styles.insertButtonStyle}
hoverColor="var(--affine-text-primary-color)"
>
Insert list block only
</Button>
<Button
icon={<PlusIcon />}
size="small"
className={styles.insertButtonStyle}
hoverColor="var(--affine-text-primary-color)"
>
Insert all
</Button>
</div>
) : null}
</div>
</div>
);
};