Skip to content

Commit 3c3485f

Browse files
yihuiliaoLFDanLu
andauthored
Update examples and imports in RSP DropZone docs (#5138)
* Update examples and imports in RSP DropZone docs * fix typecheck * fix typecheck again * fix spacing --------- Co-authored-by: Daniel Lu <dl1644@gmail.com>
1 parent e6d57e7 commit 3c3485f

File tree

1 file changed

+173
-99
lines changed

1 file changed

+173
-99
lines changed

packages/@react-spectrum/dropzone/docs/DropZone.mdx

Lines changed: 173 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ import {DropZone} from '@react-spectrum/dropzone';
2121
import {Heading} from '@react-spectrum/text';
2222
import {Content} from '@react-spectrum/view';
2323
import {IllustratedMessage} from '@react-spectrum/illustratedmessage';
24-
import {Text} from 'react-aria-components';
25-
import {FileTrigger} from 'react-aria-components';
2624
import {Button} from '@react-spectrum/button';
2725
```
2826

@@ -43,102 +41,36 @@ category: Drag and drop
4341

4442
```tsx example
4543
import Upload from '@spectrum-icons/illustrations/Upload';
46-
47-
<DropZone
48-
maxWidth="size-3000">
49-
<IllustratedMessage>
50-
<Upload />
51-
<Heading>
52-
<Text slot="label">
53-
Drag and drop your file
54-
</Text>
55-
</Heading>
56-
</IllustratedMessage>
57-
</DropZone>
58-
```
59-
60-
61-
## Content
62-
63-
A drop zone accepts an [IllustratedMessage](IllustratedMessage.html) as a child which is comprised of three areas: an illustration, a title, and a body. Each of these sections can be populated by providing the following components to the IllustratedMessage as children: a SVG, a [Heading](Heading.html) (title), and a [Content](Content.html) (body). A [FileTrigger](../react-aria/FileTrigger.html) is commonly paired with a DropZone to allow a user to choose files from their device.
64-
65-
```tsx example
66-
<DropZone
67-
maxWidth="size-3000">
68-
<IllustratedMessage>
69-
<Upload />
70-
<Heading>
71-
<Text slot="label">
72-
Drag and drop here
73-
</Text>
74-
</Heading>
75-
<Content>
76-
<FileTrigger>
77-
<Button variant="primary">Browse</Button>
78-
</FileTrigger>
79-
</Content>
80-
</IllustratedMessage>
81-
</DropZone>
82-
```
83-
84-
### Accessibility
85-
86-
A visual label should be provided to `DropZone` using a `Text` element with a `label` slot. If it is not provided, then an `aria-label` or `aria-labelledby` prop must be passed to identify the visually hidden button to assistive technology.
87-
88-
### Internationalization
89-
90-
In order to internationalize a drop zone, a localized string should be passed to the `Text` element with a `label` slot or to the `aria-label` prop, in addition to the `replaceMessage` prop.
91-
92-
## Events
93-
94-
`DropZone` supports drop operations via mouse, keyboard, and touch. You can handle all of these via the `onDrop` prop. In addition, the `onDropEnter`, `onDropMove`, and `onDropExit` events are fired as the user enter and exists the dropzone during a drag operation.
95-
96-
The following example uses an `onDrop` handler to update the filled status stored in React state.
97-
98-
```tsx example
99-
import File from '@spectrum-icons/illustrations/File';
44+
import {Text} from 'react-aria-components';
10045

10146
function Example() {
10247
let [isFilled, setIsFilled] = React.useState(false);
103-
let [filledSrc, setFilledSrc] = React.useState(null);
104-
48+
10549
return (
10650
<>
10751
<Draggable />
10852
<DropZone
10953
maxWidth="size-3000"
11054
isFilled={isFilled}
111-
onDrop={async (e) => {
112-
e.items.find(async (item) => {
113-
if (item.kind === 'file') {
114-
setFilledSrc(item.name);
115-
setIsFilled(true);
116-
117-
} else if (item.kind === 'text' && item.types.has('text/plain')) {
118-
setFilledSrc(await item.getText('text/plain'));
119-
setIsFilled(true);
120-
}
121-
});
122-
}}>
55+
onDrop={() => setIsFilled(true)}>
12356
<IllustratedMessage>
12457
<Upload />
12558
<Heading>
12659
<Text slot="label">
127-
Drag and drop here
60+
Drag and drop your file
12861
</Text>
12962
</Heading>
13063
</IllustratedMessage>
13164
</DropZone>
132-
{isFilled &&
133-
<div className="files">
134-
<File />
135-
{filledSrc}
136-
</div>}
65+
{isFilled &&
66+
<div className="dropped">
67+
You dropped something!
68+
</div>
69+
}
13770
</>
138-
);
71+
)
13972
}
14073
```
141-
14274
The `Draggable` component used above is defined below. See [useDrag](../react-aria/useDrag.html) for more details and documentation.
14375

14476
<details>
@@ -185,14 +117,117 @@ function Draggable() {
185117
opacity: 0.5;
186118
}
187119

188-
.files{
120+
.dropped {
189121
margin-top: 20px;
190122
}
191123
```
192-
193124
</details>
194125

