Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 83 additions & 64 deletions src/interfaces/coral_web/src/components/Agents/AgentsSidePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Link from 'next/link';
import { IconButton } from '@/components/IconButton';
import { Button, Icon, IconProps, Logo, Tooltip } from '@/components/Shared';
import { env } from '@/env.mjs';
import { useIsDesktop } from '@/hooks/breakpoint';
import { useSettingsStore } from '@/stores';
import { cn } from '@/utils';

Expand All @@ -18,6 +19,9 @@ export const AgentsSidePanel: React.FC<React.PropsWithChildren> = ({ children })
setIsAgentsSidePanelOpen,
} = useSettingsStore();

const isDesktop = useIsDesktop();
const isMobile = !isDesktop;

const navigationItems: {
label: string;
icon: IconProps['name'];
Expand All @@ -29,78 +33,93 @@ export const AgentsSidePanel: React.FC<React.PropsWithChildren> = ({ children })
];

return (
<div
className={cn(
'box-content px-4 py-6',
'flex flex-grow flex-col gap-y-8 rounded-lg border',
'border-marble-400 bg-marble-100',
'transition-[min-width,max-width]',
{
'min-w-12 max-w-12': !isAgentsSidePanelOpen,
'min-w-64 max-w-64': isAgentsSidePanelOpen,
}
)}
<Transition
show={isAgentsSidePanelOpen || isDesktop}
as="div"
className={cn('absolute bottom-0 left-0 top-0 z-30 lg:static', {
'right-1/4': isAgentsSidePanelOpen,
})}
enter="transition-all transform ease-in-out duration-500"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transition-all transform ease-in-out duration-500"
leaveFrom="translate-x-0 opacity-100"
leaveTo="-translate-x-full opacity-0"
>
<div
className={cn('flex flex-shrink-0 items-center', {
'justify-between gap-x-3': isAgentsSidePanelOpen,
'justify-center': !isAgentsSidePanelOpen,
})}
className={cn(
'box-content h-full px-4 py-6',
'flex flex-grow flex-col gap-y-8 rounded-lg border',
'border-marble-400 bg-marble-100',
'transition-[min-width,max-width]',
{
'min-w-12 max-w-12': !isAgentsSidePanelOpen,
'min-w-64 max-w-64': isAgentsSidePanelOpen,
}
)}
>
<Transition
show={isAgentsSidePanelOpen}
as="div"
enter="transition-all transform ease-in-out duration-200"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
<div
className={cn('flex flex-shrink-0 items-center', {
'justify-between gap-x-3': isAgentsSidePanelOpen || isMobile,
'justify-center': !isAgentsSidePanelOpen && isDesktop,
})}
>
<Link href="/" shallow>
<div className="mr-3 flex items-baseline">
<Logo hasCustomLogo={env.NEXT_PUBLIC_HAS_CUSTOM_LOGO === 'true'} />
</div>
</Link>
</Transition>
<Transition
show={isAgentsSidePanelOpen || isMobile}
appear
as="div"
enter="transition-all transform ease-in-out duration-200"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
>
<Link href="/" shallow>
<div className="mr-3 flex items-baseline">
<Logo hasCustomLogo={env.NEXT_PUBLIC_HAS_CUSTOM_LOGO === 'true'} />
</div>
</Link>
</Transition>

<IconButton
iconName="close-drawer"
onClick={() => setIsAgentsSidePanelOpen(!isAgentsSidePanelOpen)}
className={cn('transition delay-100 duration-200 ease-in-out', {
'rotate-180 transform text-secondary-700': isAgentsSidePanelOpen,
})}
/>
</div>
<div className="flex-grow overflow-y-auto">{children}</div>
{isAgentsSidePanelOpen ? (
<div className="flex flex-shrink-0 flex-col gap-y-4">
{navigationItems.map(({ label, icon, href, onClick }) => (
<Button
key={label}
kind="secondary"
className="truncate text-secondary-900"
startIcon={<Icon name={icon} kind="outline" className="text-secondary-900" />}
label={label}
href={href}
shallow
onClick={onClick}
/>
))}
<IconButton
iconName="close-drawer"
onClick={() => setIsAgentsSidePanelOpen(!isAgentsSidePanelOpen)}
className={cn('transition delay-100 duration-200 ease-in-out', {
'rotate-180 transform text-secondary-700': isAgentsSidePanelOpen || isMobile,
})}
/>
</div>
) : (
<div className="flex flex-shrink-0 flex-col gap-y-4">
{navigationItems.map(({ label, icon, href, onClick }) => (
<Tooltip key={label} label={label} hover placement="right">
<IconButton
iconName={icon}
iconClassName="text-secondary-900"
<div className="flex-grow overflow-y-auto">{children}</div>
{isAgentsSidePanelOpen || isMobile ? (
<div className="flex flex-shrink-0 flex-col gap-y-4">
{navigationItems.map(({ label, icon, href, onClick }) => (
<Button
key={label}
kind="secondary"
className="truncate text-secondary-900"
startIcon={<Icon name={icon} kind="outline" className="text-secondary-900" />}
label={label}
href={href}
shallow
onClick={onClick}
href={href}
className="w-full text-secondary-900"
/>
</Tooltip>
))}
</div>
)}
</div>
))}
</div>
) : (
<div className="flex flex-shrink-0 flex-col gap-y-4">
{navigationItems.map(({ label, icon, href, onClick }) => (
<Tooltip key={label} label={label} hover placement="right">
<IconButton
iconName={icon}
iconClassName="text-secondary-900"
shallow
onClick={onClick}
href={href}
className="w-full text-secondary-900"
/>
</Tooltip>
))}
</div>
)}
</div>
</Transition>
);
};
44 changes: 14 additions & 30 deletions src/interfaces/coral_web/src/components/Agents/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Transition } from '@headlessui/react';
import { capitalize } from 'lodash';
import React, { Children, PropsWithChildren } from 'react';

