Skip to content

Deprecate DropdownMenu v1 + Remove DropdownMenu v2 #1898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .changeset/deprecate-dropdownmenu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
'@primer/react': major
---

### DropdownMenu

DropdownMenu has been deprecated in favor of ActionMenu with ActionList

See example with selection: https://primer.style/react/ActionMenu#with-selection

Migration guide:

1. Instead of using `items` prop, use `ActionList` inside `ActionMenu`
2. Use `selectionVariant="single"` on `ActionList` to set the right semantics for selection
3. Instead of using `selectedItem` prop, use `selected` prop on `ActionList.Item`
4. Instead of using `renderAnchor` and `placeholder` props on `DropdownMenu`, use `ActionMenu.Button` or `ActionMenu.Anchor`
5. Instead of using `onChange` prop on `DropdownMenu`, use `onSelect` prop on `ActionList.Item`
6. Instead of using `groupMetadata` on `DropdownMenu`, use `ActionList.Group`
7. Instead of `overlayProps` on `DropdownMenu`, use `ActionMenu.Overlay`

<table>
<tr>
<th> Before (v34)</th> <th> After (v35)</th>
</tr>
<tr>
<td valign="top">

```js
const fieldTypes = [
{key: 0, text: 'Text'},
{key: 1, text: 'Number'},
{key: 3, text: 'Date'},
{key: 4, text: 'Single select'},
{key: 5, text: 'Iteration'}
]

const Example = () => {
const [selectedType, setSelectedType] = React.useState()

return (
<DropdownMenu
renderAnchor={({children, ...anchorProps}) => (
<ButtonInvisible {...anchorProps}>
{children} <GearIcon />
</ButtonInvisible>
)}
placeholder="Field type"
items={fieldTypes}
selectedItem={selectedType}
onChange={setSelectedType}
overlayProps={{width: 'medium'}}
/>
)
}
```

</td>
<td valign="top">

```jsx
const fieldTypes = [
{id: 0, text: 'Text'},
{id: 1, text: 'Number'},
{id: 3, text: 'Date'},
{id: 4, text: 'Single select'},
{id: 5, text: 'Iteration'}
]

const Example = () => {
const [selectedType, setSelectedType] = React.useState()

render(
<ActionMenu>
<ActionMenu.Button aria-label="Select field type">{selectedType.name || 'Field type'}</ActionMenu.Button>
<ActionMenu.Overlay width="medium">
<ActionList selectionVariant="single">
{fieldTypes.map(type => (
<ActionList.Item
key={type.id}
selected={type.id === selectedType.id}
onSelect={() => setSelectedType(type)}
>
{type.name}
</ActionList.Item>
))}
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>
)
}
```

</td>
</tr>
</table>

To continue to use the deprecated API for now, change the import path to `@primer/react/deprecated`:

```js
import {DropdownMenu} from '@primer/react/deprecated'
```

You can use the [one-time codemod](https://github.com/primer/react-migrate#readme) to change your import statements automatically.

### drafts/DropdownMenu2

DropdownMenu2 has been removed in favor of ActionMenu with ActionList
3 changes: 1 addition & 2 deletions docs/content/ActionList.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: ActionList
status: Alpha
source: https://github.com/primer/react/tree/main/src/ActionList
storybook: '/react/storybook?path=/story/composite-components-actionlist'
description: An ActionList is a list of items that can be activated or selected. ActionList is the base component for many menu-type components, including DropdownMenu and ActionMenu.
description: An ActionList is a list of items that can be activated or selected. ActionList is the base component for many menu-type components, including ActionMenu and SelectPanel.
---

import {Avatar} from '@primer/react'
Expand Down Expand Up @@ -445,5 +445,4 @@ render(<SelectFields />)
## Related components

- [ActionMenu](/ActionMenu)
- [DropdownMenu](/DropdownMenu)
- [SelectPanel](/SelectPanel)
5 changes: 4 additions & 1 deletion docs/content/ActionMenu.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ const Example = () => {
<ActionList selectionVariant="single">
{fieldTypes.map((type, index) => (
<ActionList.Item key={index} selected={index === selectedIndex} onSelect={() => setSelectedIndex(index)}>
<type.icon /> {type.name}
<ActionList.LeadingVisual>
<type.icon />
</ActionList.LeadingVisual>
{type.name}
</ActionList.Item>
))}
</ActionList>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,91 @@
---
componentId: dropdown_menu
title: DropdownMenu
status: Alpha
status: Deprecated
---

A `DropdownMenu` provides an anchor (button by default) that will open a floating menu of selectable items. The menu can be opened and navigated using keyboard or mouse. When an item is selected, the menu will close and the `onChange` callback will be called. If the default anchor button is used, the anchor contents will be updated with the selection.

## Deprecation

Use [new version of ActionMenu](/ActionMenu#with-selection) with composable API, design updates and accessibility fixes.

**Before**

```jsx
const fieldTypes = [
{key: 0, text: 'Text'},
{key: 1, text: 'Number'},
{key: 3, text: 'Date'},
{key: 4, text: 'Single select'},
{key: 5, text: 'Iteration'}
]

const Example = () => {
const [selectedType, setSelectedType] = React.useState()

return (
<DropdownMenu
renderAnchor={({children, ...anchorProps}) => (
<ButtonInvisible {...anchorProps}>
{children} <GearIcon />
</ButtonInvisible>
)}
placeholder="Field type"
items={fieldTypes}
selectedItem={selectedType}
onChange={setSelectedType}
/>
)
}
```

**After**

Instead of `DropdownMenu`, you can use the `ActionMenu` with `ActionList selectionVariant=single`, this will give menu items the correct semantics:

```jsx
const fieldTypes = [
{id: 0, text: 'Text'},
{id: 1, text: 'Number'},
{id: 3, text: 'Date'},
{id: 4, text: 'Single select'},
{id: 5, text: 'Iteration'}
]

const Example = () => {
const [selectedType, setSelectedType] = React.useState()

render(
<ActionMenu>
<ActionMenu.Button aria-label="Select field type">{selectedType.name || 'Field type'}</ActionMenu.Button>
<ActionMenu.Overlay>
<ActionList selectionVariant="single">
{fieldTypes.map(type => (
<ActionList.Item
key={type.id}
selected={type.id === selectedType.id}
onSelect={() => setSelectedType(type)}
>
{type.name}
</ActionList.Item>
))}
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>
)
}
```

Or continue using deprecated API:

```js
import {DropdownMenu} from '@primer/react/deprecated'
```

## Example

```javascript live noinline
```javascript live noinline deprecated
function DemoComponent() {
const items = React.useMemo(
() => [
Expand Down
Loading