Homepage / index pattern design cleanup (#16005)

Rebuilds most of the homepage using EUI components. Adjusts styles to be closer to mocks.
This commit is contained in:
dave.snider@gmail.com 2018-01-12 15:59:54 -08:00 committed by GitHub
parent e6b65fc4c6
commit c5001b1f55
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 347 additions and 282 deletions

View file

@ -2,11 +2,15 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Synopsis } from './synopsis';
import {
KuiTabs,
KuiTab,
KuiFlexItem,
KuiFlexGrid,
} from 'ui_framework/components';
EuiTabs,
EuiTab,
EuiFlexItem,
EuiFlexGrid,
EuiPage,
EuiTitle,
EuiSpacer,
} from '@elastic/eui';
import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
const ALL_TAB_ID = 'all';
@ -51,14 +55,14 @@ export class FeatureDirectory extends React.Component {
renderTabs = () => {
return this.tabs.map((tab, index) => (
<KuiTab
<EuiTab
className="homeDirectoryTab"
onClick={() => this.onSelectedTabChanged(tab.id)}
isSelected={tab.id === this.state.selectedTabId}
key={index}
>
{tab.name}
</KuiTab>
</EuiTab>
));
}
@ -75,37 +79,36 @@ export class FeatureDirectory extends React.Component {
})
.map((directory) => {
return (
<KuiFlexItem key={directory.id}>
<EuiFlexItem key={directory.id}>
<Synopsis
description={directory.description}
iconUrl={this.props.addBasePath(directory.icon)}
title={directory.title}
url={this.props.addBasePath(directory.path)}
wrapInPanel
/>
</KuiFlexItem>
</EuiFlexItem>
);
});
};
render() {
return (
<div className="kuiView home">
<div className="kuiViewContent">
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<h1 className="kuiTitle ">
Directory
</h1>
</div>
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<KuiTabs className="homeDirectoryTabs">
{this.renderTabs()}
</KuiTabs>
<KuiFlexGrid columns={4} className="homeDirectory">
{ this.renderDirectories() }
</KuiFlexGrid>
</div>
</div>
</div>
<EuiPage className="home">
<EuiTitle size="l">
<h1>
Directory
</h1>
</EuiTitle>
<EuiSpacer size="m" />
<EuiTabs className="homeDirectoryTabs">
{this.renderTabs()}
</EuiTabs>
<EuiSpacer />
<EuiFlexGrid columns={4}>
{ this.renderDirectories() }
</EuiFlexGrid>
</EuiPage>
);
}
}

View file

