brumate/ui

DropZone

An area that takes drops of text and files, and pastes from keyboard users.

Drop or paste text or files here
<script>
  import { $signal } from 'brumate/signals';
  import Button from '@brumate/ui/Button.brm';
  import DropZone from '@brumate/ui/DropZone.brm';
  import FileTrigger from '@brumate/ui/FileTrigger.brm';
  import Text from '@brumate/ui/Text.brm';
  import type { DropEvent } from '@brumate/ui/drop.ts';
  import Icon from '../../src/components/Icon.brm';

  let received = $signal<string[]>([]);

  async function dropped(event: DropEvent) {
    const names: string[] = [];
    for (const item of event.items) {
      if (item.kind === 'file') {
        names.push(item.name);
      } else if (item.types.has('text/plain')) {
        names.push(await item.getText('text/plain'));
      }
    }
    received = names;
  }
</script>

<DropZone class="ui-dropzone" onDrop=dropped>
  <Text slot="label">
    #if (received.length > 0) {
      {received.join(', ')}
    } #else {
      Drop or paste text or files here
    }
  </Text>
  <FileTrigger allowsMultiple onSelect=((files) => (received = [...(files ?? [])].map((file) => file.name)))>
    <Button class="ui-button"><Icon name="upload" /> Browse</Button>
  </FileTrigger>
</DropZone>
<DropZone onDrop=dropped>
  <Text slot="label">Drop files here</Text>
</DropZone>

Keyboard and screen readers

Styles

Attribute When
data-drop-target A drag that it takes is over it.
data-hovered The pointer is over it.
data-focused Its button has the focus.
data-focus-visible Its button has the focus from the keys.
data-disabled It refuses drops.

Drops need scripts. The server renders the area and its label.