Skip to content

Commit

Permalink
[EuiHeaderLinks] Providing more flexibility in display (#4046)
Browse files Browse the repository at this point in the history
* [EuiHeaderLinks] Adding `gutterSize` flexibility
* [EuiHeaderLinks] Fix spacing and extend popover props
* Removing `#` from `hrefs` in examples
* [EuiPopover] Fix `container` from being passed to DOM as attribute
* Fixing up all the header examples
  - No importing of external doc examples
  - All Elastic logos
  - Remove all actual links that might send the user to the index page
  - Only the first example shows all the popovers
  - The Full screen demo has the rest
* [EuiHide/ShowFor] Add `all` and `none` options for sizes
  - Then update `popoverBreakpoints` prop in EuiHeaderLinks to also allow for `all` and `none`.
* Fixing all popover scrolls in fixed examples
  • Loading branch information
cchaos authored Sep 22, 2020
1 parent 528c292 commit b6f793d
Show file tree
Hide file tree
Showing 31 changed files with 1,020 additions and 762 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
- Added column header menu to `EuiDataGrid` ([#3087](https://github.com/elastic/eui/pull/3087))
- Added horizontal line separator to `EuiContextMenu` ([#4018](https://github.com/elastic/eui/pull/4018))
- Added controlled pagination props to `EuiInMemoryTablee` ([#4038](https://github.com/elastic/eui/pull/4038))
- Added `gutterSize`, `popoverBreakpoints`, `popoverButtonProps`, and `popoverProps` props to `EuiHeaderLinks` ([#4046](https://github.com/elastic/eui/pull/4046))
- Added `'all'` and `'none'` options to the `sizes` prop of `EuiHideFor` and `EuiShowFor` ([#4046](https://github.com/elastic/eui/pull/4046))

**Bug fixes**

Expand Down
322 changes: 305 additions & 17 deletions src-docs/src/views/header/header.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import React from 'react';
import React, { useState } from 'react';
import { Link } from 'react-router-dom';

import {
EuiAvatar,
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiHeader,
EuiHeaderBreadcrumbs,
EuiHeaderLogo,
EuiHeaderSection,
EuiHeaderSectionItem,
EuiHeaderSectionItemButton,
EuiHeaderLogo,
EuiIcon,
EuiKeyPadMenu,
EuiKeyPadMenuItem,
EuiLink,
EuiPopover,
EuiPopoverFooter,
EuiPopoverTitle,
EuiSelectable,
EuiSelectableMessage,
EuiSelectableTemplateSitewide,
EuiSpacer,
EuiText,
} from '../../../../src/components';

import HeaderAppMenu from './header_app_menu';
import HeaderUserMenu from './header_user_menu';
import HeaderSpacesMenu from './header_spaces_menu';
import { htmlIdGenerator } from '../../../../src/services';

export default () => {
const renderLogo = () => (
<EuiHeaderLogo
iconType="logoKibana"
iconType="logoElastic"
href="#"
onClick={e => e.preventDefault()}
aria-label="Go to home page"
/>
);
Expand All @@ -30,7 +44,6 @@ export default () => {
href: '#',
onClick: e => {
e.preventDefault();
console.log('You clicked management');
},
'data-test-subj': 'breadcrumbsAnimals',
className: 'customClass',
Expand All @@ -40,23 +53,20 @@ export default () => {
href: '#',
onClick: e => {
e.preventDefault();
console.log('You clicked truncation test');
},
},
{
text: 'hidden',
text: 'Hidden',
href: '#',
onClick: e => {
e.preventDefault();
console.log('You clicked hidden');
},
},
{
text: 'Users',
href: '#',
onClick: e => {
e.preventDefault();
console.log('You clicked users');
},
},
{
Expand All @@ -72,10 +82,29 @@ export default () => {
);
};

const renderSearch = () => (
<EuiHeaderSectionItemButton aria-label="Search">
<EuiIcon type="search" size="m" />
</EuiHeaderSectionItemButton>
const search = (
<EuiSelectableTemplateSitewide
options={[]}
searchProps={{
compressed: true,
}}
popoverButton={
<EuiHeaderSectionItemButton aria-label="Sitewide search">
<EuiIcon type="search" size="m" />
</EuiHeaderSectionItemButton>
}
emptyMessage={
<EuiSelectableMessage style={{ minHeight: 300 }}>
<p>
Please see the component page for{' '}
<Link to="/forms/selectable">
<strong>EuiSelectableTemplateSitewide</strong>
</Link>{' '}
on how to configure your sitewide search.
</p>
</EuiSelectableMessage>
}
/>
);

return (
Expand All @@ -92,7 +121,7 @@ export default () => {
{renderBreadcrumbs()}

<EuiHeaderSection side="right">
<EuiHeaderSectionItem>{renderSearch()}</EuiHeaderSectionItem>
<EuiHeaderSectionItem>{search}</EuiHeaderSectionItem>

<EuiHeaderSectionItem>
<HeaderUserMenu />
Expand All @@ -105,3 +134,262 @@ export default () => {
</EuiHeader>
);
};

const HeaderUserMenu = () => {
const id = htmlIdGenerator()();
const [isOpen, setIsOpen] = useState(false);

const onMenuButtonClick = () => {
setIsOpen(!isOpen);
};

const closeMenu = () => {
setIsOpen(false);
};

const button = (
<EuiHeaderSectionItemButton
aria-controls={id}
aria-expanded={isOpen}
aria-haspopup="true"
aria-label="Account menu"
onClick={onMenuButtonClick}>
<EuiAvatar name="John Username" size="s" />
</EuiHeaderSectionItemButton>
);

return (
<EuiPopover
id={id}
ownFocus
button={button}
isOpen={isOpen}
anchorPosition="downRight"
closePopover={closeMenu}
panelPaddingSize="none">
<div style={{ width: 320 }}>
<EuiFlexGroup
gutterSize="m"
className="euiHeaderProfile"
responsive={false}>
<EuiFlexItem grow={false}>
<EuiAvatar name="John Username" size="xl" />
</EuiFlexItem>

<EuiFlexItem>
<EuiText>
<p>John Username</p>
</EuiText>

<EuiSpacer size="m" />

<EuiFlexGroup>
<EuiFlexItem>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiLink>Edit profile</EuiLink>
</EuiFlexItem>

<EuiFlexItem grow={false}>
<EuiLink>Log out</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</div>
</EuiPopover>
);
};

const HeaderSpacesMenu = () => {
const id = htmlIdGenerator()();
const spacesValues = [
{
label: 'Sales team',
prepend: <EuiAvatar type="space" name="Sales Team" size="s" />,
checked: 'on',
},
{
label: 'Engineering',
prepend: <EuiAvatar type="space" name="Engineering" size="s" />,
},
{
label: 'Security',
prepend: <EuiAvatar type="space" name="Security" size="s" />,
},
{
label: 'Default',
prepend: <EuiAvatar type="space" name="Default" size="s" />,
},
];

const additionalSpaces = [
{
label: 'Sales team 2',
prepend: <EuiAvatar type="space" name="Sales Team 2" size="s" />,
},
{
label: 'Engineering 2',
prepend: <EuiAvatar type="space" name="Engineering 2" size="s" />,
},
{
label: 'Security 2',
prepend: <EuiAvatar type="space" name="Security 2" size="s" />,
},
{
label: 'Default 2',
prepend: <EuiAvatar type="space" name="Default 2" size="s" />,
},
];

const [spaces, setSpaces] = useState(spacesValues);
const [selectedSpace, setSelectedSpace] = useState(
spaces.filter(option => option.checked)[0]
);
const [isOpen, setIsOpen] = useState(false);

const isListExtended = () => {
return spaces.length > 4 ? true : false;
};

const onMenuButtonClick = () => {
setIsOpen(!isOpen);
};

const closePopover = () => {
setIsOpen(false);
};

const onChange = options => {
setSpaces(options);
setSelectedSpace(options.filter(option => option.checked)[0]);
setIsOpen(false);
};

const addMoreSpaces = () => {
setSpaces(spaces.concat(additionalSpaces));
};

const button = (
<EuiHeaderSectionItemButton
aria-controls={id}
aria-expanded={isOpen}
aria-haspopup="true"
aria-label="Spaces menu"
onClick={onMenuButtonClick}>
{selectedSpace.prepend}
</EuiHeaderSectionItemButton>
);

return (
<EuiPopover
id={id}
ownFocus
button={button}
isOpen={isOpen}
anchorPosition="downLeft"
closePopover={closePopover}
panelPaddingSize="none">
<EuiSelectable
searchable={isListExtended()}
searchProps={{
placeholder: 'Find a space',
compressed: true,
}}
options={spaces}
singleSelection="always"
style={{ width: 300 }}
onChange={onChange}
listProps={{
rowHeight: 40,
showIcons: false,
}}>
{(list, search) => (
<>
<EuiPopoverTitle>{search || 'Your spaces'}</EuiPopoverTitle>
{list}
<EuiPopoverFooter>
<EuiButton
size="s"
fullWidth
onClick={addMoreSpaces}
disabled={isListExtended()}>
Add more spaces
</EuiButton>
</EuiPopoverFooter>
</>
)}
</EuiSelectable>
</EuiPopover>
);
};

const HeaderAppMenu = () => {
const idGenerator = htmlIdGenerator();
const popoverId = idGenerator('popover');
const keypadId = idGenerator('keypad');

const [isOpen, setIsOpen] = useState(false);

const onMenuButtonClick = () => {
setIsOpen(!isOpen);
};

const closeMenu = () => {
setIsOpen(false);
};

const button = (
<EuiHeaderSectionItemButton
aria-controls={keypadId}
aria-expanded={isOpen}
aria-haspopup="true"
aria-label="Apps menu with 1 new app"
notification="1"
onClick={onMenuButtonClick}>
<EuiIcon type="apps" size="m" />
</EuiHeaderSectionItemButton>
);

return (
<EuiPopover
id={popoverId}
ownFocus
button={button}
isOpen={isOpen}
anchorPosition="downRight"
closePopover={closeMenu}>
<EuiKeyPadMenu id={keypadId} style={{ width: 288 }}>
<EuiKeyPadMenuItem label="Discover">
<EuiIcon type="discoverApp" size="l" />
</EuiKeyPadMenuItem>

<EuiKeyPadMenuItem label="Dashboard">
<EuiIcon type="dashboardApp" size="l" />
</EuiKeyPadMenuItem>

<EuiKeyPadMenuItem label="Dev Tools">
<EuiIcon type="devToolsApp" size="l" />
</EuiKeyPadMenuItem>

<EuiKeyPadMenuItem label="Machine Learning">
<EuiIcon type="machineLearningApp" size="l" />
</EuiKeyPadMenuItem>

<EuiKeyPadMenuItem label="Graph">
<EuiIcon type="graphApp" size="l" />
</EuiKeyPadMenuItem>

<EuiKeyPadMenuItem label="Visualize">
<EuiIcon type="visualizeApp" size="l" />
</EuiKeyPadMenuItem>

<EuiKeyPadMenuItem label="Timelion" betaBadgeLabel="Beta">
<EuiIcon type="timelionApp" size="l" />
</EuiKeyPadMenuItem>
</EuiKeyPadMenu>
</EuiPopover>
);
};
Loading

0 comments on commit b6f793d

Please sign in to comment.