@ -20,6 +20,7 @@ import {
EuiFlexItem,
EuiFlexGrid,
EuiText,
EuiTextColor,
} from '@elastic/eui';
import { FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
@ -56,7 +57,7 @@ export function Home({ addBasePath, directories }) {
return (
<div className="kuiVerticalRhythm">
<KuiCardGroup>
<KuiCard style={cardStyle}>
<KuiCard style={cardStyle} className="euiPanel">
<KuiCardDescription>
<KuiCardDescriptionTitle>
<img
@ -77,12 +78,12 @@ export function Home({ addBasePath, directories }) {
buttonType="secondary"
href={addBasePath(`${kbnBaseUrl}#/home/tutorial_directory/logging`)}
>
Add data
Add log data
</KuiLinkButton>
</KuiCardFooter>
</KuiCard>
<KuiCard style={cardStyle}>
<KuiCard style={cardStyle} className="euiPanel">
<KuiCardDescription>
<KuiCardDescriptionTitle>
<img
@ -103,19 +104,19 @@ export function Home({ addBasePath, directories }) {
buttonType="secondary"
href={addBasePath(`${kbnBaseUrl}#/home/tutorial_directory/metrics`)}
>
Add data
Add metric data
</KuiLinkButton>
</KuiCardFooter>
</KuiCard>
<KuiCard style={cardStyle}>
<KuiCard style={cardStyle} className="euiPanel">
<KuiCardDescription>
<KuiCardDescriptionTitle>
<img
src={addBasePath('/plugins/kibana/assets/app_security.svg')}
/>
<p>
Security Analytics
Security analytics
</p>
</KuiCardDescriptionTitle>
@ -129,7 +130,7 @@ export function Home({ addBasePath, directories }) {
buttonType="secondary"
href={addBasePath(`${kbnBaseUrl}#/home/tutorial_directory/security`)}
>
Add data
Add security events
</KuiLinkButton>
</KuiCardFooter>
</KuiCard>
@ -149,33 +150,32 @@ export function Home({ addBasePath, directories }) {
<EuiTitle size="l">
<h1>Add Data to Kibana</h1>
</EuiTitle>
<EuiText>
<p>
Use these solutions to quickly turn your data into pre-built dashboards and monitoring systems.
</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>
<p className="kuiText kuiSubduedText">
<EuiTextColor color="subdued">
<EuiText>
<p>
Data already in Elasticsearch?
</p>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<KuiLinkButton
buttonType="secondary"
href={addBasePath('/app/kibana#/management/kibana/index')}
>
Set up index patterns
</KuiLinkButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiText>
</EuiTextColor>
<EuiSpacer size="s" />
<a href="/app/kibana#/management/kibana/index" className="euiButton euiButton--primary euiButton--small">
<span className="euiButton__content">
Set up index patterns
</span>
</a>
</EuiFlexItem>
</EuiFlexGroup>
<p className="kuiText kuiSubduedText kuiVerticalRhythm kuiVerticalRhythmSmall">
These turnkey solutions will help you quickly add data into Kibana and turn it into
pre-built dashboards and monitoring systems.
</p>
<EuiSpacer />
{ renderPromo() }

View file

@ -2,39 +2,66 @@ import './synopsis.less';
import React from 'react';
import PropTypes from 'prop-types';
import {
KuiFlexGroup,
KuiFlexItem
} from 'ui_framework/components';
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiTitle,
EuiText,
EuiTextColor,
} from '@elastic/eui';
export function Synopsis({ description, iconUrl, title, url }) {
let img;
export function Synopsis({ description, iconUrl, title, url, wrapInPanel }) {
let optionalImg;
if (iconUrl) {
img = (
<img
className="synopsisIcon"
src={iconUrl}
alt=""
/>
optionalImg = (
<EuiFlexItem grow={false}>
<img
className="synopsisIcon"
src={iconUrl}
alt=""
/>
</EuiFlexItem>
);
}
const content = (
<EuiFlexGroup>
{optionalImg}
<EuiFlexItem className="synopsisContent">
<EuiTitle size="s" className="synopsisTitle">
<h4>
{title}
</h4>
</EuiTitle>
<EuiText className="synopsisBody">
<p>
<EuiTextColor color="subdued">
{description}
</EuiTextColor>
</p>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);
let synopsisDisplay = content;
if (wrapInPanel) {
synopsisDisplay = (
<EuiPanel className="synopsisPanel">
{content}
</EuiPanel>
);
}
return (
<a
href={url}
className="kuiLink synopsis"
className="euiLink synopsis"
data-test-subj={`homeSynopsisLink${title.toLowerCase()}`}
>
<KuiFlexGroup>
<KuiFlexItem grow={false}>{img}</KuiFlexItem>
<KuiFlexItem className="synopsisContent">
<h4 className="kuiTextTitle synopsisTitle">
{title}
</h4>
<p className="kuiText kuiSubduedText">
{description}
</p>
</KuiFlexItem>
</KuiFlexGroup>
{synopsisDisplay}
</a>
);
}

View file

@ -1,19 +1,33 @@
@import (reference) "~ui/styles/variables.less";
.synopsis {
display: flex;
flex-grow: 1;
}
.synopsis:hover {
text-decoration: none;
.kuiTextTitle {
.synopsisTitle {
text-decoration: underline;
}
}
.synopsisContent {
margin-left: 10px !important;
.synopsis:focus {
text-decoration: none;
.synopsisPanel {
border: solid 1px @globalColorBlue;
}
.synopsisBody {
text-decoration: none;
}
}
.synopsisTitle {
font-size: 16px;
font-weight: normal;
color: @globalColorBlue;
}
.synopsisIcon {

View file

@ -2,7 +2,7 @@
exports[`should render content with markdown 1`] = `
<div
className="kuiText kuiSubduedText tutorialContent markdown-body"
className="euiText euiTextColor--subdued tutorialContent markdown-body"
dangerouslySetInnerHTML={
Object {
"__html": "<p>I am <em>some</em> <a href=\\"https://en.wikipedia.org/wiki/Content\\" target=\\"_blank\\" rel=\\"noopener noreferrer\\">content</a> with <code>markdown</code></p>

View file

@ -1,133 +1,151 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should render ELASTIC_CLOUD instructions when isCloudEnabled is true 1`] = `
<div
className="kuiView home"
<EuiPage
className="home"
>
<div
className="kuiViewContent kuiViewContent--constrainedWidth"
<EuiLink
color="primary"
href="#/home"
type="button"
>
<a
className="kuiLink"
href="#/home"
Home
</EuiLink>
/
<EuiLink
color="primary"
href="#/home/tutorial_directory"
type="button"
>
Add Data
</EuiLink>
<EuiSpacer
size="s"
/>
<div>
<Introduction
description="tutorial used to drive jest tests"
title="jest test tutorial"
/>
<EuiSpacer
size="l"
/>
<div
className="text-center"
/>
<EuiSpacer
size="l"
/>
<EuiPanel
grow={true}
hasShadow={false}
paddingSize="l"
>
Home
</a>
/
<a
className="kuiLink"
href="#/home/tutorial_directory"
>
Add Data
</a>
<div>
<Introduction
description="tutorial used to drive jest tests"
title="jest test tutorial"
<InstructionSet
instructionVariants={
Array [
Object {
"id": "platform id",
"instructions": Array [
Object {
"title": "elasticCloud instructions",
},
],
},
]
}
key="0"
offset={1}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
title="Instruction title"
/>
<div
className="text-center kuiVerticalRhythm"
/>
<div
className="homePanel kuiVerticalRhythm"
>
<InstructionSet
instructionVariants={
Array [
Object {
"id": "platform id",
"instructions": Array [
Object {
"title": "elasticCloud instructions",
},
],
},
]
}
key="0"
offset={1}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
title="Instruction title"
/>
</div>
</div>
</EuiPanel>
</div>
</div>
</EuiPage>
`;
exports[`should render ON_PREM instructions with instructions cloud toggle when isCloudEnabled is false 1`] = `
<div
className="kuiView home"
<EuiPage
className="home"
>
<div
className="kuiViewContent kuiViewContent--constrainedWidth"
<EuiLink
color="primary"
href="#/home"
type="button"
>
<a
className="kuiLink"
href="#/home"
Home
</EuiLink>
/
<EuiLink
color="primary"
href="#/home/tutorial_directory"
type="button"
>
Add Data
</EuiLink>
<EuiSpacer
size="s"
/>
<div>
<Introduction
description="tutorial used to drive jest tests"
title="jest test tutorial"
/>
<EuiSpacer
size="l"
/>
<div
className="text-center"
>
Home
</a>
/
<a
className="kuiLink"
href="#/home/tutorial_directory"
>
Add Data
</a>
<div>
<Introduction
description="tutorial used to drive jest tests"
title="jest test tutorial"
<RadioButtonGroup
buttons={
Array [
Object {
"dataTestSubj": "onPremBtn",
"label": "On premise",
"onClick": [Function],
},
Object {
"dataTestSubj": "onPremElasticCloudBtn",
"label": "Elastic Cloud",
"onClick": [Function],
},
]
}
selectedBtnLabel="On premise"
/>
<div
className="text-center kuiVerticalRhythm"
>
<RadioButtonGroup
buttons={
Array [
Object {
"dataTestSubj": "onPremBtn",
"label": "On premise",
"onClick": [Function],
},
Object {
"dataTestSubj": "onPremElasticCloudBtn",
"label": "Elastic Cloud",
"onClick": [Function],
},
]
}
selectedBtnLabel="On premise"
/>
</div>
<div
className="homePanel kuiVerticalRhythm"
>
<InstructionSet
instructionVariants={
Array [
Object {
"id": "platform id",
"instructions": Array [
Object {
"title": "onPrem instructions",
},
],
},
]
}
key="0"
offset={1}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
title="Instruction title"
/>
</div>
</div>
<EuiSpacer
size="l"
/>
<EuiPanel
grow={true}
hasShadow={false}
paddingSize="l"
>
<InstructionSet
instructionVariants={
Array [
Object {
"id": "platform id",
"instructions": Array [
Object {
"title": "onPrem instructions",
},
],
},
]
}
key="0"
offset={1}
paramValues={Object {}}
replaceTemplateStrings={[Function]}
setParameter={[Function]}
title="Instruction title"
/>
</EuiPanel>
</div>
</div>
</EuiPage>
`;

View file

@ -21,7 +21,7 @@ markdownIt.renderer.rules.link_open = function (tokens, idx, options, env, self)
};
export function Content({ className, text }) {
const classes = classNames('kuiText kuiSubduedText tutorialContent markdown-body', className);
const classes = classNames('euiText euiTextColor--subdued tutorialContent markdown-body', className);
return (
<div
className={classes}

View file

@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip } from 'pivotal-ui/react/tooltip';
import { OverlayTrigger } from 'pivotal-ui/react/overlay-trigger';
import { KuiButton } from 'ui_framework/components';
import { EuiButton } from '@elastic/eui';
import { copyToClipboard } from '../../copy_to_clipboard';
const UNCOPIED_MSG = 'Copy to clipboard';
@ -43,13 +43,13 @@ export class CopyButton extends React.Component {
</Tooltip>
}
>
<KuiButton
buttonType="secondary"
<EuiButton
size="s"
onClick={this.copySnippet}
onMouseOut={this.resetTooltipText}
>
Copy snippet
</KuiButton>
</EuiButton>
</OverlayTrigger>
);
}

View file

@ -24,7 +24,7 @@ export function Instruction({ commands, paramValues, textPost, textPre, replaceT
if (textPost) {
post = (
<div>
<EuiSpacer size="s" />
<EuiSpacer size="m" />
<Content
text={replaceTemplateStrings(textPost)}
/>
@ -43,7 +43,7 @@ export function Instruction({ commands, paramValues, textPost, textPre, replaceT
);
commandBlock = (
<div>
<EuiSpacer size="s" />
<EuiSpacer size="m" />
<EuiCodeBlock language="sh">
{cmdText}
</EuiCodeBlock>
@ -71,6 +71,8 @@ export function Instruction({ commands, paramValues, textPost, textPre, replaceT
{post}
<EuiSpacer />
</div>
);
}

View file

@ -1,15 +1,10 @@
import './introduction.less';
import React from 'react';
import PropTypes from 'prop-types';
import { Content } from './content';
import { EuiTitle, EuiFlexItem, EuiFlexGroup, EuiSpacer, EuiImage } from '@elastic/eui';
import {
KuiLinkButton,
} from 'ui_framework/components';
import {
EuiImage,
EuiSpacer,
} from '@elastic/eui';
export function Introduction({ description, previewUrl, title, exportedFieldsUrl }) {
let img;
@ -42,23 +37,19 @@ export function Introduction({ description, previewUrl, title, exportedFieldsUrl
);
}
return (
<div className="introduction kuiVerticalRhythm">
<div className="kuiFlexGroup kuiFlexGroup--gutterLarge">
<div className="kuiFlexItem">
<h1 className="kuiTitle kuiVerticalRhythm">
{title}
</h1>
<Content className="kuiVerticalRhythm" text={description}/>
{exportedFields}
</div>
<div className="kuiFlexItem kuiFlexItem--flexGrowZero">
{img}
</div>
</div>
</div>
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle size="l">
<h2>{title}</h2>
</EuiTitle>
<EuiSpacer />
<Content text={description} />
{exportedFields}
</EuiFlexItem>
<EuiFlexItem grow={false}>
{img}
</EuiFlexItem>
</EuiFlexGroup>
);
}

View file

@ -1,3 +0,0 @@
.introduction {
margin: 24px;
}

View file

@ -5,6 +5,7 @@ import PropTypes from 'prop-types';
import { Introduction } from './introduction';
import { InstructionSet } from './instruction_set';
import { RadioButtonGroup } from './radio_button_group';
import { EuiSpacer, EuiPage, EuiPanel, EuiLink, EuiText } from '@elastic/eui';
const INSTRUCTIONS_TYPE = {
ELASTIC_CLOUD: 'elasticCloud',
@ -157,9 +158,11 @@ export class Tutorial extends React.Component {
if (this.state.notFound) {
content = (
<div className="homePanel">
<p className="kuiText kuiSubduedText kuiVerticalRhythm kuiVerticalRhythmSmall">
Unable to find tutorial {this.props.tutorialId}
</p>
<EuiText>
<p>
Unable to find tutorial {this.props.tutorialId}
</p>
</EuiText>
</div>
);
}
@ -185,23 +188,25 @@ export class Tutorial extends React.Component {
exportedFieldsUrl={exportedFieldsUrl}
/>
<div className="text-center kuiVerticalRhythm">
<EuiSpacer />
<div className="text-center">
{this.renderInstructionSetsToggle()}
</div>
<div className="homePanel kuiVerticalRhythm">
<EuiSpacer />
<EuiPanel paddingSize="l">
{this.renderInstructionSets(instructions)}
</div>
</EuiPanel>
</div>
);
}
return (
<div className="kuiView home">
<div className="kuiViewContent kuiViewContent--constrainedWidth">
<a className="kuiLink" href="#/home">Home</a> / <a className="kuiLink" href="#/home/tutorial_directory">Add Data</a>
{content}
</div>
</div>
<EuiPage className="home">
<EuiLink href="#/home">Home</EuiLink> / <EuiLink href="#/home/tutorial_directory">Add Data</EuiLink>
<EuiSpacer size="s" />
{content}
</EuiPage>
);
}
}

View file

@ -1,12 +1,3 @@
.tutorialContent {
/*
* 1. remove bottom margin placed on p element by bootstrap
*/
p {
margin-bottom: 0; /* 1 */
}
}
.text-center > .kuiButtonGroup {
display: inline-block !important;
}

View file

@ -1,12 +1,18 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Synopsis } from './synopsis';
import {
KuiTabs,
KuiTab,
KuiFlexItem,
KuiFlexGrid,
} from 'ui_framework/components';
EuiPage,
EuiTabs,
EuiTab,
EuiFlexItem,
EuiFlexGrid,
EuiSpacer,
EuiTitle,
} from '@elastic/eui';
import { getTutorials } from '../load_tutorials';
const ALL = 'all';
@ -55,14 +61,14 @@ export class TutorialDirectory extends React.Component {
renderTabs = () => {
return this.tabs.map((tab, index) => (
<KuiTab
<EuiTab
className="homeDirectoryTab"
onClick={() => this.onSelectedTabChanged(tab.id)}
isSelected={tab.id === this.state.selectedTabId}
key={index}
>
{tab.name}
</KuiTab>
</EuiTab>
));
}
@ -76,40 +82,41 @@ export class TutorialDirectory extends React.Component {
})
.map((tutorial) => {
return (
<KuiFlexItem key={tutorial.name}>
<EuiFlexItem key={tutorial.name}>
<Synopsis
description={tutorial.shortDescription}
title={tutorial.name}
wrapInPanel
url={this.props.addBasePath(`#/home/tutorial/${tutorial.id}`)}
/>
</KuiFlexItem>
</EuiFlexItem>
);
});
};
render() {
return (
<div className="kuiView home">
<div className="kuiViewContent">
<EuiPage className="home">
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<a className="kuiLink" href="#/home">Home</a>
<h1 className="kuiTitle ">
Add Data to Kibana
</h1>
</div>
<a className="kuiLink" href="#/home">Home</a>
<EuiSpacer size="s" />
<EuiTitle size="l">
<h1>
Add Data to Kibana
</h1>
</EuiTitle>
<div className="kuiViewContentItem kuiVerticalRhythmXLarge">
<KuiTabs>
{this.renderTabs()}
</KuiTabs>
<KuiFlexGrid columns={4} className="homeDirectory">
{ this.renderTutorials() }
</KuiFlexGrid>
</div>
<EuiSpacer size="m" />
</div>
</div>
<EuiTabs>
{this.renderTabs()}
</EuiTabs>
<EuiSpacer />
<EuiFlexGrid columns={4}>
{ this.renderTutorials() }
</EuiFlexGrid>
</EuiPage>
);
}
}

View file

@ -1,8 +1,13 @@
@import (reference) "~ui/styles/variables.less";
.home {
home-app {
background-color: @globalColorLightestGray;
}
.home {
min-height: 100vh;
max-width: 1200px;
margin: auto;
}
.kuiCard__descriptionTitle img {

View file

@ -39,6 +39,7 @@
<label
class="euiCheckbox__label"
for="indexPatternCreationIncludeSystemIndices"
style="white-space: nowrap"
>
Include system indices
</label>
@ -83,16 +84,16 @@
ng-if="!controller.isFetchingExistingIndices"
>
<div>
<h2 class="euiTitle euiTitle--small euiTextColor euiTextColor--subdued">
<h2 class="euiTitle euiTitle--small">
Couldn't find any Elasticsearch data
</h2>
<div class="euiSpacer euiSpacer--s"></div>
<p class="euiTextColor euiTextColor--subdued">
<p>
<span>
You'll need to index some data into Elasticsearch before you can create an index pattern.
</span>
<a
class="euiLink"
class="euiLink euiLink--primary"
aria-label="Learn how to index data into Elasticsearch"
documentation-href="indexPatterns.loadingData"
target="_blank"

View file

@ -54,7 +54,7 @@
* 4. Fix an IE bug which causes the last child to overflow the container.
* 5. Fixing this bug means we now need to align the children to the right.
*/
:focus {
:focus:not([class^="eui"]) {
z-index: 1;
/* 1 */
outline: none !important;

View file

@ -1,6 +1,10 @@
// Removes outline, but still provides a two color box shadow that works anywhere.
// We apply brute force focus states to anything not coming from Eui
// which has focus states designed at the component level.
:focus {
@include focus;
&:not([class^="eui"]),
{
@include focus;
}
}
/**