Skip to content

Commit

Permalink
some basic ui styling
Browse files Browse the repository at this point in the history
  • Loading branch information
nl0 committed Jul 8, 2024
1 parent 47f3b26 commit e6712dd
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 59 deletions.
196 changes: 166 additions & 30 deletions catalog/app/components/Assistant/UI/Chat/Chat.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import cx from 'classnames'
import * as React from 'react'
import * as M from '@material-ui/core'

Check warning on line 3 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L1-L3

Added lines #L1 - L3 were not covered by tests
// import * as Lab from '@material-ui/lab'

// import Skeleton from 'components/Skeleton'
import Markdown from 'components/Markdown'

Check warning on line 6 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L6

Added line #L6 was not covered by tests

import * as Model from '../../Model'

Check warning on line 8 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L8

Added line #L8 was not covered by tests

Expand All @@ -20,11 +21,14 @@ function Message({
role,
content,
}: ConversationDispatchProps & ReturnType<typeof Model.Conversation.Event.Message>) {
// XXX: render markdown?
return (

Check warning on line 24 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L21-L24

Added lines #L21 - L24 were not covered by tests
<div>
<b>{role === 'user' ? 'You' : 'Assistant'}</b>: {JSON.stringify(content)}
</div>
<MessageContainer role={role}>
{Model.Content.MessageContentBlock.$match(content, {
Text: ({ text }) => <Markdown data={text} />,
Image: ({ format }) => `${format} image`,
Document: ({ name, format }) => `${format} document "${name}"`,

Check warning on line 29 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L27-L29

Added lines #L27 - L29 were not covered by tests
})}
</MessageContainer>
)
}

