Skip to content

Commit

Permalink
Feat(IDP-1314); fix collapse menuitem (#478)
Browse files Browse the repository at this point in the history
* fix: menuitem

* fix: menuitem

* fix: svg alt attribute

* reset: package.json

* reset: package.json

* fixed: eslint typeError

* fixed: flacky tes. tadding timeout to useModal test

* fixed: useModal test

* Update src/components/Typography/BodyX/BodyX.tsx

* added: missing modal.utils test

* Update .eslintrc.cjs

Co-authored-by: Luca Maltagliati <lmalta95@gmail.com>

* Update src/components/Menu/Menu.utils.test.tsx

Co-authored-by: Luca Maltagliati <lmalta95@gmail.com>

* feat: fix test

* Update tsconfig.json

---------

Co-authored-by: Luca Maltagliati <lmalta95@gmail.com>
Co-authored-by: Giovanna Monti <60603265+GiovannaMonti@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 4, 2024
1 parent ebf8ace commit b1e4c7f
Show file tree
Hide file tree
Showing 19 changed files with 3,054 additions and 3,758 deletions.
7 changes: 5 additions & 2 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ module.exports = {
ignorePatterns: [
".eslintrc.cjs",
"jest.config.js",
"src/vite-env.d.ts"
"src/vite-env.d.ts",
// FIXME: This component has a react/boolean-prop naming problem, because boolean props do not have the symbol at the beginning of the name.
"src/components/Typography/BodyX/BodyX.tsx",
"src/components/Typography/HX/HX.tsx"
],
parser: "@typescript-eslint/parser",
parserOptions: {
Expand Down Expand Up @@ -44,7 +47,7 @@ module.exports = {
groups: [
["builtin", "external"],
["internal", "parent", "sibling", "index"],
],
],
"newlines-between": "always"
}],
"max-statements": "off",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
},
"dependencies": {
"@fontsource/inter": "^5.0.18",
"antd": "^5.9.2",
"antd": "5.9.2",
"lodash-es": "^4.17.21",
"react-icons": "^4.11.0"
},
Expand Down
4 changes: 0 additions & 4 deletions src/components/Button/__snapshots__/Button.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ exports[`Button Component renders button with icon left correctly 1`] = `
type="button"
>
<svg
alt="PiCircleHalfTiltLight"
aria-label="PiCircleHalfTiltLight"
color="white"
fill="currentColor"
Expand Down Expand Up @@ -61,7 +60,6 @@ exports[`Button Component renders button with icon right correctly 1`] = `
Button
</div>
<svg
alt="PiCircleHalfTiltLight"
aria-label="PiCircleHalfTiltLight"
color="white"
fill="currentColor"
Expand Down Expand Up @@ -89,7 +87,6 @@ exports[`Button Component renders circle button correctly 1`] = `
type="button"
>
<svg
alt="PiCircleHalfTiltLight"
aria-label="PiCircleHalfTiltLight"
color="white"
fill="currentColor"
Expand Down Expand Up @@ -384,7 +381,6 @@ exports[`Button Component renders square button correctly 1`] = `
type="button"
>
<svg
alt="PiCircleHalfTiltLight"
aria-label="PiCircleHalfTiltLight"
color="white"
fill="currentColor"
Expand Down
2 changes: 0 additions & 2 deletions src/components/Card/__snapshots__/Card.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ exports[`Card Component renders card correctly 1`] = `
type="button"
>
<svg
alt="PiBookOpen"
aria-label="PiBookOpen"
color="#005dc9"
fill="currentColor"
Expand Down Expand Up @@ -119,7 +118,6 @@ exports[`Card Component renders header only 1`] = `
type="button"
>
<svg
alt="PiBookOpen"
aria-label="PiBookOpen"
color="#005dc9"
fill="currentColor"
Expand Down
1 change: 0 additions & 1 deletion src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ export const Icon = ({

return (
<IconComponent
alt={name}
aria-label={name}
className={className}
color={color ?? defaultColor}
Expand Down
4 changes: 0 additions & 4 deletions src/components/Icon/__snapshots__/Icon.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
exports[`Icon Component renders Ant icon correctly 1`] = `
<DocumentFragment>
<svg
alt="AiOutlineHome"
aria-label="AiOutlineHome"
fill="currentColor"
height="24"
Expand All @@ -24,7 +23,6 @@ exports[`Icon Component renders Ant icon correctly 1`] = `
exports[`Icon Component renders Feather icon correctly 1`] = `
<DocumentFragment>
<svg
alt="FiHome"
aria-label="FiHome"
fill="none"
height="24"
Expand All @@ -50,7 +48,6 @@ exports[`Icon Component renders Feather icon correctly 1`] = `
exports[`Icon Component renders Phosphor icon correctly 1`] = `
<DocumentFragment>
<svg
alt="PiHouse"
aria-label="PiHouse"
fill="currentColor"
height="24"
Expand All @@ -71,7 +68,6 @@ exports[`Icon Component renders Phosphor icon correctly 1`] = `
exports[`Icon Component renders custom icon correctly 1`] = `
<DocumentFragment>
<svg
alt="MiaPlatform"
aria-label="MiaPlatform"
data-file-name="SvgMiaPlatform"
height="24"
Expand Down
4 changes: 2 additions & 2 deletions src/components/Menu/Menu.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
--collapsed-margin: calc(var(--spacing-margin-xs, 4) * 1px);

:global([role*=menuitem]) {
display: flex;
align-items: center;
display: flex !important;
align-items: center !important;
}

:global(.mia-platform-menu-sub) {
Expand Down
24 changes: 13 additions & 11 deletions src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

import { Menu as AntMenu, ConfigProvider, Skeleton } from 'antd'
import { ReactElement, useMemo, useState } from 'react'
import { ReactElement, useCallback, useMemo, useState } from 'react'
import classNames from 'classnames'

import { Hierarchy, ItemType, Mode } from './Menu.types'
Expand Down Expand Up @@ -63,17 +63,19 @@ export const Menu = ({

const theme = useTheme()
const menuTheme = isPrimary ? primaryTheme(theme) : defaultTheme(theme)
const [selectedItem, setSelectedItem] = useState(defaultSelectedKey)

const menuClassNames = useMemo(() => classNames([
menu,
isPrimary && 'primary',
]), [isPrimary])
const menuClassNames = useMemo(() => classNames([menu, isPrimary && 'primary']), [isPrimary])

const [selectedItem, setSelectedItem] = useState(defaultSelectedKey)
const onSelect = useCallback(({ key }: {key: string}) => setSelectedItem(key), [])

const getPopupContainer = useCallback((targetNode: HTMLElement) => {
const element = document.querySelector(`.${menu}`)?.parentElement
if (!element) { return targetNode }
return element
}, [])

const formattedItems = useMemo(() => (
formatLabels(items, selectedKey || selectedItem, isCollapsed, hierarchy)
), [items, selectedKey, selectedItem, isCollapsed, hierarchy])
const formattedItems = formatLabels(items, selectedKey || selectedItem, isCollapsed, hierarchy)

return (
<ConfigProvider theme={{ components: { Menu: menuTheme } }}>
Expand All @@ -87,7 +89,7 @@ export const Menu = ({
defaultOpenKeys={defaultOpenKeys}
defaultSelectedKeys={defaultSelectedKey ? [defaultSelectedKey] : undefined}
// getPopupContainer is needed for nested menus to inherit CSS properties in the vertical mode
getPopupContainer={() => document.querySelector(`.${menu}`)!}
getPopupContainer={getPopupContainer}
inlineCollapsed={isCollapsed}
inlineIndent={0}
items={formattedItems}
Expand All @@ -98,7 +100,7 @@ export const Menu = ({
selectedKeys={(selectedKey && [selectedKey]) || (selectedItem && [selectedItem]) || undefined}
onClick={onClick}
onOpenChange={onOpenChange}
onSelect={({ key }) => setSelectedItem(key)}
onSelect={onSelect}
/>
</Skeleton>
</ConfigProvider>
Expand Down
150 changes: 150 additions & 0 deletions src/components/Menu/Menu.utils.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/**
* Copyright 2024 Mia srl
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/

import { } from '../../test-utils'
import { Hierarchy, Item, ItemType } from './Menu.types'
import formatLabels from './Menu.utils'

type TestCaseType = Record<string, {
params: {
items?: Item[],
selectedItem?: string,
isCollapsed?: boolean,
hierarchy?: Hierarchy
},
expectedResult: unknown[]
}>

describe('Menu Component', () => {
beforeEach(() => {
jest.resetAllMocks()
})

const testCases: TestCaseType = {
'expect to return empty array': {
params: {
items: undefined,
selectedItem: 'key',
isCollapsed: false,
hierarchy: Hierarchy.Default,
},
expectedResult: [],
},
'expect to return corretly items': {
params: {
items: [{ label: 'menu-item', key: 'uniqueKey', icon: <div /> }],
selectedItem: 'key',
isCollapsed: false,
hierarchy: Hierarchy.Default,
},
expectedResult: [{
key: 'uniqueKey',
label: 'menu-item',
icon: <div><div /></div>,
}],
},
'expect to return divider type': {
params: {
items: [{
type: ItemType.Divider,
key: 'divider',
}],
},
expectedResult: [{
type: ItemType.Divider,
key: 'divider',
icon: undefined,
label: undefined,
}],
},
'expect to return group type': {
params: {
items: [{
type: ItemType.Group,
key: 'group',
}],
},
expectedResult: [{
key: 'group',
icon: undefined,
label: undefined,
}],
},
'expect to return category type': {
params: {
items: [{
type: ItemType.Category,
label: 'category label',
key: 'category',
title: 'title',
}],
},
expectedResult: [{
key: 'category',
icon: undefined,
type: 'group',
label: 'CATEGORY LABEL',
title: 'TITLE',
}],
},
'expect to return category type with children and collapse set to true': {
params: {
items: [{
type: ItemType.Category,
label: 'category label',
key: 'category',
title: 'title',
children: [{
key: 'uniqueKey',
label: 'menu-item',
icon: <div />,
}],
}],
isCollapsed: true,
},
expectedResult: [{
key: 'uniqueKey',
label: 'menu-item',
icon: <div><div /></div>,
}],
},
'expect to see styles for Primary item': {
params: {
items: [{ label: 'menu-item', key: 'uniqueKey', icon: <div /> }],
selectedItem: 'uniqueKey',
hierarchy: Hierarchy.Primary,
},
expectedResult: [{
key: 'uniqueKey',
label: 'menu-item',
icon: <div><div /></div>,
style: {
boxShadow: '0px 1px 4px -1px rgba(0, 0, 0, 0.12)',
},
}],
},
}

Object.entries(testCases).forEach(([testName, { params, expectedResult }]) => {
test(testName, () => {
const { items, selectedItem, isCollapsed, hierarchy } = params
const result = formatLabels(items, selectedItem, isCollapsed, hierarchy)
expect(result).toEqual(expectedResult)
})
})
})
5 changes: 2 additions & 3 deletions src/components/Menu/Menu.utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,14 @@ function formatLabels(
isCollapsed?: boolean,
hierarchy?: Hierarchy
): AntItemType[] {
return items.map(({ title, label, type, key, children, icon, ...item }) => {
return items.flatMap(({ title, label, type, key, children, icon, ...item }) => {
if (type === Category && isCollapsed) {
return formatLabels(children, selectedItem, isCollapsed, hierarchy)
}

return {
...item,
label,
title,
key,
icon: icon && <div>{icon}</div>,
...type === Category && {
Expand All @@ -66,7 +65,7 @@ function formatLabels(
children: formatLabels(children, selectedItem, isCollapsed, hierarchy),
},
}
}).flat()
})
}

export default formatLabels
Loading

0 comments on commit b1e4c7f

Please sign in to comment.