@atlaskit/navigation-system 5.40.0 → 6.1.0
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.
- package/CHANGELOG.md +34 -0
- package/constellation/index/examples.mdx +5 -11
- package/constellation/layout/examples.mdx +3 -2
- package/constellation/layout/usage.mdx +3 -4
- package/constellation/side-nav-items/index.mdx +17 -0
- package/constellation/top-nav-items/examples.mdx +5 -5
- package/constellation/top-nav-items/usage.mdx +1 -2
- package/dist/cjs/components/badge-container.js +1 -1
- package/dist/cjs/components/list-item.js +1 -1
- package/dist/cjs/components/list.js +1 -1
- package/dist/cjs/components/skip-links/skip-link.js +3 -3
- package/dist/cjs/components/skip-links/skip-links-container.js +1 -1
- package/dist/cjs/index.js +0 -111
- package/dist/cjs/ui/page-layout/aside.js +1 -1
- package/dist/cjs/ui/page-layout/banner.js +1 -1
- package/dist/cjs/ui/page-layout/main/main-sticky-header.js +1 -1
- package/dist/cjs/ui/page-layout/main/main.js +1 -1
- package/dist/cjs/ui/page-layout/panel-splitter/panel-splitter.js +1 -1
- package/dist/cjs/ui/page-layout/panel.js +1 -1
- package/dist/cjs/ui/page-layout/ribbon.js +1 -1
- package/dist/cjs/ui/page-layout/root.js +1 -1
- package/dist/cjs/ui/page-layout/side-nav/side-nav-content.js +1 -1
- package/dist/cjs/ui/page-layout/side-nav/side-nav-footer.js +1 -1
- package/dist/cjs/ui/page-layout/side-nav/side-nav-header.js +1 -1
- package/dist/cjs/ui/page-layout/side-nav/side-nav.js +1 -1
- package/dist/cjs/ui/page-layout/side-nav/toggle-button.js +1 -1
- package/dist/cjs/ui/page-layout/top-nav/top-nav-end.js +1 -1
- package/dist/cjs/ui/page-layout/top-nav/top-nav-middle.js +1 -1
- package/dist/cjs/ui/page-layout/top-nav/top-nav-start.js +1 -1
- package/dist/cjs/ui/page-layout/top-nav/top-nav.js +1 -1
- package/dist/cjs/ui/top-nav-items/custom-title.js +1 -1
- package/dist/cjs/ui/top-nav-items/nav-logo/app-logo.js +1 -1
- package/dist/cjs/ui/top-nav-items/nav-logo/custom-logo.js +3 -3
- package/dist/cjs/ui/top-nav-items/nav-logo/logo-renderer.js +1 -1
- package/dist/cjs/ui/top-nav-items/search.js +1 -1
- package/dist/cjs/ui/top-nav-items/themed/button.js +1 -1
- package/dist/es2019/components/badge-container.js +1 -1
- package/dist/es2019/components/list-item.js +1 -1
- package/dist/es2019/components/list.js +1 -1
- package/dist/es2019/components/skip-links/skip-link.js +2 -2
- package/dist/es2019/components/skip-links/skip-links-container.js +1 -1
- package/dist/es2019/index.js +0 -9
- package/dist/es2019/ui/page-layout/aside.js +1 -1
- package/dist/es2019/ui/page-layout/banner.js +1 -1
- package/dist/es2019/ui/page-layout/main/main-sticky-header.js +1 -1
- package/dist/es2019/ui/page-layout/main/main.js +1 -1
- package/dist/es2019/ui/page-layout/panel-splitter/panel-splitter.js +1 -1
- package/dist/es2019/ui/page-layout/panel.js +1 -1
- package/dist/es2019/ui/page-layout/ribbon.js +1 -1
- package/dist/es2019/ui/page-layout/root.js +1 -1
- package/dist/es2019/ui/page-layout/side-nav/side-nav-content.js +1 -1
- package/dist/es2019/ui/page-layout/side-nav/side-nav-footer.js +1 -1
- package/dist/es2019/ui/page-layout/side-nav/side-nav-header.js +1 -1
- package/dist/es2019/ui/page-layout/side-nav/side-nav.js +1 -1
- package/dist/es2019/ui/page-layout/side-nav/toggle-button.js +1 -1
- package/dist/es2019/ui/page-layout/top-nav/top-nav-end.js +1 -1
- package/dist/es2019/ui/page-layout/top-nav/top-nav-middle.js +1 -1
- package/dist/es2019/ui/page-layout/top-nav/top-nav-start.js +1 -1
- package/dist/es2019/ui/page-layout/top-nav/top-nav.js +1 -1
- package/dist/es2019/ui/top-nav-items/custom-title.js +1 -1
- package/dist/es2019/ui/top-nav-items/nav-logo/app-logo.js +1 -1
- package/dist/es2019/ui/top-nav-items/nav-logo/custom-logo.js +2 -2
- package/dist/es2019/ui/top-nav-items/nav-logo/logo-renderer.js +1 -1
- package/dist/es2019/ui/top-nav-items/search.js +1 -1
- package/dist/es2019/ui/top-nav-items/themed/button.js +1 -1
- package/dist/esm/components/badge-container.js +1 -1
- package/dist/esm/components/list-item.js +1 -1
- package/dist/esm/components/list.js +1 -1
- package/dist/esm/components/skip-links/skip-link.js +2 -2
- package/dist/esm/components/skip-links/skip-links-container.js +1 -1
- package/dist/esm/index.js +0 -9
- package/dist/esm/ui/page-layout/aside.js +1 -1
- package/dist/esm/ui/page-layout/banner.js +1 -1
- package/dist/esm/ui/page-layout/main/main-sticky-header.js +1 -1
- package/dist/esm/ui/page-layout/main/main.js +1 -1
- package/dist/esm/ui/page-layout/panel-splitter/panel-splitter.js +1 -1
- package/dist/esm/ui/page-layout/panel.js +1 -1
- package/dist/esm/ui/page-layout/ribbon.js +1 -1
- package/dist/esm/ui/page-layout/root.js +1 -1
- package/dist/esm/ui/page-layout/side-nav/side-nav-content.js +1 -1
- package/dist/esm/ui/page-layout/side-nav/side-nav-footer.js +1 -1
- package/dist/esm/ui/page-layout/side-nav/side-nav-header.js +1 -1
- package/dist/esm/ui/page-layout/side-nav/side-nav.js +1 -1
- package/dist/esm/ui/page-layout/side-nav/toggle-button.js +1 -1
- package/dist/esm/ui/page-layout/top-nav/top-nav-end.js +1 -1
- package/dist/esm/ui/page-layout/top-nav/top-nav-middle.js +1 -1
- package/dist/esm/ui/page-layout/top-nav/top-nav-start.js +1 -1
- package/dist/esm/ui/page-layout/top-nav/top-nav.js +1 -1
- package/dist/esm/ui/top-nav-items/custom-title.js +1 -1
- package/dist/esm/ui/top-nav-items/nav-logo/app-logo.js +1 -1
- package/dist/esm/ui/top-nav-items/nav-logo/custom-logo.js +2 -2
- package/dist/esm/ui/top-nav-items/nav-logo/logo-renderer.js +1 -1
- package/dist/esm/ui/top-nav-items/search.js +1 -1
- package/dist/esm/ui/top-nav-items/themed/button.js +1 -1
- package/dist/types/index.d.ts +0 -9
- package/dist/types/ui/page-layout/top-nav/top-nav-start.d.ts +1 -4
- package/dist/types-ts4.5/index.d.ts +0 -9
- package/dist/types-ts4.5/ui/page-layout/top-nav/top-nav-start.d.ts +1 -4
- package/package.json +6 -9
- package/constellation/side-nav-items/code.mdx +0 -89
- package/constellation/side-nav-items/drag-and-drop.mdx +0 -1079
- package/constellation/side-nav-items/examples.mdx +0 -235
- package/constellation/side-nav-items/images/side-nav-anatomy-1.png +0 -0
- package/constellation/side-nav-items/images/side-nav-anatomy-2.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-1.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-2.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-3.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-4.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-5.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-6.png +0 -0
- package/constellation/side-nav-items/images/side-nav-do-7.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-1.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-10.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-2.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-3.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-4.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-5.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-6.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-7.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-8.png +0 -0
- package/constellation/side-nav-items/images/side-nav-dont-9.png +0 -0
- package/constellation/side-nav-items/usage.mdx +0 -328
- package/dist/cjs/entry-points/side-nav-items/button-menu-item.js +0 -18
- package/dist/cjs/entry-points/side-nav-items/container-avatar.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/drag-and-drop/drag-handle.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/drag-and-drop/drag-preview.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/drag-and-drop/drop-indicator.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/drag-and-drop/group-drop-indicator.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/drag-and-drop/hitbox.js +0 -18
- package/dist/cjs/entry-points/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/expandable-menu-item.js +0 -30
- package/dist/cjs/entry-points/side-nav-items/flyout-menu-item.js +0 -48
- package/dist/cjs/entry-points/side-nav-items/link-menu-item.js +0 -18
- package/dist/cjs/entry-points/side-nav-items/menu-list-item.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/menu-list.js +0 -12
- package/dist/cjs/entry-points/side-nav-items/menu-section.js +0 -24
- package/dist/cjs/entry-points/side-nav-items/top-level-spacer.js +0 -12
- package/dist/es2019/entry-points/side-nav-items/button-menu-item.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/container-avatar.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/drag-and-drop/drag-handle.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/drag-and-drop/drag-preview.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/drag-and-drop/drop-indicator.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/drag-and-drop/group-drop-indicator.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/drag-and-drop/hitbox.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/expandable-menu-item.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/flyout-menu-item.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/link-menu-item.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/menu-list-item.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/menu-list.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/menu-section.js +0 -1
- package/dist/es2019/entry-points/side-nav-items/top-level-spacer.js +0 -1
- package/dist/esm/entry-points/side-nav-items/button-menu-item.js +0 -1
- package/dist/esm/entry-points/side-nav-items/container-avatar.js +0 -1
- package/dist/esm/entry-points/side-nav-items/drag-and-drop/drag-handle.js +0 -1
- package/dist/esm/entry-points/side-nav-items/drag-and-drop/drag-preview.js +0 -1
- package/dist/esm/entry-points/side-nav-items/drag-and-drop/drop-indicator.js +0 -1
- package/dist/esm/entry-points/side-nav-items/drag-and-drop/group-drop-indicator.js +0 -1
- package/dist/esm/entry-points/side-nav-items/drag-and-drop/hitbox.js +0 -1
- package/dist/esm/entry-points/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop.js +0 -1
- package/dist/esm/entry-points/side-nav-items/expandable-menu-item.js +0 -1
- package/dist/esm/entry-points/side-nav-items/flyout-menu-item.js +0 -1
- package/dist/esm/entry-points/side-nav-items/link-menu-item.js +0 -1
- package/dist/esm/entry-points/side-nav-items/menu-list-item.js +0 -1
- package/dist/esm/entry-points/side-nav-items/menu-list.js +0 -1
- package/dist/esm/entry-points/side-nav-items/menu-section.js +0 -1
- package/dist/esm/entry-points/side-nav-items/top-level-spacer.js +0 -1
- package/dist/types/entry-points/side-nav-items/button-menu-item.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/container-avatar.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/drag-and-drop/drag-handle.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/drag-and-drop/drag-preview.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/drag-and-drop/drop-indicator.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/drag-and-drop/group-drop-indicator.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/drag-and-drop/hitbox.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/expandable-menu-item.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/flyout-menu-item.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/link-menu-item.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/menu-list-item.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/menu-list.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/menu-section.d.ts +0 -1
- package/dist/types/entry-points/side-nav-items/top-level-spacer.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/button-menu-item.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/container-avatar.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/drag-and-drop/drag-handle.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/drag-and-drop/drag-preview.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/drag-and-drop/drop-indicator.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/drag-and-drop/group-drop-indicator.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/drag-and-drop/hitbox.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/expandable-menu-item.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/flyout-menu-item.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/link-menu-item.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/menu-list-item.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/menu-list.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/menu-section.d.ts +0 -1
- package/dist/types-ts4.5/entry-points/side-nav-items/top-level-spacer.d.ts +0 -1
- package/side-nav-items/button-menu-item/package.json +0 -17
- package/side-nav-items/container-avatar/package.json +0 -17
- package/side-nav-items/drag-and-drop/drag-handle/package.json +0 -17
- package/side-nav-items/drag-and-drop/drag-preview/package.json +0 -17
- package/side-nav-items/drag-and-drop/drop-indicator/package.json +0 -17
- package/side-nav-items/drag-and-drop/group-drop-indicator/package.json +0 -17
- package/side-nav-items/drag-and-drop/hitbox/package.json +0 -17
- package/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop/package.json +0 -17
- package/side-nav-items/expandable-menu-item/package.json +0 -17
- package/side-nav-items/flyout-menu-item/package.json +0 -17
- package/side-nav-items/link-menu-item/package.json +0 -17
- package/side-nav-items/menu-list/package.json +0 -17
- package/side-nav-items/menu-list-item/package.json +0 -17
- package/side-nav-items/menu-section/package.json +0 -17
- package/side-nav-items/top-level-spacer/package.json +0 -17
|
@@ -1,1079 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Side nav items
|
|
3
|
-
description: Menu items and elements for the side nav area.
|
|
4
|
-
order: 2
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
import SectionMessage, { SectionMessageAction } from '@atlaskit/section-message';
|
|
8
|
-
import Lozenge from '@atlaskit/lozenge';
|
|
9
|
-
import { IconButton } from '@atlaskit/button/new';
|
|
10
|
-
import ShowMoreHorizontalIcon from '@atlaskit/icon/core/show-more-horizontal';
|
|
11
|
-
import { AllMenuItems } from '../../examples/constellation/drag-and-drop/simple';
|
|
12
|
-
import { StandaloneJiraSidebar } from '../../examples/constellation/drag-and-drop/standalone-jira-sidebar';
|
|
13
|
-
|
|
14
|
-
This guide will show you how to setup drag and drop for menu items in the side navigation. These
|
|
15
|
-
guidelines correspond to our wider drag and drop
|
|
16
|
-
[design guidelines](/components/pragmatic-drag-and-drop/design-guidelines) and
|
|
17
|
-
[accessibility guidelines](/components/pragmatic-drag-and-drop/accessibility-guidelines/), adding
|
|
18
|
-
some specific affordances and decisions specifically for our side navigation.
|
|
19
|
-
|
|
20
|
-
<Example Component={StandaloneJiraSidebar} appearance="showcase-only" />
|
|
21
|
-
|
|
22
|
-
<details>
|
|
23
|
-
<summary>Thinking about our approach</summary>
|
|
24
|
-
|
|
25
|
-
Our approach to drag and drop in the sidebar has been guided by three concerns:
|
|
26
|
-
|
|
27
|
-
1. **Performance**: we only want consumers who need drag and drop to include code for it.
|
|
28
|
-
2. **Flexibility**: we have created a system that lets you achieve any drag and drop operation you
|
|
29
|
-
could think of, and puts you in control of all of the business logic
|
|
30
|
-
3. **Consistency**: we want drag and drop operations in the sidebar to all feel the same to our
|
|
31
|
-
users
|
|
32
|
-
|
|
33
|
-
These desired outcomes have pushed us towards a solution were we provide a lot of the small pieces,
|
|
34
|
-
and it is up to you to put them together.
|
|
35
|
-
|
|
36
|
-
</details>
|
|
37
|
-
|
|
38
|
-
<SectionMessage title="Required" appearance="warning">
|
|
39
|
-
|
|
40
|
-
It is so important that you stay within these guidelines for your experiences as it will promote
|
|
41
|
-
user experience consistency as well as enable us to more easily evolve all experiences.
|
|
42
|
-
|
|
43
|
-
</SectionMessage>
|
|
44
|
-
|
|
45
|
-
<SectionMessage title="Pre reading" appearance="discovery" actions={<SectionMessageAction href="/components/pragmatic-drag-and-drop">Learn about Pragmatic drag and drop</SectionMessageAction>}>
|
|
46
|
-
|
|
47
|
-
This guide assumes you already have a working knowledge of Pragmatic drag and drop.
|
|
48
|
-
|
|
49
|
-
</SectionMessage>
|
|
50
|
-
|
|
51
|
-
## Before a drag
|
|
52
|
-
|
|
53
|
-
**<Lozenge appearance="success" isBold>Goal</Lozenge> let a user know that a menu item can be
|
|
54
|
-
dragged**
|
|
55
|
-
|
|
56
|
-
All types of sidebar menu items can be dragged (`ButtonMenuItem`, `LinkMenuItem`,
|
|
57
|
-
`FlyoutMenuItemTrigger`, `ExpandableMenuItemTrigger`).
|
|
58
|
-
|
|
59
|
-
By default, menu items are _not draggable_ and you need to opt into making them draggable. To make a
|
|
60
|
-
menu item draggable there are two things you need to do:
|
|
61
|
-
|
|
62
|
-
1. Set `hasDragIndicator` to `true` on the menu item
|
|
63
|
-
2. Make the menu item `draggable()`
|
|
64
|
-
|
|
65
|
-
### hasDragIndicator
|
|
66
|
-
|
|
67
|
-
Setting `hasDragIndicator` to true on a menu item will enable visual affordances on the menu item to
|
|
68
|
-
make it clear that the item is draggable:
|
|
69
|
-
|
|
70
|
-
- Showing a drag handle icon before the start of the menu item on `:hover`
|
|
71
|
-
- **Changing** the cursor to `grab` after `800ms`. We have a delayed cursor change as
|
|
72
|
-
[dragging is a non-primary action](/components/pragmatic-drag-and-drop/design-guidelines#cursor-changes)
|
|
73
|
-
|
|
74
|
-
`hasDragIndicator` will not automatically make the menu item a `draggable` (which is why we avoided
|
|
75
|
-
the prop name `isDraggable` or `draggable`) - you need to make the item a `draggable` element in
|
|
76
|
-
step 2.
|
|
77
|
-
|
|
78
|
-
```tsx
|
|
79
|
-
function Item({ item }) {
|
|
80
|
-
return <ButtonMenuItem hasDragIndicator>{item.content}</ButtonMenuItem>;
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### Make the menu item `draggable()`
|
|
85
|
-
|
|
86
|
-
You make a menu item _actually_ draggable by users with `draggable({element})` from Pragmatic drag
|
|
87
|
-
and drop.
|
|
88
|
-
|
|
89
|
-
Be sure to use the forwarded `ref` from the menu item as the `draggable` element, and not another
|
|
90
|
-
`ref` such as `visualContentRef`. We want users to be able to drag from the main interactive element
|
|
91
|
-
of a menu item (the `ref`), but not from buttons (eg `actions` or `actionsOnHover`) that appear on
|
|
92
|
-
top of menu items.
|
|
93
|
-
|
|
94
|
-
With `useMenuItemDragAndDrop()` _(recommended)_
|
|
95
|
-
|
|
96
|
-
```tsx
|
|
97
|
-
function Item({ item }) {
|
|
98
|
-
const { draggableButtonRef } = useMenuItemDragAndDrop({
|
|
99
|
-
draggable: {
|
|
100
|
-
/*...*/
|
|
101
|
-
},
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
return (
|
|
105
|
-
<ButtonMenuItem ref={draggableButtonRef} hasDragIndicator>
|
|
106
|
-
{item.content}
|
|
107
|
-
</ButtonMenuItem>
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Without `useMenuItemDragAndDrop()`
|
|
113
|
-
|
|
114
|
-
```tsx
|
|
115
|
-
function Item({ item }) {
|
|
116
|
-
const ref = useRef<HTMLDivElement | null>(null);
|
|
117
|
-
|
|
118
|
-
useEffect(() => {
|
|
119
|
-
const element = ref.current;
|
|
120
|
-
invariant(element && dropTarget);
|
|
121
|
-
|
|
122
|
-
return draggable({
|
|
123
|
-
element,
|
|
124
|
-
});
|
|
125
|
-
}, []);
|
|
126
|
-
|
|
127
|
-
return (
|
|
128
|
-
<ButtonMenuItem ref={ref} hasDragIndicator>
|
|
129
|
-
{item.content}
|
|
130
|
-
</ButtonMenuItem>
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Start of a drag
|
|
136
|
-
|
|
137
|
-
**<Lozenge appearance="success" isBold>Goal</Lozenge> make it clear what is dragging**
|
|
138
|
-
|
|
139
|
-
When a drag is starting, there are two things you need to do:
|
|
140
|
-
|
|
141
|
-
1. Setup the drag preview
|
|
142
|
-
|
|
143
|
-
We have a `<DragPreview />` component that embodies the visual language we want for menu item drag
|
|
144
|
-
previews:
|
|
145
|
-
|
|
146
|
-
- Only displays essential information - `elemBefore` and content (the `children`)
|
|
147
|
-
- Is limited in width
|
|
148
|
-
([due to web platform design constraints](/components/pragmatic-drag-and-drop/web-platform-design-constraints))
|
|
149
|
-
|
|
150
|
-
```tsx
|
|
151
|
-
import { DragPreview } from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/drag-preview';
|
|
152
|
-
import ProjectIcon from '@atlaskit/icon/core/project';
|
|
153
|
-
|
|
154
|
-
function ProjectsDragPreview() {
|
|
155
|
-
return <DragPreview elemBefore={<ProjectIcon label="" />} content="Projects" />;
|
|
156
|
-
}
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
If no `elemBefore` is provided, then the `elemBefore` will automatically collapse. There is no need
|
|
160
|
-
to pass in `COLLAPSE_ELEM_BEFORE`. We do this as there is no need to maintain vertical side
|
|
161
|
-
navigation vertical alignment in the drag preview.
|
|
162
|
-
|
|
163
|
-
```tsx
|
|
164
|
-
import { DragPreview } from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/drag-preview';
|
|
165
|
-
|
|
166
|
-
function ProjectsDragPreview() {
|
|
167
|
-
return <DragPreview content="Projects" />;
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
<SectionMessage>
|
|
172
|
-
|
|
173
|
-
`useMenuItemDragAndDrop()` does a lot of the wiring talked about below. Please try to use the hook
|
|
174
|
-
first before reaching for the lower level pieces.
|
|
175
|
-
|
|
176
|
-
</SectionMessage>
|
|
177
|
-
|
|
178
|
-
Please ensure the drag preview is pushed away from the users pointer (with `pointerOutsideOfPreview`
|
|
179
|
-
from Pragmatic drag and drop) by our
|
|
180
|
-
[standard amount](/components/pragmatic-drag-and-drop/design-guidelines)
|
|
181
|
-
(`{x: token('space.200'), y: token('space.100')`).
|
|
182
|
-
|
|
183
|
-
See our
|
|
184
|
-
[drag preview guidelines](/components/pragmatic-drag-and-drop/core-package/adapters/element/drag-previews)
|
|
185
|
-
for more information about mounting native drag previews.
|
|
186
|
-
|
|
187
|
-
2. Pass `isDragging={true}` to the menu item
|
|
188
|
-
|
|
189
|
-
This will lower the opacity on the item being dragged as our
|
|
190
|
-
[standard visual cue](/components/pragmatic-drag-and-drop/design-guidelines) that something is being
|
|
191
|
-
dragged.
|
|
192
|
-
|
|
193
|
-
## While dragging
|
|
194
|
-
|
|
195
|
-
**<Lozenge appearance="success" isBold>Goal</Lozenge> make it clear what the result of the drag will
|
|
196
|
-
be**
|
|
197
|
-
|
|
198
|
-
There are four things you need to do in order to make it possible for a menu item to be dropped on:
|
|
199
|
-
|
|
200
|
-
1. Make the menu item a _drop target_
|
|
201
|
-
2. Add hitbox information to the menu item
|
|
202
|
-
3. Display drop indicators as needed on menu item
|
|
203
|
-
4. Display a group drop indicator around the current group of menu items
|
|
204
|
-
|
|
205
|
-
1, 2 and 3 can more easily be achieved with `useMenuItemDragAndDrop()`; and 4 requires some light
|
|
206
|
-
wiring by consumers.
|
|
207
|
-
|
|
208
|
-
### Making a menu item a drop target
|
|
209
|
-
|
|
210
|
-
#### Use `visualContentRef`
|
|
211
|
-
|
|
212
|
-
To make a menu item a drop target you call `dropTargetForElements` with the `visualContentRef`
|
|
213
|
-
provided by all menu items.
|
|
214
|
-
|
|
215
|
-
_Rationale:_
|
|
216
|
-
|
|
217
|
-
- It is the full width of the element. We want to enable users to be able to drag only vertically to
|
|
218
|
-
be able to drag into nested menu items
|
|
219
|
-
- It wraps all elements in the menu item and so will be triggered even when dragging over `actions`
|
|
220
|
-
and other elements on top of the main interactive element.
|
|
221
|
-
|
|
222
|
-
With `useMenuItemDragAndDrop()` _(recommended)_
|
|
223
|
-
|
|
224
|
-
```tsx
|
|
225
|
-
function Item({ item }) {
|
|
226
|
-
const { draggableButtonRef, dropTargetRef } = useMenuItemDragAndDrop({});
|
|
227
|
-
|
|
228
|
-
return (
|
|
229
|
-
<ButtonMenuItem visualContentRef={dropTargetRef} ref={draggableButtonRef}>
|
|
230
|
-
{item.content}
|
|
231
|
-
</ButtonMenuItem>
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
Custom implementation
|
|
237
|
-
|
|
238
|
-
```tsx
|
|
239
|
-
function Item({ item }) {
|
|
240
|
-
const dropTargetRef = useRef<HTMLDivElement | null>(null);
|
|
241
|
-
const ref = useRef<HTMLDivElement | null>(null);
|
|
242
|
-
|
|
243
|
-
useEffect(() => {
|
|
244
|
-
const element = ref.current;
|
|
245
|
-
const dropTarget = dropTargetRef.current;
|
|
246
|
-
invariant(element && dropTarget);
|
|
247
|
-
|
|
248
|
-
return combine(
|
|
249
|
-
// make the menu item a drop target
|
|
250
|
-
dropTargetForElements({
|
|
251
|
-
element: dropTarget,
|
|
252
|
-
// make the drop target sticky
|
|
253
|
-
getIsSticky: () => true,
|
|
254
|
-
// prevent dropping on self
|
|
255
|
-
canDrop: ({ source }) => source.element !== element && source.data.type === 'menu-item',
|
|
256
|
-
}),
|
|
257
|
-
// make the menu item draggable
|
|
258
|
-
draggable({
|
|
259
|
-
element,
|
|
260
|
-
}),
|
|
261
|
-
);
|
|
262
|
-
}, []);
|
|
263
|
-
|
|
264
|
-
return (
|
|
265
|
-
<ButtonMenuItem ref={ref} visualContentRef={dropTargetRef}>
|
|
266
|
-
{item.content}
|
|
267
|
-
</ButtonMenuItem>
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
#### Stickiness
|
|
273
|
-
|
|
274
|
-
<SectionMessage>
|
|
275
|
-
|
|
276
|
-
[Background information about stickiness](/components/pragmatic-drag-and-drop/core-package/drop-targets#getissticky)
|
|
277
|
-
|
|
278
|
-
</SectionMessage>
|
|
279
|
-
|
|
280
|
-
If you are setting up drop targets without `useMenuItemDragAndDrop()` it is important that you make
|
|
281
|
-
the menu item drop target sticky `getIsSticky: () => true`. The `<GroupDropIndicator>` should _not_
|
|
282
|
-
be sticky, and it will clear stickiness when you leave the group. Stickiness on the menu items helps
|
|
283
|
-
to have a nicer experience when dragging over a group that contains gaps in drop targets, for
|
|
284
|
-
example when there are titles in the sidebar.
|
|
285
|
-
|
|
286
|
-
#### Don't allow menu items to drop on themselves
|
|
287
|
-
|
|
288
|
-
If you are setting up drop targets without `useMenuItemDragAndDrop()`, you need to manually ensure
|
|
289
|
-
that a menu item cannot drop on itself with `canDrop()`
|
|
290
|
-
|
|
291
|
-
```ts
|
|
292
|
-
dropTargetForElements({
|
|
293
|
-
element: dropTarget,
|
|
294
|
-
// Don't allow dropping on itself
|
|
295
|
-
canDrop: ({ source }) => source.element !== element && source.data.type === 'menu-item',
|
|
296
|
-
});
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
### Add hitbox information to a menu item
|
|
300
|
-
|
|
301
|
-
The hitbox is responsible for examining the user input when over a drop target and outputting the
|
|
302
|
-
appropriate operation for that input. For a menu item, you can specify which of the following
|
|
303
|
-
operations are permitted:
|
|
304
|
-
|
|
305
|
-
- `"reorder-before"`
|
|
306
|
-
- `"reorder-after"`
|
|
307
|
-
- `"combine"`
|
|
308
|
-
|
|
309
|
-
A result of a hitbox function call, will result in an `Instruction` which you can use to determine
|
|
310
|
-
what operation should be completed when the drag finishes, as well as for displaying the drop
|
|
311
|
-
indicator during a drag operation.
|
|
312
|
-
|
|
313
|
-
Each operation has three possible values:
|
|
314
|
-
|
|
315
|
-
- `"not-available"` (default)
|
|
316
|
-
- `"available"`
|
|
317
|
-
- `"blocked"` (similar to `"available"`, but will show warning colors. See below for more
|
|
318
|
-
information)
|
|
319
|
-
|
|
320
|
-
The hitbox for an drop target will automatically adjust to accommodate each additional available
|
|
321
|
-
operation.
|
|
322
|
-
|
|
323
|
-
```ts
|
|
324
|
-
type Operation = 'reorder-before' | 'reorder-after' | 'combine';
|
|
325
|
-
|
|
326
|
-
type Instruction = {
|
|
327
|
-
// What the operation is
|
|
328
|
-
operation: Operation;
|
|
329
|
-
|
|
330
|
-
// whether or not the operation was "blocked"
|
|
331
|
-
blocked: boolean;
|
|
332
|
-
};
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
With `useMenuItemDragAndDrop()` _(recommended)_
|
|
336
|
-
|
|
337
|
-
```tsx
|
|
338
|
-
import { useMenuItemDragAndDrop } from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop';
|
|
339
|
-
|
|
340
|
-
function OurButtonItem() {
|
|
341
|
-
const { state, draggableButtonRef, dragPreview, dropTargetRef, dropIndicator } =
|
|
342
|
-
useMenuItemDragAndDrop({
|
|
343
|
-
dropTarget: {
|
|
344
|
-
getOperations: () => ({
|
|
345
|
-
'reorder-before': 'available',
|
|
346
|
-
combine: 'available',
|
|
347
|
-
'reorder-after': 'available',
|
|
348
|
-
}),
|
|
349
|
-
},
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
return (
|
|
353
|
-
<>
|
|
354
|
-
<ButtonMenuItem
|
|
355
|
-
elemBefore={<BasketballIcon label="" />}
|
|
356
|
-
ref={draggableButtonRef}
|
|
357
|
-
isDragging={state.type === 'dragging'}
|
|
358
|
-
hasDragIndicator
|
|
359
|
-
dropIndicator={dropIndicator}
|
|
360
|
-
visualContentRef={dropTargetRef}
|
|
361
|
-
>
|
|
362
|
-
Button menu item
|
|
363
|
-
</ButtonMenuItem>
|
|
364
|
-
{dragPreview}
|
|
365
|
-
</>
|
|
366
|
-
);
|
|
367
|
-
}
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
Manually adding operations
|
|
371
|
-
|
|
372
|
-
```tsx
|
|
373
|
-
import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
374
|
-
import {
|
|
375
|
-
attachInstruction,
|
|
376
|
-
extractInstruction,
|
|
377
|
-
type Instruction,
|
|
378
|
-
} from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/hitbox';
|
|
379
|
-
|
|
380
|
-
function Item({ item }) {
|
|
381
|
-
const dropTargetRef = useRef<HTMLDivElement | null>(null);
|
|
382
|
-
const ref = useRef<HTMLDivElement | null>(null);
|
|
383
|
-
|
|
384
|
-
useEffect(() => {
|
|
385
|
-
const element = ref.current;
|
|
386
|
-
const dropTarget = dropTargetRef.current;
|
|
387
|
-
invariant(element && dropTarget);
|
|
388
|
-
|
|
389
|
-
return combine(
|
|
390
|
-
// make the menu item a drop target
|
|
391
|
-
dropTargetForElements({
|
|
392
|
-
element: dropTarget,
|
|
393
|
-
getData: ({ input, element }) => {
|
|
394
|
-
// your base data you want to attach to the drop target
|
|
395
|
-
const data = {
|
|
396
|
-
type: 'menu-item',
|
|
397
|
-
itemId: 'A',
|
|
398
|
-
};
|
|
399
|
-
// this will 'attach' an `Instruction` to your data object
|
|
400
|
-
return attachInstruction(data, {
|
|
401
|
-
input,
|
|
402
|
-
element,
|
|
403
|
-
operations: {
|
|
404
|
-
'reorder-before': 'available',
|
|
405
|
-
'reorder-after': 'available',
|
|
406
|
-
combine: 'available',
|
|
407
|
-
},
|
|
408
|
-
});
|
|
409
|
-
},
|
|
410
|
-
onDrop: (args) => {
|
|
411
|
-
const instruction: Instruction | null = extractInstruction(args.self.data);
|
|
412
|
-
},
|
|
413
|
-
}),
|
|
414
|
-
// make the menu item draggable
|
|
415
|
-
draggable({
|
|
416
|
-
element,
|
|
417
|
-
}),
|
|
418
|
-
);
|
|
419
|
-
}, []);
|
|
420
|
-
|
|
421
|
-
return (
|
|
422
|
-
<ButtonMenuItem ref={ref} visualContentRef={dropTargetRef}>
|
|
423
|
-
{item.content}
|
|
424
|
-
</ButtonMenuItem>
|
|
425
|
-
);
|
|
426
|
-
}
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
#### Preventing operations
|
|
430
|
-
|
|
431
|
-
If you don't want an operation to be available, you have a few options.
|
|
432
|
-
|
|
433
|
-
1. Set `canDrop: () => false`
|
|
434
|
-
2. Set an operation to `"not-available"`
|
|
435
|
-
|
|
436
|
-
With `useMenuItemDragAndDrop()` _(recommended)_
|
|
437
|
-
|
|
438
|
-
```ts
|
|
439
|
-
useMenuItemDragAndDrop({
|
|
440
|
-
dropTarget: {
|
|
441
|
-
getOperations: () => ({
|
|
442
|
-
'reorder-before': 'available',
|
|
443
|
-
'reorder-after': 'not-available', // reordering after no longer available
|
|
444
|
-
}),
|
|
445
|
-
},
|
|
446
|
-
});
|
|
447
|
-
```
|
|
448
|
-
|
|
449
|
-
Without `useMenuItemDragAndDrop()`
|
|
450
|
-
|
|
451
|
-
```ts
|
|
452
|
-
return attachInstruction(data, {
|
|
453
|
-
input,
|
|
454
|
-
element,
|
|
455
|
-
operations: {
|
|
456
|
-
'reorder-before': 'available',
|
|
457
|
-
'reorder-after': 'not-available', // reordering after no longer available
|
|
458
|
-
},
|
|
459
|
-
});
|
|
460
|
-
```
|
|
461
|
-
|
|
462
|
-
3. Don't include an operation in `operations`
|
|
463
|
-
|
|
464
|
-
With `useMenuItemDragAndDrop()` _(recommended)_
|
|
465
|
-
|
|
466
|
-
```ts
|
|
467
|
-
useMenuItemDragAndDrop({
|
|
468
|
-
dropTarget: {
|
|
469
|
-
getOperations: () => ({
|
|
470
|
-
'reorder-before': 'available',
|
|
471
|
-
// 'reorder-after' and 'combine' are "not-available" by default
|
|
472
|
-
}),
|
|
473
|
-
},
|
|
474
|
-
});
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
Without `useMenuItemDragAndDrop()`
|
|
478
|
-
|
|
479
|
-
```ts
|
|
480
|
-
return attachInstruction(data, {
|
|
481
|
-
input,
|
|
482
|
-
element,
|
|
483
|
-
operations: {
|
|
484
|
-
'reorder-before': 'available',
|
|
485
|
-
// 'reorder-after' and 'combine' are "not-available" by default
|
|
486
|
-
},
|
|
487
|
-
});
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
#### Blocking operations
|
|
491
|
-
|
|
492
|
-
Sometimes you want to explicitly call out that an operation is not permitted _right now_. An example
|
|
493
|
-
of this is draft pages in Confluence which cannot be the target of a drag operation, but once page
|
|
494
|
-
is no longer a draft it could be the target of a drag operation. In these cases, it can be helpful
|
|
495
|
-
to make it explicit to the user that a particular drag operation can not permitted. You can use
|
|
496
|
-
`blocked` for this use case. When an operation is blocked, it will be used by our _drop indicator_
|
|
497
|
-
to show a drop indicator with a warning color.
|
|
498
|
-
|
|
499
|
-
```ts
|
|
500
|
-
useMenuItemDragAndDrop({
|
|
501
|
-
dropTarget: {
|
|
502
|
-
getOperations: () => ({
|
|
503
|
-
combine: 'blocked',
|
|
504
|
-
}),
|
|
505
|
-
},
|
|
506
|
-
});
|
|
507
|
-
```
|
|
508
|
-
|
|
509
|
-
### Drop indicators
|
|
510
|
-
|
|
511
|
-
Drop indicators are used to make it clear what the result of a drag operation will be. There are two
|
|
512
|
-
types of drop indicators that are **required** for you to setup:
|
|
513
|
-
|
|
514
|
-
1. Drop indicators that appear on menu items
|
|
515
|
-
2. Drop indicators that appear around groups of menu items (`<GroupDropIndicator/>`)
|
|
516
|
-
|
|
517
|
-
#### Menu item drop indicator
|
|
518
|
-
|
|
519
|
-
A menu item `<DropIndicator>` component is responsible for the visual representation of an
|
|
520
|
-
`Instruction` from the `hitbox`. In order for the `<DropIndicator>` to be rendered correctly, it is
|
|
521
|
-
important that you provide the component to the `dropIndicator` prop on a menu item.
|
|
522
|
-
|
|
523
|
-
The `<DropIndicator />` is handled for you when leveraging `useMenuItemDragAndDrop()`
|
|
524
|
-
|
|
525
|
-
```tsx
|
|
526
|
-
import { useMenuItemDragAndDrop } from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/use-menu-item-drag-and-drop';
|
|
527
|
-
|
|
528
|
-
function OurButtonItem() {
|
|
529
|
-
const { state, draggableButtonRef, dragPreview, dropTargetRef, dropIndicator } =
|
|
530
|
-
useMenuItemDragAndDrop({
|
|
531
|
-
dropTarget: {
|
|
532
|
-
getOperations: () => ({
|
|
533
|
-
'reorder-before': 'available',
|
|
534
|
-
'reorder-after': 'available',
|
|
535
|
-
}),
|
|
536
|
-
},
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
return (
|
|
540
|
-
<>
|
|
541
|
-
<ButtonMenuItem
|
|
542
|
-
elemBefore={<BasketballIcon label="" />}
|
|
543
|
-
ref={draggableButtonRef}
|
|
544
|
-
isDragging={state.type === 'dragging'}
|
|
545
|
-
hasDragIndicator
|
|
546
|
-
// 👇 pass the drop indicator ReactNode into the dropIndicator prop
|
|
547
|
-
dropIndicator={dropIndicator}
|
|
548
|
-
visualContentRef={dropTargetRef}
|
|
549
|
-
>
|
|
550
|
-
Button menu item
|
|
551
|
-
</ButtonMenuItem>
|
|
552
|
-
{dragPreview}
|
|
553
|
-
</>
|
|
554
|
-
);
|
|
555
|
-
}
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
Rough idea when not using `useMenuItemDragAndDrop()`
|
|
559
|
-
|
|
560
|
-
```tsx
|
|
561
|
-
import { DropIndicator } from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/drop-indicator';
|
|
562
|
-
|
|
563
|
-
function Item({ item }) {
|
|
564
|
-
const [state, setState] = useState<TItemState>({ type: 'idle' });
|
|
565
|
-
const dropIndicator = state.type === 'is-over' && state.instruction && (
|
|
566
|
-
<DropIndicator instruction={state.instruction} />
|
|
567
|
-
);
|
|
568
|
-
|
|
569
|
-
return (
|
|
570
|
-
<ButtonMenuItem
|
|
571
|
-
ref={ref}
|
|
572
|
-
elemBefore={item.elemBefore}
|
|
573
|
-
isDragging={state.type === 'dragging'}
|
|
574
|
-
// 👇 pass the drop indicator to the dropIndicator prop
|
|
575
|
-
dropIndicator={dropIndicator}
|
|
576
|
-
visualContentRef={dropTargetRef}
|
|
577
|
-
hasDragIndicator
|
|
578
|
-
>
|
|
579
|
-
{item.content}
|
|
580
|
-
</ButtonMenuItem>
|
|
581
|
-
);
|
|
582
|
-
}
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
#### Group drop indicator
|
|
586
|
-
|
|
587
|
-
As a part of the design language for drag and drop in the sidebar, we also add a visual affordance
|
|
588
|
-
around the section that the user is dragging over. This is to help make it even clearer where
|
|
589
|
-
something will end up after a drop.
|
|
590
|
-
|
|
591
|
-
To achieve this, you need to wrap any groups of draggable menu items in our `<GroupDropIndicator>`.
|
|
592
|
-
A group is any logical list of menu items at the same level in the side navigation. A group could be
|
|
593
|
-
all items on a particular level, or a logical subset of items at a particular level (eg a "recent
|
|
594
|
-
projects" section).
|
|
595
|
-
|
|
596
|
-
- You need to setup the `<GroupDropIndicator>` as a drop target
|
|
597
|
-
- The drop target should _not_ have stickiness. This is important as it is the mechanism for
|
|
598
|
-
clearing stickiness on menu item drop targets.
|
|
599
|
-
- Set `isActive={true}` on the `<GroupDropIndicator>` when it is the innermost available
|
|
600
|
-
`<GroupDropIndicator>`
|
|
601
|
-
|
|
602
|
-
<Example Component={AllMenuItems} appearance="showcase-only" />
|
|
603
|
-
|
|
604
|
-
```tsx
|
|
605
|
-
import { GroupDropIndicator } from '@atlaskit/navigation-system/side-nav-items/drag-and-drop/group-drop-indicator';
|
|
606
|
-
|
|
607
|
-
function isInnerMostGroup({ location, self }: ElementDropTargetEventBasePayload): boolean {
|
|
608
|
-
const [innerMost] = location.current.dropTargets.filter(
|
|
609
|
-
(dropTarget) => dropTarget.data.type === 'menu-item-group',
|
|
610
|
-
);
|
|
611
|
-
return innerMost?.element === self.element;
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
export function MyMenuItemGroup() {
|
|
615
|
-
const [isInnerMostOver, setIsInnerMostOver] = useState<boolean>(false);
|
|
616
|
-
const ref = useRef<HTMLDivElement | null>(null);
|
|
617
|
-
|
|
618
|
-
useEffect(() => {
|
|
619
|
-
const element = ref.current;
|
|
620
|
-
invariant(element);
|
|
621
|
-
return dropTargetForElements({
|
|
622
|
-
element,
|
|
623
|
-
canDrop: ({ source }) => source.data.type === 'menu-item',
|
|
624
|
-
getData: () => ({ type: 'menu-item-group' }),
|
|
625
|
-
onDragStart: (args) => setIsInnerMostOver(isInnerMostGroup(args)),
|
|
626
|
-
onDropTargetChange: (args) => setIsInnerMostOver(isInnerMostGroup(args)),
|
|
627
|
-
onDrop: () => setIsInnerMostOver(false),
|
|
628
|
-
});
|
|
629
|
-
}, []);
|
|
630
|
-
|
|
631
|
-
return (
|
|
632
|
-
<GroupDropIndicator isActive={isInnerMostOver} ref={ref}>
|
|
633
|
-
<OurLinkMenuItem />
|
|
634
|
-
<OurButtonItem />
|
|
635
|
-
<OurFlyoutItem />
|
|
636
|
-
<OurExpandableItem />
|
|
637
|
-
</GroupDropIndicator>
|
|
638
|
-
);
|
|
639
|
-
}
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
### Automatic scrolling
|
|
643
|
-
|
|
644
|
-
During a drag operation, it is important that a user be able to effortlessly scroll the sidebar in
|
|
645
|
-
order to easily place a dragging item in any position.
|
|
646
|
-
[Please wire up `autoScrollForElements`](/components/pragmatic-drag-and-drop/optional-packages/auto-scroll/about)
|
|
647
|
-
on the `ref` that the `<SideNavContent>` returns to ensure the scrollable portion of the sidebar
|
|
648
|
-
automatically scrolls during a drag operation.
|
|
649
|
-
|
|
650
|
-
```tsx
|
|
651
|
-
import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
|
|
652
|
-
|
|
653
|
-
function Sidebar() {
|
|
654
|
-
const scrollableRef = useRef<HTMLDivElement | null>(null);
|
|
655
|
-
|
|
656
|
-
// setup auto scrolling for sidenav scroll container
|
|
657
|
-
useEffect(() => {
|
|
658
|
-
const scrollable = scrollableRef.current;
|
|
659
|
-
invariant(scrollable);
|
|
660
|
-
return autoScrollForElements({
|
|
661
|
-
element: scrollable,
|
|
662
|
-
canScroll: ({ source }) => source.data.type === 'menu-item',
|
|
663
|
-
});
|
|
664
|
-
}, []);
|
|
665
|
-
|
|
666
|
-
return <SideNavContent ref={scrollableRef}>{/* ... */}</SideNavContent>;
|
|
667
|
-
}
|
|
668
|
-
```
|
|
669
|
-
|
|
670
|
-
## On drop
|
|
671
|
-
|
|
672
|
-
**<Lozenge appearance="success" isBold>Goal</Lozenge> immediately update the interface**
|
|
673
|
-
|
|
674
|
-
1. Figure out what `Operation` to do
|
|
675
|
-
|
|
676
|
-
Using `extractInstruction` you can extract the `Instruction` to be performed.
|
|
677
|
-
|
|
678
|
-
```ts
|
|
679
|
-
type Operation = 'reorder-before' | 'reorder-after' | 'combine';
|
|
680
|
-
|
|
681
|
-
type Instruction = {
|
|
682
|
-
// What the operation is
|
|
683
|
-
operation: Operation;
|
|
684
|
-
|
|
685
|
-
// whether or not the operation was "blocked"
|
|
686
|
-
blocked: boolean;
|
|
687
|
-
};
|
|
688
|
-
```
|
|
689
|
-
|
|
690
|
-
```tsx
|
|
691
|
-
useEffect(() => {
|
|
692
|
-
return monitorForElements({
|
|
693
|
-
canMonitor: ({ source }) => source.data.type === 'menu-item',
|
|
694
|
-
onDrop({ source, location }) {
|
|
695
|
-
const dragging = source.data;
|
|
696
|
-
const [innerMost] = location.current.dropTargets;
|
|
697
|
-
|
|
698
|
-
if (!innerMost) {
|
|
699
|
-
return;
|
|
700
|
-
}
|
|
701
|
-
const dropTargetData = innerMost.data;
|
|
702
|
-
|
|
703
|
-
const instruction: Instruction | null = extractInstruction(dropTargetData);
|
|
704
|
-
if (!instruction) {
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
// Do something based on the instruction
|
|
709
|
-
});
|
|
710
|
-
}, []);
|
|
711
|
-
|
|
712
|
-
```
|
|
713
|
-
|
|
714
|
-
2. Optimistically update the interface
|
|
715
|
-
|
|
716
|
-
When a drag operation is finished, you need to optimistically update the interface (don't wait for
|
|
717
|
-
the update to persist on the server). Don't lock the interface while the update is persisting, allow
|
|
718
|
-
them to continue to engage with the interface (including performing more drag and drop operations).
|
|
719
|
-
|
|
720
|
-
If an update fails, please let the user know in the interface through a flag; and synchronize the
|
|
721
|
-
interface with the server state. The interface can become locked during this synchronization if
|
|
722
|
-
needed.
|
|
723
|
-
|
|
724
|
-
3. Flash the moved menu item
|
|
725
|
-
|
|
726
|
-
Leverage
|
|
727
|
-
[`triggerPostMoveFlash`](/components/pragmatic-drag-and-drop/optional-packages/flourish/trigger-post-move-flash/examples)
|
|
728
|
-
to trigger a flash on the interactive element (it's `ref`) of the moved menu item. This gives
|
|
729
|
-
helpful clarity to users about what has changed.
|
|
730
|
-
|
|
731
|
-
See our complete example above to see how you can achieve this.
|
|
732
|
-
|
|
733
|
-
Some possible options:
|
|
734
|
-
|
|
735
|
-
- Keep a registry of `HTMLElement`s for all menu items, so you can look up the menu item element
|
|
736
|
-
after it has been moved
|
|
737
|
-
- Lookup elements with data attributes after the drop. Not ideal, but can get the job done.
|
|
738
|
-
|
|
739
|
-
## useMenuItemDragAndDrop
|
|
740
|
-
|
|
741
|
-
We have created a `react` hook `useMenuItemDragAndDrop()` which takes care of a lot of plumbing when
|
|
742
|
-
setting up drag and drop for menu items in the sidebar. We strongly recommend that you start with
|
|
743
|
-
this hook, and if it doesn't work for you, then you can build up everything using the pieces we
|
|
744
|
-
expose.
|
|
745
|
-
|
|
746
|
-
```tsx
|
|
747
|
-
import { getProjectData, isProjectData } from './helpers';
|
|
748
|
-
|
|
749
|
-
function Project({ project }: { project: TProject }) {
|
|
750
|
-
const { state, draggableAnchorRef, dragPreview, dropTargetRef, dropIndicator } =
|
|
751
|
-
useMenuItemDragAndDrop({
|
|
752
|
-
draggable: {
|
|
753
|
-
getInitialData: () => getProjectData(project),
|
|
754
|
-
getDragPreviewPieces: () => ({
|
|
755
|
-
elemBefore: <ProjectIcon label="" color="currentColor" />,
|
|
756
|
-
content: project.name,
|
|
757
|
-
}),
|
|
758
|
-
},
|
|
759
|
-
dropTarget: {
|
|
760
|
-
getData: () => getProjectData(project),
|
|
761
|
-
getOperations: () => ({
|
|
762
|
-
'reorder-after': 'available',
|
|
763
|
-
'reorder-before': 'available',
|
|
764
|
-
}),
|
|
765
|
-
canDrop: ({ source }) => isProjectData(source.data),
|
|
766
|
-
},
|
|
767
|
-
});
|
|
768
|
-
|
|
769
|
-
return (
|
|
770
|
-
<>
|
|
771
|
-
<LinkMenuItem
|
|
772
|
-
href={project.href}
|
|
773
|
-
elemBefore={project.icon}
|
|
774
|
-
ref={draggableAnchorRef}
|
|
775
|
-
isDragging={state.type === 'dragging'}
|
|
776
|
-
hasDragIndicator
|
|
777
|
-
dropIndicator={dropIndicator}
|
|
778
|
-
visualContentRef={dropTargetRef}
|
|
779
|
-
>
|
|
780
|
-
{project.name}
|
|
781
|
-
</LinkMenuItem>
|
|
782
|
-
{dragPreview}
|
|
783
|
-
</>
|
|
784
|
-
);
|
|
785
|
-
}
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
What `useMenuItemDragAndDrop` does for you:
|
|
789
|
-
|
|
790
|
-
- Sets up a `draggable()` (with conditional dragging)
|
|
791
|
-
- Sets up a `dropTargetForElements()` (with conditional dropping)
|
|
792
|
-
- Prevents dropping on self
|
|
793
|
-
- Sets up the `<DragPreview>`, pushes it away from the users pointer by the desired amount, and
|
|
794
|
-
mounts it to a `react` portal
|
|
795
|
-
- Attaches `Operation`s to the drop target
|
|
796
|
-
- Returns the correct drop indicator for the current `Operation`.
|
|
797
|
-
- Manages it's own state in a performant way and let's you respond to state changes
|
|
798
|
-
- Automatically makes the drop target sticky (stickiness will be cleared by `GroupDropIndicator`)
|
|
799
|
-
|
|
800
|
-
Arguments:
|
|
801
|
-
|
|
802
|
-
- `draggable`: object containing arguments relevant for setting up the `draggable()`. Don't include
|
|
803
|
-
the `draggable` property if you don't ever want the menu item it be a draggable.
|
|
804
|
-
- `draggable.canDrag`: Whether or not the element should be `draggable` (useful for conditional
|
|
805
|
-
dragging)
|
|
806
|
-
- `draggable.getInitialData()`: data to attach to the `draggable` (see
|
|
807
|
-
[draggable | getInitialData](TODO))
|
|
808
|
-
- `draggable.getDragPreviewPieces()`: provide the `ReactNode`s to be used when rendering the
|
|
809
|
-
`<DragPreview />`
|
|
810
|
-
|
|
811
|
-
- `dropTarget`: object containg arguments relevant for setting up a menu item as a drop target.
|
|
812
|
-
Don't include the `dropTarget` property if you don't ever want the menu item it be a draggable.
|
|
813
|
-
- `dropTarget.canDrop()`: whether or not the menu item can be dropped on (see
|
|
814
|
-
[dropTargetForElements | canDrop](TODO))
|
|
815
|
-
- `dropTarget.getData()`: data to attach to the drop target (see [dropTarget | getData](TODO))
|
|
816
|
-
- `dropTarget.getOperations()`: which drop `Operation`s
|
|
817
|
-
(`"reorder-before" | "reorder-after" | "combine`") are permitted on the menu item
|
|
818
|
-
|
|
819
|
-
Return value:
|
|
820
|
-
|
|
821
|
-
- `state`: an object containing what the drag and drop state of the menu item is
|
|
822
|
-
(`"idle" | "preview" | "dragging" | "is-over"`)
|
|
823
|
-
- `draggableAnchorRef`: used to mark an anchor element as the draggable element. Use this if the
|
|
824
|
-
menu item is an anchor.
|
|
825
|
-
- `draggableButtonRef`: used to mark an button element as the draggable element. Use this if the
|
|
826
|
-
menu item is an button.
|
|
827
|
-
- `dropTargetRef`: must be used to mark the `HTMLDivElement` as the `dropTargetForElements`
|
|
828
|
-
- `dragPreview`: a `ReactNode` to be included in your `react` tree which will be used to render the
|
|
829
|
-
`<DragPreview />`
|
|
830
|
-
- `dropIndicator`: a `ReactNode` containing the drop indicator if it's needed
|
|
831
|
-
|
|
832
|
-
## Accessible actions
|
|
833
|
-
|
|
834
|
-
**<Lozenge appearance="success" isBold>Goal</Lozenge> provide a delightful way for folks leveraging
|
|
835
|
-
assistive technologies to achieve the same outcomes as a drag and drop operation**
|
|
836
|
-
|
|
837
|
-
All menu items that have drag and drop enabled must also include an alternative mechanism to achieve
|
|
838
|
-
the same outcomes as drag and drop operations.
|
|
839
|
-
|
|
840
|
-
<Example Component={StandaloneJiraSidebar} appearance="showcase-only" />
|
|
841
|
-
|
|
842
|
-
What you need to do (for all menu items _except_ `FlyoutMenuItemTrigger`)
|
|
843
|
-
|
|
844
|
-
- All menu items with drag and drop enabled must have a "more" button as `actionsOnHover`
|
|
845
|
-
- The more menu should be a trigger for a `DropdownMenu`
|
|
846
|
-
- The `DropdownMenu` menu should contain an entry called `"Reorder ${entityName}"` or `"Move"`. The
|
|
847
|
-
`DropdownMenu` can also contain other actions for the entity (eg "Archive").
|
|
848
|
-
|
|
849
|
-
For `FlyoutMenuItemTrigger`:
|
|
850
|
-
|
|
851
|
-
- `FlyoutMenuItemTrigger` does not support `actionsOnHover`, so you need to put a
|
|
852
|
-
`"Reorder ${entityName}"` menu item in the `FlyoutMenuItemContent` of the `FlyoutMenuItem`.
|
|
853
|
-
- It is known that this is a minor inconsistency with other menu items; however, this was decided to
|
|
854
|
-
be the best available option based on how our menu items work today.
|
|
855
|
-
|
|
856
|
-
### Move operations
|
|
857
|
-
|
|
858
|
-
There are two categories of movement actions:
|
|
859
|
-
|
|
860
|
-
1. Only reordering is available
|
|
861
|
-
|
|
862
|
-
Show a further submenu with available operations. The possible operations are:
|
|
863
|
-
|
|
864
|
-
1. "Move to top"
|
|
865
|
-
2. "Move up"
|
|
866
|
-
3. "Move down"
|
|
867
|
-
4. "Move to bottom"
|
|
868
|
-
|
|
869
|
-
- When an item is in the last position: "Move down" and "Move to bottom" should be disabled
|
|
870
|
-
- When an item is in the first position: "Move to top" and "Move up" should be disabled
|
|
871
|
-
- When there is only one item in the group, the `"Reorder ${entityName}"` dropdown menu should be
|
|
872
|
-
disabled.
|
|
873
|
-
|
|
874
|
-
_See "project" menu items in the above example for what this looks like_
|
|
875
|
-
|
|
876
|
-
2. More complex operations are available
|
|
877
|
-
|
|
878
|
-
When operations other than just reordering are possible (eg combining, moving to different levels in
|
|
879
|
-
the navigation and so on), then show a modal containing a form with a way for a user to input any
|
|
880
|
-
available action.
|
|
881
|
-
|
|
882
|
-
_See "filter" menu items in the above example for what this looks like_
|
|
883
|
-
|
|
884
|
-
### Focus restoration
|
|
885
|
-
|
|
886
|
-
After an item has been moved with an action menu, and the control triggering the action had focus,
|
|
887
|
-
then the **menu item** `ref` should be given focus in it's new location. At this stage we have
|
|
888
|
-
decided not to give focus to the more menu dropdown button as that is not universally available on
|
|
889
|
-
the menu item (eg for flyout menu items, we are putting the move action in the flyout).
|
|
890
|
-
|
|
891
|
-
See
|
|
892
|
-
["Let the user easily continue to trigger more outcomes"](/components/pragmatic-drag-and-drop/accessibility-guidelines#3-let-the-user-easily-continue-to-trigger-more-outcomes)
|
|
893
|
-
in our drag and drop accessibility guide.
|
|
894
|
-
|
|
895
|
-
When working with complex movement actions (eg move into child) this will require expanding all
|
|
896
|
-
parent expandable menu items when the drag finishes.
|
|
897
|
-
|
|
898
|
-
## Special guidance
|
|
899
|
-
|
|
900
|
-
### ExpandableMenuItem
|
|
901
|
-
|
|
902
|
-
Sometimes you want the `ExpandableMenuItemTrigger` to be your drop target, and sometimes you want
|
|
903
|
-
the `ExpandableMenuItemTrigger` and the `ExpandableMenuItemContent` to be a single drop target.
|
|
904
|
-
|
|
905
|
-
_In our provided example, when dragging a top level menu item, the whole `ExpandableMenuItem` is a
|
|
906
|
-
drop target, whereas when dragging a filter, the `ExpandableMenuItemTrigger` is the drop target._
|
|
907
|
-
|
|
908
|
-
When the `ExpandableMenuItemTrigger` is the drop target, you should attach the `dropTargetRef` and
|
|
909
|
-
provide the `dropIndicator` to the `ExpandableMenuItemTrigger`.
|
|
910
|
-
|
|
911
|
-
```tsx
|
|
912
|
-
function Project({ project }: { project: TProject }) {
|
|
913
|
-
const { state, draggableAnchorRef, dragPreview, dropTargetRef, dropIndicator } =
|
|
914
|
-
useMenuItemDragAndDrop({
|
|
915
|
-
draggable: {
|
|
916
|
-
getInitialData: () => getProjectData(project),
|
|
917
|
-
getDragPreviewPieces: () => ({
|
|
918
|
-
elemBefore: project.icon,
|
|
919
|
-
content: project.name,
|
|
920
|
-
}),
|
|
921
|
-
},
|
|
922
|
-
dropTarget: {
|
|
923
|
-
getData: () => getProjectData(project),
|
|
924
|
-
getOperations: () => ({
|
|
925
|
-
'reorder-after': 'available',
|
|
926
|
-
'reorder-before': 'available',
|
|
927
|
-
}),
|
|
928
|
-
canDrop: ({ source }) => isProjectData(source.data),
|
|
929
|
-
},
|
|
930
|
-
});
|
|
931
|
-
|
|
932
|
-
return (
|
|
933
|
-
<>
|
|
934
|
-
<LinkMenuItem
|
|
935
|
-
href={project.href}
|
|
936
|
-
elemBefore={project.icon}
|
|
937
|
-
ref={draggableAnchorRef}
|
|
938
|
-
isDragging={state.type === 'dragging'}
|
|
939
|
-
hasDragIndicator
|
|
940
|
-
// 👇 drop target is the the trigger
|
|
941
|
-
visualContentRef={dropTargetRef}
|
|
942
|
-
dropIndicator={dropIndicator}
|
|
943
|
-
>
|
|
944
|
-
{project.name}
|
|
945
|
-
</LinkMenuItem>
|
|
946
|
-
{dragPreview}
|
|
947
|
-
</>
|
|
948
|
-
);
|
|
949
|
-
}
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
When the whole `ExpandableMenuItem` is the drop target, you should attach the `dropTargetRef` and
|
|
953
|
-
provide the `dropIndicator` to the `ExpandableMenuItem`.
|
|
954
|
-
|
|
955
|
-
```tsx
|
|
956
|
-
export function ProjectsMenuItem() {
|
|
957
|
-
const { state, draggableButtonRef, dragPreview, dropTargetRef, dropIndicator } =
|
|
958
|
-
useMenuItemDragAndDrop({
|
|
959
|
-
draggable: {
|
|
960
|
-
getInitialData: () => getTopLevelItemData('projects'),
|
|
961
|
-
getDragPreviewPieces: () => ({
|
|
962
|
-
elemBefore: <ProjectIcon label="" color="currentColor" />,
|
|
963
|
-
content: 'Projects',
|
|
964
|
-
}),
|
|
965
|
-
},
|
|
966
|
-
dropTarget: {
|
|
967
|
-
getData: () => getTopLevelItemData('projects'),
|
|
968
|
-
getOperations: () => ({
|
|
969
|
-
'reorder-after': 'available',
|
|
970
|
-
'reorder-before': 'available',
|
|
971
|
-
}),
|
|
972
|
-
canDrop: ({ source }) => isTopLevelItemData(source.data),
|
|
973
|
-
},
|
|
974
|
-
});
|
|
975
|
-
|
|
976
|
-
return (
|
|
977
|
-
<>
|
|
978
|
-
<ExpandableMenuItem
|
|
979
|
-
// 👇 drop target is the whole expandable item
|
|
980
|
-
ref={dropTargetRef}
|
|
981
|
-
// 👇 pass the drop indicator to the whole expandable item
|
|
982
|
-
dropIndicator={dropIndicator}
|
|
983
|
-
>
|
|
984
|
-
<ExpandableMenuItemTrigger
|
|
985
|
-
// 👇 trigger is still the draggable
|
|
986
|
-
ref={draggableButtonRef}
|
|
987
|
-
isDragging={state.type === 'dragging'}
|
|
988
|
-
hasDragIndicator
|
|
989
|
-
elemBefore={<ProjectIcon label="" color="currentColor" />}
|
|
990
|
-
>
|
|
991
|
-
Projects
|
|
992
|
-
</ExpandableMenuItemTrigger>
|
|
993
|
-
<ExpandableMenuItemContent>{/* ... */}</ExpandableMenuItemContent>
|
|
994
|
-
</ExpandableMenuItem>
|
|
995
|
-
{dragPreview}
|
|
996
|
-
</>
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
```
|
|
1000
|
-
|
|
1001
|
-
### ExpandableMenuItemTrigger
|
|
1002
|
-
|
|
1003
|
-
#### Drag start
|
|
1004
|
-
|
|
1005
|
-
When dragging any menu item, all expandable menu items that are valid drop targets, or contain valid
|
|
1006
|
-
drop targets, should have their `<ExpandableMenuItemTrigger>` should no longer show any custom
|
|
1007
|
-
`elemBefore` and use the default icons. Expandable menu items can be expanded during a drag, and
|
|
1008
|
-
showing their chevrons is a helpful way for users to see at a glance which parts of the side
|
|
1009
|
-
navigation can potentially be nested into
|
|
1010
|
-
|
|
1011
|
-
```tsx
|
|
1012
|
-
<ExpandableMenuItemTrigger elemBefore={isFilterDragging ? null : item.elemBefore}>
|
|
1013
|
-
{filter.name}
|
|
1014
|
-
</ExpandableMenuItemTrigger>
|
|
1015
|
-
```
|
|
1016
|
-
|
|
1017
|
-
When dragging a `<ExpandableMenuItemTrigger>` you should collapse the expandable menu when the drag
|
|
1018
|
-
is starting. This prevents the strange case of a parent dragging into itself.
|
|
1019
|
-
|
|
1020
|
-
#### While dragging
|
|
1021
|
-
|
|
1022
|
-
If a user drags over of `<ExpandableMenuItemTrigger>` for `500ms` with the `"combine"` operation,
|
|
1023
|
-
and the menu item is not expanded, then it should be expanded. This allows users to drag into
|
|
1024
|
-
collapsed menu items.
|
|
1025
|
-
|
|
1026
|
-
#### On drop
|
|
1027
|
-
|
|
1028
|
-
Once the drag is completed, you should restore the collapsed state of the
|
|
1029
|
-
`ExpandableMenuItemTrigger`
|
|
1030
|
-
|
|
1031
|
-
- If it was collapsed before the drag started: keep it collapsed
|
|
1032
|
-
- If it was expanded before the drag started: expand it again after the drag as completed
|
|
1033
|
-
|
|
1034
|
-
The dragged `ExpandableMenuItemTrigger` must be visible after the drag has finished. This will
|
|
1035
|
-
involve expanding any parent `ExpandableMenuItemTrigger` needed.
|
|
1036
|
-
|
|
1037
|
-
An example: Dragging Filter A and the drop operation is a `"combine"` on a collapsed Filter B
|
|
1038
|
-
`ExpandableMenuItemTrigger`. Outcome: Filter B should be expanded to make Filter A visible after the
|
|
1039
|
-
drop.
|
|
1040
|
-
|
|
1041
|
-
### FlyoutMenuItemTrigger
|
|
1042
|
-
|
|
1043
|
-
#### Drag start
|
|
1044
|
-
|
|
1045
|
-
All `<FlyoutMenuItemTrigger>`s should be closed when dragging _any_ menu item.
|
|
1046
|
-
|
|
1047
|
-
#### While dragging
|
|
1048
|
-
|
|
1049
|
-
<SectionMessage title="Not supported (yet)" appearance="warning">
|
|
1050
|
-
|
|
1051
|
-
It is currently _not supported_ to drop an item onto a `FlyoutMenuItemTrigger` or into
|
|
1052
|
-
`FlyoutMenuItemContent`. There are some experience questions to be worked through to support this.
|
|
1053
|
-
We thought we would wait and see if anybody needed this before spending too much time on it. If you
|
|
1054
|
-
have need of this use case, please reach out and we can prioritize working through the design
|
|
1055
|
-
challenges.
|
|
1056
|
-
|
|
1057
|
-
</SectionMessage>
|
|
1058
|
-
|
|
1059
|
-
#### Accessible actions for flyouts
|
|
1060
|
-
|
|
1061
|
-
See our [accessible actions](#accessible-actions) section for `FlyoutMenuItemTrigger` specific
|
|
1062
|
-
guidance.
|
|
1063
|
-
|
|
1064
|
-
### anchors
|
|
1065
|
-
|
|
1066
|
-
By default, menu items that are **anchor elements (`<a>`)** are _not_ draggable (unlike standard
|
|
1067
|
-
anchor elements that are **draggable** by default).
|
|
1068
|
-
|
|
1069
|
-
Menu items that are anchors:
|
|
1070
|
-
|
|
1071
|
-
- `LinkMenuItem`
|
|
1072
|
-
- `ExpandableMenuItemTrigger` with a `href`
|
|
1073
|
-
- `FlyoutMenuItemTrigger` with a `href`
|
|
1074
|
-
|
|
1075
|
-
If you want one of these menu items to be draggable, then you need to wire them up for drag and drop
|
|
1076
|
-
according to this guide. For anchor elements, the URL information is _automatically_ attached to the
|
|
1077
|
-
native drag data, so the anchor can be dragged into the browser menu bar, other external application
|
|
1078
|
-
and so on. You are welcome to attach additional information using
|
|
1079
|
-
[`getInitialData()` and `getInitialDataForExternal()` from Pragmatic drag and drop](/components/pragmatic-drag-and-drop/core-package/adapters/element/about#draggable).
|