From e6bf8d8265a8228ed0bd71ffef427c9617be0478 Mon Sep 17 00:00:00 2001 From: Luis Santos Date: Wed, 4 Oct 2023 11:09:33 +0100 Subject: [PATCH] doc: improvements --- .../components/navigationmenu/index.mdx | 167 +++++++++--------- .../components/navigationmenu/props.ts | 28 +-- .../web/NavigationMenu.test.tsx | 85 +++++---- .../NavigationMenu.test.tsx.snap | 108 ++++------- 4 files changed, 179 insertions(+), 209 deletions(-) diff --git a/packages/doc/content/components/components/navigationmenu/index.mdx b/packages/doc/content/components/components/navigationmenu/index.mdx index 40093c77ae..e20d9c8873 100644 --- a/packages/doc/content/components/components/navigationmenu/index.mdx +++ b/packages/doc/content/components/components/navigationmenu/index.mdx @@ -4,7 +4,7 @@ metaTitle: 'NavigationMenu' metaDescription: 'NavigationMenu Component' --- -import { ArrowRight, Help, Doc, Money, MenuMore } from '@gympass/yoga-icons'; +import { ArrowRight, Help, Doc, MenuMore } from '@gympass/yoga-icons'; import { theme } from '@gympass/yoga'; import { NavigationMenuProps, @@ -27,9 +27,7 @@ Gympass `` displays a navigation menu with 3 optional main are `` should be used to display items and subitems. -The menu is responsive by default. The items to be displayed in the bottom bar are handle by components `` and ``. - -The responsiveness is controled by props.

+The menu is responsive by default and controled by props. `` and `` should be used to display the items in the bottom bar.

Available components: @@ -64,36 +62,38 @@ const MainPage = styled.main` padding: 10px; `; -render(() => { - const renderWrapper = ({ children }) => ( - {children} - ); +const itemGroups = [ + [ + { + expanded: true, + icon: Doc, + label: 'Subscription', + tag: 'new', + subitems: [{ label: 'Details' }], + }, + { + active: true, + icon: Doc, + label: 'Billing', + }, + ], + [ + { + icon: Help, + label: 'Help', + }, + ], +]; - const IconComponent = ({ icon }) => ; - - const itemGroups = [ - [ - { - expanded: true, - icon: Doc, - label: 'Subscription', - tag: 'new', - subitems: [{ label: 'Details' }], - }, - { - active: true, - icon: Doc, - label: 'Billing', - }, - ], - [ - { - icon: Help, - label: 'Help', - }, - ], - ]; +// Whether the link handles the active attribute automatically (e.g., link from react-router-dom) +// then the item's active prop is not needed +const renderWrapper = ({ children }) => ( + {children} +); + +const IconComponent = ({ icon }) => ; +render(() => { return ( @@ -166,55 +166,54 @@ const MainPage = styled.main` padding: 10px; `; +const itemMainGroup = [ + { + expanded: true, + icon: Doc, + label: 'Subscription', + tag: 'new', + subitems: [{ label: 'Details' }], + }, + { + active: true, + icon: Doc, + label: 'Billing', + }, +]; + +const itemGroups = [ + [...itemMainGroup], + [ + { + icon: Help, + label: 'Help', + }, + ], +]; + +const IconComponent = ({ icon }) => ; + render(() => { const [isOpenOnMobile, setIsOpenOnMobile] = useState(false); + // Whether the link handles the active attribute automatically (e.g., link from react-router-dom) + // then the item's active prop is not needed const renderWrapper = ({ children }) => ( - setIsOpenOnMobile(false)} - > + setIsOpenOnMobile(false)}> {children} ); - const IconComponent = ({ icon }) => ; - - const itemMainGroup = [ - { - expanded: true, - icon: Doc, - label: 'Subscription', - tag: 'new', - subitems: [{ label: 'Details' }], - }, - { - active: true, - icon: Doc, - label: 'Billing', - }, - ]; - - const itemGroups = [ - [...itemMainGroup], - [ - { - icon: Help, - label: 'Help', - }, - ], - ]; - const bottomItems = [ - ...itemMainGroup - .slice(0, 2) - .map(({ active, icon, label }) => ({ - active, - icon, - label, - wrapper: renderWrapper, - })), + ...itemMainGroup.slice(0, 2).map(({ active, icon, label }) => ({ + active, + icon, + label, + wrapper: renderWrapper, + })), { + // Missing the active logic here. + // It must be active when none of the other left items are active. icon: MenuMore, label: 'More', wrapper: ({ children }) => ( @@ -225,8 +224,9 @@ render(() => { return ( - {/* Due to the structure of the yoga page it is not possible to demonstrate all responsive behavior */} - {/* To achieve this replace openOnMobile={false} by openOnMobile={isOpenOnMobile} */} + {/* It is not possible to demonstrate all the responsive behavior here. */} + {/* When clicking on the "More" item, the entire menu will be displayed above the bottom bar. */} + {/* To get the entire flow the openOnMobile={false} prop must be replaced by openOnMobile={isOpenOnMobile} */} { /> + Main page + {bottomItems.map(({ active, icon, label, wrapper }) => ( { #### Menu subcomponent with an action -When the Menu subcomponent has an action associated it exposes the onClick event. - ```javascript state -const StyledBox = styled(Box)` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; +const StyledAvatar = styled(Avatar.Circle)` background-color: ${theme.colors.vibin}; `; @@ -305,11 +300,9 @@ render(() => { - - C - - + + C + } title="Company" subtitle="Reseller" @@ -323,8 +316,6 @@ render(() => { #### Switcher subcomponent with actions -When the Switcher subcomponent has associated actions, they are displayed so that the user can select one of them. - ```javascript state const StyledAvatar = styled(Avatar.Circle)` background-color: ${theme.colors.white}; diff --git a/packages/doc/content/components/components/navigationmenu/props.ts b/packages/doc/content/components/components/navigationmenu/props.ts index 038d1e806d..860f3754be 100644 --- a/packages/doc/content/components/components/navigationmenu/props.ts +++ b/packages/doc/content/components/components/navigationmenu/props.ts @@ -7,15 +7,17 @@ export const NavigationMenuProps = [ }, { name: 'openOnMobile', - description: { text: 'Indicates if the menu is open/close in mobile' }, + description: { text: 'Indicates whether the menu is open/close in mobile' }, type: { name: 'bool' }, required: false, + defaultValue: { value: 'false' }, }, { name: 'responsive', - description: { text: `Indicates if the menu should be responsive` }, + description: { text: `Indicates whether the menu should be responsive` }, type: { name: 'bool' }, required: false, + defaultValue: { value: 'true' }, }, ]; @@ -36,14 +38,14 @@ export const MenuProps = [ }, { name: 'title', - description: { text: 'Text to be displayed displayed as title' }, + description: { text: 'Text to be displayed as title' }, type: { name: 'string' }, required: true, }, { name: 'onClick', description: { - text: 'Event triggered when clicking in the component', + text: 'Event triggered when clicking on the component', }, type: { name: 'func' }, required: false, @@ -70,7 +72,7 @@ export const SwitcherActionProps = [ { name: 'onClick', description: { - text: 'Event triggered when clicking in the action', + text: 'Event triggered when clicking on the action', }, type: { name: 'func' }, required: true, @@ -129,10 +131,11 @@ export const ItemProps = [ name: 'active', description: { text: - 'Indicates if the item is active/inactive. This prop is not required if the wrapper already handles this.', + 'Indicates whether the item is active/inactive. This prop is not necessary when the wrapper already handles this.', }, type: { name: 'bool' }, required: false, + defaultValue: { value: 'false' }, }, { name: 'children', @@ -142,7 +145,7 @@ export const ItemProps = [ }, { name: 'expanded', - description: { text: 'Controls when hide/show the subitems' }, + description: { text: 'Controls when to hide/show subitems' }, type: { name: 'bool' }, required: false, defaultValue: { value: 'false' }, @@ -161,9 +164,10 @@ export const ItemProps = [ }, { name: 'responsive', - description: { text: `Indicates if the item should be responsive` }, + description: { text: `Indicates whether the item should be responsive` }, type: { name: 'bool' }, required: false, + defaultValue: { value: 'true' }, }, { name: 'tag', @@ -184,10 +188,11 @@ export const SubitemProps = [ name: 'active', description: { text: - 'Indicates if the subitem is active/inactive. This prop is not required if the wrapper already handles this.', + 'Indicates whether the item is active/inactive. This prop is not necessary when the wrapper already handles this.', }, type: { name: 'bool' }, required: false, + defaultValue: { value: 'false' }, }, { name: 'label', @@ -208,7 +213,7 @@ export const BottomItemsProps = [ name: 'children', description: { text: 'Items to be displayed in the mobile bottom bar' }, type: { name: 'node' }, - required: false, + required: true, }, ]; @@ -217,10 +222,11 @@ export const BottomItemProps = [ name: 'active', description: { text: - 'Indicates if the item is active/inactive. This prop is not required if the wrapper already handles this.', + 'Indicates whether the item is active/inactive. This prop is not necessary when the wrapper already handles this.', }, type: { name: 'bool' }, required: false, + defaultValue: { value: 'false' }, }, { name: 'icon', diff --git a/packages/yoga/src/NavigationMenu/web/NavigationMenu.test.tsx b/packages/yoga/src/NavigationMenu/web/NavigationMenu.test.tsx index 46b2a7aef2..5b740d405e 100644 --- a/packages/yoga/src/NavigationMenu/web/NavigationMenu.test.tsx +++ b/packages/yoga/src/NavigationMenu/web/NavigationMenu.test.tsx @@ -1,19 +1,42 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { Home } from '@gympass/yoga-icons'; import { ThemeProvider, Avatar, Icon } from '@gympass/yoga'; +import { Help, Doc } from '@gympass/yoga-icons'; import NavigationMenu from './NavigationMenu'; describe('', () => { describe('Snapshots', () => { - it('should match NavigationMenu', () => { + it('should match NavigationMenu', () => { const renderWrapper = ({ children }) => {children}; - const IconComponent = () => ; + const IconComponent = ({ icon }) => ; + + const itemGroups = [ + [ + { + expanded: true, + icon: Doc, + label: 'Subscription', + tag: 'new', + subitems: [{ label: 'Details' }], + }, + { + active: true, + icon: Doc, + label: 'Billing', + }, + ], + [ + { + icon: Help, + label: 'Help', + }, + ], + ]; const { container } = render( - + } @@ -23,32 +46,29 @@ describe('', () => { - - } - label="Subscription" - wrapper={renderWrapper} - tag="new" - > - - - } - label="Billing" - wrapper={renderWrapper} - /> - - - } - label="Help" - wrapper={renderWrapper} - /> - + {itemGroups.map(group => ( + + {group.map(item => ( + } + label={item.label} + responsive={false} + wrapper={renderWrapper} + tag={item.tag} + > + {item.subitems && + item.subitems.map(({ label }) => ( + + ))} + + ))} + + ))} @@ -59,7 +79,6 @@ describe('', () => { /> - ); , ); @@ -69,7 +88,7 @@ describe('', () => { it('should match NavigationMenu.Menu with an action', () => { const { container } = render( - + } @@ -101,7 +120,7 @@ describe('', () => { const { container } = render( - + Snapshots should match NavigationMenu 1`] = ` +exports[` Snapshots should match NavigationMenu 1`] = ` .c3 { border-radius: 9999px; background-color: #9898A6; @@ -208,7 +208,7 @@ exports[` Snapshots should match NavigationMenu 1`] = ` border-radius: 8px; } -.c21 { +.c20 { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; @@ -284,10 +284,12 @@ exports[` Snapshots should match NavigationMenu 1`] = ` .c10 a.active > .c11 { background-color: #F5F5FA; + background-color: #FFEEF2; } .c10 a.active > .c11 .c15 { color: #D8385E; + font-weight: 500; } .c10 a.active > .c11 svg { @@ -298,7 +300,7 @@ exports[` Snapshots should match NavigationMenu 1`] = ` background-color: #231B22; } -.c20 { +.c21 { -webkit-transition: background-color 300ms ease-in-out; transition: background-color 300ms ease-in-out; background-color: transparent; @@ -307,50 +309,54 @@ exports[` Snapshots should match NavigationMenu 1`] = ` cursor: pointer; } -.c20 svg { +.c21 svg { height: 20px; width: 20px; } -.c20:hover, -.c20:focus { - background-color: #D7D7E0; +.c21 a { + -webkit-text-decoration: none; + text-decoration: none; + cursor: auto; } -.c20:hover .c15, -.c20:focus .c15 { - color: #231B22; +.c21 a.active { + cursor: auto; } -.c20:hover svg, -.c20:focus svg { - fill: #231B22; +.c21 a.active > .c11 { + background-color: #F5F5FA; + background-color: #FFEEF2; } -.c20 a { - -webkit-text-decoration: none; - text-decoration: none; +.c21 a.active > .c11 .c15 { + color: #D8385E; + font-weight: 500; } -.c20 a.active { - cursor: auto; +.c21 a.active > .c11 svg { + fill: #D8385E; } -.c20 a.active > .c11 { +.c21 a.active > .c11 > .c18 { + background-color: #231B22; +} + +.c21 a > .c11 { background-color: #F5F5FA; background-color: #FFEEF2; } -.c20 a.active > .c11 .c15 { +.c21 a > .c11 .c15 { color: #D8385E; font-weight: 500; } -.c20 a.active > .c11 svg { +.c21 a > .c11 svg { fill: #D8385E; } -.c20 a.active > .c11 > .c18 { +.c21 a > .c11 > .c18 { background-color: #231B22; } @@ -422,31 +428,6 @@ exports[` Snapshots should match NavigationMenu 1`] = ` gap: 4px; } -@media (min-width:1024px) { - .c10 a.active > .c11 { - background-color: #FFEEF2; - } -} - -@media (min-width:1024px) { - .c10 a.active > .c11 .c15 { - font-weight: 500; - } -} - -@media (max-width:1024px) { - .c0 { - position: absolute; - width: 100%; - height: calc(100% - 74px); - z-index: 10; - Top: 0; - right: -100%; - -webkit-transition: right 300ms ease-in-out; - transition: right 300ms ease-in-out; - } -} - - ); `; @@ -772,19 +752,6 @@ exports[` Snapshots should match NavigationMenu.Menu with an a gap: 4px; } -@media (max-width:1024px) { - .c0 { - position: absolute; - width: 100%; - height: calc(100% - 74px); - z-index: 10; - Top: 0; - right: -100%; - -webkit-transition: right 300ms ease-in-out; - transition: right 300ms ease-in-out; - } -} -
Snapshots should match NavigationMenu.Switcher with gap: 4px; } -@media (max-width:1024px) { - .c0 { - position: absolute; - width: 100%; - height: calc(100% - 74px); - z-index: 10; - Top: 0; - right: -100%; - -webkit-transition: right 300ms ease-in-out; - transition: right 300ms ease-in-out; - } -} -