Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
app/cody: small window UI for cody chat page (#53384)
Browse files Browse the repository at this point in the history
Closes https://github.com/sourcegraph/sourcegraph/issues/53112

Significantly improves the small window/mobile UI in the Cody chat page,
perfect for docking the App on the side of the screen.

## Test plan


https://github.com/sourcegraph/sourcegraph/assets/206864/406589c6-a73b-41a8-8f97-86e6f7c34021
  • Loading branch information
limitedmage authored Jun 13, 2023
1 parent 2f1faff commit 1cd36d2
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 10 deletions.
83 changes: 83 additions & 0 deletions client/web/src/cody/chat/CodyChatPage.module.scss
Original file line number Diff line number Diff line change
@@ -1,13 +1,55 @@
@import 'wildcard/src/global-styles/breakpoints';

.page-header {
display: flex;
margin-bottom: 1rem;

@media (--sm-breakpoint-down) {
display: none;
}
}

.chat-main-wrapper {
display: flex;
flex-direction: column;
filter: none;
border: 1px solid var(--border-color-2);
border-radius: var(--border-radius);
padding: 0;

@media (--sm-breakpoint-down) {
&-with-mobile-history {
display: none;
}
}
}

.page {
@media (--sm-breakpoint-down) {
// These need to be !important to override the `py-4` default padding on the page
padding-top: 0 !important;
padding-bottom: 0 !important;
}
}

.page-wrapper {
padding-top: 0.625rem;
height: 93%;

@media (--sm-breakpoint-down) {
padding-top: 0;
height: 100%;
}
}

.sidebar-wrapper {
display: flex;
flex-direction: column;
height: 100%;

@media (--sm-breakpoint-down) {
display: none;
}
}

.sidebar {
Expand Down Expand Up @@ -53,3 +95,44 @@
cursor: pointer;
}
}

.mobile-top-bar {
display: none;

@media (--sm-breakpoint-down) {
display: flex;
justify-content: space-around;
align-items: center;
padding: 0.25rem 0.5rem;
border-bottom: 1px solid var(--border-color-2);
}
}

.mobile-top-bar-button {
color: var(--text-muted);
padding: 0.5rem 2rem;
justify-content: center;

&:active {
background-color: var(--color-bg-1);
}
}

.mobile-top-bar-divider {
height: 1.25rem;
}

.mobile-history-wrapper {
display: none;

@media (--sm-breakpoint-down) {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
}
}

.mobile-history {
overflow-y: auto;
}
87 changes: 77 additions & 10 deletions client/web/src/cody/chat/CodyChatPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import React, { useEffect, useState } from 'react'

import { mdiClose, mdiCogOutline, mdiDelete, mdiDotsVertical, mdiOpenInNew, mdiPlus, mdiChevronRight } from '@mdi/js'
import {
mdiClose,
mdiCogOutline,
mdiDelete,
mdiDotsVertical,
mdiOpenInNew,
mdiPlus,
mdiChevronRight,
mdiViewList,
} from '@mdi/js'
import classNames from 'classnames'
import { useLocation, useNavigate } from 'react-router-dom'

Expand Down Expand Up @@ -41,6 +50,7 @@ import styles from './CodyChatPage.module.scss'

interface CodyChatPageProps {
authenticatedUser: AuthenticatedUser | null
isSourcegraphApp: boolean
context: Pick<SourcegraphContext, 'authProviders'>
}

Expand Down Expand Up @@ -78,7 +88,11 @@ const onTranscriptHistoryLoad = (
}
}

export const CodyChatPage: React.FunctionComponent<CodyChatPageProps> = ({ authenticatedUser, context }) => {
export const CodyChatPage: React.FunctionComponent<CodyChatPageProps> = ({
authenticatedUser,
context,
isSourcegraphApp,
}) => {
const { pathname } = useLocation()
const navigate = useNavigate()

Expand Down Expand Up @@ -119,6 +133,12 @@ export const CodyChatPage: React.FunctionComponent<CodyChatPageProps> = ({ authe
}
}, [transcriptId, loaded, pathname, navigate])

const [showMobileHistory, setShowMobileHistory] = useState<boolean>(false)
// Close mobile history list when transcript changes
useEffect(() => {
setShowMobileHistory(false)
}, [transcript])

if (!loaded) {
return null
}
Expand All @@ -137,7 +157,7 @@ export const CodyChatPage: React.FunctionComponent<CodyChatPageProps> = ({ authe
}

return (
<Page className="overflow-hidden">
<Page className={classNames('d-flex flex-column', styles.page)}>
<PageTitle title="Cody AI Chat" />
<PageHeader
actions={
Expand All @@ -154,23 +174,25 @@ export const CodyChatPage: React.FunctionComponent<CodyChatPageProps> = ({ authe
graph.
</>
}
className="mb-3"
className={styles.pageHeader}
>
<PageHeader.Heading as="h2" styleAs="h1">
<PageHeader.Breadcrumb icon={CodyColorIcon}>
<div className="d-inline-flex align-items-center">
Cody Chat
<Badge variant="info" className="ml-2">
Beta
</Badge>
{!isSourcegraphApp && (
<Badge variant="info" className="ml-2">
Beta
</Badge>
)}
</div>
</PageHeader.Breadcrumb>
</PageHeader.Heading>
</PageHeader>

{/* Page content */}
<div className={classNames('row mb-5', styles.pageWrapper)}>
<div className="d-flex flex-column col-sm-3 h-100">
<div className={classNames('row flex-1 overflow-hidden', styles.pageWrapper)}>
<div className={classNames('col-md-3', styles.sidebarWrapper)}>
<div className={styles.sidebarHeader}>
<H4>
<b>Chats</b>
Expand Down Expand Up @@ -285,9 +307,54 @@ export const CodyChatPage: React.FunctionComponent<CodyChatPageProps> = ({ authe
))}
</div>

<div className={classNames('d-flex flex-column col-sm-9 h-100', styles.chatMainWrapper)}>
<div
className={classNames(
'col-md-9 h-100',
styles.chatMainWrapper,
showMobileHistory && styles.chatMainWrapperWithMobileHistory
)}
>
<div className={styles.mobileTopBar}>
<Button
variant="icon"
className={styles.mobileTopBarButton}
onClick={() => setShowMobileHistory(true)}
>
<Icon aria-hidden={true} svgPath={mdiViewList} className="mr-2" />
All chats
</Button>
<div className={classNames('border-right', styles.mobileTopBarDivider)} />
<Button variant="icon" className={styles.mobileTopBarButton} onClick={initializeNewChat}>
<Icon aria-hidden={true} svgPath={mdiPlus} className="mr-2" />
New chat
</Button>
</div>
<ChatUI codyChatStore={codyChatStore} />
</div>

{showMobileHistory && (
<div className={styles.mobileHistoryWrapper}>
<div className={styles.mobileTopBar}>
<Button
variant="icon"
className={classNames('w-100', styles.mobileTopBarButton)}
onClick={() => setShowMobileHistory(false)}
>
<Icon aria-hidden={true} svgPath={mdiClose} className="mr-2" />
Close
</Button>
</div>
<div className={styles.mobileHistory}>
<HistoryList
currentTranscript={transcript}
transcriptHistory={transcriptHistory}
truncateMessageLength={60}
loadTranscriptFromHistory={loadTranscriptFromHistory}
deleteHistoryItem={deleteHistoryItem}
/>
</div>
</div>
)}
</div>
</Page>
)
Expand Down

0 comments on commit 1cd36d2

Please sign in to comment.