195126

127+
128+
## Content
129+
130+
A drop zone accepts an [IllustratedMessage](IllustratedMessage.html) as a child which is comprised of three areas: an illustration, a title, and a body. Each of these sections can be populated by providing the following components to the IllustratedMessage as children: a SVG, a [Heading](Heading.html) (title), and a [Content](Content.html) (body). A [FileTrigger](../react-aria/FileTrigger.html) is commonly paired with a DropZone to allow a user to choose files from their device.
131+
132+
```tsx example
133+
import {FileTrigger} from 'react-aria-components';
134+
import {Text} from 'react-aria-components';
135+
136+
function Example() {
137+
let [isFilled, setIsFilled] = React.useState(false);
138+
139+
return (
140+
<>
141+
<Draggable />
142+
<DropZone
143+
maxWidth="size-3000"
144+
isFilled={isFilled}
145+
onDrop={() => setIsFilled(true)}>
146+
<IllustratedMessage>
147+
<Upload />
148+
<Heading>
149+
<Text slot="label">
150+
Drag and drop here
151+
</Text>
152+
</Heading>
153+
<Content>
154+
<FileTrigger
155+
onSelect={()=> setIsFilled(true)}>
156+
<Button variant="primary">Browse</Button>
157+
</FileTrigger>
158+
</Content>
159+
</IllustratedMessage>
160+
</DropZone>
161+
{isFilled &&
162+
<div className="dropped">
163+
You dropped something!
164+
</div>
165+
}
166+
</>
167+
)
168+
}
169+
```
170+
171+
### Accessibility
172+
173+
A visual label should be provided to `DropZone` using a `Text` element with a `label` slot. If it is not provided, then an `aria-label` or `aria-labelledby` prop must be passed to identify the visually hidden button to assistive technology.
174+
175+
### Internationalization
176+
177+
In order to internationalize a drop zone, a localized string should be passed to the `Text` element with a `label` slot or to the `aria-label` prop, in addition to the `replaceMessage` prop.
178+
179+
## Events
180+
181+
`DropZone` supports drop operations via mouse, keyboard, and touch. You can handle all of these via the `onDrop` prop. In addition, the `onDropEnter`, `onDropMove`, and `onDropExit` events are fired as the user enter and exists the dropzone during a drag operation.
182+
183+
The following example uses an `onDrop` handler to update the filled status stored in React state.
184+
185+
```tsx example
186+
import File from '@spectrum-icons/illustrations/File';
187+
import {Text} from 'react-aria-components';
188+
189+
function Example() {
190+
let [isFilled, setIsFilled] = React.useState(false);
191+
let [filledSrc, setFilledSrc] = React.useState(null);
192+
193+
return (
194+
<>
195+
<Draggable />
196+
<DropZone
197+
maxWidth="size-3000"
198+
isFilled={isFilled}
199+
onDrop={async (e) => {
200+
e.items.find(async (item) => {
201+
if (item.kind === 'file') {
202+
setFilledSrc(item.name);
203+
setIsFilled(true);
204+
205+
} else if (item.kind === 'text' && item.types.has('text/plain')) {
206+
setFilledSrc(await item.getText('text/plain'));
207+
setIsFilled(true);
208+
}
209+
});
210+
}}>
211+
<IllustratedMessage>
212+
<Upload />
213+
<Heading>
214+
<Text slot="label">
215+
Drag and drop here
216+
</Text>
217+
</Heading>
218+
</IllustratedMessage>
219+
</DropZone>
220+
{isFilled &&
221+
<div className="dropped">
222+
<File />
223+
{filledSrc}
224+
</div>}
225+
</>
226+
);
227+
}
228+
```
229+
230+
196231
## Props
197232

