@atlaskit/dropdown-menu 10.1.9 → 11.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/CHANGELOG.md +150 -0
  2. package/__perf__/default.tsx +1 -1
  3. package/__perf__/dropdown-menu.tsx +216 -0
  4. package/codemods/11.0.0-lite-mode.tsx +39 -0
  5. package/codemods/__tests__/11.0.0-lite-mode.test.tsx +48 -0
  6. package/codemods/__tests__/convert-position.test.tsx +88 -0
  7. package/codemods/__tests__/convert-triggerType.test.tsx +100 -0
  8. package/codemods/__tests__/deprecate-items.test.tsx +108 -0
  9. package/codemods/__tests__/deprecate-onItemActivated.test.tsx +108 -0
  10. package/codemods/__tests__/deprecate-onPositioned.test.tsx +108 -0
  11. package/codemods/__tests__/deprecate-shouldFitContainer.tsx +108 -0
  12. package/codemods/__tests__/rename-imports.tsx +136 -0
  13. package/codemods/__tests__/replace-position-to-placement.test.tsx +84 -0
  14. package/codemods/__tests__/replace-shouldAllowMultipleLine.test.tsx +122 -0
  15. package/codemods/__tests__/update-component-callsites.tsx +66 -0
  16. package/codemods/migrates/convert-trigger-type.tsx +57 -0
  17. package/codemods/migrates/deprecate-items.tsx +9 -0
  18. package/codemods/migrates/deprecate-onItemActivated.tsx +9 -0
  19. package/codemods/migrates/deprecate-onPositioned.tsx +9 -0
  20. package/codemods/migrates/deprecate-shouldFitContainer.tsx +9 -0
  21. package/codemods/migrates/rename-imports.tsx +22 -0
  22. package/codemods/migrates/replace-position-to-placement.tsx +38 -0
  23. package/codemods/migrates/replace-shouldAllowMultiline.tsx +47 -0
  24. package/codemods/migrates/update-component-callsites.tsx +13 -0
  25. package/codemods/utils/convert-position.tsx +24 -0
  26. package/codemods/utils/create-rename-import.tsx +41 -0
  27. package/codemods/utils/create-update-callsite.tsx +32 -0
  28. package/dist/cjs/checkbox/dropdown-item-checkbox-group.js +31 -0
  29. package/dist/cjs/checkbox/dropdown-item-checkbox.js +108 -0
  30. package/dist/cjs/dropdown-menu-item-group.js +22 -0
  31. package/dist/cjs/dropdown-menu-item.js +67 -0
  32. package/dist/cjs/dropdown-menu.js +194 -0
  33. package/dist/cjs/index.js +21 -29
  34. package/dist/cjs/{components/item/DropdownItemRadio.js → internal/components/focus-manager.js} +40 -9
  35. package/dist/cjs/internal/components/menu-wrapper.js +68 -0
  36. package/dist/cjs/internal/context/checkbox-group-context.js +14 -0
  37. package/dist/cjs/internal/context/selection-store.js +76 -0
  38. package/dist/cjs/internal/hooks/use-checkbox-state.js +68 -0
  39. package/dist/cjs/internal/hooks/use-radio-state.js +84 -0
  40. package/dist/cjs/internal/hooks/use-register-item-with-focus-manager.js +29 -0
  41. package/dist/cjs/internal/utils/get-icon-colors.js +25 -0
  42. package/dist/cjs/internal/utils/handle-focus.js +58 -0
  43. package/dist/cjs/internal/utils/is-checkbox-item.js +11 -0
  44. package/dist/cjs/internal/utils/is-radio-item.js +11 -0
  45. package/dist/cjs/internal/utils/is-voice-over-supported.js +23 -0
  46. package/dist/cjs/internal/utils/reset-options-in-group.js +23 -0
  47. package/dist/cjs/radio/dropdown-item-radio-group.js +89 -0
  48. package/dist/cjs/radio/dropdown-item-radio.js +108 -0
  49. package/dist/cjs/version.json +1 -1
  50. package/dist/es2019/checkbox/dropdown-item-checkbox-group.js +21 -0
  51. package/dist/es2019/checkbox/dropdown-item-checkbox.js +67 -0
  52. package/dist/es2019/dropdown-menu-item-group.js +11 -0
  53. package/dist/es2019/dropdown-menu-item.js +49 -0
  54. package/dist/es2019/dropdown-menu.js +151 -0
  55. package/dist/es2019/index.js +7 -11
  56. package/dist/es2019/internal/components/focus-manager.js +40 -0
  57. package/dist/es2019/internal/components/menu-wrapper.js +44 -0
  58. package/dist/es2019/internal/context/checkbox-group-context.js +6 -0
  59. package/dist/es2019/internal/context/selection-store.js +54 -0
  60. package/dist/es2019/internal/hooks/use-checkbox-state.js +45 -0
  61. package/dist/es2019/internal/hooks/use-radio-state.js +56 -0
  62. package/dist/es2019/internal/hooks/use-register-item-with-focus-manager.js +19 -0
  63. package/dist/es2019/internal/utils/get-icon-colors.js +17 -0
  64. package/dist/es2019/internal/utils/handle-focus.js +48 -0
  65. package/dist/es2019/internal/utils/is-checkbox-item.js +4 -0
  66. package/dist/es2019/internal/utils/is-radio-item.js +4 -0
  67. package/dist/es2019/internal/utils/is-voice-over-supported.js +11 -0
  68. package/dist/es2019/internal/utils/reset-options-in-group.js +7 -0
  69. package/dist/es2019/radio/dropdown-item-radio-group.js +56 -0
  70. package/dist/es2019/radio/dropdown-item-radio.js +67 -0
  71. package/dist/es2019/version.json +1 -1
  72. package/dist/esm/checkbox/dropdown-item-checkbox-group.js +19 -0
  73. package/dist/esm/checkbox/dropdown-item-checkbox.js +81 -0
  74. package/dist/esm/dropdown-menu-item-group.js +11 -0
  75. package/dist/esm/dropdown-menu-item.js +52 -0
  76. package/dist/esm/dropdown-menu.js +168 -0
  77. package/dist/esm/index.js +7 -11
  78. package/dist/esm/internal/components/focus-manager.js +39 -0
  79. package/dist/esm/internal/components/menu-wrapper.js +45 -0
  80. package/dist/esm/internal/context/checkbox-group-context.js +6 -0
  81. package/dist/esm/internal/context/selection-store.js +58 -0
  82. package/dist/esm/internal/hooks/use-checkbox-state.js +55 -0
  83. package/dist/esm/internal/hooks/use-radio-state.js +70 -0
  84. package/dist/esm/internal/hooks/use-register-item-with-focus-manager.js +19 -0
  85. package/dist/esm/internal/utils/get-icon-colors.js +17 -0
  86. package/dist/esm/internal/utils/handle-focus.js +47 -0
  87. package/dist/esm/internal/utils/is-checkbox-item.js +4 -0
  88. package/dist/esm/internal/utils/is-radio-item.js +4 -0
  89. package/dist/esm/internal/utils/is-voice-over-supported.js +15 -0
  90. package/dist/esm/internal/utils/reset-options-in-group.js +13 -0
  91. package/dist/esm/radio/dropdown-item-radio-group.js +66 -0
  92. package/dist/esm/radio/dropdown-item-radio.js +81 -0
  93. package/dist/esm/version.json +1 -1
  94. package/dist/types/checkbox/dropdown-item-checkbox-group.d.ts +16 -0
  95. package/dist/types/checkbox/dropdown-item-checkbox.d.ts +13 -0
  96. package/dist/types/dropdown-menu-item-group.d.ts +11 -0
  97. package/dist/types/dropdown-menu-item.d.ts +13 -0
  98. package/dist/types/dropdown-menu.d.ts +13 -0
  99. package/dist/types/index.d.ts +8 -10
  100. package/dist/types/internal/components/focus-manager.d.ts +19 -0
  101. package/dist/types/internal/components/menu-wrapper.d.ts +11 -0
  102. package/dist/types/internal/context/checkbox-group-context.d.ts +5 -0
  103. package/dist/types/internal/context/selection-store.d.ts +27 -0
  104. package/dist/types/internal/hooks/use-checkbox-state.d.ts +14 -0
  105. package/dist/types/internal/hooks/use-radio-state.d.ts +9 -0
  106. package/dist/types/internal/hooks/use-register-item-with-focus-manager.d.ts +4 -0
  107. package/dist/types/internal/utils/get-icon-colors.d.ts +8 -0
  108. package/dist/types/internal/utils/handle-focus.d.ts +2 -0
  109. package/dist/types/internal/utils/is-checkbox-item.d.ts +1 -0
  110. package/dist/types/internal/utils/is-radio-item.d.ts +1 -0
  111. package/dist/types/internal/utils/is-voice-over-supported.d.ts +2 -0
  112. package/dist/types/internal/utils/reset-options-in-group.d.ts +4 -0
  113. package/dist/types/radio/dropdown-item-radio-group.d.ts +25 -0
  114. package/dist/types/radio/dropdown-item-radio.d.ts +13 -0
  115. package/dist/types/types.d.ts +254 -79
  116. package/package.json +35 -20
  117. package/dist/cjs/components/DropdownMenu.js +0 -230
  118. package/dist/cjs/components/DropdownMenuStateless.js +0 -523
  119. package/dist/cjs/components/context/DropdownItemClickManager.js +0 -72
  120. package/dist/cjs/components/context/DropdownItemFocusManager.js +0 -178
  121. package/dist/cjs/components/context/DropdownItemSelectionCache.js +0 -131
  122. package/dist/cjs/components/context/DropdownItemSelectionManager.js +0 -185
  123. package/dist/cjs/components/group/DropdownItemGroup.js +0 -61
  124. package/dist/cjs/components/group/DropdownItemGroupCheckbox.js +0 -16
  125. package/dist/cjs/components/group/DropdownItemGroupRadio.js +0 -16
  126. package/dist/cjs/components/group/ert-group-selection.js +0 -8
  127. package/dist/cjs/components/hoc/withItemSelectionManager.js +0 -66
  128. package/dist/cjs/components/hoc/withToggleInteraction.js +0 -175
  129. package/dist/cjs/components/item/DropdownItem.js +0 -19
  130. package/dist/cjs/components/item/DropdownItemCheckbox.js +0 -28
  131. package/dist/cjs/components/item/ert-item-checkbox.js +0 -8
  132. package/dist/cjs/components/item/ert-item-radio.js +0 -8
  133. package/dist/cjs/components/item/ert-item.js +0 -8
  134. package/dist/cjs/styled/WidthConstrainer.js +0 -21
  135. package/dist/cjs/util/contextNamespace.js +0 -19
  136. package/dist/cjs/util/getDisplayName.js +0 -14
  137. package/dist/cjs/util/keys.js +0 -18
  138. package/dist/cjs/util/safeContextCall.js +0 -27
  139. package/dist/cjs/util/supportsVoiceover.js +0 -17
  140. package/dist/es2019/components/DropdownMenu.js +0 -156
  141. package/dist/es2019/components/DropdownMenuStateless.js +0 -459
  142. package/dist/es2019/components/context/DropdownItemClickManager.js +0 -31
  143. package/dist/es2019/components/context/DropdownItemFocusManager.js +0 -134
  144. package/dist/es2019/components/context/DropdownItemSelectionCache.js +0 -68
  145. package/dist/es2019/components/context/DropdownItemSelectionManager.js +0 -140
  146. package/dist/es2019/components/group/DropdownItemGroup.js +0 -17
  147. package/dist/es2019/components/group/DropdownItemGroupCheckbox.js +0 -3
  148. package/dist/es2019/components/group/DropdownItemGroupRadio.js +0 -3
  149. package/dist/es2019/components/group/ert-group-selection.js +0 -1
  150. package/dist/es2019/components/hoc/withItemSelectionManager.js +0 -20
  151. package/dist/es2019/components/hoc/withToggleInteraction.js +0 -119
  152. package/dist/es2019/components/item/DropdownItem.js +0 -3
  153. package/dist/es2019/components/item/DropdownItemCheckbox.js +0 -5
  154. package/dist/es2019/components/item/DropdownItemRadio.js +0 -5
  155. package/dist/es2019/components/item/ert-item-checkbox.js +0 -1
  156. package/dist/es2019/components/item/ert-item-radio.js +0 -1
  157. package/dist/es2019/components/item/ert-item.js +0 -1
  158. package/dist/es2019/styled/WidthConstrainer.js +0 -6
  159. package/dist/es2019/util/contextNamespace.js +0 -6
  160. package/dist/es2019/util/getDisplayName.js +0 -4
  161. package/dist/es2019/util/keys.js +0 -6
  162. package/dist/es2019/util/safeContextCall.js +0 -10
  163. package/dist/es2019/util/supportsVoiceover.js +0 -5
  164. package/dist/esm/components/DropdownMenu.js +0 -215
  165. package/dist/esm/components/DropdownMenuStateless.js +0 -516
  166. package/dist/esm/components/context/DropdownItemClickManager.js +0 -59
  167. package/dist/esm/components/context/DropdownItemFocusManager.js +0 -164
  168. package/dist/esm/components/context/DropdownItemSelectionCache.js +0 -113
  169. package/dist/esm/components/context/DropdownItemSelectionManager.js +0 -174
  170. package/dist/esm/components/group/DropdownItemGroup.js +0 -43
  171. package/dist/esm/components/group/DropdownItemGroupCheckbox.js +0 -3
  172. package/dist/esm/components/group/DropdownItemGroupRadio.js +0 -3
  173. package/dist/esm/components/group/ert-group-selection.js +0 -1
  174. package/dist/esm/components/hoc/withItemSelectionManager.js +0 -47
  175. package/dist/esm/components/hoc/withToggleInteraction.js +0 -155
  176. package/dist/esm/components/item/DropdownItem.js +0 -3
  177. package/dist/esm/components/item/DropdownItemCheckbox.js +0 -7
  178. package/dist/esm/components/item/DropdownItemRadio.js +0 -7
  179. package/dist/esm/components/item/ert-item-checkbox.js +0 -1
  180. package/dist/esm/components/item/ert-item-radio.js +0 -1
  181. package/dist/esm/components/item/ert-item.js +0 -1
  182. package/dist/esm/styled/WidthConstrainer.js +0 -9
  183. package/dist/esm/util/contextNamespace.js +0 -8
  184. package/dist/esm/util/getDisplayName.js +0 -6
  185. package/dist/esm/util/keys.js +0 -6
  186. package/dist/esm/util/safeContextCall.js +0 -18
  187. package/dist/esm/util/supportsVoiceover.js +0 -9
  188. package/dist/types/components/DropdownMenu.d.ts +0 -36
  189. package/dist/types/components/DropdownMenuStateless.d.ts +0 -82
  190. package/dist/types/components/context/DropdownItemClickManager.d.ts +0 -19
  191. package/dist/types/components/context/DropdownItemFocusManager.d.ts +0 -35
  192. package/dist/types/components/context/DropdownItemSelectionCache.d.ts +0 -31
  193. package/dist/types/components/context/DropdownItemSelectionManager.d.ts +0 -34
  194. package/dist/types/components/group/DropdownItemGroup.d.ts +0 -12
  195. package/dist/types/components/group/DropdownItemGroupCheckbox.d.ts +0 -55
  196. package/dist/types/components/group/DropdownItemGroupRadio.d.ts +0 -55
  197. package/dist/types/components/group/ert-group-selection.d.ts +0 -6
  198. package/dist/types/components/hoc/withItemSelectionManager.d.ts +0 -63
  199. package/dist/types/components/hoc/withToggleInteraction.d.ts +0 -98
  200. package/dist/types/components/item/DropdownItem.d.ts +0 -65
  201. package/dist/types/components/item/DropdownItemCheckbox.d.ts +0 -80
  202. package/dist/types/components/item/DropdownItemRadio.d.ts +0 -80
  203. package/dist/types/components/item/ert-item-checkbox.d.ts +0 -2
  204. package/dist/types/components/item/ert-item-radio.d.ts +0 -2
  205. package/dist/types/components/item/ert-item.d.ts +0 -2
  206. package/dist/types/styled/WidthConstrainer.d.ts +0 -7
  207. package/dist/types/util/contextNamespace.d.ts +0 -4
  208. package/dist/types/util/getDisplayName.d.ts +0 -3
  209. package/dist/types/util/keys.d.ts +0 -6
  210. package/dist/types/util/safeContextCall.d.ts +0 -6
  211. package/dist/types/util/supportsVoiceover.d.ts +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,155 @@
