From 820ab5858f4c45441a563bd85f57556bf9e619db Mon Sep 17 00:00:00 2001 From: Eran Machiels Date: Mon, 28 Dec 2020 11:02:27 +0100 Subject: [PATCH] WIP navigation --- .../Navigation/Vertical/ListItem.tsx | 46 +++++++----- .../Navigation/Vertical/NavigationContext.ts | 10 +++ .../Navigation/VerticalNavigation.tsx | 71 ++++++++++++++----- src/components/Overlay/OverlayTrigger.tsx | 6 +- src/components/Overlay/index.tsx | 7 +- src/style/components/_navigation.scss | 13 ++-- www/src/index.tsx | 29 +++++--- 7 files changed, 123 insertions(+), 59 deletions(-) create mode 100644 src/components/Navigation/Vertical/NavigationContext.ts diff --git a/src/components/Navigation/Vertical/ListItem.tsx b/src/components/Navigation/Vertical/ListItem.tsx index 77bdda6..04d82f4 100644 --- a/src/components/Navigation/Vertical/ListItem.tsx +++ b/src/components/Navigation/Vertical/ListItem.tsx @@ -1,9 +1,11 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import clsx from 'clsx'; +import { NavigationContext } from './NavigationContext'; interface NavigationListItemProps extends React.HTMLAttributes { active?: boolean; + content?: React.ReactNode; icon?: React.ReactElement; } @@ -15,25 +17,31 @@ const NavigationListItem = React.forwardRef ( -
- {icon && ( -
- {icon} -
- )} - - {children} - -
-)); +): React.ReactElement => { + return ( + + {() => ( +
+ {icon && ( +
+ {icon} +
+ )} + + {children} + +
+ )} +
+ ) +}); NavigationListItem.displayName = 'NavigationListItem'; NavigationListItem.propTypes = { diff --git a/src/components/Navigation/Vertical/NavigationContext.ts b/src/components/Navigation/Vertical/NavigationContext.ts new file mode 100644 index 0000000..2c8c86e --- /dev/null +++ b/src/components/Navigation/Vertical/NavigationContext.ts @@ -0,0 +1,10 @@ +import { createContext } from 'react'; +export interface NavigationContextProps { + tooltipsWhenCollapsed: boolean; + collapsed: boolean; +} + +export const NavigationContext = createContext({ + tooltipsWhenCollapsed: true, + collapsed: false +}); diff --git a/src/components/Navigation/VerticalNavigation.tsx b/src/components/Navigation/VerticalNavigation.tsx index d092134..9b40ec9 100644 --- a/src/components/Navigation/VerticalNavigation.tsx +++ b/src/components/Navigation/VerticalNavigation.tsx @@ -7,8 +7,9 @@ import NavigationTop from '@/components/Navigation/Vertical/Top'; import NavigationList from '@/components/Navigation/Vertical/List'; import NavigationListItem from '@/components/Navigation/Vertical/ListItem'; import NavigationDivider from '@/components/Navigation/Vertical/Divider'; -import { useState } from 'react'; -import { VerticalNavigationScope } from './Vertical/VerticalNavigationScope'; +import { useEffect, useState } from 'react'; +import { VerticalNavigationScope } from '@/components/Navigation/Vertical/VerticalNavigationScope'; +import { NavigationContext } from './Vertical/NavigationContext'; export interface VerticalNavigationStatics { Top: typeof NavigationTop; @@ -17,26 +18,51 @@ export interface VerticalNavigationStatics { Divider: typeof NavigationDivider; } -export interface SideNavigationProps extends React.HTMLAttributes { +export interface VerticalNavigationProps extends React.HTMLAttributes { + /** + * Variant of the menu. With this prop, the color of the menu can be set. + */ variant?: Variant | string; + /** + * Indicates whether the menu collapse is controllable. + */ collapsable?: boolean; + /** + * Indicating whether the menu is collapsed. Can be used to make the navigation a controllable component + */ + collapsed?: boolean; + /** + * Indicates whether a tooltip with the menu text must be shown when menu is collapsed. Default: true + */ + tooltipsWhenCollapsed?: boolean; + /** + * Children of the menu. This can be either a React ChildNode or callback function to access various actions + */ children: React.ReactNode | ((scope: VerticalNavigationScope) => React.ReactNode); } // @ts-ignore -const VerticalNavigation: ForwardComponentWithStatics = +const VerticalNavigation: ForwardComponentWithStatics = React.forwardRef(( { children, className, - variant + variant, + collapsed, + tooltipsWhenCollapsed = true }, ref ): React.ReactElement => { - const [collapsed, setCollapsed] = useState(false); + const [isCollapsed, setCollapsed] = useState(false); + + useEffect(() => { + if (collapsed) { + setCollapsed(collapsed); + } + }, [collapsed]) const makeScope = (): VerticalNavigationScope => ({ - collapsed, + collapsed: isCollapsed, collapse: () => setCollapsed(!collapsed) }); @@ -45,17 +71,24 @@ const VerticalNavigation: ForwardComponentWithStatics - {children} - +
+ {children} +
+ ) }); @@ -63,7 +96,9 @@ VerticalNavigation.displayName = 'VerticalNavigation'; VerticalNavigation.propTypes = { children: PropTypes.node, className: PropTypes.string, - variant: PropTypes.string + variant: PropTypes.string, + collapsed: PropTypes.bool, + tooltipsWhenCollapsed: PropTypes.bool } VerticalNavigation.Top = NavigationTop; diff --git a/src/components/Overlay/OverlayTrigger.tsx b/src/components/Overlay/OverlayTrigger.tsx index a6b7630..125eefe 100644 --- a/src/components/Overlay/OverlayTrigger.tsx +++ b/src/components/Overlay/OverlayTrigger.tsx @@ -5,6 +5,7 @@ import Overlay from '@/components/Overlay/index'; import { Placement, PositioningStrategy } from '@popperjs/core'; import { Trigger, triggerPropTypes } from '@/components/Overlay/Trigger'; import { AnimatePresence } from 'framer-motion'; +import { Modifier } from '@popperjs/core/lib/types'; interface OverlayTriggerProps { arrow?: boolean; @@ -15,6 +16,7 @@ interface OverlayTriggerProps { className?: string; trigger?: Trigger | string; motion?: string; + config?: Array>>; } const OverlayTrigger = ({ @@ -25,7 +27,8 @@ const OverlayTrigger = ({ placement, positionStrategy, trigger = 'hover', - motion + motion, + config }: OverlayTriggerProps): React.ReactElement => { const [shown, setShown] = useState(false); const triggerRef = useRef(); @@ -71,6 +74,7 @@ const OverlayTrigger = ({ placement={placement} positionStrategy={positionStrategy} className={className} + config={config} > {overlay} diff --git a/src/components/Overlay/index.tsx b/src/components/Overlay/index.tsx index 14f4840..3a3cb88 100644 --- a/src/components/Overlay/index.tsx +++ b/src/components/Overlay/index.tsx @@ -20,6 +20,7 @@ interface OverlayProps { arrow?: boolean; positionStrategy?: PositioningStrategy; motion?: string; + config?: Array>>; } const Overlay = ({ @@ -29,7 +30,8 @@ const Overlay = ({ placement = 'top', arrow = true, positionStrategy = 'absolute', - motion: triggerMotion + motion: triggerMotion, + config }: React.PropsWithChildren): React.ReactElement => { const ref = useRef(null); const popper = useRef(); @@ -40,7 +42,8 @@ const Overlay = ({ options: { element: '.arrow' } - }] : []) + }] : []), + ...(config || []) ]); const createPopperOptions = (): PopperOptions => ({ diff --git a/src/style/components/_navigation.scss b/src/style/components/_navigation.scss index ad93355..047b9d2 100644 --- a/src/style/components/_navigation.scss +++ b/src/style/components/_navigation.scss @@ -75,14 +75,6 @@ .vertical-navigation-list-item-text { display: none; } - - &:hover { - white-space: nowrap; - - .vertical-navigation-list-item-text { - display: block; - } - } } } } @@ -98,3 +90,8 @@ background: var(--primary-color-light-background); } } + +.vertical-navigation-tooltip { + margin-left: 0.5rem; + background: #000; +} diff --git a/www/src/index.tsx b/www/src/index.tsx index 08cc18d..79b4808 100644 --- a/www/src/index.tsx +++ b/www/src/index.tsx @@ -3,7 +3,8 @@ import { useState } from 'react'; import * as ReactDom from 'react-dom'; import '../../src/style/index.scss'; import { Button, Card, Col, Grid, Icon, Page, Row, SelectField, Tag, TextField, Variant } from '../../src'; -import logo from '@/images/coderan/logo.svg'; +import logoFull from '@/images/coderan/logo.svg'; +import logoLetter from '@/images/coderan/logo-letter.svg'; import Container from '../../src/components/Container/Container'; import FormGroup from '../../src/components/Form/Group'; import FormLabel from '../../src/components/Form/Label'; @@ -36,21 +37,27 @@ const TestControllable = () => { ReactDom.render( - - {({ collapse }) => ( + + {({ collapse, collapsed }) => ( <> - - + {collapsed ? ( + + ) : ( + + )} - }> - Home - - }> - User - + } + content="Home" + /> + } + content="Tooltips" + /> )}