Skip to content

Commit

Permalink
chore: add preview and style chat component
Browse files Browse the repository at this point in the history
  • Loading branch information
yasell committed Feb 3, 2025
1 parent 9c7f5a9 commit 01021da
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 34 deletions.
27 changes: 27 additions & 0 deletions apps/design-system/src/pages/view-preview/view-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { SignUpView } from '@subjects/views/signup'
import { SpaceSettingsMembers } from '@subjects/views/space-settings-members/space-settings-members'
import { useTranslationsStore } from '@utils/viewUtils'

import { Chat } from '@harnessio/ui/components'
import { NotFoundPage } from '@harnessio/ui/views'

import { CommitDetailsDiffViewWrapper } from './commit-details-diff-view-wrapper'
Expand Down Expand Up @@ -161,6 +162,32 @@ export const viewPreviews: Record<string, ReactNode> = {
<PipelineGraphWrapper />
</RepoViewWrapper>
),
'chat-preview': (
<RepoViewWrapper>
<div className="max-w-[460px] h-full border-r border-borders-4">
<Chat.Root>
<Chat.Body>
<Chat.Message>
Hey Olivia! I&#39;ve finished with the requirements doc! I made some notes in the gdoc as well for Phoenix
to look over.
</Chat.Message>
<Chat.Message self>Awesome! Thanks, I&#39;ll take a look at this today.</Chat.Message>
<Chat.Separator title="Today" />
<Chat.Message>
No rush though — we still have to wait for Lana&#39;s design. Click the button in the actions panel below
to see branches which require your attention to fix and redeploy.
</Chat.Message>
<Chat.Message>Hey Olivia, can you please review the latest design when you have a chance?</Chat.Message>
<Chat.Message self>Sure thing, I&#39;ll have a look today. They&#39;re looking great!</Chat.Message>
<Chat.Typing />
</Chat.Body>
<Chat.Footer>
<Chat.Input />
</Chat.Footer>
</Chat.Root>
</div>
</RepoViewWrapper>
),
'pipeline-graph-minimal': (
<RepoViewWrapper>
<PipelineGraphMinimalWrapper />
Expand Down
67 changes: 33 additions & 34 deletions packages/ui/src/components/chat.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,69 @@
import { ChangeEvent, KeyboardEvent, ReactNode, RefObject } from 'react'

import { Button, Icon, Input, Text } from '@/components'
import { Button, Icon, Input } from '@/components'
import ChatAvatarIcon from '@/icons/chat-avatar.svg'
import { cn } from '@/utils/cn'

// Root Container
const Root: React.FC<{ children: ReactNode }> = ({ children }) => {
return <div className="w-full h-full overflow-y-auto flex flex-col">{children}</div>
return <div className="w-full h-full overflow-y-auto flex flex-col bg-background-1">{children}</div>
}

// Body
const Body: React.FC<{ children: ReactNode }> = ({ children }) => {
return <div className="flex-1 flex flex-col gap-6 mb-3 p-6">{children}</div>
return (
<div className="flex-1 flex flex-col gap-y-6 mb-5 px-6 py-4">
<div className="flex items-center justify-between">
<p className="text-foreground-1 text-16 font-medium">AI Assistant</p>
<Button size="icon" variant="custom" className="text-icons-4 -mr-2 hover:text-icons-2">
<Icon name="close" size={16} />
<span className="sr-only">Close</span>
</Button>
</div>
{children}
</div>
)
}

// Footer
const Footer: React.FC<{ children: ReactNode }> = ({ children }) => {
return <div className="sticky bottom-0 p-6 pt-0 bg-background">{children}</div>
return <div className="sticky bottom-0 px-5 py-6">{children}</div>
}

// Message Component
interface MessageProps {
self?: boolean
time?: string
avatar?: ReactNode
actions?: ReactNode
children: ReactNode
}

const Message: React.FC<MessageProps> = ({ self, time, avatar, actions, children }) => {
const Message: React.FC<MessageProps> = ({ self, avatar, actions, children }) => {
return (
<div
className={cn('flex gap-x-3 content-center items-start', {
'place-content-end': self
})}
>
<div className="mt-0.5">{!self && avatar}</div>
{!self && <div className="mt-0.5">{avatar ? avatar : <ChatAvatarIcon />}</div>}
<div
className={cn('flex flex-col gap-1.5', {
className={cn('flex flex-col gap-3', {
'w-[85%] items-end': self,
'w-full': !self
})}
>
<div
className={cn('text-foreground-3 leading-relaxed', {
'px-3 py-2 bg-background-8 rounded-lg': self
className={cn('text-14 text-foreground-1 leading-relaxed', {
'px-3.5 py-2 bg-background-8 rounded-[8px_8px_2px_8px]': self
})}
>
{children}
</div>
<div className="flex gap-3 items-center justify-between mt-1">
<div>{actions && <div className="flex gap-1 items-center justify-start">{actions}</div>}</div>
{time && (
<Text size={1} className="text-primary opacity-20">
{time}
</Text>
)}
</div>
{actions && (
<div className="flex gap-3 items-center justify-between mt-1">
<div className="flex gap-1 items-center justify-start">{actions}</div>
</div>
)}
</div>
</div>
)
Expand All @@ -68,17 +76,9 @@ interface TypingProps {

const Typing: React.FC<TypingProps> = ({ avatar }) => {
return (
<div className="flex items-center gap-3 mt-3">
{avatar}
<div className="flex gap-1 text-success text-lg font-medium" aria-live="polite">
<span className="dot animate-bounce">&middot;</span>
<span className="dot animate-bounce" style={{ animationDelay: '0.15s' }}>
&middot;
</span>
<span className="dot animate-bounce" style={{ animationDelay: '0.3s' }}>
&middot;
</span>
</div>
<div className="flex items-center gap-x-3.5 mt-3">
{avatar || <ChatAvatarIcon />}
<span className="w-2.5 h-2.5 rounded-full bg-foreground-2" aria-hidden />
</div>
)
}
Expand Down Expand Up @@ -112,25 +112,24 @@ const InputField: React.FC<InputFieldProps> = ({
onSend = () => {},
placeholder = 'Type a message...',
disabled = false,
sendIcon = <Icon name="chevron-up" size={16} />
sendIcon = <Icon className="-rotate-90" name="arrow-long" size={14} />
}) => {
return (
<div className="sticky bottom-0 bg-background flex items-center gap-2">
<div className="sticky bottom-0 flex items-center gap-2">
<Input
ref={inputRef}
className="flex-1 pt-6 px-4 pb-16 rounded-lg focus:ring-0"
className="flex-1 h-11 px-3 rounded-lg focus:ring-0 focus-visible:h-16 focus-visible:pb-8"
value={value}
onChange={onChange}
onKeyDown={onKeyDown}
placeholder={placeholder}
aria-label="Chat input"
/>
<Button
className="absolute right-3 bottom-2 z-10 size-7 rounded-full"
onClick={onSend}
variant="outline"
size="icon"
disabled={disabled}
className="absolute right-3.5 bottom-3.5 z-10 w-6 h-6"
>
{sendIcon}
</Button>
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export * from './sidebar/sidebar'
export * from './separator'
export * from './label-marker'
export * from './problems'
export * from './chat'

export * as NodeGroup from './node-group'
export * as ShaBadge from './sha-badge'
Expand Down
24 changes: 24 additions & 0 deletions packages/ui/src/icons/chat-avatar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 01021da

Please sign in to comment.