diff --git a/src-docs/src/views/header/header_alert.js b/src-docs/src/views/header/header_alert.js index 88e440e08b4..278e2616da4 100644 --- a/src-docs/src/views/header/header_alert.js +++ b/src-docs/src/views/header/header_alert.js @@ -29,42 +29,9 @@ import { } from '../../../../src/components'; import { htmlIdGenerator } from '../../../../src/services'; -export default () => { - const [position, setPosition] = useState('static'); - - return ( - <> - setPosition(e.target.checked ? 'fixed' : 'static')} - /> - - - - - Elastic - - - - - - - - - - - - - - ); -}; - -const HeaderUpdates = ({ flyoutOrPopover = 'flyout' }) => { +const HeaderUpdates = () => { const [isFlyoutVisible, setIsFlyoutVisible] = useState(false); - const [showBadge, setShowBadge] = useState(true); + const [isPopoverVisible, setIsPopoverVisible] = useState(false); const alerts = [ { @@ -146,88 +113,55 @@ const HeaderUpdates = ({ flyoutOrPopover = 'flyout' }) => { setIsFlyoutVisible(false); }; + const closePopover = () => { + setIsPopoverVisible(false); + }; + const showFlyout = () => { - setShowBadge(false); setIsFlyoutVisible(!isFlyoutVisible); }; - const button = ( + const showPopover = () => { + setIsPopoverVisible(!isPopoverVisible); + }; + + const bellButton = ( showFlyout()} - notification={showBadge}> - + notification={true}> + ); - let content; - if (flyoutOrPopover === 'flyout') { - content = ( - <> - {button} - {isFlyoutVisible && ( - - closeFlyout()} - size="s" - id="headerNewsFeed" - aria-labelledby="flyoutSmallTitle"> - - -

What's new

-
-
- - {alerts.map((alert, i) => ( - - ))} - - - - - closeFlyout()} - flush="left"> - Close - - - - -

Version 7.0

-
-
-
-
-
-
- )} - - ); - } + const cheerButton = ( + + + + ); - if (flyoutOrPopover === 'popover') { - content = ( - closeFlyout()} - panelPaddingSize="none"> - What's new -
- + const flyout = ( + + + + +

What's new

+
+
+ {alerts.map((alert, i) => ( { badge={alert.badge} /> ))} -
- - -

Version 7.0

-
-
-
- ); - } + + + + + + Close + + + + +

Version 7.0

+
+
+
+
+ + + ); + + const popover = ( + + What's new +
+ + {alerts.map((alert, i) => ( + + ))} +
+ + +

Version 7.0

+
+
+
+ ); - return content; + return ( + <> + {bellButton} + {popover} + {isFlyoutVisible && flyout} + + ); }; const HeaderUserMenu = () => { @@ -319,3 +302,48 @@ const HeaderUserMenu = () => { ); }; + +export default () => { + const [position, setPosition] = useState('static'); + const [theme, setTheme] = useState('light'); + + return ( + <> + + + setPosition(e.target.checked ? 'fixed' : 'static')} + /> + + + + setTheme(e.target.checked ? 'dark' : 'light')} + /> + + + + + + + + + Elastic + + + + + + + + + + + + + ); +}; diff --git a/src-docs/src/views/header/header_animate.js b/src-docs/src/views/header/header_animate.js new file mode 100644 index 00000000000..fa1711461fb --- /dev/null +++ b/src-docs/src/views/header/header_animate.js @@ -0,0 +1,134 @@ +import React, { + forwardRef, + useCallback, + useImperativeHandle, + useRef, + useState, +} from 'react'; + +import { + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiHeader, + EuiHeaderLogo, + EuiHeaderSectionItemButton, + EuiIcon, + EuiSpacer, +} from '../../../../src/components'; + +const HeaderUpdates = forwardRef( + ({ showNotification, notificationsNumber }, ref) => { + const bellRef = useRef(); + const cheerRef = useRef(); + + // wrapping the `euiAnimate` methods to make them available through this component's `ref` + const euiAnimate = useCallback(() => { + bellRef.current?.euiAnimate(); + cheerRef.current?.euiAnimate(); + }, []); + + // we're using the `useImperativeHandle` which allows the child to expose a function to the parent + // this way we can trigger the animations on both child components: `bellRef` and `cheerRef` + useImperativeHandle( + ref, + () => ({ + euiAnimate, + }), + [euiAnimate] + ); + + const bellButton = ( + + + + ); + + const cheerButton = ( + + + + ); + + return ( + <> + {bellButton} + {cheerButton} + + ); + } +); +HeaderUpdates.displayName = 'HeaderUpdates'; + +export default () => { + const [showNotification, setShowNotification] = useState(false); + const headerUpdatesRef = useRef(); + const [notificationsNumber, setNotificationsNumber] = useState(0); + + const notify = () => { + if (!showNotification) { + setNotificationsNumber(1); + setShowNotification(true); + } else { + setNotificationsNumber(notificationsNumber + 1); + } + + headerUpdatesRef.current?.euiAnimate(); + }; + + return ( + <> + + + + Notify & animate + + + + + { + setShowNotification(false); + setNotificationsNumber(0); + }}> + Reset + + + + + + + Elastic], + borders: 'none', + }, + { + items: [ + , + ], + borders: 'none', + }, + ]} + /> + + ); +}; diff --git a/src-docs/src/views/header/header_example.js b/src-docs/src/views/header/header_example.js index 2a674e0ddd8..6143beaa5ef 100644 --- a/src-docs/src/views/header/header_example.js +++ b/src-docs/src/views/header/header_example.js @@ -37,6 +37,10 @@ import HeaderAlert from './header_alert'; const headerAlertSource = require('!!raw-loader!./header_alert'); const headerAlertHtml = renderToHtml(HeaderAlert); +import HeaderAnimate from './header_animate'; +const headerAnimateSource = require('!!raw-loader!./header_animate'); +const headerAnimateHtml = renderToHtml(HeaderAnimate); + import HeaderLinks from './header_links'; const headerLinksSource = require('!!raw-loader!./header_links'); const headerLinksHtml = renderToHtml(HeaderLinks); @@ -67,7 +71,8 @@ const headerSnippet = ` -`; + +`; const headerSectionsSnippet = ` `; +const headerAlertSnippet = ` + + + + + + + + + + + + + + +`; + +const headerAnimateSnippet = `const bellRef = useRef(); + +// wrapping the 'euiAnimate' methods to make them available through this component's 'ref' +const euiAnimate = useCallback(() => { + bellRef.current?.euiAnimate(); +}, []); + +// we're using the useImperativeHandle which allows the child to expose a function to the parent +useImperativeHandle( + ref, + () => ({ + euiAnimate, + }), + [euiAnimate] +); + +const bellButton = ( + + + +);`; + export const HeaderExample = { title: 'Header', sections: [ @@ -313,16 +366,59 @@ export const HeaderExample = {

The example below shows how to incorporate{' '} - EuiHeaderAlert components to show a list of - updates. + EuiHeaderAlert components to show a list of updates + inside a{' '} + + EuiFlyout + {' '} + and a{' '} + + EuiPopover + {' '} + .

), props: { EuiHeaderAlert, + EuiHeaderSectionItemButton, }, + snippet: headerAlertSnippet, demo: , }, + { + title: 'Header notifications', + source: [ + { + type: GuideSectionTypes.JS, + code: headerAnimateSource, + }, + { + type: GuideSectionTypes.HTML, + code: headerAnimateHtml, + }, + ], + text: ( + <> +

+ To alert or notify users about the additional information they are + receiving, use the EuiHeaderSectionItemButton{' '} + notification prop. You can pass a{' '} + node that will render inside a{' '} + EuiBadgeNotification or pass{' '} + true to render a simple dot. You can also animate + the button by calling the euiAnimate() method on + the EuiHeaderSectionItemButton{' '} + ref. +

+ + ), + props: { + EuiHeaderSectionItemButton, + }, + snippet: headerAnimateSnippet, + demo: , + }, { title: 'Stacked headers', source: [ diff --git a/src/components/header/_mixins.scss b/src/components/header/_mixins.scss index b693f759d2b..129edf89532 100644 --- a/src/components/header/_mixins.scss +++ b/src/components/header/_mixins.scss @@ -4,7 +4,7 @@ .euiHeaderLogo__text, .euiHeaderLink, - .euiHeaderSectionItem__button { + .euiHeaderSectionItemButton { color: $euiColorGhost; } @@ -20,7 +20,7 @@ .euiHeaderLogo, .euiHeaderLink, - .euiHeaderSectionItem__button { + .euiHeaderSectionItemButton { &:hover { background: transparentize(lightOrDarkTheme($euiColorDarkShade, $euiColorLightestShade), .5); } diff --git a/src/components/header/header_links/__snapshots__/header_links.test.tsx.snap b/src/components/header/header_links/__snapshots__/header_links.test.tsx.snap index aa42a20fce1..f64ef0db596 100644 --- a/src/components/header/header_links/__snapshots__/header_links.test.tsx.snap +++ b/src/components/header/header_links/__snapshots__/header_links.test.tsx.snap @@ -80,12 +80,16 @@ exports[`EuiHeaderLinks popover props is rendered 1`] = ` > diff --git a/src/components/header/header_section/__snapshots__/header_section_item_button.test.tsx.snap b/src/components/header/header_section/__snapshots__/header_section_item_button.test.tsx.snap index a8f3b53c283..f90543d19f9 100644 --- a/src/components/header/header_section/__snapshots__/header_section_item_button.test.tsx.snap +++ b/src/components/header/header_section/__snapshots__/header_section_item_button.test.tsx.snap @@ -3,28 +3,39 @@ exports[`EuiHeaderSectionItemButton is rendered 1`] = ` `; exports[`EuiHeaderSectionItemButton renders children 1`] = ` `; exports[`EuiHeaderSectionItemButton renders notification as a badge 1`] = ` ); } diff --git a/src/components/header/index.ts b/src/components/header/index.ts index 7d1b5f7058d..6c1276d0612 100644 --- a/src/components/header/index.ts +++ b/src/components/header/index.ts @@ -31,4 +31,5 @@ export { EuiHeaderSection, EuiHeaderSectionItem, EuiHeaderSectionItemButton, + EuiHeaderSectionItemButtonProps, } from './header_section';