Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/react-aria-components/docs/DropZone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,11 @@ function Example() {
}
```

If a `DropZone` is rendered in a positioned scroll container, focusing the visually hidden drop
button may cause the container to scroll. The `dropButtonStyle` prop can be used to adjust the
position of this internal button wrapper, for example `dropButtonStyle={{position: 'fixed', top: 0,
left: 0}}`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The current dropzone docs are actually located at https://github.com/adobe/react-spectrum/blob/main/packages/dev/s2-docs/pages/react-aria/DropZone.mdx
so you'll want to move them there. I'm ok with adding these docs there since the DropZone docs are pretty light as is, but others can weigh in since I know we have a stance of keeping all the docs light whenever possible as is

## Visual feedback

A dropzone displays visual feedback to the user when a drag hovers over the drop target by passing the `getDropOperation` function. If a drop target only supports data of specific types (e.g. images, videos, text, etc.), then it should implement the `getDropOperation` prop and return `cancel` for types that aren't supported. This will prevent visual feedback indicating that the drop target accepts the dragged data when this is not true. [Read more about getDropOperation.](https://react-spectrum.adobe.com/react-aria/useDrop.html#getdropoperation)
Expand Down
10 changes: 8 additions & 2 deletions packages/react-aria-components/src/DropZone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {getEventTarget, nodeContains} from 'react-aria/private/utils/shadowdom/D
import intlMessages from '../intl/*.json';
import {isFocusable} from 'react-aria/private/utils/isFocusable';
import {mergeProps} from 'react-aria/mergeProps';
import React, {createContext, ForwardedRef, forwardRef, useRef} from 'react';
import React, {createContext, CSSProperties, ForwardedRef, forwardRef, useRef} from 'react';
import {TextContext} from './Text';
import {useButton} from 'react-aria/useButton';
import {useClipboard} from 'react-aria/useClipboard';
Expand Down Expand Up @@ -87,6 +87,11 @@ export interface DropZoneProps
* @default 'react-aria-DropZone'
*/
className?: ClassNameOrFunction<DropZoneRenderProps>;
/**
* The inline style for the visually hidden drop button used for keyboard and screen reader drop
* interactions.
*/
dropButtonStyle?: CSSProperties;
}

export const DropZoneContext = createContext<ContextValue<DropZoneProps, HTMLDivElement>>(null);
Expand All @@ -100,6 +105,7 @@ export const DropZone = forwardRef(function DropZone(
) {
let {isDisabled = false} = props;
[props, ref] = useContextProps(props, ref, DropZoneContext);
let {dropButtonStyle} = props;
let dropzoneRef = useObjectRef(ref);
let buttonRef = useRef<HTMLButtonElement>(null);
let {dropProps, dropButtonProps, isDropTarget} = useDrop({
Expand Down Expand Up @@ -162,7 +168,7 @@ export const DropZone = forwardRef(function DropZone(
data-focus-visible={isFocusVisible || undefined}
data-drop-target={isDropTarget || undefined}
data-disabled={isDisabled || undefined}>
<VisuallyHidden>
<VisuallyHidden style={dropButtonStyle}>
<button
{...mergeProps(buttonProps, focusProps, clipboardProps, labelProps)}
ref={buttonRef}
Expand Down
12 changes: 12 additions & 0 deletions packages/react-aria-components/test/DropZone.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,18 @@ describe('DropZone', () => {
await user.click(button);
expect(document.activeElement).toBe(button);
});

it('should support custom styles on the visually hidden drop button wrapper', () => {
let {getByRole} = render(
<DropZone dropButtonStyle={{position: 'fixed', top: 0, left: 0}} />
);

expect(getByRole('button').parentElement).toHaveStyle({
position: 'fixed',
top: '0px',
left: '0px'
});
});
});

describe('via keyboard', function () {
Expand Down