diff --git a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation.tsx b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation.tsx index de3470f760311..ba13f7813f05d 100644 --- a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation.tsx +++ b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation.tsx @@ -17,6 +17,7 @@ import { useConversationId } from '../../hooks/use_conversation_id'; import { useSendMessage } from '../../context/send_message_context'; import { useConversationScrollActions } from '../../hooks/use_conversation_scroll_actions'; import { useConversationStatus } from '../../hooks/use_conversation'; +import { ConversationContent } from './conversation_grid'; const fullHeightStyles = css` height: 100%; @@ -70,39 +71,41 @@ export const Conversation: React.FC<{}> = () => { left: 50%; transform: translateX(-50%); `; + const contentStyles = css` + ${fullHeightStyles} + align-items: stretch; + `; + + if (!hasActiveConversation) { + return ; + } return ( {(EuiResizablePanel, EuiResizableButton) => { return ( <> - {hasActiveConversation ? ( - -
- -
- {showScrollButton && ( - - )} -
- ) : ( - -
- -
-
- )} + +
+ +
+ {showScrollButton && ( + + )} +
- + + + ); diff --git a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.styles.ts b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.styles.ts new file mode 100644 index 0000000000000..269df53081c9b --- /dev/null +++ b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.styles.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useEuiTheme } from '@elastic/eui'; + +export const useConversationGridCenterColumnWidth = () => { + const { euiTheme } = useEuiTheme(); + const contentMaxWidth = `calc(${euiTheme.size.xl} * 25)`; + return contentMaxWidth; +}; diff --git a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.tsx b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.tsx index 68332a243e73e..663fa7a62dacb 100644 --- a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.tsx +++ b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_grid.tsx @@ -8,6 +8,9 @@ import { useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import React from 'react'; +import { useConversationGridCenterColumnWidth } from './conversation_grid.styles'; + +// Main grid interface ConversationGridProps { children: React.ReactNode; @@ -17,10 +20,13 @@ interface ConversationGridProps { export const ConversationGrid: React.FC = ({ children, className }) => { const { euiTheme } = useEuiTheme(); const sideColumnWidth = `minmax(calc(${euiTheme.size.xxl} * 2), 1fr)`; - const contentMaxWidth = `calc(${euiTheme.size.xl} * 25)`; + const contentMarginWidth = euiTheme.size.l; + const centerColumnWidth = useConversationGridCenterColumnWidth(); const gridStyles = css` display: grid; - grid-template-columns: ${sideColumnWidth} minmax(auto, ${contentMaxWidth}) ${sideColumnWidth}; + grid-template-columns: + ${sideColumnWidth} ${contentMarginWidth} minmax(auto, ${centerColumnWidth}) + ${contentMarginWidth} ${sideColumnWidth}; align-items: center; width: 100%; `; @@ -32,22 +38,88 @@ export const ConversationGrid: React.FC = ({ children, cl ); }; -interface ConversationContentProps { +interface ConversationGridContainerProps { children: React.ReactNode; className?: string; } -const contentStyles = css` - grid-column: 2; +// Left side column + +const leftContainerStyles = css` + grid-column: 1; +`; + +export const ConversationLeft: React.FC = ({ + children, + className, +}) => { + return ( +
+ {children} +
+ ); +}; + +// Center column without the margins + +const centerContainerStyles = css` + grid-column: 3; +`; + +export const ConversationCenter: React.FC = ({ + children, + className, +}) => { + return ( +
+ {children} +
+ ); +}; + +// Right side column + +const rightContainerStyles = css` + grid-column: 5; +`; + +export const ConversationRight: React.FC = ({ + children, + className, +}) => { + return ( +
+ {children} +
+ ); +}; + +// Shorthand for using centered content in the grid + +export const ConversationContent: React.FC = ({ + children, + className, +}) => { + return ( + + {children} + + ); +}; + +// Shorthand for using centered content with margins in the grid + +const contentWithMarginsStyles = css` + grid-column: 2 / 5; `; -export const ConversationContent: React.FC = ({ +export const ConversationContentWithMargins: React.FC = ({ children, className, }) => { return ( -
{children}
+
{children}
); }; diff --git a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_header.tsx b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_header.tsx index 03cdc7b7f26e9..770fb604b57c4 100644 --- a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_header.tsx +++ b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_header.tsx @@ -8,7 +8,12 @@ import React from 'react'; import { useHasActiveConversation } from '../../hooks/use_conversation'; import { ConversationActions } from './conversation_actions'; -import { ConversationGrid } from './conversation_grid'; +import { + ConversationCenter, + ConversationGrid, + ConversationLeft, + ConversationRight, +} from './conversation_grid'; import { ConversationSidebarToggle } from './conversation_sidebar/conversation_sidebar_toggle'; import { ConversationTitle } from './conversation_title'; @@ -24,11 +29,17 @@ export const ConversationHeader: React.FC = ({ const hasActiveConversation = useHasActiveConversation(); return ( - + + + {hasActiveConversation && ( <> - - + + + + + + )} diff --git a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_input/conversation_input_form.tsx b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_input/conversation_input_form.tsx index 0c5cbbe94d959..1effa4641bc08 100644 --- a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_input/conversation_input_form.tsx +++ b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/conversation_input/conversation_input_form.tsx @@ -11,12 +11,11 @@ import { i18n } from '@kbn/i18n'; import React, { useState } from 'react'; import { useSendMessage } from '../../../context/send_message_context'; import { useIsSendingMessage } from '../../../hooks/use_is_sending_message'; -import { ConversationContent } from '../conversation_grid'; import { ConversationInputActions } from './conversation_input_actions'; import { ConversationInputTextArea } from './conversation_input_text_area'; interface ConversationInputFormProps { - onSubmit: () => void; + onSubmit?: () => void; } const fullHeightStyles = css` @@ -36,13 +35,9 @@ export const ConversationInputForm: React.FC = ({ on } sendMessage({ message: input }); setInput(''); - onSubmit(); + onSubmit?.(); }; - const contentStyles = css` - ${fullHeightStyles} - align-items: stretch; - `; const formContainerStyles = css` ${fullHeightStyles} padding: ${euiTheme.size.base}; @@ -56,29 +51,27 @@ export const ConversationInputForm: React.FC = ({ on `; return ( - - - - { - if (pendingMessage) { - setInput(pendingMessage); - } - }} - /> - - + + + { + if (pendingMessage) { + setInput(pendingMessage); + } + }} + /> + ); }; diff --git a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/new_conversation_prompt.tsx b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/new_conversation_prompt.tsx index ec2a2ef739ca7..bd4d6f3413cc4 100644 --- a/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/new_conversation_prompt.tsx +++ b/x-pack/platform/plugins/shared/onechat/public/application/components/conversations/new_conversation_prompt.tsx @@ -6,6 +6,7 @@ */ import { + EuiCard, EuiFlexGroup, EuiFlexItem, EuiIcon, @@ -13,28 +14,27 @@ import { EuiTitle, EuiLink, EuiButton, + useEuiFontSize, useEuiTheme, } from '@elastic/eui'; +import type { ReactNode } from 'react'; import React from 'react'; import { css } from '@emotion/react'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { useNavigation } from '../../hooks/use_navigation'; import { appPaths } from '../../utils/app_paths'; -import { ConversationContent } from './conversation_grid'; +import { ConversationContentWithMargins } from './conversation_grid'; +import { ConversationInputForm } from './conversation_input/conversation_input_form'; +import { useConversationGridCenterColumnWidth } from './conversation_grid.styles'; +import { docsPaths } from '../../utils/docs_paths'; const fullHeightStyles = css` height: 100%; `; -export const NewConversationPrompt: React.FC<{}> = () => { - const { euiTheme } = useEuiTheme(); +const WelcomeText: React.FC<{}> = () => { const { createOnechatUrl } = useNavigation(); - const promptStyles = css` - max-inline-size: calc(${euiTheme.size.l} * 19); - padding: ${euiTheme.size.l}; - margin: 0 auto; - `; const labels = { container: i18n.translate('xpack.onechat.newConversationPrompt.container', { defaultMessage: 'New conversation welcome prompt', @@ -66,45 +66,216 @@ export const NewConversationPrompt: React.FC<{}> = () => { ), }; return ( - - - - - - - -

{labels.title}

-
-
- - -

{labels.subtitle}

-
-
- - + + + + + +

{labels.title}

+
+
+ + +

{labels.subtitle}

+
+
+ + + {i18n.translate('xpack.onechat.newConversationPrompt.agentBuilderDocs', { + defaultMessage: 'Read the docs', + })} + + +
+ ); +}; + +const cards: Array<{ + key: string; + title: ReactNode; + description: ReactNode; + iconType: string; + link: { path: string } | { url: string }; +}> = [ + // Create agent + { + key: 'createAgent', + title: ( + + ), + description: ( + + ), + iconType: 'plus', + link: { path: appPaths.agents.new }, + }, + // Manage agents + { + key: 'manageAgents', + title: ( + + ), + description: ( + + ), + iconType: 'controls', + link: { path: appPaths.agents.list }, + }, + // Manage tools + { + key: 'manageTools', + title: ( + + ), + description: ( + + ), + iconType: 'wrench', + link: { path: appPaths.tools.list }, + }, + // Documentation + { + key: 'documentation', + title: ( + + ), + description: ( + + ), + iconType: 'documentation', + link: { url: docsPaths.root }, + }, +]; + +const QuickNavigationCards: React.FC<{}> = () => { + const { createOnechatUrl } = useNavigation(); + const { euiTheme } = useEuiTheme(); + const titleStyles = css` + ${useEuiFontSize('s')} + font-weight: ${euiTheme.font.weight.bold}; + `; + const descriptionStyles = css` + ${useEuiFontSize('xs')} + color: ${euiTheme.colors.textSubdued}; + `; + const iconBackgroundStyles = css` + padding: ${euiTheme.size.s}; + background-color: ${euiTheme.colors.lightestShade}; + border-radius: ${euiTheme.border.radius.medium}; + `; + return ( + + {cards.map(({ key, title, description, iconType, link }) => { + return ( + + {title}} + description={{description}} + icon={ + + + + + } - )} - > - {i18n.translate('xpack.onechat.newConversationPrompt.agentBuilderDocs', { - defaultMessage: 'Read the docs', - })} - - - -
+ href={'url' in link ? link.url : createOnechatUrl(link.path)} + /> + + ); + })} + + ); +}; + +const mainContainerStyles = css` + grid-column: 2; +`; + +const MainContainer: React.FC<{ children: ReactNode }> = ({ children }) => ( +
{children}
+); + +const withMarginContainerStyles = css` + grid-column: 1 / 4; +`; + +const WithMarginsContainer: React.FC<{ children: ReactNode }> = ({ children }) => ( +
{children}
+); + +export const NewConversationPrompt: React.FC<{}> = () => { + const { euiTheme } = useEuiTheme(); + const centerColumnWidth = useConversationGridCenterColumnWidth(); + const inputRowHeight = `calc(${euiTheme.size.l} * 7)`; + const gridStyles = css` + display: grid; + grid-template-columns: 1fr ${centerColumnWidth} 1fr; + grid-template-rows: auto ${inputRowHeight} auto; + row-gap: ${euiTheme.size.l}; + `; + return ( + +
+ + + + + + + + + +
+
); }; diff --git a/x-pack/platform/plugins/shared/onechat/public/application/utils/docs_paths.ts b/x-pack/platform/plugins/shared/onechat/public/application/utils/docs_paths.ts new file mode 100644 index 0000000000000..810b19c8a2899 --- /dev/null +++ b/x-pack/platform/plugins/shared/onechat/public/application/utils/docs_paths.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +const docsRoot = 'https://www.elastic.co/docs/solutions/search/elastic-agent-builder'; +export const docsPaths = { + root: docsRoot, +};