Skip to content

Commit

Permalink
[Beta] Add EuiTour component (elastic#2766)
Browse files Browse the repository at this point in the history
* initial commit

* laying groundwork for steps

* saving progress

* saving progress

* cleaning up some TODO items

* use form for demo

* added localStorage to demo

* uncomment screereader only for step indicator

* API refactor; useEuiTour

* WIP

* interface and docs clean up

* more docs

* add goto action

* refactor useEuiTour

* beacon component

* use euibeacon

* beacon test

* tour_step_indicator test

* tour_step test

* beta label

* change hasBeacon boolean prop to decoration enum prop

* reducer guards

* replaceable footer action

* docs updates

* src changes

* use GuideFullScreen

* beacon transition

* misc a11y

* step example

* use new component name style

* docs clean up

* Update src-docs/src/views/tour/step.js

Co-Authored-By: Caroline Horn <[email protected]>

* Update src-docs/src/views/beacon/beacon_example.js

Co-Authored-By: Caroline Horn <[email protected]>

* Update src/components/tour/_tour.scss

Co-Authored-By: Caroline Horn <[email protected]>

* Update src-docs/src/views/tour/step.js

Co-Authored-By: Caroline Horn <[email protected]>

* Update src-docs/src/views/tour/tour_example.js

Co-Authored-By: Caroline Horn <[email protected]>

* Update src-docs/src/views/tour/tour_example.js

Co-Authored-By: Caroline Horn <[email protected]>

* Update src-docs/src/views/tour/tour_example.js

Co-Authored-By: Caroline Horn <[email protected]>

* lint fixes

* misc formatting

* move interface

* comments and tests

* start EuiTour example closed by default

* onFinish only

* handle one-step tours

* clean up

* docs updates

* popover tests

* docs update

* update complete/incomplete logic

* misc feedback updates

* tour reducer action types

* 1-based indexing

* remove isTourActive from step api; docs clean up

* add payload options for goto and finish

* new badge

* CL

* CL

Co-authored-by: Greg Thompson <[email protected]>
Co-authored-by: Caroline Horn <[email protected]>
  • Loading branch information
3 people authored Apr 14, 2020
1 parent ea44fd7 commit 1a514a1
Show file tree
Hide file tree
Showing 38 changed files with 2,061 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
- Converted `NavDrawer`, `NavDrawerGroup`, and `NavDrawerFlyout` to TypeScript ([#3268](https://github.com/elastic/eui/pull/3268))
- Converted `EuiDatePicker`, `EuiDatePickerRange`, `EuiSuperDatePicker`, and `EuiSuperUpdateButton` to TypeScript ([#2891](https://github.com/elastic/eui/pull/2891))
- Improved condensed `EuiTabs` focus states ([#3299](https://github.com/elastic/eui/pull/3299))
- Added `EuiTour`, `EuiTourStep`, and `useEuiTour` components ([#2766](https://github.com/elastic/eui/pull/2766))
- Added `EuiBeacon` component ([#2766](https://github.com/elastic/eui/pull/2766))
- Added `offset` and `arrowChildren` props to `EuiPopover` for anchor element customization ([#2766](https://github.com/elastic/eui/pull/2766))

## [`22.5.0`](https://github.com/elastic/eui/tree/v22.5.0)

Expand Down
6 changes: 6 additions & 0 deletions src-docs/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import { AvatarExample } from './views/avatar/avatar_example';

import { BadgeExample } from './views/badge/badge_example';

import { BeaconExample } from './views/beacon/beacon_example';

import { BottomBarExample } from './views/bottom_bar/bottom_bar_example';

import { BreadcrumbsExample } from './views/breadcrumbs/breadcrumbs_example';
Expand Down Expand Up @@ -204,6 +206,8 @@ import { ToolTipExample } from './views/tool_tip/tool_tip_example';

import { ToggleExample } from './views/toggle/toggle_example';

import { TourExample } from './views/tour/tour_example';

import { WindowEventExample } from './views/window_event/window_event_example';

import { Changelog } from './views/package/changelog';
Expand Down Expand Up @@ -382,6 +386,7 @@ const navigation = [
TitleExample,
ToastExample,
ToolTipExample,
TourExample,
].map(example => createExample(example)),
},
{
Expand Down Expand Up @@ -418,6 +423,7 @@ const navigation = [
name: 'Utilities',
items: [
AccessibilityExample,
BeaconExample,
IsColorDarkExample,
ColorPaletteExample,
CopyExample,
Expand Down
11 changes: 10 additions & 1 deletion src-docs/src/services/full_screen/full_screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ export const GuideFullScreen: FunctionComponent<{
children: (setFullScreen: (isFullScreen: boolean) => void) => ReactElement;
buttonText?: ReactNode;
isFullScreen?: boolean;
onOpen?: () => void;
}> = ({
children,
isFullScreen = false,
buttonText = 'Show fullscreen demo',
onOpen,
}) => {
const [fullScreen, setFullScreen] = useState(isFullScreen);

Expand All @@ -31,9 +33,16 @@ export const GuideFullScreen: FunctionComponent<{
};
}, [fullScreen]);

const openFullScreen = () => {
setFullScreen(true);
if (onOpen) {
onOpen();
}
};

return (
<Fragment>
<EuiButton onClick={() => setFullScreen(true)} iconType="fullScreen">
<EuiButton onClick={openFullScreen} iconType="fullScreen">
{buttonText}
</EuiButton>

Expand Down
1 change: 1 addition & 0 deletions src-docs/src/services/full_screen/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { GuideFullScreen } from './full_screen';
2 changes: 2 additions & 0 deletions src-docs/src/services/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export { translateUsingPseudoLocale } from './string/pseudo_locale_translator';
export { registerTheme, applyTheme } from './theme/theme';

export { getRouterLinkProps, registerRouter } from './routing/routing';

export { GuideFullScreen } from './full_screen';
9 changes: 9 additions & 0 deletions src-docs/src/views/beacon/beacon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react';

import { EuiBeacon } from '../../../../src/components';

export default () => (
<>
<EuiBeacon />
</>
);
39 changes: 39 additions & 0 deletions src-docs/src/views/beacon/beacon_example.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';

import { renderToHtml } from '../../services';

import { GuideSectionTypes } from '../../components';

import { EuiBeacon, EuiText } from '../../../../src/components';

import Beacon from './beacon';
const beaconSource = require('!!raw-loader!./beacon');
const beaconHtml = renderToHtml(Beacon);

export const BeaconExample = {
title: 'Beacon',
sections: [
{
source: [
{
type: GuideSectionTypes.JS,
code: beaconSource,
},
{
type: GuideSectionTypes.HTML,
code: beaconHtml,
},
],
text: (
<EuiText>
<p>
Use the <strong>EuiBeacon</strong> component to draw visual
attention to a specific location or element.
</p>
</EuiText>
),
props: { EuiBeacon },
demo: <Beacon />,
},
],
};
238 changes: 238 additions & 0 deletions src-docs/src/views/tour/fullscreen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import React, { Fragment, useEffect, useState } from 'react';

import { GuideFullScreen } from '../../services';

import {
EuiButton,
EuiButtonEmpty,
EuiColorPicker,
EuiColorPickerSwatch,
EuiPage,
EuiPageBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiPageContent,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiPageContentBody,
EuiSpacer,
EuiStat,
EuiTab,
EuiTabs,
EuiTextArea,
EuiTitle,
EuiTourStep,
useEuiTour,
} from '../../../../src/components';

const demoTourSteps = [
{
step: 1,
title: 'Step 1',
},
{
step: 2,
title: 'Step 2',
anchorPosition: 'upCenter',
content: <p>What is your favorite color?</p>,
},
{
step: 3,
title: 'Step 3',
content: <p>Click here for more cool things.</p>,
anchorPosition: 'downRight',
minWidth: 'auto',
},
{
step: 4,
title: 'Step 4',
anchorPosition: 'downLeft',
decoration: 'none',
},
];

const tourConfig = {
currentTourStep: 1,
isTourActive: true,
tourPopoverWidth: true,
tourSubtitle: 'Demo tour',
};

export default () => {
const [color, setColor] = useState('#000');
const [selectedTabId, setSelectedTabId] = useState('query');
const [
[euiTourStepOne, euiTourStepTwo, euiTourStepThree, euiTourStepFour],
actions,
reducerState,
] = useEuiTour(demoTourSteps, tourConfig);

useEffect(() => {
console.log('Update', reducerState);
}, [reducerState]);

const onSelectColor = color => {
setColor(color);
if (reducerState.currentTourStep === 2) {
actions.goToStep(3);
}
};

const onTabClick = id => {
if (id === 'stat' && reducerState.currentTourStep === 3) {
actions.goToStep(4);
}
setSelectedTabId(id);
};

const onReset = () => {
actions.resetTour();
setSelectedTabId('query');
};

const tabs = [
{
id: 'query',
name: 'Query',
disabled: false,
content: (
<div>
<EuiSpacer />
<EuiTourStep
{...euiTourStepOne}
content={
<div>
<p>This is a neat thing. You enter queries here.</p>
<EuiSpacer />
<EuiButton color="primary" onClick={actions.incrementStep}>
Ok, got it.
</EuiButton>
</div>
}>
<EuiTextArea
placeholder="Placeholder text"
aria-label="Enter ES SQL query"
defaultValue="{queryValue}"
style={{ width: 400 }}
/>
</EuiTourStep>

<EuiSpacer />

<EuiTourStep
{...euiTourStepTwo}
footerAction={
<EuiButtonEmpty
color="text"
flush="right"
size="xs"
onClick={actions.incrementStep}>
{"I don't have a favorite color"}
</EuiButtonEmpty>
}>
<EuiColorPicker
onChange={onSelectColor}
color={color}
mode="swatch"
button={
<EuiColorPickerSwatch
color={color}
aria-label="Select a color"
/>
}
/>
</EuiTourStep>
</div>
),
},
{
id: 'stat',
name: (
<EuiTourStep {...euiTourStepThree}>
<span>Stats</span>
</EuiTourStep>
),
disabled: false,
content: (
<div>
<EuiSpacer />
<EuiTourStep
{...euiTourStepFour}
content={
<div>
<p>That about does it.</p>
<EuiSpacer />
<EuiButton color="primary" onClick={onReset}>
Take me to the start.
</EuiButton>
</div>
}>
<div>
<EuiStat title="22,123" description="Queries" />
</div>
</EuiTourStep>
</div>
),
},
];

return (
<GuideFullScreen onOpen={onReset}>
{setIsFullScreen => (
<React.Fragment>
<EuiPage className="guideFullScreenOverlay" style={{ zIndex: 9000 }}>
<EuiPageBody>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>My app</h1>
</EuiTitle>
</EuiPageHeaderSection>
<EuiPageHeaderSection>
<EuiButton
fill
onClick={() => setIsFullScreen(false)}
iconType="exit"
aria-label="Exit fullscreen demo">
Exit fullscreen demo
</EuiButton>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle>
<h2>A new feature to demo</h2>
</EuiTitle>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentBody>
<EuiTabs>
{tabs.map((tab, index) => (
<EuiTab
id={tab.id}
onClick={() => onTabClick(tab.id)}
isSelected={tab.id === selectedTabId}
key={index}>
{tab.name}
</EuiTab>
))}
</EuiTabs>
{tabs.map((tab, index) => (
<Fragment key={index}>
{tab.id === selectedTabId && (
<div role="tabpanel" aria-labelledby={tab.id}>
{tab.content}
</div>
)}
</Fragment>
))}
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
</React.Fragment>
)}
</GuideFullScreen>
);
};
Loading

0 comments on commit 1a514a1

Please sign in to comment.