Skip to content

Commit

Permalink
Draggable: Allow elementId based elements to be attached to the owner…
Browse files Browse the repository at this point in the history
…Document body (#49911)

* Draggable: Allow elementId based elements to be attached to the ownerDocument body

* Update changelog

* Remove comment

* Add missing fullstop in changelog

* Switch to appendToOwnerDocument, simplify stories

* Update changelog entry

* Fix formatting issue

Co-authored-by: Lena Morita <[email protected]>

---------

Co-authored-by: Lena Morita <[email protected]>
  • Loading branch information
andrewserong and mirka authored Apr 20, 2023
1 parent b8733ad commit 5aa3e75
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 35 deletions.
1 change: 1 addition & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

### Enhancements

- `Draggable`: Add `appendToOwnerDocument` prop to allow elementId based elements to be attached to the ownerDocument body ([#49911](https://github.com/WordPress/gutenberg/pull/49911)).
- `TreeGrid`: Modify keyboard navigation code to use a data-expanded attribute if aria-expanded is to be controlled outside of the TreeGrid component ([#48461](https://github.com/WordPress/gutenberg/pull/48461)).
- `Modal`: Equalize internal spacing ([#49890](https://github.com/WordPress/gutenberg/pull/49890)).
- `Modal`: Increased border radius ([#49870](https://github.com/WordPress/gutenberg/pull/49870)).
Expand Down
9 changes: 8 additions & 1 deletion packages/components/src/draggable/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,16 @@ Note that the drag handle needs to declare the `draggable="true"` property and b

The component accepts the following props:

### `appendToOwnerDocument`: `boolean`

Whether to append the cloned element to the `ownerDocument` body. By default, elements sourced by id are appended to the element's wrapper.

- Required: No
- Default: `false`

### `elementId`: `string`

The HTML id of the element to clone on drag
The HTML id of the element to clone on drag.

- Required: Yes

Expand Down
7 changes: 6 additions & 1 deletion packages/components/src/draggable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export function Draggable( {
onDragStart,
onDragOver,
onDragEnd,
appendToOwnerDocument = false,
cloneClassname,
elementId,
transferData,
Expand Down Expand Up @@ -173,7 +174,11 @@ export function Draggable( {
cloneWrapper.appendChild( clone );

// Inject the cloneWrapper into the DOM.
elementWrapper?.appendChild( cloneWrapper );
if ( appendToOwnerDocument ) {
ownerDocument.body.appendChild( cloneWrapper );
} else {
elementWrapper?.appendChild( cloneWrapper );
}
}

// Mark the current cursor coordinates.
Expand Down
102 changes: 69 additions & 33 deletions packages/components/src/draggable/stories/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { DragEvent } from 'react';
/**
* WordPress dependencies
*/
import { useInstanceId } from '@wordpress/compose';
import { useState } from '@wordpress/element';
import { Icon, more } from '@wordpress/icons';

Expand All @@ -32,46 +33,68 @@ export default meta;

const DefaultTemplate: ComponentStory< typeof Draggable > = ( args ) => {
const [ isDragging, setDragging ] = useState( false );
const instanceId = useInstanceId( DefaultTemplate );

// Allow for the use of ID in the example.
return (
<div>
<p>Is Dragging? { isDragging ? 'Yes' : 'No!' }</p>
<p
style={ {
padding: '1em',
position: 'relative',
zIndex: 1000,
backgroundColor: 'whitesmoke',
} }
>
Is Dragging? { isDragging ? 'Yes' : 'No!' }
</p>
<div
/* eslint-disable no-restricted-syntax, eslint-comments/disable-enable-pair */
id="draggable-example-box"
style={ { display: 'inline-flex' } }
style={ {
zIndex: 100,
position: 'relative',
} }
>
<Draggable { ...args } elementId="draggable-example-box">
{ ( { onDraggableStart, onDraggableEnd } ) => {
const handleOnDragStart = ( event: DragEvent ) => {
setDragging( true );
onDraggableStart( event );
};
const handleOnDragEnd = ( event: DragEvent ) => {
setDragging( false );
onDraggableEnd( event );
};

return (
<div
onDragStart={ handleOnDragStart }
onDragEnd={ handleOnDragEnd }
draggable
style={ {
alignItems: 'center',
display: 'flex',
justifyContent: 'center',
width: 100,
height: 100,
background: '#ddd',
} }
>
<Icon icon={ more } />
</div>
);
<div
id={ `draggable-example-box-${ instanceId }` }
style={ {
display: 'inline-flex',
position: 'relative',
} }
</Draggable>
>
<Draggable
{ ...args }
elementId={ `draggable-example-box-${ instanceId }` }
>
{ ( { onDraggableStart, onDraggableEnd } ) => {
const handleOnDragStart = ( event: DragEvent ) => {
setDragging( true );
onDraggableStart( event );
};
const handleOnDragEnd = ( event: DragEvent ) => {
setDragging( false );
onDraggableEnd( event );
};

return (
<div
onDragStart={ handleOnDragStart }
onDragEnd={ handleOnDragEnd }
draggable
style={ {
alignItems: 'center',
display: 'flex',
justifyContent: 'center',
width: 100,
height: 100,
background: '#ddd',
} }
>
<Icon icon={ more } />
</div>
);
} }
</Draggable>
</div>
</div>
</div>
);
Expand All @@ -81,3 +104,16 @@ export const Default: ComponentStory< typeof Draggable > = DefaultTemplate.bind(
{}
);
Default.args = {};

/**
* `appendToOwnerDocument` is used to append the element being dragged to the body of the owner document.
*
* This is useful when the element being dragged should not receive styles from its parent.
* For example, when the element's parent sets a `z-index` value that would cause the dragged
* element to be rendered behind other elements.
*/
export const AppendElementToOwnerDocument: ComponentStory< typeof Draggable > =
DefaultTemplate.bind( {} );
AppendElementToOwnerDocument.args = {
appendToOwnerDocument: true,
};
7 changes: 7 additions & 0 deletions packages/components/src/draggable/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ export type DraggableProps = {
*/
onDraggableEnd: ( event: DragEvent ) => void;
} ) => JSX.Element | null;
/**
* Whether to append the cloned element to the `ownerDocument` body.
* By default, elements sourced by id are appended to the element's wrapper.
*
* @default false
*/
appendToOwnerDocument?: boolean;
/**
* Classname for the cloned element.
*/
Expand Down

1 comment on commit 5aa3e75

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 5aa3e75.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/4759745336
📝 Reported issues:

Please sign in to comment.