[Serverless Search] Serverless Getting Started UI Polish (#167118)

Fixes a long list of julian's UI bugs. Tested on both stateful and
serverless. See videos on visual fixes.


1a450bf6-7477-40a4-a020-a5172b56ef4c


92b40ecd-d888-4fd6-af91-045e81a1843f

Things to note:
- I had to adjust the asset path here as locally on main the images were
broken (the header for example).
This commit is contained in:
Joseph McElroy 2023-09-25 21:11:12 +01:00 committed by GitHub
parent 1c427a4a1e
commit 3043bed962
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 99 additions and 98 deletions

View file

@ -87,7 +87,7 @@ export const CodeBox: React.FC<CodeBoxProps> = ({
return ( return (
<EuiThemeProvider colorMode="dark"> <EuiThemeProvider colorMode="dark">
<EuiPanel paddingSize="xs" className="codeBoxPanel" data-test-subj="codeBlockControlsPanel"> <EuiPanel paddingSize="xs" className="codeBoxPanel" data-test-subj="codeBlockControlsPanel">
<EuiFlexGroup alignItems="center"> <EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
<EuiFlexItem> <EuiFlexItem>
<EuiThemeProvider colorMode="light"> <EuiThemeProvider colorMode="light">
<EuiPopover <EuiPopover
@ -104,7 +104,7 @@ export const CodeBox: React.FC<CodeBoxProps> = ({
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiCopy textToCopy={codeSnippet}> <EuiCopy textToCopy={codeSnippet}>
{(copy) => ( {(copy) => (
<EuiButtonEmpty color="text" iconType="copy" size="s" onClick={copy}> <EuiButtonEmpty color="text" iconType="copyClipboard" size="s" onClick={copy}>
{i18n.translate('searchApiPanels.welcomeBanner.codeBox.copyButtonLabel', { {i18n.translate('searchApiPanels.welcomeBanner.codeBox.copyButtonLabel', {
defaultMessage: 'Copy', defaultMessage: 'Copy',
})} })}
@ -127,6 +127,7 @@ export const CodeBox: React.FC<CodeBoxProps> = ({
transparentBackground transparentBackground
fontSize="m" fontSize="m"
language={languageType || selectedLanguage.languageStyling || selectedLanguage.id} language={languageType || selectedLanguage.languageStyling || selectedLanguage.id}
overflowHeight={500}
> >
{codeSnippet} {codeSnippet}
</EuiCodeBlock> </EuiCodeBlock>

View file

@ -18,7 +18,7 @@ export const GithubLink: React.FC<{
return ( return (
<EuiFlexGroup alignItems="center" gutterSize="xs" justifyContent="flexEnd"> <EuiFlexGroup alignItems="center" gutterSize="xs" justifyContent="flexEnd">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiIcon size="s" type={`${assetBasePath}github.svg`} /> <EuiIcon size="s" type={`${assetBasePath}/github.svg`} />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiText size="s"> <EuiText size="s">

View file

@ -93,6 +93,7 @@ export const IngestData: React.FC<IngestDataProps> = ({
defaultMessage: 'Ingest data', defaultMessage: 'Ingest data',
})} })}
> >
<EuiSpacer size="l" />
<EuiFormFieldset <EuiFormFieldset
legend={{ legend={{
children: i18n.translate('searchApiPanels.welcomeBanner.ingestData.ingestLegendLabel', { children: i18n.translate('searchApiPanels.welcomeBanner.ingestData.ingestLegendLabel', {

View file

@ -8,7 +8,7 @@
import React from 'react'; import React from 'react';
import { EuiSpacer, EuiCallOut, EuiText, EuiPanelProps } from '@elastic/eui'; import { EuiSpacer, EuiPanelProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n'; import { i18n } from '@kbn/i18n';
import type { ApplicationStart } from '@kbn/core-application-browser'; import type { ApplicationStart } from '@kbn/core-application-browser';
import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { SharePluginStart } from '@kbn/share-plugin/public';
@ -73,21 +73,6 @@ export const InstallClientPanel: React.FC<InstallClientProps> = ({
/> />
<EuiSpacer /> <EuiSpacer />
<Link language={language} assetBasePath={assetBasePath} /> <Link language={language} assetBasePath={assetBasePath} />
<EuiSpacer />
<EuiCallOut
iconType="iInCircle"
title={i18n.translate('searchApiPanels.welcomeBanner.apiCallOut.title', {
defaultMessage: 'Call the API with Console',
})}
color="primary"
>
<EuiText size="s">
{i18n.translate('searchApiPanels.welcomeBanner.apiCallout.content', {
defaultMessage:
'Console enables you to call Elasticsearch and Kibana REST APIs directly, without needing to install a language client.',
})}
</EuiText>
</EuiCallOut>
</> </>
); );
return ( return (

View file

@ -35,20 +35,19 @@ export const IntegrationsPanel: React.FC<IntegrationsPanelProps> = ({
return ( return (
<EuiThemeProvider colorMode="dark"> <EuiThemeProvider colorMode="dark">
<EuiPanel paddingSize="xl"> <EuiPanel paddingSize="xl">
<EuiFlexGroup alignItems="center" justifyContent="flexStart"> <EuiFlexGroup alignItems="flexStart" justifyContent="flexStart">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiIcon type="logoLogstash" size="xxl" /> <EuiIcon type="logoLogstash" size="xxl" />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
<EuiTitle size="l"> <EuiTitle size="s">
<h3> <h3>
{i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashTitle', { {i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashTitle', {
defaultMessage: 'Logstash', defaultMessage: 'Logstash',
})} })}
</h3> </h3>
</EuiTitle> </EuiTitle>
<EuiSpacer size="s" />
<EuiSpacer size="xs" />
<EuiText size="s"> <EuiText size="s">
<p> <p>
{i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashDescription', { {i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashDescription', {
@ -57,16 +56,16 @@ export const IntegrationsPanel: React.FC<IntegrationsPanelProps> = ({
})} })}
</p> </p>
</EuiText> </EuiText>
<EuiSpacer size="s" /> <EuiSpacer size="m" />
<EuiFlexGroup justifyContent="flexStart"> <EuiFlexGroup justifyContent="flexStart" gutterSize="l">
<EuiFlexItem> <EuiFlexItem grow={false}>
<EuiText size="s"> <EuiText size="s">
<EuiLink href={docLinks.logstash} target="_blank"> <EuiLink href={docLinks.logstash} target="_blank">
{LEARN_MORE_LABEL} {LEARN_MORE_LABEL}
</EuiLink> </EuiLink>
</EuiText> </EuiText>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem grow={false}>
<GithubLink <GithubLink
href="https://github.com/elastic/logstash" href="https://github.com/elastic/logstash"
label={i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashLink', { label={i18n.translate('searchApiPanels.welcomeBanner.ingestData.logstashLink', {
@ -79,39 +78,39 @@ export const IntegrationsPanel: React.FC<IntegrationsPanelProps> = ({
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
<EuiSpacer size="xl" /> <EuiSpacer size="xl" />
<EuiFlexGroup alignItems="center" justifyContent="flexStart"> <EuiFlexGroup alignItems="flexStart" justifyContent="flexStart">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiIcon type="logoBeats" size="xxl" /> <EuiIcon type="logoBeats" size="xxl" />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
<EuiTitle size="l"> <EuiTitle size="s">
<h3> <h3>
{i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsTitle', { {i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsTitle', {
defaultMessage: 'Beats', defaultMessage: 'Beats',
})} })}
</h3> </h3>
</EuiTitle> </EuiTitle>
<EuiSpacer size="xs" /> <EuiSpacer size="s" />
<EuiText size="s"> <EuiText size="s">
{i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsDescription', { {i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsDescription', {
defaultMessage: defaultMessage:
'Lightweight, single-purpose data shippers for Elasticsearch. Use Beats to send operational data from your servers.', 'Lightweight, single-purpose data shippers for Elasticsearch. Use Beats to send operational data from your servers.',
})} })}
</EuiText> </EuiText>
<EuiSpacer size="s" /> <EuiSpacer size="m" />
<EuiFlexGroup justifyContent="flexStart"> <EuiFlexGroup justifyContent="flexStart" gutterSize="l">
<EuiFlexItem> <EuiFlexItem grow={false}>
<EuiText size="s"> <EuiText size="s">
<EuiLink href={docLinks.beats} target="_blank"> <EuiLink href={docLinks.beats} target="_blank">
{LEARN_MORE_LABEL} {LEARN_MORE_LABEL}
</EuiLink> </EuiLink>
</EuiText> </EuiText>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem grow={false}>
<GithubLink <GithubLink
href="https://github.com/elastic/beats" href="https://github.com/elastic/beats"
label={i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsLink', { label={i18n.translate('searchApiPanels.welcomeBanner.ingestData.beatsLink', {
defaultMessage: 'beats', defaultMessage: 'Beats',
})} })}
assetBasePath={assetBasePath} assetBasePath={assetBasePath}
/> />
@ -119,36 +118,36 @@ export const IntegrationsPanel: React.FC<IntegrationsPanelProps> = ({
</EuiFlexGroup> </EuiFlexGroup>
</EuiFlexItem> </EuiFlexItem>
</EuiFlexGroup> </EuiFlexGroup>
<EuiSpacer size="l" /> <EuiSpacer size="xl" />
<EuiFlexGroup alignItems="center" justifyContent="flexStart"> <EuiFlexGroup alignItems="flexStart" justifyContent="flexStart">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiIcon type="logoEnterpriseSearch" size="xxl" /> <EuiIcon type="logoEnterpriseSearch" size="xxl" />
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem>
<EuiTitle size="l"> <EuiTitle size="s">
<h3> <h3>
{i18n.translate('searchApiPanels.welcomeBanner.ingestData.connectorsTitle', { {i18n.translate('searchApiPanels.welcomeBanner.ingestData.connectorsTitle', {
defaultMessage: 'Connector Client', defaultMessage: 'Connector Client',
})} })}
</h3> </h3>
</EuiTitle> </EuiTitle>
<EuiSpacer size="xs" /> <EuiSpacer size="s" />
<EuiText size="s"> <EuiText size="s">
{i18n.translate('searchApiPanels.welcomeBanner.ingestData.connectorsDescription', { {i18n.translate('searchApiPanels.welcomeBanner.ingestData.connectorsDescription', {
defaultMessage: defaultMessage:
'Specialized integrations for syncing data from third-party sources to Elasticsearch. Use Elastic Connectors to sync content from a range of databases and object stores.', 'Specialized integrations for syncing data from third-party sources to Elasticsearch. Use Elastic Connectors to sync content from a range of databases and object stores.',
})} })}
</EuiText> </EuiText>
<EuiSpacer size="s" /> <EuiSpacer size="m" />
<EuiFlexGroup justifyContent="flexStart"> <EuiFlexGroup justifyContent="flexStart" gutterSize="l">
<EuiFlexItem> <EuiFlexItem grow={false}>
<EuiText size="s"> <EuiText size="s">
<EuiLink href={docLinks.connectors} target="_blank"> <EuiLink href={docLinks.connectors} target="_blank">
{LEARN_MORE_LABEL} {LEARN_MORE_LABEL}
</EuiLink> </EuiLink>
</EuiText> </EuiText>
</EuiFlexItem> </EuiFlexItem>
<EuiFlexItem> <EuiFlexItem grow={false}>
<GithubLink <GithubLink
href="https://github.com/elastic/connectors-python" href="https://github.com/elastic/connectors-python"
label={i18n.translate( label={i18n.translate(

View file

@ -6,7 +6,7 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import React from 'react'; import React, { Fragment } from 'react';
import { import {
EuiFlexGroup, EuiFlexGroup,
@ -41,14 +41,14 @@ export const OverviewPanel: React.FC<OverviewPanelProps> = ({
return ( return (
<> <>
<EuiSpacer size="xxl" /> <EuiSpacer size="xxl" />
<EuiFlexGroup alignItems="center"> <EuiFlexGroup alignItems="flexStart" gutterSize="xl">
{leftPanelContent && <EuiFlexItem grow={6}>{leftPanelContent}</EuiFlexItem>} {leftPanelContent && <EuiFlexItem grow={6}>{leftPanelContent}</EuiFlexItem>}
<EuiFlexItem grow={4}> <EuiFlexItem grow={4}>
<EuiPanel color="subdued" {...overviewPanelProps}> <EuiPanel paddingSize="none" color="subdued" {...overviewPanelProps}>
<EuiTitle> <EuiTitle size="s">
<h2>{title}</h2> <h2>{title}</h2>
</EuiTitle> </EuiTitle>
<EuiSpacer /> <EuiSpacer size="m" />
{description && <EuiText>{description}</EuiText>} {description && <EuiText>{description}</EuiText>}
{children} {children}
{links && links.length > 0 ? ( {links && links.length > 0 ? (
@ -59,11 +59,14 @@ export const OverviewPanel: React.FC<OverviewPanelProps> = ({
</EuiTitle> </EuiTitle>
<EuiSpacer size="s" /> <EuiSpacer size="s" />
{links.map(({ label, href }, index) => ( {links.map(({ label, href }, index) => (
<EuiText size="s" key={`overviewPanel.link.${index}`}> <Fragment key={`overviewPanel.link.${index}`}>
<EuiLink key={index} href={href} target="_blank"> <EuiText size="s">
{label} <EuiLink key={index} href={href} target="_blank">
</EuiLink> {label}
</EuiText> </EuiLink>
</EuiText>
<EuiSpacer size="xs" />
</Fragment>
))} ))}
</> </>
) : null} ) : null}

View file

@ -40,7 +40,7 @@ export const TryInConsoleButton = ({
if (!consolePreviewLink) return null; if (!consolePreviewLink) return null;
return ( return (
<EuiButtonEmpty href={consolePreviewLink} iconType="popout" target="_blank"> <EuiButtonEmpty href={consolePreviewLink} iconType="popout" target="_blank" size="s">
<FormattedMessage <FormattedMessage
id="searchApiPanels.welcomeBanner.tryInConsoleButton" id="searchApiPanels.welcomeBanner.tryInConsoleButton"
defaultMessage="Try in console" defaultMessage="Try in console"

View file

@ -37,50 +37,57 @@ export const WelcomeBanner: React.FC<WelcomeBannerProps> = ({
image, image,
showDescription = true, showDescription = true,
}) => ( }) => (
<EuiFlexGroup justifyContent="spaceBetween"> <>
<EuiFlexItem grow={false}> <EuiSpacer size="xxl" />
{/* Reversing column direction here so screenreaders keep h1 as the first element */} <EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexGroup justifyContent="flexStart" direction="columnReverse" gutterSize="s"> <EuiFlexItem grow={2}>
<EuiFlexItem grow={false}> {/* Reversing column direction here so screenreaders keep h1 as the first element */}
<EuiTitle className="serverlessSearchHeaderTitle" size="s"> <EuiFlexGroup justifyContent="flexStart" direction="columnReverse" gutterSize="s">
<h1>
{i18n.translate('searchApiPanels.welcomeBanner.header.title', {
defaultMessage: 'Get started with Elasticsearch',
})}
</h1>
</EuiTitle>
</EuiFlexItem>
{Boolean(user) && (
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
<EuiTitle size="xxxs"> <EuiTitle size="l">
<h2> <h1>
{user {i18n.translate('searchApiPanels.welcomeBanner.header.title', {
? i18n.translate('searchApiPanels.welcomeBanner.header.greeting.customTitle', { defaultMessage: 'Get started with Elasticsearch',
defaultMessage: 'Hi {name}!', })}
values: { name: user.full_name || user.username }, </h1>
})
: i18n.translate('searchApiPanels.welcomeBanner.header.greeting.defaultTitle', {
defaultMessage: 'Hi!',
})}
</h2>
</EuiTitle> </EuiTitle>
</EuiFlexItem> </EuiFlexItem>
{Boolean(user) && (
<EuiFlexItem grow={false}>
<EuiTitle size="xxs">
<h4>
{user
? i18n.translate('searchApiPanels.welcomeBanner.header.greeting.customTitle', {
defaultMessage: 'Hi {name}!',
values: { name: user.full_name || user.username },
})
: i18n.translate('searchApiPanels.welcomeBanner.header.greeting.defaultTitle', {
defaultMessage: 'Hi!',
})}
</h4>
</EuiTitle>
</EuiFlexItem>
)}
</EuiFlexGroup>
<EuiSpacer />
{showDescription && (
<EuiText>
{i18n.translate('searchApiPanels.welcomeBanner.header.description', {
defaultMessage:
"Set up your programming language client, ingest some data, and you'll be ready to start searching within minutes.",
})}
</EuiText>
)} )}
</EuiFlexGroup> </EuiFlexItem>
<EuiSpacer />
{showDescription && (
<EuiText>
{i18n.translate('searchApiPanels.welcomeBanner.header.description', {
defaultMessage:
"Set up your programming language client, ingest some data, and you'll be ready to start searching within minutes.",
})}
</EuiText>
)}
<EuiSpacer size="xxl" />
</EuiFlexItem>
<EuiFlexItem grow={false}> <EuiFlexItem grow={1}>
<EuiImage alt="" src={image ? image : `${assetBasePath}serverless_header.png`} size="554px" /> <EuiImage
</EuiFlexItem> alt=""
</EuiFlexGroup> src={image ? image : `${assetBasePath}/serverless_header.png`}
size="original"
/>
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="xxl" />
</>
); );

View file

@ -86,6 +86,7 @@ export const ApiKeyPanel = ({ setClientApiKey }: { setClientApiKey: (value: stri
})} })}
</h3> </h3>
</EuiTitle> </EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s"> <EuiText size="s">
{i18n.translate('xpack.serverlessSearch.apiKey.panel.description', { {i18n.translate('xpack.serverlessSearch.apiKey.panel.description', {
defaultMessage: defaultMessage:
@ -94,8 +95,8 @@ export const ApiKeyPanel = ({ setClientApiKey }: { setClientApiKey: (value: stri
</EuiText> </EuiText>
<EuiSpacer size="l" /> <EuiSpacer size="l" />
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center"> <EuiFlexGroup justifyContent="spaceBetween" alignItems="center">
<EuiFlexItem> <EuiFlexItem grow={false}>
<EuiFlexGroup> <EuiFlexGroup gutterSize="m">
<EuiFlexItem> <EuiFlexItem>
<span> <span>
<EuiButton <EuiButton

View file

@ -10,3 +10,7 @@
.serverlessSearchOverviewFooterSection { .serverlessSearchOverviewFooterSection {
background-color: transparentize($euiColorPrimary, .9); background-color: transparentize($euiColorPrimary, .9);
} }
.serverlessSearchCloudDetailsCopyPanel {
word-break: break-all;
}

View file

@ -153,7 +153,7 @@ export const ElasticsearchOverview = () => {
<EuiTitle size="xxxs"> <EuiTitle size="xxxs">
<h6> <h6>
{i18n.translate('xpack.serverlessSearch.cloudIdDetails.url.title', { {i18n.translate('xpack.serverlessSearch.cloudIdDetails.url.title', {
defaultMessage: 'Cloud URL', defaultMessage: 'Elasticsearch Endpoint',
})} })}
</h6> </h6>
</EuiTitle> </EuiTitle>