import { AgentsSidePanel } from '@/components/Agents/AgentsSidePanel';
import { MobileHeader } from '@/components/Agents/MobileHeader';
import { ConfigurationDrawer } from '@/components/Conversation/ConfigurationDrawer';
import { PageHead } from '@/components/Shared/PageHead';
import { useIsDesktop } from '@/hooks/breakpoint';
import { useSettingsStore } from '@/stores';
import { cn } from '@/utils/cn';

export const LeftSection: React.FC<React.PropsWithChildren> = ({ children }) => <>{children}</>;
Expand All @@ -22,11 +20,6 @@ type Props = {
On small devices (e.g. mobile), the left drawer and main section are stacked vertically.
*/
export const Layout: React.FC<Props> = ({ title = 'Chat', children }) => {
const {
settings: { isMobileConvListPanelOpen },
} = useSettingsStore();
const isDesktop = useIsDesktop();

let leftElement: React.ReactNode = null;
let mainElement: React.ReactNode = null;

Expand All @@ -47,32 +40,23 @@ export const Layout: React.FC<Props> = ({ title = 'Chat', children }) => {
<>
<PageHead title={capitalize(title)} />
<div className="flex h-screen w-full flex-1 flex-col gap-3 bg-secondary-100 p-3">
<div className={cn('relative flex h-full flex-grow flex-nowrap gap-3 overflow-hidden')}>
<div
className={cn(
'relative flex h-full flex-grow flex-col flex-nowrap gap-3 overflow-hidden lg:flex-row'
)}
>
<MobileHeader />
<AgentsSidePanel>{leftElement}</AgentsSidePanel>
<Transition
as="main"
show={!isMobileConvListPanelOpen || isDesktop}
enterFrom="translate-x-full lg:translate-x-0"
enterTo="translate-x-0"
leaveFrom="translate-x-0"
leaveTo="translate-x-full lg:translate-x-0"
<section
className={cn(
'z-main-section flex flex-grow lg:min-w-0',
'absolute h-full w-full lg:static lg:h-auto',
'transition-transform duration-500 ease-in-out lg:transition-none'
'relative flex h-full min-w-0 flex-grow flex-col',
'rounded-lg border',
'border-marble-400 bg-marble-100',
'overflow-hidden'
)}
>
<section
className={cn(
'relative flex h-full min-w-0 flex-grow flex-col',
'rounded-lg border',
'border-marble-400 bg-marble-100',
'overflow-hidden'
)}
>
{mainElement}
</section>
</Transition>
{mainElement}
</section>
<ConfigurationDrawer />
</div>
</div>
Expand Down
21 changes: 21 additions & 0 deletions src/interfaces/coral_web/src/components/Agents/MobileHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Logo } from '@/components/Shared';
import { useSettingsStore } from '@/stores';

export const MobileHeader: React.FC = () => {
const {
settings: { isAgentsSidePanelOpen },
setIsAgentsSidePanelOpen,
} = useSettingsStore();

const onToggleAgentsSidePanel = () => {
setIsAgentsSidePanelOpen(!isAgentsSidePanelOpen);
};

return (
<header className="flex h-11 items-center justify-start rounded-lg border border-marble-400 bg-marble-200 px-4 lg:hidden">
<button onClick={onToggleAgentsSidePanel}>
<Logo />
</button>
</header>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const useHeaderMenu = ({ conversationId }: { conversationId?: string }) => {
const { resetConversation } = useConversationStore();
const { resetCitations } = useCitationsStore();

const { settings, setSettings } = useSettingsStore();
const { setSettings } = useSettingsStore();
const { resetFileParams } = useParamsStore();
const router = useRouter();
const { welcomeGuideState, progressWelcomeGuideStep, finishWelcomeGuide } =
Expand Down Expand Up @@ -79,6 +79,7 @@ export const Header: React.FC<Props> = ({ isStreaming }) => {
const { welcomeGuideState } = useWelcomeGuideState();

const isDesktop = useIsDesktop();
const isMobile = !isDesktop;
const { menuItems, handleNewChat, handleOpenSettings } = useHeaderMenu({
conversationId: id,
});
Expand All @@ -93,7 +94,7 @@ export const Header: React.FC<Props> = ({ isStreaming }) => {
'relative flex min-w-0 flex-grow items-center gap-x-1 overflow-hidden py-4'
)}
>
{(!isDesktop || !isConvListPanelOpen) && (
{(isMobile || !isConvListPanelOpen) && (
<Transition
show={true}
appear
Expand All @@ -104,14 +105,11 @@ export const Header: React.FC<Props> = ({ isStreaming }) => {
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
as="div"
className={cn({
'lg:hidden': isConvListPanelOpen,
})}
>
<IconButton
iconName="side-panel"
onClick={() => {
setSettings({ isConfigDrawerOpen: false });
setSettings({ isConfigDrawerOpen: false, isAgentsSidePanelOpen: false });
setIsConvListPanelOpen(true);
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ export const ConversationListPanel: React.FC<Props> = ({ className }) => {
<Transition.Child
ref={panelRef}
as="nav"
enterFrom="lg:opacity-0"
enterTo="lg:opacity-100"
enterFrom="opacity-100 lg:opacity-0"
enterTo="opacity-100"
leaveFrom="lg:opacity-100"
leaveTo="lg:opacity-0"
leaveTo="opacity-100 lg:opacity-0"
className={cn(
'transition-opacity ease-in-out lg:duration-500',
'flex h-full w-full flex-grow flex-col',
Expand Down
Loading