From c67f634d0522fc344b25fb2e7cfa795fd30135c4 Mon Sep 17 00:00:00 2001 From: rubenthoms <69145689+rubenthoms@users.noreply.github.com> Date: Thu, 7 Oct 2021 14:28:23 +0200 Subject: [PATCH] Aligned text over multiple lines and improved auto-size. (#173) * Aligned text over multiple lines and improved auto-size. * Improved spacing in menu and changed color of section icon * Better alignment of elements in menu when some have an icon while others do not. * Implemented max and min width for menu. --- CHANGELOG.md | 5 +- react/src/demo/App.tsx | 2 +- react/src/lib/components/Menu/Menu.css | 21 ++++ react/src/lib/components/Menu/Menu.tsx | 49 +++++--- .../Menu/components/Group/Group.tsx | 16 ++- .../components/MenuContent/MenuContent.tsx | 113 ++++++++++-------- .../Menu/components/MenuDrawer/MenuDrawer.css | 1 - .../Menu/components/MenuDrawer/MenuDrawer.tsx | 1 + .../components/Menu/components/Page/Page.css | 1 - .../components/Menu/components/Page/Page.tsx | 18 ++- .../Menu/components/Section/Section.css | 4 + .../Menu/components/Section/Section.tsx | 16 ++- react/src/lib/components/Overlay/Overlay.css | 2 +- 13 files changed, 171 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 145ee6cf..0bc989d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [UNRELEASED] - YYYY-MM-DD ### Changed -- [#161](https://github.com/equinor/webviz-core-components/pull/161) - Updated to `Dash 2.0`. + +- [#161](https://github.com/equinor/webviz-core-components/pull/161) - Updated to `Dash 2.0`. +- [#173](https://github.com/equinor/webviz-core-components/pull/173) - Improved menu layout and auto-width. ### Fixed @@ -19,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#172](https://github.com/equinor/webviz-core-components/pull/172) - Bug fix: No margin between plugins. ### Added + - [#154](https://github.com/equinor/webviz-core-components/pull/154) - Implemented new menu component. ## [0.5.1] - 2021-07-12 diff --git a/react/src/demo/App.tsx b/react/src/demo/App.tsx index bcb6a1d2..9b742f64 100644 --- a/react/src/demo/App.tsx +++ b/react/src/demo/App.tsx @@ -59,7 +59,7 @@ const App: React.FC = () => { content: [ { type: "group", - title: "Group", + title: "Demos", content: [ { type: "page", diff --git a/react/src/lib/components/Menu/Menu.css b/react/src/lib/components/Menu/Menu.css index 501f7969..ed931163 100644 --- a/react/src/lib/components/Menu/Menu.css +++ b/react/src/lib/components/Menu/Menu.css @@ -9,6 +9,7 @@ .Menu__Ruler { font-family: sans-serif; + white-space: nowrap; } .Menu__Icon { @@ -19,3 +20,23 @@ .Menu__disabled { cursor: not-allowed; } + +.Menu__Item { + display: flex; + flex-direction: row; + align-items: center; +} + +.Menu__Item > span { + display: inline-block; + white-space: pre-wrap; + word-wrap: break-word; +} + +.Menu__Item > span.Icon { + max-width: calc(100% - 40px); +} + +.Menu__Item > span.IconPlaceholder { + padding-left: 40px; +} diff --git a/react/src/lib/components/Menu/Menu.tsx b/react/src/lib/components/Menu/Menu.tsx index 6511921e..916c351b 100644 --- a/react/src/lib/components/Menu/Menu.tsx +++ b/react/src/lib/components/Menu/Menu.tsx @@ -102,27 +102,33 @@ const getNavigationMaxWidth = ( navigationItems: PropertyNavigationType ): number => { const recursivelyParseItems = ( - item: PropertyPageType | PropertyGroupType | PropertySectionType, + items: (PropertyPageType | PropertyGroupType | PropertySectionType)[], + iconAtParentLevel?: boolean, depth = 0 ) => { - let maxWidth = depth * 16 + calculateTextWidth(item.title); - if (item.type !== "page") { - item.content.forEach( - (el) => - (maxWidth = Math.max( - maxWidth, - recursivelyParseItems(el, depth + 1) - )) + let maxWidth = 0; + const atLeastOneIconUsed = items.some((el) => el.icon !== undefined); + items.forEach((item) => { + maxWidth = Math.max( + maxWidth, + depth * 16 + + calculateTextWidth(item.title) + + (item.icon || iconAtParentLevel ? 40 : 0) ); - } + if (item.type !== "page") { + maxWidth = Math.max( + maxWidth, + recursivelyParseItems( + item.content, + atLeastOneIconUsed, + depth + 1 + ) + ); + } + }); return maxWidth; }; - let maxWidth = 0; - navigationItems.forEach( - (el: PropertyPageType | PropertyGroupType | PropertySectionType) => - (maxWidth = Math.max(recursivelyParseItems(el), maxWidth)) - ); - return maxWidth; + return recursivelyParseItems(navigationItems); }; /** @@ -166,15 +172,20 @@ export const Menu: React.FC = (props) => { const windowSize = useWindowSize(); const menuContentSpacing = 50; + const menuPadding = 32; React.useEffect(() => { setNavigationsItemsWithAssignedIds( makeNavigationItemsWithAssignedIds(props.navigationItems) ); setMenuWidth( - Math.min( - getNavigationMaxWidth(props.navigationItems) * 1.1 + 40, - windowSize.width / 2 + Math.max( + 250, + Math.min( + getNavigationMaxWidth(props.navigationItems) + menuPadding, + windowSize.width / 4, + 400 + ) ) ); }, [props.navigationItems, windowSize.width]); diff --git a/react/src/lib/components/Menu/components/Group/Group.tsx b/react/src/lib/components/Menu/components/Group/Group.tsx index 1970476a..86a3e3d2 100644 --- a/react/src/lib/components/Menu/components/Group/Group.tsx +++ b/react/src/lib/components/Menu/components/Group/Group.tsx @@ -14,6 +14,7 @@ type GroupProps = { title: string; level: number; icon?: string; + applyIconIndentation: boolean; forceOpen?: boolean; children?: React.ReactNode; }; @@ -41,13 +42,23 @@ export const Group: React.FC = (props) => { }} >
{props.icon && ( )} - {props.title} + + {props.title} +
{ const recursivelyMakeNavigation = ( items: NavigationItemType[], + iconAtParentLevel?: boolean, level = 1 - ): JSX.Element => ( - <> - {items.map((item) => { - if (item.type === "section") { - return ( -
- {recursivelyMakeNavigation( - (item as SectionType).content - )} -
- ); - } else if (item.type === "group") { - return ( - - {recursivelyMakeNavigation( - (item as GroupType).content, - level + 1 - )} - - ); - } else if (item.type === "page") { - return ( - - onPageChange((item as PageType).href) - } - /> - ); - } else { - return null; - } - })} - - ); + ): JSX.Element => { + const atLeastOneIconUsed = items.some((el) => el.icon !== undefined); + return ( + <> + {items.map((item) => { + if (item.type === "section") { + return ( +
+ {recursivelyMakeNavigation( + (item as SectionType).content, + atLeastOneIconUsed + )} +
+ ); + } else if (item.type === "group") { + return ( + + {recursivelyMakeNavigation( + (item as GroupType).content, + atLeastOneIconUsed, + level + 1 + )} + + ); + } else if (item.type === "page") { + return ( + + onPageChange((item as PageType).href) + } + /> + ); + } else { + return null; + } + })} + + ); + }; return recursivelyMakeNavigation(navigation); }; diff --git a/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.css b/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.css index 7e7f6d32..0f54a725 100644 --- a/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.css +++ b/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.css @@ -5,7 +5,6 @@ width: fit-content; z-index: 1001; display: inline-block; - max-width: 300px; } .Menu__MenuDrawerContentWrapper { diff --git a/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.tsx b/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.tsx index d16150e0..da18ad15 100644 --- a/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.tsx +++ b/react/src/lib/components/Menu/components/MenuDrawer/MenuDrawer.tsx @@ -205,6 +205,7 @@ export const MenuDrawer = React.forwardRef( right: position.right, bottom: position.bottom, width: props.maxWidth + "px", + maxWidth: props.maxWidth + "px", }} > {props.pinned && ( diff --git a/react/src/lib/components/Menu/components/Page/Page.css b/react/src/lib/components/Menu/components/Page/Page.css index cf88655a..a51cad18 100644 --- a/react/src/lib/components/Menu/components/Page/Page.css +++ b/react/src/lib/components/Menu/components/Page/Page.css @@ -2,7 +2,6 @@ padding: 16px; padding-left: 40px; text-decoration: none; - display: block; color: black; } diff --git a/react/src/lib/components/Menu/components/Page/Page.tsx b/react/src/lib/components/Menu/components/Page/Page.tsx index d0902ad8..181e74a5 100644 --- a/react/src/lib/components/Menu/components/Page/Page.tsx +++ b/react/src/lib/components/Menu/components/Page/Page.tsx @@ -11,6 +11,7 @@ type PageProps = { href: string; level: number; icon?: string; + applyIconIndentation: boolean; onClick: () => void; }; @@ -19,7 +20,9 @@ export const Page: React.FC = (props) => { return ( ) => { props.onClick(); @@ -34,7 +37,17 @@ export const Page: React.FC = (props) => { active={active} /> )} - {props.title} + + {props.title} + ); }; @@ -44,5 +57,6 @@ Page.propTypes = { href: PropTypes.string.isRequired, level: PropTypes.number.isRequired, icon: PropTypes.string, + applyIconIndentation: PropTypes.bool.isRequired, onClick: PropTypes.func.isRequired, }; diff --git a/react/src/lib/components/Menu/components/Section/Section.css b/react/src/lib/components/Menu/components/Section/Section.css index e88b2c3c..2a3b4e3d 100644 --- a/react/src/lib/components/Menu/components/Section/Section.css +++ b/react/src/lib/components/Menu/components/Section/Section.css @@ -7,6 +7,10 @@ flex-direction: row; } +.Menu__SectionTitle > svg * { + fill: #007079; +} + .Menu__Section { padding-bottom: 24px; margin-top: 24px; diff --git a/react/src/lib/components/Menu/components/Section/Section.tsx b/react/src/lib/components/Menu/components/Section/Section.tsx index 153ee3f5..e3df61cd 100644 --- a/react/src/lib/components/Menu/components/Section/Section.tsx +++ b/react/src/lib/components/Menu/components/Section/Section.tsx @@ -8,13 +8,14 @@ import "./Section.css"; type SectionProps = { title: string; icon?: string; + applyIconIndentation: boolean; children?: React.ReactNode; }; export const Section: React.FC = (props) => { return (
-
+
{props.icon && ( = (props) => { active={false} /> )} - {props.title} + + {props.title} +
{props.children}
@@ -32,6 +43,7 @@ export const Section: React.FC = (props) => { Section.propTypes = { title: PropTypes.string.isRequired, icon: PropTypes.string, + applyIconIndentation: PropTypes.bool.isRequired, children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node, diff --git a/react/src/lib/components/Overlay/Overlay.css b/react/src/lib/components/Overlay/Overlay.css index dc5a9ca3..edf42714 100644 --- a/react/src/lib/components/Overlay/Overlay.css +++ b/react/src/lib/components/Overlay/Overlay.css @@ -5,5 +5,5 @@ left: 0; top: 0; background-color: black; - z-index: 100; + z-index: 999; }