From aaa6c8c7a3dd863fbcebf7a1d1e7dff9e7fad438 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Thu, 19 Sep 2019 15:10:16 +0200 Subject: [PATCH 01/12] feat(SideNavigation): Initial Component Implementation --- .../SideNavigation/SideNavigation.jss.ts | 35 + .../SideNavigation/SideNavigation.test.tsx | 103 +++ .../SideNavigation.test.tsx.snap | 664 ++++++++++++++++++ .../SideNavigation/demo.stories.tsx | 38 + .../src/components/SideNavigation/index.tsx | 106 +++ .../SideNavigationListItem.jss.ts | 57 ++ .../SideNavigationListItem/index.tsx | 174 +++++ .../main/src/enums/SideNavigationOpenState.ts | 5 + packages/main/src/index.ts | 6 + packages/main/src/lib/SideNavigation.ts | 3 + .../main/src/lib/SideNavigationListItem.ts | 3 + .../main/src/lib/SideNavigationOpenState.ts | 3 + 12 files changed, 1197 insertions(+) create mode 100644 packages/main/src/components/SideNavigation/SideNavigation.jss.ts create mode 100644 packages/main/src/components/SideNavigation/SideNavigation.test.tsx create mode 100644 packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap create mode 100644 packages/main/src/components/SideNavigation/demo.stories.tsx create mode 100644 packages/main/src/components/SideNavigation/index.tsx create mode 100644 packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts create mode 100644 packages/main/src/components/SideNavigationListItem/index.tsx create mode 100644 packages/main/src/enums/SideNavigationOpenState.ts create mode 100644 packages/main/src/lib/SideNavigation.ts create mode 100644 packages/main/src/lib/SideNavigationListItem.ts create mode 100644 packages/main/src/lib/SideNavigationOpenState.ts diff --git a/packages/main/src/components/SideNavigation/SideNavigation.jss.ts b/packages/main/src/components/SideNavigation/SideNavigation.jss.ts new file mode 100644 index 00000000000..8e0f5956563 --- /dev/null +++ b/packages/main/src/components/SideNavigation/SideNavigation.jss.ts @@ -0,0 +1,35 @@ +import { JSSTheme } from '../../interfaces/JSSTheme'; + +export const sideNavigationStyles = ({ parameters }: JSSTheme) => ({ + sideNavigation: { + height: '1000px', + borderRight: `0.0625rem solid ${parameters.sapUiGroupContentBorderColor}`, + backgroundColor: parameters.sapUiListBackground, + display: 'flex', + flexDirection: 'column', + transition: 'width 500ms' + }, + + expanded: { + width: '15rem' + }, + + condensed: { + width: '2.75rem', + '& $footerItemsSeparator': { + marginLeft: '0.5rem', + marginRight: '0.5rem' + } + }, + + collapsed: { + width: '15rem', + marginLeft: '-15.0625rem' + }, + + footerItemsSeparator: { + margin: '0.25rem 0.875rem', + height: '0.125rem', + backgroundColor: parameters.sapUiListBorderColor + } +}); diff --git a/packages/main/src/components/SideNavigation/SideNavigation.test.tsx b/packages/main/src/components/SideNavigation/SideNavigation.test.tsx new file mode 100644 index 00000000000..f15152da76b --- /dev/null +++ b/packages/main/src/components/SideNavigation/SideNavigation.test.tsx @@ -0,0 +1,103 @@ +import { mountThemedComponent } from '@shared/tests/utils'; +import { SideNavigation } from '@ui5/webcomponents-react/lib/SideNavigation'; +import { SideNavigationListItem } from '@ui5/webcomponents-react/lib/SideNavigationListItem'; +import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; +import React from 'react'; + +describe('SideNavigation', () => { + test('Expanded', () => { + const wrapper = mountThemedComponent( + , + + ]} + > + + + + + + + + + + + ); + expect(wrapper.render()).toMatchSnapshot(); + }); + + test('Expanded without Icons', () => { + const wrapper = mountThemedComponent( + , + + ]} + > + + + + + + + + + + + ); + expect(wrapper.render()).toMatchSnapshot(); + }); + + test('Condensed', () => { + const wrapper = mountThemedComponent( + , + + ]} + > + + + + + + + + + + + ); + expect(wrapper.render()).toMatchSnapshot(); + }); + test('Collapsed', () => { + const wrapper = mountThemedComponent( + , + + ]} + > + + + + + + + + + + + ); + expect(wrapper.render()).toMatchSnapshot(); + }); +}); diff --git a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap new file mode 100644 index 00000000000..6b185cf6741 --- /dev/null +++ b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap @@ -0,0 +1,664 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SideNavigation Collapsed 1`] = ` +
+ + + + + + + + + + + +
+ +
+ + + + My Opportunities + + + My Leads + + + My CPQS + + + +
+ + + + + + + + + + + + + + + +
+`; + +exports[`SideNavigation Condensed 1`] = ` +
+ + + + + + + + + + + +
+ +
+ + + + My Opportunities + + + My Leads + + + My CPQS + + + +
+ + + + + + + + + + + + + + + +
+`; + +exports[`SideNavigation Expanded 1`] = ` +
+ + + + + Overview + + + + + + Calendar + + + + + + Customers + + + + + + Sales + + + + + + + My Opportunities + + + + + + My Leads + + + + + + My CPQS + + + + + + Deliveries + + + + + + + + + + Legal Information + + + + + + Useful Links + + + +
+`; + +exports[`SideNavigation Expanded without Icons 1`] = ` +
+ + + + Overview + + + + + Calendar + + + + + Customers + + + + + Sales + + + + + + My Opportunities + + + + + My Leads + + + + + My CPQS + + + + + Deliveries + + + + + + + + + Legal Information + + + + + Useful Links + + + +
+`; diff --git a/packages/main/src/components/SideNavigation/demo.stories.tsx b/packages/main/src/components/SideNavigation/demo.stories.tsx new file mode 100644 index 00000000000..778657c8f4b --- /dev/null +++ b/packages/main/src/components/SideNavigation/demo.stories.tsx @@ -0,0 +1,38 @@ +import { action } from '@storybook/addon-actions'; +import { select, text, boolean } from '@storybook/addon-knobs'; +import { SideNavigation } from '@ui5/webcomponents-react/lib/SideNavigation'; +import { SideNavigationListItem } from '@ui5/webcomponents-react/lib/SideNavigationListItem'; +import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; +import React from 'react'; + +export const defaultStory = () => ( + , + + ]} + > + + + + + + + + + + +); + +defaultStory.story = { + name: 'Default' +}; + +export default { + title: 'Components | SideNavigation', + component: SideNavigation +}; diff --git a/packages/main/src/components/SideNavigation/index.tsx b/packages/main/src/components/SideNavigation/index.tsx new file mode 100644 index 00000000000..691ca652283 --- /dev/null +++ b/packages/main/src/components/SideNavigation/index.tsx @@ -0,0 +1,106 @@ +import { Event, StyleClassHelper } from '@ui5/webcomponents-react-base'; +import { List } from '@ui5/webcomponents-react/lib/List'; +import { ListMode } from '@ui5/webcomponents-react/lib/ListMode'; +import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; +import React, { Children, cloneElement, FC, forwardRef, ReactNode, Ref, useEffect, useState, useCallback } from 'react'; +import { createUseStyles } from 'react-jss'; +import { CommonProps } from '../../interfaces/CommonProps'; +import { JSSTheme } from '../../interfaces/JSSTheme'; +import { sideNavigationStyles } from './SideNavigation.jss'; + +export interface SideNavigationProps extends CommonProps { + openState?: SideNavigationOpenState; + children?: ReactNode; + footerItems?: ReactNode[]; + selectedId?: string | number; + onItemSelect?: (event: Event) => void; + noIcons?: boolean; +} + +const useStyles = createUseStyles>(sideNavigationStyles); + +const SideNavigation: FC = forwardRef((props: SideNavigationProps, ref: Ref) => { + const { children, openState, footerItems, selectedId, onItemSelect, noIcons } = props; + + const classes = useStyles(); + + const [internalSelectedId, setInternalSelectedId] = useState(selectedId); + + useEffect(() => { + setInternalSelectedId(selectedId); + }, [selectedId, setInternalSelectedId]); + + const sideNavigationClasses = StyleClassHelper.of(classes.sideNavigation); + + switch (openState) { + case SideNavigationOpenState.Expanded: { + sideNavigationClasses.put(classes.expanded); + break; + } + case SideNavigationOpenState.Condensed: { + sideNavigationClasses.put(classes.condensed); + break; + } + case SideNavigationOpenState.Collapsed: { + sideNavigationClasses.put(classes.collapsed); + break; + } + } + + const onListItemSelected = useCallback( + (e) => { + const listItem = e.getParameter('item'); + if (listItem.dataset.hasChildren === 'true') { + return; + } + + setInternalSelectedId(listItem.dataset.id); + onItemSelect( + Event.of(null, e, { + selectedItem: listItem + }) + ); + }, + [onItemSelect, setInternalSelectedId] + ); + + return ( +
+ + {Children.map(children, (child: any) => + cloneElement(child, { + openState: openState, + selectedId: internalSelectedId, + onListItemSelected, + noIcons + }) + )} + + + {footerItems.length && } + {footerItems && ( + + {footerItems.map((item: any, index) => + cloneElement(item, { + openState: openState, + key: index, + selectedId: internalSelectedId, + onListItemSelected, + noIcons + }) + )} + + )} +
+ ); +}); + +SideNavigation.displayName = 'SideNavigation'; + +SideNavigation.defaultProps = { + openState: SideNavigationOpenState.Expanded, + footerItems: [], + selectedId: null +}; + +export { SideNavigation }; diff --git a/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts new file mode 100644 index 00000000000..eae57b8ca3b --- /dev/null +++ b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts @@ -0,0 +1,57 @@ +import { JSSTheme } from '../../interfaces/JSSTheme'; + +export const sideNavigationListItemStyles = ({ parameters }: JSSTheme) => ({ + listItem: {}, + + noIcons: { + '& $text': { + paddingLeft: '1rem' + }, + '&[data-is-child] $text': { + paddingLeft: '2rem' + }, + boxSizing: 'border-box' + }, + + icon: { + '--sapUiContentNonInteractiveIconColor': parameters.sapUiContentIconColor, + fontSize: '1.125rem', + width: '2.75rem', + height: '2.75rem' + }, + + text: {}, + + expandArrow: { + '--sapUiContentNonInteractiveIconColor': parameters.sapUiContentIconColor, + fontSize: '0.875rem', + width: '2.5rem', + height: '2.5rem', + marginLeft: 'auto' + }, + + expanded: { + '--ui5-listitem-border-bottom': 'none' + }, + + compact: { + '& $icon': { + fontSize: '1rem', + height: '2rem' + }, + '& $expandArrow': { + height: '2rem' + } + }, + + condensedExpandTriangle: { + width: '0', + height: '0', + borderStyle: 'solid', + borderWidth: '0 0 6px 6px', + borderColor: `transparent transparent ${parameters.sapUiContentIconColor} transparent`, + position: 'absolute', + right: '0.125rem', + bottom: '0.1875rem' + } +}); diff --git a/packages/main/src/components/SideNavigationListItem/index.tsx b/packages/main/src/components/SideNavigationListItem/index.tsx new file mode 100644 index 00000000000..fbc63bf0430 --- /dev/null +++ b/packages/main/src/components/SideNavigationListItem/index.tsx @@ -0,0 +1,174 @@ +import { StyleClassHelper } from '@ui5/webcomponents-react-base'; +import { ContentDensity } from '@ui5/webcomponents-react/lib/ContentDensity'; +import { CustomListItem } from '@ui5/webcomponents-react/lib/CustomListItem'; +import { Icon } from '@ui5/webcomponents-react/lib/Icon'; +import { List } from '@ui5/webcomponents-react/lib/List'; +import { Popover } from '@ui5/webcomponents-react/lib/Popover'; +import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; +import { StandardListItem } from '@ui5/webcomponents-react/lib/StandardListItem'; +import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; +import { Text } from '@ui5/webcomponents-react/lib/Text'; +import React, { + Children, + cloneElement, + FC, + forwardRef, + ReactNode, + ReactNodeArray, + Ref, + useCallback, + useEffect, + useState +} from 'react'; +import { createUseStyles, useTheme } from 'react-jss'; +import { CommonProps } from '../../interfaces/CommonProps'; +import { JSSTheme } from '../../interfaces/JSSTheme'; +import { sideNavigationListItemStyles } from './SideNavigationListItem.jss'; + +export interface SideNavigationListItemProps extends CommonProps { + icon?: string; + text: string; + id: number | string; + children?: ReactNode | ReactNodeArray; +} + +const useStyles = createUseStyles>( + sideNavigationListItemStyles +); +const SideNavigationListItem: FC = forwardRef( + (props: SideNavigationListItemProps, ref: Ref) => { + const { icon, text, id, children, tooltip, slot, className, style } = props; + + const [isExpanded, setExpanded] = useState(false); + + const handleToggleExpand = useCallback(() => { + setExpanded(!isExpanded); + }, [isExpanded, setExpanded]); + + const classes = useStyles(); + const theme = useTheme() as JSSTheme; + + const listItemClasses = StyleClassHelper.of(classes.listItem); + if (theme.contentDensity === ContentDensity.Compact) { + listItemClasses.put(classes.compact); + } + + if (className) { + listItemClasses.put(className); + } + + if (isExpanded) { + listItemClasses.put(classes.expanded); + } + + const noIcons = props['noIcons']; + if (noIcons) { + listItemClasses.put(classes.noIcons); + } + + const childCount = Children.count(children); + const validChildren = Children.toArray(children).filter(Boolean); + + const isOpenStateExpanded = props['openState'] === SideNavigationOpenState.Expanded; + + useEffect(() => { + if (validChildren.length) { + const selectedElement = validChildren.find((child: any) => child.props.id === props['selectedId']); + if (selectedElement) { + setExpanded(isOpenStateExpanded); + } + } + }, [props['selectedId'], id, children, setExpanded, isOpenStateExpanded]); + + const isSelfSelected = props['selectedId'] === id; + const hasSelectedChild = + !isOpenStateExpanded && + childCount > 0 && + !!validChildren.find((child: any) => child.props.id === props['selectedId']); + + const onPopoverListItemSelect = useCallback( + (e) => { + props['onListItemSelected'](e); + e.getOriginalEvent().preventDefault(); + e.getOriginalEvent().stopPropagation(); + e.getOriginalEvent().stopImmediatePropagation(); + }, + [props['onListItemSelected']] + ); + + return ( + <> + 0} + data-is-child={props['isChild']} + > + {(isOpenStateExpanded || childCount === 0) && icon && !noIcons && ( + + )} + {!isOpenStateExpanded && icon && childCount > 0 && !noIcons && ( + } + > + + {validChildren.map((child: any, index) => { + return ( + + {child.props.text} + + ); + })} + + + )} + {!isOpenStateExpanded && icon && childCount > 0 &&
} + {!icon && !noIcons && } + {isOpenStateExpanded && {text}} + {isOpenStateExpanded && childCount > 0 && ( + + )} + + {isOpenStateExpanded && + isExpanded && + validChildren.map((child: any, index: number) => { + const style = child.props.style || {}; + if (index !== childCount - 1) { + style['--ui5-listitem-border-bottom'] = 'none'; + } + + return cloneElement(child, { + icon: null, + style, + openState: props['openState'], + selectedId: props['selectedId'], + noIcons, + isChild: true + }); + })} + + ); + } +); + +SideNavigationListItem.displayName = 'SideNavigationListItem'; + +SideNavigationListItem.defaultProps = {}; + +export { SideNavigationListItem }; diff --git a/packages/main/src/enums/SideNavigationOpenState.ts b/packages/main/src/enums/SideNavigationOpenState.ts new file mode 100644 index 00000000000..18ba6e703b0 --- /dev/null +++ b/packages/main/src/enums/SideNavigationOpenState.ts @@ -0,0 +1,5 @@ +export enum SideNavigationOpenState { + Expanded = 'Expanded', + Condensed = 'Condensed', + Collapsed = 'Collapsed' +} diff --git a/packages/main/src/index.ts b/packages/main/src/index.ts index 2de90f59449..ac807763ad3 100644 --- a/packages/main/src/index.ts +++ b/packages/main/src/index.ts @@ -78,6 +78,9 @@ import { Select } from './lib/Select'; import { SemanticColor } from './lib/SemanticColor'; import { ShellBar } from './lib/ShellBar'; import { ShellBarItem } from './lib/ShellBarItem'; +import { SideNavigation } from './lib/SideNavigation'; +import { SideNavigationListItem } from './lib/SideNavigationListItem'; +import { SideNavigationOpenState } from './lib/SideNavigationOpenState'; import { Size } from './lib/Size'; import { Spinner } from './lib/Spinner'; import { StandardListItem } from './lib/StandardListItem'; @@ -182,6 +185,9 @@ export { SemanticColor, ShellBar, ShellBarItem, + SideNavigation, + SideNavigationListItem, + SideNavigationOpenState, Size, Spinner, StandardListItem, diff --git a/packages/main/src/lib/SideNavigation.ts b/packages/main/src/lib/SideNavigation.ts new file mode 100644 index 00000000000..922493895be --- /dev/null +++ b/packages/main/src/lib/SideNavigation.ts @@ -0,0 +1,3 @@ +import { SideNavigation } from '../components/SideNavigation'; + +export { SideNavigation }; diff --git a/packages/main/src/lib/SideNavigationListItem.ts b/packages/main/src/lib/SideNavigationListItem.ts new file mode 100644 index 00000000000..d2f6c8916cb --- /dev/null +++ b/packages/main/src/lib/SideNavigationListItem.ts @@ -0,0 +1,3 @@ +import { SideNavigationListItem } from '../components/SideNavigationListItem'; + +export { SideNavigationListItem }; diff --git a/packages/main/src/lib/SideNavigationOpenState.ts b/packages/main/src/lib/SideNavigationOpenState.ts new file mode 100644 index 00000000000..e9ffcc3d00c --- /dev/null +++ b/packages/main/src/lib/SideNavigationOpenState.ts @@ -0,0 +1,3 @@ +import { SideNavigationOpenState } from '../enums/SideNavigationOpenState'; + +export { SideNavigationOpenState }; From 296777b47ffbda6e6424527caeaa125fdbf4b1ee Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 11:29:45 +0200 Subject: [PATCH 02/12] WIP: Fixed Active Icon and Text Color --- .../SideNavigationListItem/SideNavigationListItem.jss.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts index eae57b8ca3b..e84cb387bde 100644 --- a/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts +++ b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts @@ -1,7 +1,14 @@ import { JSSTheme } from '../../interfaces/JSSTheme'; export const sideNavigationListItemStyles = ({ parameters }: JSSTheme) => ({ - listItem: {}, + listItem: { + '&:active': { + '--sapUiBaseText': parameters.sapUiListActiveTextColor, + '& $icon': { + '--sapUiContentNonInteractiveIconColor': parameters.sapUiListActiveTextColor + } + } + }, noIcons: { '& $text': { From 304d330601174f0b8050b1b6a4f5e39a6ebe7c24 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 12:05:14 +0200 Subject: [PATCH 03/12] WIP: Fixed Styles --- .../SideNavigation/SideNavigation.jss.ts | 2 +- .../components/SideNavigation/demo.stories.tsx | 1 + .../src/components/SideNavigation/index.tsx | 17 +++++++++++++---- .../components/SideNavigationListItem/index.tsx | 5 +++-- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/main/src/components/SideNavigation/SideNavigation.jss.ts b/packages/main/src/components/SideNavigation/SideNavigation.jss.ts index 8e0f5956563..6c51aa1f82d 100644 --- a/packages/main/src/components/SideNavigation/SideNavigation.jss.ts +++ b/packages/main/src/components/SideNavigation/SideNavigation.jss.ts @@ -2,7 +2,7 @@ import { JSSTheme } from '../../interfaces/JSSTheme'; export const sideNavigationStyles = ({ parameters }: JSSTheme) => ({ sideNavigation: { - height: '1000px', + height: '100%', borderRight: `0.0625rem solid ${parameters.sapUiGroupContentBorderColor}`, backgroundColor: parameters.sapUiListBackground, display: 'flex', diff --git a/packages/main/src/components/SideNavigation/demo.stories.tsx b/packages/main/src/components/SideNavigation/demo.stories.tsx index 778657c8f4b..1f50d8698aa 100644 --- a/packages/main/src/components/SideNavigation/demo.stories.tsx +++ b/packages/main/src/components/SideNavigation/demo.stories.tsx @@ -11,6 +11,7 @@ export const defaultStory = () => ( selectedId={text('selectedId', 'sales-leads')} onItemSelect={action('onItemSelect')} noIcons={boolean('noIcons', false)} + style={{ height: '900px' }} footerItems={[ , diff --git a/packages/main/src/components/SideNavigation/index.tsx b/packages/main/src/components/SideNavigation/index.tsx index 691ca652283..25f139b9cbe 100644 --- a/packages/main/src/components/SideNavigation/index.tsx +++ b/packages/main/src/components/SideNavigation/index.tsx @@ -2,7 +2,7 @@ import { Event, StyleClassHelper } from '@ui5/webcomponents-react-base'; import { List } from '@ui5/webcomponents-react/lib/List'; import { ListMode } from '@ui5/webcomponents-react/lib/ListMode'; import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; -import React, { Children, cloneElement, FC, forwardRef, ReactNode, Ref, useEffect, useState, useCallback } from 'react'; +import React, { Children, cloneElement, FC, forwardRef, ReactNode, Ref, useCallback, useEffect, useState } from 'react'; import { createUseStyles } from 'react-jss'; import { CommonProps } from '../../interfaces/CommonProps'; import { JSSTheme } from '../../interfaces/JSSTheme'; @@ -20,7 +20,7 @@ export interface SideNavigationProps extends CommonProps { const useStyles = createUseStyles>(sideNavigationStyles); const SideNavigation: FC = forwardRef((props: SideNavigationProps, ref: Ref) => { - const { children, openState, footerItems, selectedId, onItemSelect, noIcons } = props; + const { children, openState, footerItems, selectedId, onItemSelect, noIcons, style, className } = props; const classes = useStyles(); @@ -47,10 +47,19 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio } } + if (className) { + sideNavigationClasses.put(className); + } + const onListItemSelected = useCallback( (e) => { const listItem = e.getParameter('item'); if (listItem.dataset.hasChildren === 'true') { + if (openState === SideNavigationOpenState.Condensed) { + requestAnimationFrame(() => { + listItem.selected = false; + }); + } return; } @@ -61,11 +70,11 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio }) ); }, - [onItemSelect, setInternalSelectedId] + [onItemSelect, setInternalSelectedId, openState] ); return ( -
+
{Children.map(children, (child: any) => cloneElement(child, { diff --git a/packages/main/src/components/SideNavigationListItem/index.tsx b/packages/main/src/components/SideNavigationListItem/index.tsx index fbc63bf0430..ff96ca46063 100644 --- a/packages/main/src/components/SideNavigationListItem/index.tsx +++ b/packages/main/src/components/SideNavigationListItem/index.tsx @@ -4,9 +4,9 @@ import { CustomListItem } from '@ui5/webcomponents-react/lib/CustomListItem'; import { Icon } from '@ui5/webcomponents-react/lib/Icon'; import { List } from '@ui5/webcomponents-react/lib/List'; import { Popover } from '@ui5/webcomponents-react/lib/Popover'; +import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; import { StandardListItem } from '@ui5/webcomponents-react/lib/StandardListItem'; -import { PopoverVerticalAlign } from '@ui5/webcomponents-react/lib/PopoverVerticalAlign'; import { Text } from '@ui5/webcomponents-react/lib/Text'; import React, { Children, @@ -21,6 +21,7 @@ import React, { useState } from 'react'; import { createUseStyles, useTheme } from 'react-jss'; +import { ListItemTypes } from '../..'; import { CommonProps } from '../../interfaces/CommonProps'; import { JSSTheme } from '../../interfaces/JSSTheme'; import { sideNavigationListItemStyles } from './SideNavigationListItem.jss'; @@ -99,7 +100,7 @@ const SideNavigationListItem: FC = forwardRef( return ( <> 0 ? hasSelectedChild : isSelfSelected} ref={ref} className={listItemClasses.valueOf()} tooltip={tooltip} From 1979d912fec105f39ad10edefc8dd939affc0996 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 12:11:25 +0200 Subject: [PATCH 04/12] WIP: Fixed Selection --- packages/main/src/components/SideNavigation/index.tsx | 10 ++-------- .../src/components/SideNavigationListItem/index.tsx | 1 - 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/main/src/components/SideNavigation/index.tsx b/packages/main/src/components/SideNavigation/index.tsx index 25f139b9cbe..6aa2d0093ea 100644 --- a/packages/main/src/components/SideNavigation/index.tsx +++ b/packages/main/src/components/SideNavigation/index.tsx @@ -1,6 +1,5 @@ import { Event, StyleClassHelper } from '@ui5/webcomponents-react-base'; import { List } from '@ui5/webcomponents-react/lib/List'; -import { ListMode } from '@ui5/webcomponents-react/lib/ListMode'; import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; import React, { Children, cloneElement, FC, forwardRef, ReactNode, Ref, useCallback, useEffect, useState } from 'react'; import { createUseStyles } from 'react-jss'; @@ -55,11 +54,6 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio (e) => { const listItem = e.getParameter('item'); if (listItem.dataset.hasChildren === 'true') { - if (openState === SideNavigationOpenState.Condensed) { - requestAnimationFrame(() => { - listItem.selected = false; - }); - } return; } @@ -75,7 +69,7 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio return (
- + {Children.map(children, (child: any) => cloneElement(child, { openState: openState, @@ -88,7 +82,7 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio {footerItems.length && } {footerItems && ( - + {footerItems.map((item: any, index) => cloneElement(item, { openState: openState, diff --git a/packages/main/src/components/SideNavigationListItem/index.tsx b/packages/main/src/components/SideNavigationListItem/index.tsx index ff96ca46063..23c1a17c3da 100644 --- a/packages/main/src/components/SideNavigationListItem/index.tsx +++ b/packages/main/src/components/SideNavigationListItem/index.tsx @@ -21,7 +21,6 @@ import React, { useState } from 'react'; import { createUseStyles, useTheme } from 'react-jss'; -import { ListItemTypes } from '../..'; import { CommonProps } from '../../interfaces/CommonProps'; import { JSSTheme } from '../../interfaces/JSSTheme'; import { sideNavigationListItemStyles } from './SideNavigationListItem.jss'; From 398c61ffef0d6dbfa19f838741f3d7bd25c35e09 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 12:20:55 +0200 Subject: [PATCH 05/12] WIP: Added netlify config --- netlify.toml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 netlify.toml diff --git a/netlify.toml b/netlify.toml new file mode 100644 index 00000000000..3b4414c7ce8 --- /dev/null +++ b/netlify.toml @@ -0,0 +1,19 @@ +# Settings in the [build] context are global and are applied to all contexts +# unless otherwise overridden by more specific contexts. +[build] + # Directory to change to before starting a build. + # This is where we will look for package.json/.nvmrc/etc. + base = "./" + + # Directory (relative to root of your repo) that contains the deploy-ready + # HTML files and assets generated by the build. If a base directory has + # been specified, include it in the publish directory path. + publish = ".out/" + + # Default build command. + command = "npm run build:storybook" + +# Deploy Preview context: all deploys generated from a pull/merge request will +# inherit these settings. +[context.deploy-preview] + SKIP_DOC_GENERATION=true From e9fc1546e82f786429eb8245126e052f74f8400b Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 12:25:04 +0200 Subject: [PATCH 06/12] WIP: Store last fired selection in order to prevent duplicates --- .../main/src/components/SideNavigation/index.tsx | 11 ++++++++--- .../src/components/SideNavigationListItem/index.tsx | 12 +----------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/main/src/components/SideNavigation/index.tsx b/packages/main/src/components/SideNavigation/index.tsx index 6aa2d0093ea..f357e53366d 100644 --- a/packages/main/src/components/SideNavigation/index.tsx +++ b/packages/main/src/components/SideNavigation/index.tsx @@ -16,6 +16,8 @@ export interface SideNavigationProps extends CommonProps { noIcons?: boolean; } +let lastFiredSelection = ''; + const useStyles = createUseStyles>(sideNavigationStyles); const SideNavigation: FC = forwardRef((props: SideNavigationProps, ref: Ref) => { @@ -57,14 +59,19 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio return; } + if (lastFiredSelection === listItem.dataset.id) { + return; + } + setInternalSelectedId(listItem.dataset.id); onItemSelect( Event.of(null, e, { selectedItem: listItem }) ); + lastFiredSelection = listItem.dataset.id; }, - [onItemSelect, setInternalSelectedId, openState] + [onItemSelect, setInternalSelectedId] ); return ( @@ -74,7 +81,6 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio cloneElement(child, { openState: openState, selectedId: internalSelectedId, - onListItemSelected, noIcons }) )} @@ -88,7 +94,6 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio openState: openState, key: index, selectedId: internalSelectedId, - onListItemSelected, noIcons }) )} diff --git a/packages/main/src/components/SideNavigationListItem/index.tsx b/packages/main/src/components/SideNavigationListItem/index.tsx index 23c1a17c3da..672174b801e 100644 --- a/packages/main/src/components/SideNavigationListItem/index.tsx +++ b/packages/main/src/components/SideNavigationListItem/index.tsx @@ -86,16 +86,6 @@ const SideNavigationListItem: FC = forwardRef( childCount > 0 && !!validChildren.find((child: any) => child.props.id === props['selectedId']); - const onPopoverListItemSelect = useCallback( - (e) => { - props['onListItemSelected'](e); - e.getOriginalEvent().preventDefault(); - e.getOriginalEvent().stopPropagation(); - e.getOriginalEvent().stopImmediatePropagation(); - }, - [props['onListItemSelected']] - ); - return ( <> = forwardRef( verticalAlign={PopoverVerticalAlign.Top} openBy={} > - + {validChildren.map((child: any, index) => { return ( Date: Fri, 20 Sep 2019 12:27:13 +0200 Subject: [PATCH 07/12] WIP: Updated test snapshots --- .../__snapshots__/SideNavigation.test.tsx.snap | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap index 6b185cf6741..c8892780c37 100644 --- a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap +++ b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap @@ -8,7 +8,7 @@ exports[`SideNavigation Collapsed 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -128,7 +128,7 @@ exports[`SideNavigation Collapsed 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -164,7 +164,7 @@ exports[`SideNavigation Condensed 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -284,7 +284,7 @@ exports[`SideNavigation Condensed 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -320,7 +320,7 @@ exports[`SideNavigation Expanded 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -468,7 +468,7 @@ exports[`SideNavigation Expanded 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -514,7 +514,7 @@ exports[`SideNavigation Expanded without Icons 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > @@ -633,7 +633,7 @@ exports[`SideNavigation Expanded without Icons 1`] = ` class="" footer-text="" header-text="" - mode="SingleSelect" + mode="None" no-data-text="" separators="All" > From 90a4b2a58c10d4edc5e3af010fa8323b0709f13f Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 12:31:49 +0200 Subject: [PATCH 08/12] WIP: Add Component Name as styleclass prefix --- .../SideNavigation.test.tsx.snap | 180 +++++++++--------- .../src/components/SideNavigation/index.tsx | 4 +- .../SideNavigationListItem/index.tsx | 5 +- 3 files changed, 97 insertions(+), 92 deletions(-) diff --git a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap index c8892780c37..c049a38b30d 100644 --- a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap +++ b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap @@ -2,7 +2,7 @@ exports[`SideNavigation Collapsed 1`] = `
@@ -103,17 +103,17 @@ exports[`SideNavigation Collapsed 1`] = `
@@ -122,7 +122,7 @@ exports[`SideNavigation Collapsed 1`] = ` style="flex-grow: 1;" /> @@ -158,7 +158,7 @@ exports[`SideNavigation Collapsed 1`] = ` exports[`SideNavigation Condensed 1`] = `
@@ -259,17 +259,17 @@ exports[`SideNavigation Condensed 1`] = `
@@ -278,7 +278,7 @@ exports[`SideNavigation Condensed 1`] = ` style="flex-grow: 1;" /> @@ -314,7 +314,7 @@ exports[`SideNavigation Condensed 1`] = ` exports[`SideNavigation Expanded 1`] = `
Overview Calendar Customers Sales My Opportunities My Leads My CPQS Deliveries @@ -462,7 +462,7 @@ exports[`SideNavigation Expanded 1`] = ` style="flex-grow: 1;" /> Legal Information Useful Links @@ -508,7 +508,7 @@ exports[`SideNavigation Expanded 1`] = ` exports[`SideNavigation Expanded without Icons 1`] = `
Overview Calendar Customers Sales My Opportunities My Leads My CPQS Deliveries @@ -627,7 +627,7 @@ exports[`SideNavigation Expanded without Icons 1`] = ` style="flex-grow: 1;" /> Legal Information Useful Links diff --git a/packages/main/src/components/SideNavigation/index.tsx b/packages/main/src/components/SideNavigation/index.tsx index f357e53366d..1b0aa50aa2a 100644 --- a/packages/main/src/components/SideNavigation/index.tsx +++ b/packages/main/src/components/SideNavigation/index.tsx @@ -18,7 +18,9 @@ export interface SideNavigationProps extends CommonProps { let lastFiredSelection = ''; -const useStyles = createUseStyles>(sideNavigationStyles); +const useStyles = createUseStyles>(sideNavigationStyles, { + name: 'SideNavigation' +}); const SideNavigation: FC = forwardRef((props: SideNavigationProps, ref: Ref) => { const { children, openState, footerItems, selectedId, onItemSelect, noIcons, style, className } = props; diff --git a/packages/main/src/components/SideNavigationListItem/index.tsx b/packages/main/src/components/SideNavigationListItem/index.tsx index 672174b801e..9d62ed407d7 100644 --- a/packages/main/src/components/SideNavigationListItem/index.tsx +++ b/packages/main/src/components/SideNavigationListItem/index.tsx @@ -33,7 +33,10 @@ export interface SideNavigationListItemProps extends CommonProps { } const useStyles = createUseStyles>( - sideNavigationListItemStyles + sideNavigationListItemStyles, + { + name: 'SideNavigationListItem' + } ); const SideNavigationListItem: FC = forwardRef( (props: SideNavigationListItemProps, ref: Ref) => { From 576ee2ee854a6e40dbe7993fea6caf5a7356d048 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 13:27:56 +0200 Subject: [PATCH 09/12] WIP: Added Side Navigation List Item Test --- .../SideNavigationListItem.test.tsx | 33 ++++++++++++++ .../SideNavigationListItem.test.tsx.snap | 44 +++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 packages/main/src/components/SideNavigationListItem/SideNavigationListItem.test.tsx create mode 100644 packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap diff --git a/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.test.tsx b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.test.tsx new file mode 100644 index 00000000000..c154a189861 --- /dev/null +++ b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.test.tsx @@ -0,0 +1,33 @@ +import { mountThemedComponent } from '@shared/tests/utils'; +import { SideNavigation } from '@ui5/webcomponents-react/lib/SideNavigation'; +import { SideNavigationListItem } from '@ui5/webcomponents-react/lib/SideNavigationListItem'; +import { SideNavigationOpenState } from '@ui5/webcomponents-react/lib/SideNavigationOpenState'; +import React from 'react'; +import { ContentDensity } from '../..'; + +describe('SideNavigationListItem', () => { + test('Basic', () => { + const wrapper = mountThemedComponent(); + expect(wrapper.render()).toMatchSnapshot(); + }); + + test('custom class name and style', () => { + const wrapper = mountThemedComponent( + + ); + expect(wrapper.render()).toMatchSnapshot(); + }); + + test('compact size', () => { + const wrapper = mountThemedComponent(, { + contentDensity: ContentDensity.Compact + }); + expect(wrapper.render()).toMatchSnapshot(); + }); +}); diff --git a/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap b/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap new file mode 100644 index 00000000000..1b7f6f19aba --- /dev/null +++ b/packages/main/src/components/SideNavigationListItem/__snapshots__/SideNavigationListItem.test.tsx.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SideNavigationListItem Basic 1`] = ` + + + +`; + +exports[`SideNavigationListItem compact size 1`] = ` + + + +`; + +exports[`SideNavigationListItem custom class name and style 1`] = ` + + + +`; From 5bf75d6c6ef701ae01a95592e1a7744692b007bd Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 13:39:57 +0200 Subject: [PATCH 10/12] WIP: Fixed Expand Arrow Styling --- .../SideNavigationListItem/SideNavigationListItem.jss.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts index e84cb387bde..09a8ee5d909 100644 --- a/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts +++ b/packages/main/src/components/SideNavigationListItem/SideNavigationListItem.jss.ts @@ -4,7 +4,7 @@ export const sideNavigationListItemStyles = ({ parameters }: JSSTheme) => ({ listItem: { '&:active': { '--sapUiBaseText': parameters.sapUiListActiveTextColor, - '& $icon': { + '& $icon, & $expandArrow': { '--sapUiContentNonInteractiveIconColor': parameters.sapUiListActiveTextColor } } From 79bdd1b9fed6d627e188b0cb2ff69831a73e622b Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 16:06:45 +0200 Subject: [PATCH 11/12] WIP: Selection --- .../src/components/SideNavigation/demo.stories.tsx | 6 +++--- packages/main/src/components/SideNavigation/index.tsx | 11 +++++++++-- .../src/components/SideNavigationListItem/index.tsx | 7 +++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/main/src/components/SideNavigation/demo.stories.tsx b/packages/main/src/components/SideNavigation/demo.stories.tsx index 1f50d8698aa..d4f27f66f14 100644 --- a/packages/main/src/components/SideNavigation/demo.stories.tsx +++ b/packages/main/src/components/SideNavigation/demo.stories.tsx @@ -7,14 +7,14 @@ import React from 'react'; export const defaultStory = () => ( , - + , + ]} > diff --git a/packages/main/src/components/SideNavigation/index.tsx b/packages/main/src/components/SideNavigation/index.tsx index 1b0aa50aa2a..ef73543b33a 100644 --- a/packages/main/src/components/SideNavigation/index.tsx +++ b/packages/main/src/components/SideNavigation/index.tsx @@ -17,6 +17,7 @@ export interface SideNavigationProps extends CommonProps { } let lastFiredSelection = ''; +let lastParent = ''; const useStyles = createUseStyles>(sideNavigationStyles, { name: 'SideNavigation' @@ -57,14 +58,20 @@ const SideNavigation: FC = forwardRef((props: SideNavigatio const onListItemSelected = useCallback( (e) => { const listItem = e.getParameter('item'); - if (listItem.dataset.hasChildren === 'true') { + + if (lastFiredSelection === listItem.dataset.id) { return; } - if (lastFiredSelection === listItem.dataset.id) { + if (listItem.dataset.id === lastParent) { + lastParent = ''; return; } + if (listItem.dataset.parentId) { + lastParent = listItem.dataset.parentId; + } + setInternalSelectedId(listItem.dataset.id); onItemSelect( Event.of(null, e, { diff --git a/packages/main/src/components/SideNavigationListItem/index.tsx b/packages/main/src/components/SideNavigationListItem/index.tsx index 9d62ed407d7..34cc7e25cd5 100644 --- a/packages/main/src/components/SideNavigationListItem/index.tsx +++ b/packages/main/src/components/SideNavigationListItem/index.tsx @@ -92,7 +92,7 @@ const SideNavigationListItem: FC = forwardRef( return ( <> 0 ? hasSelectedChild : isSelfSelected} + selected={isSelfSelected || hasSelectedChild} ref={ref} className={listItemClasses.valueOf()} tooltip={tooltip} @@ -107,18 +107,21 @@ const SideNavigationListItem: FC = forwardRef( )} {!isOpenStateExpanded && icon && childCount > 0 && !noIcons && ( } > + + {text} + {validChildren.map((child: any, index) => { return ( {child.props.text} From beff729bb2d8dbbc7dfac9cb798d97eca6f052d9 Mon Sep 17 00:00:00 2001 From: MarcusNotheis Date: Fri, 20 Sep 2019 16:16:28 +0200 Subject: [PATCH 12/12] WIP: Updated Snapshot --- .../SideNavigation.test.tsx.snap | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap index c049a38b30d..25b48358443 100644 --- a/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap +++ b/packages/main/src/components/SideNavigation/__snapshots__/SideNavigation.test.tsx.snap @@ -62,7 +62,7 @@ exports[`SideNavigation Collapsed 1`] = `
+ + Sales + @@ -86,6 +95,7 @@ exports[`SideNavigation Collapsed 1`] = ` @@ -218,7 +229,7 @@ exports[`SideNavigation Condensed 1`] = `
+ + Sales + @@ -242,6 +262,7 @@ exports[`SideNavigation Condensed 1`] = `