198233
<PropTable component={docs.exports.DropZone} links={docs.links} />
@@ -206,6 +241,8 @@ The user is responsible for both managing the filled state of a drop zone and ha
206241
The example below demonstrates one way of styling the filled state.
207242

208243
```tsx example
244+
import {Text} from 'react-aria-components';
245+
209246
function Example() {
210247
let [filledSrc, setFilledSrc] = React.useState(null);
211248
let [isFilled, setIsFilled] = React.useState(false);
@@ -302,6 +339,8 @@ When a drop zone is in a filled state and has an object dragged over it, a messa
302339

303340

304341
```tsx example
342+
import {Text} from 'react-aria-components';
343+
305344
function Example() {
306345
let [isFilled, setIsFilled] = React.useState(false);
307346

@@ -322,6 +361,11 @@ function Example() {
322361
</Heading>
323362
</IllustratedMessage>
324363
</DropZone>
364+
{isFilled &&
365+
<div className="dropped">
366+
You dropped something!
367+
</div>
368+
}
325369
</>
326370
);
327371
}
@@ -332,30 +376,60 @@ function Example() {
332376
A drop zone 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.](../react-aria/useDrop.html#getdropoperation)
333377

334378
```tsx example
379+
import {FileTrigger} from 'react-aria-components';
380+
import {Text} from 'react-aria-components';
381+
import {FileDropItem} from 'react-aria';
335382

336383
function Example() {
337384
let [isFilled, setIsFilled] = React.useState(false);
385+
let [filledSrc, setFilledSrc] = React.useState(null);
338386

339387
return (
340-
<DropZone
341-
maxWidth="size-3000"
342-
isFilled={isFilled}
343-
getDropOperation={(types) => types.has('image/png') ? 'copy' : 'cancel'}
344-
onDrop={() => setIsFilled(true)}>
345-
<IllustratedMessage>
346-
<Upload />
347-
<Heading>
348-
<Text slot="label">
349-
Drag and drop here
350-
</Text>
351-
</Heading>
352-
<Content>
353-
<FileTrigger>
354-
<Button variant="primary">Browse</Button>
355-
</FileTrigger>
356-
</Content>
357-
</IllustratedMessage>
358-
</DropZone>
388+
<>
389+
<DropZone
390+
maxWidth="size-3000"
391+
isFilled={isFilled}
392+
getDropOperation={(types) => types.has('image/png') ? 'copy' : 'cancel'}
393+
onDrop={async (e) => {
394+
let item = e.items.find((item: FileDropItem) => item.kind === 'file' && item.type === 'image/png') as FileDropItem;
395+
if (item) {
396+
setFilledSrc({
397+
type: item.type,
398+
name: item.name});
399+
setIsFilled(true);
400+
}
401+
}}>
402+
<IllustratedMessage>
403+
<Upload />
404+
<Heading>
405+
<Text slot="label">
406+
Drag and drop here
407+
</Text>
408+
</Heading>
409+
<Content>
410+
<FileTrigger
411+
acceptedFileTypes={['image/png']}
412+
onSelect={(e) => {
413+
let file = (Array.from(e)).find((file) => file.type === "image/png")
414+
if (file) {
415+
setFilledSrc({
416+
type: file.type,
417+
name: file.name
418+
})
419+
setIsFilled(true);
420+
}
421+
}}>
422+
<Button variant="primary">Browse</Button>
423+
</FileTrigger>
424+
</Content>
425+
</IllustratedMessage>
426+
</DropZone>
427+
{isFilled &&
428+
<div className="dropped">
429+
{`${filledSrc.type} ${filledSrc.name}`}
430+
</div>
431+
}
432+
</>
359433
);
360434
}
361435
```

0 commit comments

Comments
 (0)