1
1
  # @atlaskit/dropdown-menu
2
2
 
3
+ ## 11.0.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [`19d72473dfb`](https://bitbucket.org/atlassian/atlassian-frontend/commits/19d72473dfb) - Updates usage of deprecated token names so they're aligned with the latest naming conventions. No UI or visual changes
8
+ - [`19d72473dfb`](https://bitbucket.org/atlassian/atlassian-frontend/commits/19d72473dfb) - Bump dependency tiny-invariant to latest"
9
+ - Updated dependencies
10
+
11
+ ## 11.0.2
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies
16
+
17
+ ## 11.0.1
18
+
19
+ ### Patch Changes
20
+
21
+ - [`c2dd770a743`](https://bitbucket.org/atlassian/atlassian-frontend/commits/c2dd770a743) - Add new prop which controls is outside click should be bound using capture
22
+ - Updated dependencies
23
+
24
+ ## 11.0.0
25
+
26
+ ### Major Changes
27
+
28
+ - [`d65d8a545af`](https://bitbucket.org/atlassian/atlassian-frontend/commits/d65d8a545af) - [ux] In this version, we have significantly reduced the bundle size, improved the runtime performance and simplified the API for dropdown menu. We've also removed deprecated dependencies, which bring consistency to the spacing and padding of dropdown menu items, which may require updating VR snapshots. We've also provided codemods to help you upgrade to the latest API.
29
+
30
+ ## Running the codemod cli
31
+
32
+ To run the codemod: You first need to have the latest version installed
33
+
34
+ yarn upgrade @atlaskit/dropdown-menu@^11.0.0
35
+
36
+ Once upgraded, use @atlaskit/codemod-cli:
37
+
38
+ npx @atlaskit/codemod-cli --parser {tsx|babylon} --extensions ts,tsx,js [relativePath]
39
+
40
+ The CLI will show a list of components and versions so select @atlaskit/dropdown-menu@11.0.0 and you will automatically be upgraded. If your usage of @atlaskit/modal-dialog cannot be upgraded a comment will be left that a manual change is required.
41
+
42
+ Run npx @atlaskit/codemod-cli -h for more details on usage. For Atlassians, refer to the documentation for more details on the codemod CLI.
43
+
44
+ ## Behaviour changes
45
+
46
+ - _Portaling_ – The dropdown menu is now rendered in a React Portal and is appended at the bottom of the `<body>`. In most cases, this shouldn't make much of a difference. But if you have any tests that assert on DOM/React tree like snapshot tests, those will need to be updated.
47
+
48
+ - _Focus lock_ – As the menu is not rendered next to the trigger, the focus is trapped within the menu when the menu is open.
49
+
50
+ - _Layering_ – Another sideeffect of poratling the menu is that it is now part of the global stacking context, rather than a local stacking context. We've provided a new `zIndex` prop incase the layering is off.
51
+
52
+ - _Title and description wrapping behaviour_ – Menu items which have a long title and description now wrap into multiple line by default, instead of cutting it off and showing ellipsis. You can override the default behaviour by setting shouldTitleWrap and shouldDescriptionWrap to false.
53
+
54
+ ## Visual changes
55
+
56
+ - _Menu item padding_ – Dropdown menu items have 16px more padding horizontally.
57
+ - _Removed elemAfter in group title_ – Icon after the group title has been removed.
58
+
59
+ ## API Changes
60
+
61
+ Dropdown menu items no longer `@atlaskit/item` as the underlying component, they use `@atlaskit/menu` instead. This mean that some of the props that used to be spread over an Item are no longer supported. In addition to that, the following API changes have been made:
62
+
63
+ - `shouldFitContainer` – Deprecated. This prop has been deprecated and the codemod will remove it.
64
+ - `shouldAllowMultiline` – This prop has been split up into two: shouldTitleWrap and shouldDescriptionWrap. The codemod replaces its occurance with the two new ones.
65
+ - `onItemActivated` – The prop has been deprecated and the codemod will remove it. Use `onClick` instead.
66
+ - `onPositionEnd` – The prop has been deprecated and the codemod will remove it. Use `onOpenChange` instead.
67
+ - `boundariesElement` – The prop has been deprecated and the codemod will remove it. It is not relevant anymore as the Menu is portaled.
68
+ - `isMenuFixed` – The prop has been deprecated and the codemod will remove it. It is not relevant anymore as the Menu is portaled.
69
+ - `position` – The placement values are now consistent with Popup. They have a 1:1 mapping with the old values. The codemod maps the old values to the new.
70
+ - `zIndex` – The zIndex prop will need to be applied as an escape hatch in case the menu runs into any layering clashes with other elements on the screen.
71
+ - `items` – This prop has been deprecated because it is poor bad for performance. Pass MenuItems as children instead. The codemod removes the item prop. You’ll need to manually change it to children.
72
+ - `trigger`, `triggerProps` and `triggerType` – This API has been simplified the most. triggerType and triggerProps have been deprecated. trigger now accepts either a string or custom react element. If a string is passed, it is rendered as an @atlaskit/button. If a react component is passed, it is used as a trigger. Make sure to spread the provided props onto the component, they are used to position the component and provide accessibility attributes. The codemod handles the simplest case where the the triggerType is a string. For every other case, the codemod leaves a comment. Look at the section below on how it can be fixed in most cases.
73
+ - `isCompact` on MenuItem – The prop has been deprecated and the codemod will remove it.
74
+ - `isHidden` on MenuItem – The prop has been deprecated and the codemod will remove it.
75
+ - `autoFocus` on MenuItem – The prop has been deprecated and the codemod will remove it. Focus is directly applied to the first menu item.
76
+
77
+ ## Entrypoint changes
78
+
79
+ - `DropdownMenuStateless` – DropdownMenuStateless has been deprecated. The default export DropdownMenu handles both stateless and stateful logic. The API for DropdownMenuStateless has been retained and works as expected with DropdownMenu.The codemod converts the named import into a default import.
80
+ - `DropdownItemGroupCheckbox` – Renamed to DropdownItemCheckboxGroup. Codemod updates the import declaration.
81
+ - `DropdownItemGroupRadio` – Renamed to DropdownItemRadioGroup. Codemod updates the import declaration.
82
+
83
+ ## Updating the trigger prop
84
+
85
+ **Before**
86
+
87
+ ```
88
+ const DropdownMenuCustomTriggerButtonExample = () => {
89
+ return (
90
+ <DropdownMenu
91
+ triggerButtonProps={{ iconBefore: <MoreIcon label="more" /> }}
92
+ triggerType="button"
93
+ trigger="Click to open"
94
+ >
95
+ <DropdownItemGroup>
96
+ <DropdownItem>Edit</DropdownItem>
97
+ <DropdownItem>Share</DropdownItem>
98
+ <DropdownItem>Move</DropdownItem>
99
+ <DropdownItem>Clone</DropdownItem>
100
+ <DropdownItem>Delete</DropdownItem>
101
+ <DropdownItem>Report</DropdownItem>
102
+ </DropdownItemGroup>
103
+ </DropdownMenu>
104
+ );
105
+ };
106
+ ```
107
+
108
+ **After**
109
+
110
+ ```
111
+ const DropdownMenuCustomTriggerButtonExample = () => {
112
+ return (
113
+ <DropdownMenu
114
+ trigger={({ triggerRef, ...props }) => (
115
+ // 1. use `@atlaskit/button` or any other custom component
116
+ <Button
117
+ // 2. Spread the provided props
118
+ {...props}
119
+ // 3. Apply `triggerButtonProps` directly to button
120
+ iconBefore={<MoreIcon label="more" />}
121
+ // 4. Make sure to pass the ref
122
+ ref={triggerRef}
123
+ >
124
+ // 5. Move trigger label to be children
125
+ Click to open
126
+ </Button>
127
+ )}
128
+ >
129
+ <DropdownItemGroup>
130
+ <DropdownItem>Edit</DropdownItem>
131
+ <DropdownItem>Share</DropdownItem>
132
+ <DropdownItem>Move</DropdownItem>
133
+ <DropdownItem>Clone</DropdownItem>
134
+ <DropdownItem>Delete</DropdownItem>
135
+ <DropdownItem>Report</DropdownItem>
136
+ </DropdownItemGroup>
137
+ </DropdownMenu>
138
+ );
139
+ };
140
+ ```
141
+
142
+ ### Minor Changes
143
+
144
+ - [`36322cbce4d`](https://bitbucket.org/atlassian/atlassian-frontend/commits/36322cbce4d) - Export CustomTriggerProps type from dropdown-menu
145
+
146
+ ### Patch Changes
147
+
148
+ - [`7df1c79ae46`](https://bitbucket.org/atlassian/atlassian-frontend/commits/7df1c79ae46) - Enables DS linting rules and updates the code to adhere to the new conventions
149
+ - [`bc17a568ae8`](https://bitbucket.org/atlassian/atlassian-frontend/commits/bc17a568ae8) - Update types to include rel attribute
150
+ - [`e3a3d13a0b8`](https://bitbucket.org/atlassian/atlassian-frontend/commits/e3a3d13a0b8) - Added a performance test for use with `storybook-addon-performance`.
151
+ - Updated dependencies
152
+
3
153
  ## 10.1.9
4
154
 
5
155
  ### Patch Changes
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import DropdownMenu, { DropdownItem, DropdownItemGroup } from '../src';
4
4
 
5
5
  const DropdownMenuDefaultExample = () => (
6
- <DropdownMenu trigger="Cities in Australia" triggerType="button">
6
+ <DropdownMenu trigger="Cities in Australia">
7
7
  <DropdownItemGroup>
8
8
  <DropdownItem>Sydney</DropdownItem>
9
9
  <DropdownItem>Melbourne</DropdownItem>
@@ -0,0 +1,216 @@
1
+ import React from 'react';
2
+
3
+ import { fireEvent, screen, waitFor } from '@testing-library/dom';
4
+ import type {
5
+ InteractionTaskArgs,
6
+ PublicInteractionTask,
7
+ } from 'storybook-addon-performance';
8
+ import invariant from 'tiny-invariant';
9
+
10
+ import DropdownMenu, {
11
+ DropdownItem,
12
+ DropdownItemCheckbox,
13
+ DropdownItemCheckboxGroup,
14
+ DropdownItemGroup,
15
+ DropdownItemRadio,
16
+ DropdownItemRadioGroup,
17
+ } from '../src';
18
+
19
+ const DropdownMenuPerformance = () => (
20
+ <DropdownMenu trigger="Page actions" testId="dropdown-menu">
21
+ <DropdownItemGroup>
22
+ <DropdownItem>Edit</DropdownItem>
23
+ <DropdownItem>Copy</DropdownItem>
24
+ <DropdownItem>Delete</DropdownItem>
25
+ </DropdownItemGroup>
26
+ <DropdownItemCheckboxGroup id="flags" title="Flags">
27
+ <DropdownItemCheckbox id="tokens">Tokens</DropdownItemCheckbox>
28
+ <DropdownItemCheckbox id="dark-mode">Dark mode</DropdownItemCheckbox>
29
+ </DropdownItemCheckboxGroup>
30
+ <DropdownItemRadioGroup id="font-size" title="Font size">
31
+ <DropdownItemRadio id="smaller">Smaller</DropdownItemRadio>
32
+ <DropdownItemRadio id="default" defaultSelected>
33
+ Default
34
+ </DropdownItemRadio>
35
+ <DropdownItemRadio id="larger">Larger</DropdownItemRadio>
36
+ </DropdownItemRadioGroup>
37
+ </DropdownMenu>
38
+ );
39
+
40
+ const getTrigger = (container: HTMLElement): HTMLElement => {
41
+ const trigger: HTMLElement | null = container.querySelector(
42
+ '[data-testid="dropdown-menu--trigger"]',
43
+ );
44
+ if (trigger === null) {
45
+ throw new Error('Could not find the dropdown menu trigger');
46
+ }
47
+ return trigger;
48
+ };
49
+
50
+ const interactionTasks: PublicInteractionTask[] = [
51
+ {
52
+ name: 'Display dropdown',
53
+ description: 'Click to open the dropdown menu',
54
+ run: async ({
55
+ container,
56
+ controls,
57
+ }: InteractionTaskArgs): Promise<void> => {
58
+ const trigger = getTrigger(container);
59
+
60
+ await controls.time(async () => {
61
+ fireEvent.click(trigger);
62
+ await screen.findByText('Edit');
63
+ });
64
+ },
65
+ },
66
+ {
67
+ name: 'Hide dropdown (trigger)',
68
+ description: 'Click the trigger to hide the dropdown menu',
69
+ run: async ({
70
+ container,
71
+ controls,
72
+ }: InteractionTaskArgs): Promise<void> => {
73
+ const trigger = getTrigger(container);
74
+ fireEvent.click(trigger);
75
+
76
+ await screen.findByText('Edit');
77
+ await controls.time(async () => {
78
+ fireEvent.click(trigger);
79
+ await waitFor(() => invariant(screen.queryByText('Edit') === null));
80
+ });
81
+ },
82
+ },
83
+ {
84
+ name: 'Hide dropdown (escape)',
85
+ description: 'Press escape to hide the dropdown menu',
86
+ run: async ({
87
+ container,
88
+ controls,
89
+ }: InteractionTaskArgs): Promise<void> => {
90
+ const trigger = getTrigger(container);
91
+ fireEvent.click(trigger);
92
+
93
+ await screen.findByText('Edit');
94
+ await controls.time(async () => {
95
+ fireEvent.keyDown(container, { key: 'Escape', code: 'Escape' });
96
+ await waitFor(() => invariant(screen.queryByText('Edit') === null));
97
+ });
98
+ },
99
+ },
100
+ {
101
+ name: 'Hide dropdown (outside click)',
102
+ description: 'Click outside to hide the dropdown menu',
103
+ run: async ({
104
+ container,
105
+ controls,
106
+ }: InteractionTaskArgs): Promise<void> => {
107
+ const trigger = getTrigger(container);
108
+ fireEvent.click(trigger);
109
+
110
+ await screen.findByText('Edit');
111
+ await controls.time(async () => {
112
+ fireEvent.click(container);
113
+ await waitFor(() => invariant(screen.queryByText('Edit') === null));
114
+ });
115
+ },
116
+ },
117
+ {
118
+ name: 'Select item',
119
+ description: 'Click menu item to select it',
120
+ run: async ({
121
+ container,
122
+ controls,
123
+ }: InteractionTaskArgs): Promise<void> => {
124
+ const trigger = getTrigger(container);
125
+ fireEvent.click(trigger);
126
+
127
+ const label = await screen.findByText('Edit');
128
+ await controls.time(async () => {
129
+ label.click();
130
+ });
131
+ },
132
+ },
133
+ {
134
+ /**
135
+ * NOTE:
136
+ * This test has an unhandled error on CI, but runs fine locally.
137
+ * It doesn't stop the pipeline, but its results aren't reported.
138
+ */
139
+ name: 'Select checkbox',
140
+ description: 'Click a checkbox menu item to select it',
141
+ run: async ({
142
+ container,
143
+ controls,
144
+ }: InteractionTaskArgs): Promise<void> => {
145
+ const trigger = getTrigger(container);
146
+ fireEvent.click(trigger);
147
+
148
+ const label = await screen.findByText('Tokens');
149
+ const checkbox: HTMLElement | null = label.closest('[role="checkbox"]');
150
+ if (checkbox === null) {
151
+ throw new Error('Could not find the checkbox');
152
+ }
153
+
154
+ await controls.time(async () => {
155
+ checkbox.click();
156
+ await waitFor(
157
+ () => {
158
+ const ariaChecked = checkbox.getAttribute('aria-checked');
159
+ invariant(
160
+ ariaChecked === 'true',
161
+ `Checkbox should be checked (is "${ariaChecked}")`,
162
+ );
163
+ },
164
+ { timeout: 5000 },
165
+ );
166
+ });
167
+ },
168
+ },
169
+ {
170
+ /**
171
+ * NOTE:
172
+ * This test has an unhandled error on CI, but runs fine locally.
173
+ * It doesn't stop the pipeline, but its results aren't reported.
174
+ */
175
+ name: 'Select radio',
176
+ description: 'Click a radio menu item to select it',
177
+ run: async ({
178
+ container,
179
+ controls,
180
+ }: InteractionTaskArgs): Promise<void> => {
181
+ const trigger = getTrigger(container);
182
+ fireEvent.click(trigger);
183
+
184
+ const label = await screen.findByText('Smaller');
185
+ const radio: HTMLElement | null = label.closest('[role="radio"]');
186
+ if (radio === null) {
187
+ throw new Error('Could not find the radio');
188
+ }
189
+
190
+ await controls.time(async () => {
191
+ radio.click();
192
+ await waitFor(
193
+ () => {
194
+ const ariaChecked = radio.getAttribute('aria-checked');
195
+ invariant(
196
+ ariaChecked === 'true',
197
+ `Radio should be checked (is "${ariaChecked}")`,
198
+ );
199
+ },
200
+ { timeout: 5000 },
201
+ );
202
+ });
203
+ },
204
+ },
205
+ ];
206
+
207
+ DropdownMenuPerformance.story = {
208
+ name: 'Dropdown menu',
209
+ parameters: {
210
+ performance: {
211
+ interactions: interactionTasks,
212
+ },
213
+ },
214
+ };
215
+
216
+ export default DropdownMenuPerformance;
@@ -0,0 +1,39 @@
1
+ import { createTransformer } from '@atlaskit/codemod-utils';
2
+
3
+ import convertTriggerType from './migrates/convert-trigger-type';
4
+ import deprecateItems from './migrates/deprecate-items';
5
+ import deprecateOnItemActivated from './migrates/deprecate-onItemActivated';
6
+ import deprecateOnPositioned from './migrates/deprecate-onPositioned';
7
+ import deprecateShouldFitContainer from './migrates/deprecate-shouldFitContainer';
8
+ import {
9
+ renameDropdownItemGroupCheckbox,
10
+ renameDropdownItemGroupRadio,
11
+ renameDropdownMenuStateless,
12
+ } from './migrates/rename-imports';
13
+ import updatePositionValue from './migrates/replace-position-to-placement';
14
+ import replaceShouldAllowMultiline from './migrates/replace-shouldAllowMultiline';
15
+ import {
16
+ updateDropdownItemGroupCheckboxCallsite,
17
+ updateDropdownItemGroupRadioCallsite,
18
+ } from './migrates/update-component-callsites';
19
+
20
+ const transformer = createTransformer([
21
+ deprecateItems,
22
+ deprecateOnItemActivated,
23
+ deprecateOnPositioned,
24
+ deprecateShouldFitContainer,
25
+
26
+ replaceShouldAllowMultiline,
27
+ updatePositionValue,
28
+
29
+ renameDropdownItemGroupCheckbox,
30
+ renameDropdownItemGroupRadio,
31
+ renameDropdownMenuStateless,
32
+
33
+ updateDropdownItemGroupCheckboxCallsite,
34
+ updateDropdownItemGroupRadioCallsite,
35
+
36
+ convertTriggerType,
37
+ ]);
38
+
39
+ export default transformer;
@@ -0,0 +1,48 @@
1
+ // eslint-disable-next-line @repo/internal/fs/filename-pattern-match
2
+ jest.autoMockOff();
3
+
4
+ import transformer from '../11.0.0-lite-mode';
5
+
6
+ const defineInlineTest = require('jscodeshift/dist/testUtils').defineInlineTest;
7
+
8
+ describe('apply all needed codemods for version 11.0.0 major bump', () => {
9
+ defineInlineTest(
10
+ { default: transformer, parser: 'tsx' },
11
+ {},
12
+ `
13
+ import React from "react";
14
+ import DropdownMenu, {
15
+ DropdownItemGroupCheckbox as MyComponent, DropdownItemCheckbox,
16
+ } from "@atlaskit/dropdown-menu";
17
+
18
+ export default () => (
19
+ <DropdownMenu
20
+ trigger="Click to open"
21
+ triggerType="button"
22
+ items={[]}
23
+ onItemActivated={() => {}}
24
+ onPositioned={() => {}}
25
+ position="bottom left"
26
+ shouldFitContainer={false}
27
+ shouldAllowMultiline>
28
+ </DropdownMenu>
29
+ );
30
+ `,
31
+ `
32
+ import React from "react";
33
+ import DropdownMenu, {
34
+ DropdownItemCheckboxGroup as MyComponent, DropdownItemCheckbox,
35
+ } from "@atlaskit/dropdown-menu";
36
+
37
+ export default () => (
38
+ <DropdownMenu
39
+ trigger="Click to open"
40
+ placement="bottom-start"
41
+ shouldTitleWrap
42
+ shouldDescriptionWrap>
43
+ </DropdownMenu>
44
+ );
45
+ `,
46
+ 'should not change anything when items is not used ',
47
+ );
48
+ });
@@ -0,0 +1,88 @@
1
+ import convertPosition from '../utils/convert-position';
2
+
3
+ describe('convert old position notation', () => {
4
+ describe('edge cases', () => {
5
+ it('fallback to bottom-start', () => {
6
+ const position = convertPosition('unknown');
7
+ expect(position).toBe('bottom-start');
8
+ });
9
+
10
+ it('fallback to bottom-start', () => {
11
+ const position = convertPosition();
12
+ expect(position).toBe('bottom-start');
13
+ });
14
+
15
+ it('trim', () => {
16
+ const position = convertPosition(' top left ');
17
+ expect(position).toBe('top-start');
18
+ });
19
+ });
20
+
21
+ describe('convert top', () => {
22
+ it('convert top left', () => {
23
+ const position = convertPosition('top left');
24
+ expect(position).toBe('top-start');
25
+ });
26
+
27
+ it('convert top center', () => {
28
+ const position = convertPosition('top center');
29
+ expect(position).toBe('top');
30
+ });
31
+
32
+ it('convert top right', () => {
33
+ const position = convertPosition('top right');
34
+ expect(position).toBe('top-end');
35
+ });
36
+ });
37
+
38
+ describe('convert right', () => {
39
+ it('convert right top', () => {
40
+ const position = convertPosition('right top');
41
+ expect(position).toBe('right-start');
42
+ });
43
+
44
+ it('convert right middle', () => {
45
+ const position = convertPosition('right middle');
46
+ expect(position).toBe('right');
47
+ });
48
+
49
+ it('convert right bottom', () => {
50
+ const position = convertPosition('right bottom');
51
+ expect(position).toBe('right-end');
52
+ });
53
+ });
54
+
55
+ describe('convert bottom', () => {
56
+ it('convert bottom left', () => {
57
+ const position = convertPosition('bottom left');
58
+ expect(position).toBe('bottom-start');
59
+ });
60
+
61
+ it('convert bottom center', () => {
62
+ const position = convertPosition('bottom center');
63
+ expect(position).toBe('bottom');
64
+ });
65
+
66
+ it('convert bottom right', () => {
67
+ const position = convertPosition('bottom right');
68
+ expect(position).toBe('bottom-end');
69
+ });
70
+ });
71
+
72
+ describe('convert left', () => {
73
+ it('convert left top', () => {
74
+ const position = convertPosition('left top');
75
+ expect(position).toBe('left-start');
76
+ });
77
+
78
+ it('convert left middle', () => {
79
+ const position = convertPosition('left middle');
80
+ expect(position).toBe('left');
81
+ });
82
+
83
+ it('convert left bottom', () => {
84
+ const position = convertPosition('left bottom');
85
+ expect(position).toBe('left-end');
86
+ });
87
+ });
88
+ });
@@ -0,0 +1,100 @@
1
+ // eslint-disable-next-line @repo/internal/fs/filename-pattern-match
2
+ jest.autoMockOff();
3
+
4
+ import { createTransformer } from '@atlaskit/codemod-utils';
5
+
6
+ import convertTriggerType from '../migrates/convert-trigger-type';
7
+
8
+ const transformer = createTransformer([convertTriggerType]);
9
+
10
+ const defineInlineTest = require('jscodeshift/dist/testUtils').defineInlineTest;
11
+
12
+ describe('update position value', () => {
13
+ defineInlineTest(
14
+ { default: transformer, parser: 'tsx' },
15
+ {},
16
+ `
17
+ import React from "react";
18
+ import DropdownMenu from "@atlaskit/dropdown-menu";
19
+
20
+ export default () => (
21
+ <DropdownMenu trigger="Click to open">
22
+ </DropdownMenu>
23
+ );
24
+ `,
25
+ `
26
+ import React from "react";
27
+ import DropdownMenu from "@atlaskit/dropdown-menu";
28
+
29
+ export default () => (
30
+ <DropdownMenu trigger="Click to open">
31
+ </DropdownMenu>
32
+ );
33
+ `,
34
+ 'should not convert when triggerType prop is not provided',
35
+ );
36
+
37
+ defineInlineTest(
38
+ { default: transformer, parser: 'tsx' },
39
+ {},
40
+ `
41
+ import React from "react";
42
+ import DropdownMenu from "@atlaskit/dropdown-menu";
43
+
44
+ export default () => (
45
+ <DropdownMenu trigger="Click to open" triggerType="button">
46
+ </DropdownMenu>
47
+ );
48
+ `,
49
+ `
50
+ import React from "react";
51
+ import DropdownMenu from "@atlaskit/dropdown-menu";
52
+
53
+ export default () => (
54
+ <DropdownMenu trigger="Click to open">
55
+ </DropdownMenu>
56
+ );
57
+ `,
58
+ 'should delete triggerType prop when trigger is a string - type is button',
59
+ );
60
+
61
+ defineInlineTest(
62
+ { default: transformer, parser: 'tsx' },
63
+ {},
64
+ `
65
+ import React from "react";
66
+ import DropdownMenu from "@atlaskit/dropdown-menu";
67
+
68
+ export default () => (
69
+ <DropdownMenu
70
+ trigger={
71
+ <div>
72
+ &lt;button/&gt; trigger
73
+ </div>
74
+ }
75
+ triggerType="button">
76
+ </DropdownMenu>
77
+ );
78
+ `,
79
+ `
80
+ import React from "react";
81
+ import DropdownMenu from "@atlaskit/dropdown-menu";
82
+
83
+ export default () => (
84
+ /* TODO: (from codemod)
85
+ The usage of the 'trigger', 'triggerType' and 'triggerButtonProps' prop in this component could not be transformed and requires manual intervention.
86
+ Since version 11.0.0, we simplified the API and lean towards to only use 'trigger' prop.
87
+ For more info please reach out to #help-design-system-code. */
88
+ (<DropdownMenu
89
+ trigger={
90
+ <div>
91
+ &lt;button/&gt; trigger
92
+ </div>
93
+ }
94
+ triggerType="button">
95
+ </DropdownMenu>)
96
+ );
97
+ `,
98
+ 'should only add comments triggerType prop when trigger is an object',
99
+ );
100
+ });