Skip to content

Commit

Permalink
fix(MenuV2): better search with groups and label description (#4653)
Browse files Browse the repository at this point in the history
* fix(MenuV2): better search with groups and label description

* fix: unit testing and add more
  • Loading branch information
matthprost authored Jan 10, 2025
1 parent fb00a2d commit 61d26ae
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 110 deletions.
5 changes: 5 additions & 0 deletions .changeset/giant-jobs-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ultraviolet/ui": patch
---

Improve search engine on `<MenuV2 />` component and new prop `labelDescription` on `<MenuV2.Group />` component
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ArrowDownIcon, DotsHorizontalIcon } from '@ultraviolet/icons'
import type { ComponentProps } from 'react'
import { Breadcrumbs } from '..'
import { AvatarV2 } from '../../AvatarV2'
import { Button } from '../../Button'
import { MenuV2 } from '../../MenuV2'
import { Stack } from '../../Stack'

Expand Down Expand Up @@ -55,39 +56,60 @@ export const AdvancedUsage: StoryFn<
</Breadcrumbs.Item>
}
>
<MenuV2.Item sentiment="primary" active>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#BF95F9', '#3D1862']}
shape="circle"
size="xsmall"
/>
Default Project
</Stack>
</MenuV2.Item>
<MenuV2.Item>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FFBFAB', '#822F15']}
shape="circle"
size="xsmall"
/>
Project 1
</Stack>
</MenuV2.Item>
<MenuV2.Item>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FF9EC1', '#740D32']}
shape="circle"
size="xsmall"
/>
Project 2
</Stack>
</MenuV2.Item>
<MenuV2.Group
label="Projects"
labelDescription={
<Stack
direction="row"
alignItems="center"
justifyContent="end"
width="100%"
>
<Button
sentiment="info"
variant="ghost"
size="xsmall"
icon="plus"
>
Create Project
</Button>
</Stack>
}
>
<MenuV2.Item sentiment="primary" active borderless>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#BF95F9', '#3D1862']}
shape="circle"
size="xsmall"
/>
Default Project
</Stack>
</MenuV2.Item>
<MenuV2.Item borderless>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FFBFAB', '#822F15']}
shape="circle"
size="xsmall"
/>
Project 1
</Stack>
</MenuV2.Item>
<MenuV2.Item borderless>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FF9EC1', '#740D32']}
shape="circle"
size="xsmall"
/>
Project 2
</Stack>
</MenuV2.Item>
</MenuV2.Group>
</MenuV2>
<Breadcrumbs.Item to="/products/1">Instance</Breadcrumbs.Item>
<Breadcrumbs.Item to="/products/1/details">Overview</Breadcrumbs.Item>
Expand Down
9 changes: 6 additions & 3 deletions packages/ui/src/components/MenuV2/MenuContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export const Menu = forwardRef(
) => {
const { isVisible, setIsVisible } = useMenu()
const searchInputRef = useRef<HTMLInputElement>(null)
const [localChild, setLocalChild] = useState<ReactNode[]>()
const [localChild, setLocalChild] = useState<ReactNode[] | null>(null)
const popupRef = useRef<HTMLDivElement>(null)
const disclosureRef = useRef<HTMLButtonElement>(null)
const tempId = useId()
Expand Down Expand Up @@ -163,9 +163,12 @@ export const Menu = forwardRef(
role="dialog"
id={finalId}
ref={popupRef}
onClose={() => setIsVisible(false)}
onClose={() => {
setIsVisible(false)
setLocalChild(null)
}}
tabIndex={-1}
maxHeight={maxHeight ?? '480px'}
maxHeight={maxHeight ?? '30rem'}
maxWidth={maxWidth}
searchable={searchable}
size={size}
Expand Down
13 changes: 11 additions & 2 deletions packages/ui/src/components/MenuV2/__stories__/Group.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import type { StoryFn } from '@storybook/react'
import { InformationIcon } from '@ultraviolet/icons'
import { MenuV2 } from '..'
import { Badge } from '../../Badge'
import { Stack } from '../../Stack'
import { Tooltip } from '../../Tooltip'
import { DefaultDisclosure } from './Template.stories'

export const Group: StoryFn<typeof MenuV2> = ({ ...props }) => (
<MenuV2 {...props} disclosure={DefaultDisclosure}>
<MenuV2.Group label="Server">
<MenuV2.Group
label="Server"
labelDescription={
<Tooltip text="Your current server">
<InformationIcon size="small" />
</Tooltip>
}
>
<MenuV2.Item borderless>
<Stack
direction="row"
Expand Down Expand Up @@ -55,7 +64,7 @@ Group.parameters = {
docs: {
description: {
story:
'You can group items together using the `Menu.Group` component and adding `Menu.Item` components as children.',
'You can group items together using the `Menu.Group` component and adding `Menu.Item` components as children. On the group you can apply a `label` but also a `labelDescription` allowing to customise it further.',
},
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,41 @@ export const Searchable: StoryFn<typeof MenuV2> = () => (
/>
}
>
<MenuV2.Item sentiment="primary" active>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#BF95F9', '#3D1862']}
shape="circle"
size="xsmall"
/>
Default Project
</Stack>
</MenuV2.Item>
<MenuV2.Item>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FFBFAB', '#822F15']}
shape="circle"
size="xsmall"
/>
Project 1
</Stack>
</MenuV2.Item>
<MenuV2.Item>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FF9EC1', '#740D32']}
shape="circle"
size="xsmall"
/>
Project 2
</Stack>
</MenuV2.Item>
<MenuV2.Group label="Projects">
<MenuV2.Item sentiment="primary" active>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#BF95F9', '#3D1862']}
shape="circle"
size="xsmall"
/>
Default Project
</Stack>
</MenuV2.Item>
<MenuV2.Item>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FFBFAB', '#822F15']}
shape="circle"
size="xsmall"
/>
Project 1
</Stack>
</MenuV2.Item>
<MenuV2.Item>
<Stack direction="row" gap={1} alignItems="center">
<AvatarV2
variant="colors"
colors={['#FF9EC1', '#740D32']}
shape="circle"
size="xsmall"
/>
Project 2
</Stack>
</MenuV2.Item>
</MenuV2.Group>
</MenuV2>
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -800,8 +800,8 @@ exports[`Menu > placement > renders bottom 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1e:"
aria-describedby="menu-:r1e:"
aria-controls="menu-:r1k:"
aria-describedby="menu-:r1k:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -847,8 +847,8 @@ exports[`Menu > placement > renders left 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1h:"
aria-describedby="menu-:r1h:"
aria-controls="menu-:r1n:"
aria-describedby="menu-:r1n:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -894,8 +894,8 @@ exports[`Menu > placement > renders right 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1k:"
aria-describedby="menu-:r1k:"
aria-controls="menu-:r1q:"
aria-describedby="menu-:r1q:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -941,8 +941,8 @@ exports[`Menu > placement > renders top 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1b:"
aria-describedby="menu-:r1b:"
aria-controls="menu-:r1h:"
aria-describedby="menu-:r1h:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -989,6 +989,37 @@ exports[`Menu > renders with Menu.Group 1`] = `
</DocumentFragment>
`;

exports[`Menu > renders with Menu.Group and labelDescription 1`] = `
<DocumentFragment>
.emotion-0 {
display: inherit;
}
.emotion-0[data-container-full-width="true"] {
width: 100%;
}
<div
data-testid="testing"
>
<div
aria-controls="menu-:rb:"
aria-describedby="menu-:rb:"
class="emotion-0 emotion-1"
tabindex="-1"
>
<button
aria-expanded="true"
aria-haspopup="dialog"
type="button"
>
Menu
</button>
</div>
</div>
</DocumentFragment>
`;

exports[`Menu > renders with Menu.Item 1`] = `
<DocumentFragment>
.emotion-0 {
Expand Down Expand Up @@ -1034,8 +1065,8 @@ exports[`Menu > renders with Menu.ItemLink & Menu.Item disabled 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:re:"
aria-describedby="menu-:re:"
aria-controls="menu-:ri:"
aria-describedby="menu-:ri:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -1065,8 +1096,8 @@ exports[`Menu > renders with Menu.ItemLink 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:rb:"
aria-describedby="menu-:rb:"
aria-controls="menu-:rf:"
aria-describedby="menu-:rf:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -1252,8 +1283,8 @@ exports[`Menu > sizes > renders large 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1t:"
aria-describedby="menu-:r1t:"
aria-controls="menu-:r23:"
aria-describedby="menu-:r23:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -1299,8 +1330,8 @@ exports[`Menu > sizes > renders medium 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1q:"
aria-describedby="menu-:r1q:"
aria-controls="menu-:r20:"
aria-describedby="menu-:r20:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down Expand Up @@ -1346,8 +1377,8 @@ exports[`Menu > sizes > renders small 1`] = `
data-testid="testing"
>
<div
aria-controls="menu-:r1n:"
aria-describedby="menu-:r1n:"
aria-controls="menu-:r1t:"
aria-describedby="menu-:r1t:"
class="emotion-0 emotion-1"
tabindex="-1"
>
Expand Down
9 changes: 9 additions & 0 deletions packages/ui/src/components/MenuV2/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ describe('Menu', () => {
</MenuV2>,
))

test(`renders with Menu.Group and labelDescription`, () =>
shouldMatchEmotionSnapshotWithPortal(
<MenuV2 visible disclosure={() => <button type="button">Menu</button>}>
<MenuV2.Group label="Group" labelDescription="This is a description">
<MenuV2.Item>Menu.Item</MenuV2.Item>
</MenuV2.Group>
</MenuV2>,
))

test(`renders with Menu.ItemLink`, () =>
shouldMatchEmotionSnapshotWithPortal(
<MenuV2 visible disclosure={() => <button type="button">Menu</button>}>
Expand Down
Loading

0 comments on commit 61d26ae

Please sign in to comment.