Expand All @@ -36,15 +40,26 @@ function ToolUse({
input,
result, // dispatch,
}: ConversationDispatchProps & ReturnType<typeof Model.Conversation.Event.ToolUse>) {

Check warning on line 42 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L38-L42

Added lines #L38 - L42 were not covered by tests
return (
<div>
<b>
{name} ({toolUseId}):
</b>{' '}
{JSON.stringify(input)}
const details = (
<>

Check warning on line 44 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L44

Added line #L44 was not covered by tests
<b>Tool Use ID:</b> {toolUseId}
<br />
<b>Result:</b> {JSON.stringify(result)}
</div>
<b>Tool Name:</b> {name}
<br />
<b>Input:</b>
<pre>{JSON.stringify(input, null, 2)}</pre>
<b>Result:</b>
<pre>{JSON.stringify(result, null, 2)}</pre>
</>
)
return (

Check warning on line 55 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L55

Added line #L55 was not covered by tests
<MessageContainer role="assistant">
<M.Tooltip title={details}>
<span>
Tool Use: <b>{name}</b> ({result.status})
</span>
</M.Tooltip>
</MessageContainer>
)
}

Expand Down Expand Up @@ -80,24 +95,105 @@ function ToolUse({
// },
// }))

const useMessageContainerStyles = M.makeStyles((t) => ({

Check warning on line 98 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L98

Added line #L98 was not covered by tests
role_user: {},
role_assistant: {},
messageContainer: {
alignItems: 'flex-end',
display: 'flex',
gap: `${t.spacing(1)}px`,
'&$role_user': {
alignSelf: 'flex-end',
flexFlow: 'row-reverse',
},
'&$role_assistant': {
alignSelf: 'flex-start',
},
},
avatar: {
height: `${t.spacing(4)}px`,
width: `${t.spacing(4)}px`,
'$role_user &': {
background: t.palette.primary.main,
color: t.palette.primary.contrastText,
},
'$role_assistant &': {
background: t.palette.background.paper,
color: t.palette.text.primary,
},
},
contents: {
borderRadius: `${t.spacing(1)}px`,
padding: `${t.spacing(1.5)}px`,
...t.typography.body2,
'$role_user &': {
background: t.palette.primary.main,
borderBottomRightRadius: 0,
color: t.palette.primary.contrastText,
},
'$role_assistant &': {
background: t.palette.background.paper,
borderBottomLeftRadius: 0,
color: t.palette.text.primary,
},
},
spacer: {
flexShrink: 0,
width: `${t.spacing(4)}px`,
},
}))

interface MessageContainerProps {
role: 'user' | 'assistant'
children: React.ReactNode
}

function MessageContainer({ role, children }: MessageContainerProps) {
const classes = useMessageContainerStyles()
return (

Check warning on line 153 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L151-L153

Added lines #L151 - L153 were not covered by tests
<div className={cx(classes.messageContainer, classes[`role_${role}`])}>
<M.Avatar className={classes.avatar}>
<M.Icon fontSize="small">{role === 'user' ? 'person' : 'assistant'}</M.Icon>
</M.Avatar>
<div className={classes.contents}>{children}</div>
<div className={classes.spacer} />
</div>
)
}

const useChatStyles = M.makeStyles((t) => ({

Check warning on line 164 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L164

Added line #L164 was not covered by tests
root: {
chat: {
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
overflow: 'hidden',
},
error: {
marginTop: t.spacing(2),
header: {
padding: `${t.spacing(2)}px`,
paddingBottom: `${t.spacing(1)}px`,
},
history: {
...t.typography.body1,
maxHeight: t.spacing(70),
historyContainer: {
flexGrow: 1,
overflowY: 'auto',
// TODO: nice overflow markers
// position: 'relative',
// '&::before': {
// content: '""',
// position: 'absolute',
// },
// '&::after': {
// },
},
input: {
marginTop: t.spacing(2),
history: {
background: M.fade(t.palette.primary.main, 0.2),
display: 'flex',
flexDirection: 'column',
gap: `${t.spacing(2)}px`,
justifyContent: 'flex-end',
minHeight: '100%',
padding: `${t.spacing(2)}px`,
},
input: {},
}))

interface ChatProps {
Expand Down Expand Up @@ -127,17 +223,57 @@ export default function Chat({ state, dispatch }: ChatProps) {
},
[dispatch],
)

return (

Check warning on line 227 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L227

Added line #L227 was not covered by tests
<div className={classes.root}>
<div className={classes.history}>
{state.events.map(
Model.Conversation.Event.$match({
Message: (event) => <Message key={event.id} dispatch={dispatch} {...event} />,
ToolUse: (event) => <ToolUse key={event.id} dispatch={dispatch} {...event} />,
}),
)}
<div className={classes.chat}>
<div className={classes.header}>
<M.Typography variant="h4">Qurator</M.Typography>
<M.Typography variant="caption" color="textSecondary">
Qurator may make errors. Verify important information.
</M.Typography>
</div>
<div className={classes.historyContainer}>
<div className={classes.history}>
<MessageContainer role="assistant">
Hi! I'm Qurator. How can I help you?
</MessageContainer>
{state.events.map(
Model.Conversation.Event.$match({
Message: (event) => (

Check warning on line 242 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L242

Added line #L242 was not covered by tests
<Message key={event.id} dispatch={dispatch} {...event} />
),
ToolUse: (event) => (

Check warning on line 245 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L245

Added line #L245 was not covered by tests
<ToolUse key={event.id} dispatch={dispatch} {...event} />
),
}),
)}
{Model.Conversation.State.$match(state, {
Idle: () => null,
WaitingForAssistant: () => (

Check warning on line 252 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L251-L252

Added lines #L251 - L252 were not covered by tests
<MessageContainer role="assistant">Thinking...</MessageContainer>
),
ToolUse: ({ calls }) => {
const details = Object.entries(calls).map(([id, call]) => (

Check warning on line 256 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L255-L256

Added lines #L255 - L256 were not covered by tests
<React.Fragment key={id}>
<b>Tool Use ID:</b> {id}
<br />
<b>Tool Name:</b> {call.name}
<br />
<b>Input:</b>
<pre>{JSON.stringify(call.input, null, 2)}</pre>
</React.Fragment>
))
return (

Check warning on line 266 in catalog/app/components/Assistant/UI/Chat/Chat.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Chat.tsx#L266

Added line #L266 was not covered by tests
<MessageContainer role="assistant">
<M.Tooltip title={details}>
<span>Using tools ({calls.length})...</span>
</M.Tooltip>
</MessageContainer>
)
},
})}
</div>
</div>

<Input className={classes.input} disabled={inputDisabled} onSubmit={ask} />
</div>
)
Expand Down
50 changes: 27 additions & 23 deletions catalog/app/components/Assistant/UI/Chat/Input.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import cx from 'classnames'
import * as React from 'react'
import * as M from '@material-ui/core'

Check warning on line 3 in catalog/app/components/Assistant/UI/Chat/Input.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Input.tsx#L1-L3

Added lines #L1 - L3 were not covered by tests

const useStyles = M.makeStyles((t) => ({

Check warning on line 5 in catalog/app/components/Assistant/UI/Chat/Input.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Input.tsx#L5

Added line #L5 was not covered by tests
input: {
alignItems: 'center',
display: 'flex',
padding: `${t.spacing(2)}px`,
paddingRight: `${t.spacing(1)}px`,
},
}))

interface ChatInputProps {
className?: string
disabled?: boolean
onSubmit: (value: string) => void
}

export default function ChatInput({ className, disabled, onSubmit }: ChatInputProps) {
const classes = useStyles()

Check warning on line 21 in catalog/app/components/Assistant/UI/Chat/Input.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Input.tsx#L20-L21

Added lines #L20 - L21 were not covered by tests

const [value, setValue] = React.useState('')

Check warning on line 23 in catalog/app/components/Assistant/UI/Chat/Input.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Input.tsx#L23

Added line #L23 was not covered by tests

const handleSubmit = React.useCallback(
Expand All @@ -19,33 +31,25 @@ export default function ChatInput({ className, disabled, onSubmit }: ChatInputPr
},
[disabled, onSubmit, value],
)

return (

Check warning on line 35 in catalog/app/components/Assistant/UI/Chat/Input.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Input.tsx#L35

Added line #L35 was not covered by tests
<form onSubmit={handleSubmit}>
<M.TextField
autoFocus
className={className}
// disabled={disabled}
fullWidth
helperText="Qurator may make errors. Verify critical information yourself."
label="Chat"
<form className={cx(classes.input, className)} onSubmit={handleSubmit}>
<M.OutlinedInput
onChange={(e) => setValue(e.target.value)}

Check warning on line 38 in catalog/app/components/Assistant/UI/Chat/Input.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/Chat/Input.tsx#L38

Added line #L38 was not covered by tests
size="small"
value={value}
variant="outlined"
InputProps={{
endAdornment: (
<M.InputAdornment position="end">
<M.IconButton
disabled={disabled || !value}
onClick={handleSubmit}
type="submit"
>
<M.Icon>send</M.Icon>
</M.IconButton>
</M.InputAdornment>
),
}}
autoFocus
fullWidth
margin="dense"
placeholder="Type a message..."
/>
<M.IconButton
disabled={disabled || !value}
onClick={handleSubmit}
type="submit"
color="primary"
>
<M.Icon>send</M.Icon>
</M.IconButton>
</form>
)
}
12 changes: 6 additions & 6 deletions catalog/app/components/Assistant/UI/UI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import * as style from 'constants/style'
import * as Model from '../Model'
import Chat from './Chat'

Check warning on line 7 in catalog/app/components/Assistant/UI/UI.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/UI.tsx#L6-L7

Added lines #L6 - L7 were not covered by tests

const useSidebarStyles = M.makeStyles((t) => ({
root: {
padding: t.spacing(2),
const useSidebarStyles = M.makeStyles({

Check warning on line 9 in catalog/app/components/Assistant/UI/UI.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/UI.tsx#L9

Added line #L9 was not covered by tests
sidebar: {
display: 'flex',
height: '100%',
width: '50vw',
},
}))
})

function Sidebar() {
const classes = useSidebarStyles()

Check warning on line 18 in catalog/app/components/Assistant/UI/UI.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/UI.tsx#L17-L18

Added lines #L17 - L18 were not covered by tests
Expand All @@ -22,8 +23,7 @@ function Sidebar() {
return (

Check warning on line 23 in catalog/app/components/Assistant/UI/UI.tsx

View check run for this annotation

Codecov / codecov/patch/informational

catalog/app/components/Assistant/UI/UI.tsx#L23

Added line #L23 was not covered by tests
<M.MuiThemeProvider theme={style.appTheme}>
<M.Drawer anchor="right" open={api.visible} onClose={api.hide}>
<div className={classes.root}>
<M.Typography variant="h4">Qurator</M.Typography>
<div className={classes.sidebar}>
<Chat state={api.state} dispatch={api.dispatch} />
</div>
</M.Drawer>
Expand Down

0 comments on commit e6712dd

Please sign in to comment.