Skip to content

Commit

Permalink
feat: add filled state to dropzone component (#4617)
Browse files Browse the repository at this point in the history
* feat: add filled state to dropzone component

* chore: update golden images hash

* chore: update dropzone controlled story to have reactivity

* chore: update dropzone README to reflect interactivity

* chore: update VRT hash

* chore: update VRT hash
  • Loading branch information
rubencarvalho authored Jul 30, 2024
1 parent 816bda6 commit f6b7144
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 102 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ executors:
parameters:
current_golden_images_hash:
type: string
default: 1dfeeaaaeb1eacac0bc3ef4a0aa30a0414d86025
default: a52f23a5b75a5d9fbeff7e534f997c1d2be4690d
wireit_cache_name:
type: string
default: wireit
Expand Down
134 changes: 130 additions & 4 deletions packages/dropzone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import { Dropzone } from '@spectrum-web-components/dropzone';
## Example

```html
<sp-dropzone id="dropzone-1" style="width: 400px; height: 200px">
<sp-illustrated-message heading="Drag and Drop Your File">
<sp-dropzone id="dropzone-1" style="width: 400px;">
<sp-illustrated-message heading="Drag and drop your file">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 150 103"
Expand Down Expand Up @@ -69,8 +69,8 @@ import { Dropzone } from '@spectrum-web-components/dropzone';
When a file is dragged over the `<sp-dropzone>` element, it will display with the `dragged` attribute, as follows:

```html
<sp-dropzone id="dropzone" dragged style="width: 400px; height: 200px">
<sp-illustrated-message heading="Drag and Drop Your File">
<sp-dropzone id="dropzone" dragged style="width: 400px;">
<sp-illustrated-message heading="Drag and drop your file">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 150 103"
Expand Down Expand Up @@ -104,6 +104,132 @@ When a file is dragged over the `<sp-dropzone>` element, it will display with th
</sp-dropzone>
```

### Filled

When the `<sp-dropzone>` is in a filled state, set the `filled` attribute, as follows:

```html-live
<sp-action-button draggable="true" style="margin-block-end: 16px;">
Drag me
</sp-action-button>
<sp-dropzone tabindex="0" id="dropzone" drop-effect="copy">
<sp-illustrated-message style="--mod-illustrated-message-display: flex;" heading="Drag and drop your file" id="message">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 150 103"
width="150"
height="103"
>
<path
d="M133.7,8.5h-118c-1.9,0-3.5,1.6-3.5,3.5v27c0,0.8,0.7,1.5,1.5,1.5s1.5-0.7,1.5-1.5V23.5h119V92c0,0.3-0.2,0.5-0.5,0.5h-118c-0.3,0-0.5-0.2-0.5-0.5V69c0-0.8-0.7-1.5-1.5-1.5s-1.5,0.7-1.5,1.5v23c0,1.9,1.6,3.5,3.5,3.5h118c1.9,0,3.5-1.6,3.5-3.5V12C137.2,10.1,135.6,8.5,133.7,8.5z M15.2,21.5V12c0-0.3,0.2-0.5,0.5-0.5h118c0.3,0,0.5,0.2,0.5,0.5v9.5H15.2z M32.6,16.5c0,0.6-0.4,1-1,1h-10c-0.6,0-1-0.4-1-1s0.4-1,1-1h10C32.2,15.5,32.6,15.9,32.6,16.5z M13.6,56.1l-8.6,8.5C4.8,65,4.4,65.1,4,65.1c-0.4,0-0.8-0.1-1.1-0.4c-0.6-0.6-0.6-1.5,0-2.1l8.6-8.5l-8.6-8.5c-0.6-0.6-0.6-1.5,0-2.1c0.6-0.6,1.5-0.6,2.1,0l8.6,8.5l8.6-8.5c0.6-0.6,1.5-0.6,2.1,0c0.6,0.6,0.6,1.5,0,2.1L15.8,54l8.6,8.5c0.6,0.6,0.6,1.5,0,2.1c-0.3,0.3-0.7,0.4-1.1,0.4c-0.4,0-0.8-0.1-1.1-0.4L13.6,56.1z"
></path>
</svg>
</sp-illustrated-message>
<div>
<label for="file-input">
<sp-link
href="javascript:;"
onclick="this.parentElement.nextElementSibling.click()"
>
Select a File
</sp-link>
from your computer
</label>
<input type="file" id="file-input" style="display: none" />
</div>
<div>
or
<sp-link href="http://stock.adobe.com" target="blank">
Search Adobe Stock
</sp-link>
</div>
</sp-dropzone>
<script type="module">
customElements.whenDefined('sp-dropzone').then(() => {
const dropzone = document.getElementById('dropzone');
const message = document.getElementById('message');
const fileInput = document.getElementById('file-input');
let input;
let beingDraggedOver = false;
const updateMessage = () => {
message.heading = input !== undefined
? (beingDraggedOver ? 'Drop here to replace!' : 'You dropped something!')
: 'Drag and drop your file';
};
const handleDropOrChange = () => {
input = 'mock-file';
dropzone.setAttribute("filled", true);
beingDraggedOver = false;
updateMessage();
};
dropzone.addEventListener('dragover', (event) => {
event.preventDefault();
beingDraggedOver = true;
updateMessage();
});
dropzone.addEventListener('dragleave', () => {
beingDraggedOver = false;
updateMessage();
});
dropzone.addEventListener('drop', (event) => {
event.preventDefault();
handleDropOrChange();
});
fileInput.addEventListener('change', handleDropOrChange);
});
</script>
```

<script type="module">
customElements.whenDefined('sp-dropzone').then(() => {
const dropzone = document.getElementById('dropzone');
const message = document.getElementById('message');
const fileInput = document.getElementById('file-input');
let input;
let beingDraggedOver = false;

const updateMessage = () => {
message.heading = input !== undefined
? (beingDraggedOver ? 'Drop here to replace!' : 'You dropped something!')
: 'Drag and drop your file';
};

const handleDropOrChange = () => {
input = 'mock-file';
dropzone.setAttribute("filled", true);
beingDraggedOver = false;
updateMessage();
};

dropzone.addEventListener('dragover', (event) => {
event.preventDefault();
beingDraggedOver = true;
updateMessage();
});

dropzone.addEventListener('dragleave', () => {
beingDraggedOver = false;
updateMessage();
});

dropzone.addEventListener('drop', (event) => {
event.preventDefault();
handleDropOrChange();
});

fileInput.addEventListener('change', handleDropOrChange);
});
</script>

## Accessibility

When actions, e.g. copy/paste, can be enacted directly on the `<sp-dropzone>` element itself, be sure to supply a `tabindex` so that keyboard users can find this interaction in the tab order. For screen readers, be sure to announce what the actions are, how to complete them, and when they are completed by supplying the appropriate `role` and `aria-label` attributes.
9 changes: 9 additions & 0 deletions packages/dropzone/src/Dropzone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,18 @@ export class Dropzone extends SpectrumElement {
}
private _dropEffect: DropEffects = 'copy';

/**
* Indicates that files are currently being dragged over the dropzone.
*/
@property({ type: Boolean, reflect: true, attribute: 'dragged' })
public isDragged = false;

/**
* Set this property to indicate that the component is in a filled state.
*/
@property({ type: Boolean, attribute: 'filled' })
public isFilled = false;

private debouncedDragLeave: number | null = null;

public override connectedCallback(): void {
Expand Down
1 change: 1 addition & 0 deletions packages/dropzone/src/spectrum-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const config = {
components: [
converter.classToHost(),
converter.classToAttribute('is-dragged', 'dragged'),
converter.classToAttribute('is-filled', 'filled'),
converter.classToSlotted(
'spectrum-IllustratedMessage-illustration'
),
Expand Down
4 changes: 2 additions & 2 deletions packages/dropzone/src/spectrum-dropzone.css
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ governing permissions and limitations under the License.
);
}

:host .is-filled {
:host([filled]) {
--mod-drop-zone-background-color: rgba(
var(--spectrum-drop-zone-background-color),
var(
Expand All @@ -239,7 +239,7 @@ governing permissions and limitations under the License.
--mod-illustrated-message-display: none;
}

:host([dragged]) .is-filled {
:host([filled][dragged]) {
--mod-drop-zone-content-display: flex;
}

Expand Down
81 changes: 51 additions & 30 deletions packages/dropzone/stories/dropzone.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { defineElement } from '@spectrum-web-components/base/src/define-element.
import { state } from '@spectrum-web-components/base/src/decorators.js';

import '@spectrum-web-components/dropzone/sp-dropzone.js';
import '@spectrum-web-components/action-button/sp-action-button.js';
import { illustration } from '../test/test-svg';
import '@spectrum-web-components/illustrated-message/sp-illustrated-message.js';
import '@spectrum-web-components/link/sp-link.js';
Expand All @@ -27,6 +28,7 @@ export default {
title: 'Dropzone',
args: {
isDragged: false,
isFilled: false,
},
argTypes: {
isDragged: {
Expand All @@ -40,11 +42,23 @@ export default {
type: 'boolean',
},
},
isFilled: {
name: 'isFilled',
type: { name: 'boolean', required: false },
table: {
type: { summary: 'boolean' },
defaultValue: { summary: false },
},
control: {
type: 'boolean',
},
},
},
};

type StoryArgs = {
isDragged?: boolean;
isFilled?: boolean;
};

export const Default = (args: StoryArgs): TemplateResult => {
Expand Down Expand Up @@ -106,24 +120,50 @@ Dragged.args = {
isDragged: true,
};

export const Filled = (args: StoryArgs): TemplateResult => {
return html`
<sp-dropzone id="dropzone" ?filled=${args.isFilled}>
Filled dropzone
</sp-dropzone>
`;
};
Filled.args = {
isFilled: true,
};

class ControlledDropzone extends LitElement {
private fileName = 'mock_file.png';
@state()
private beingDraggedOver: boolean = false;

@state()
private input?: string = undefined;

override render(): TemplateResult {
return html`
<span>
${this.renderMockFile()}
<sp-action-button
draggable="true"
style="margin-block-end: 16px;"
>
Drag me
</sp-action-button>
<sp-dropzone
tabindex="0"
id="dropzone"
drop-effect="copy"
?dragged=${this.input !== undefined}
?filled=${this.input !== undefined}
@sp-dropzone-drop=${this.onChange}
@sp-dropzone-dragover=${this.onDragOver}
@sp-dropzone-dragleave=${this.onDragLeave}
>
<sp-illustrated-message heading="Drag and Drop Your File">
<sp-illustrated-message
style="--mod-illustrated-message-display: flex;"
heading=${this.input !== undefined
? this.beingDraggedOver
? 'Drop here to replace!'
: 'You dropped something!'
: 'Drag and drop your file'}
>
${illustration}
</sp-illustrated-message>
<div>
Expand All @@ -143,41 +183,22 @@ class ControlledDropzone extends LitElement {
@change=${this.onChange}
/>
</div>
${this.renderUploadButton()}
</sp-dropzone>
</span>
`;
}

private renderMockFile(): TemplateResult {
return this.input === undefined
? html`
<sp-action-button
draggable="true"
style="margin-bottom: 16px;"
>
Drag ${this.fileName}
</sp-action-button>
`
: html`
<sp-action-button style="margin-bottom: 16px;">
Added ${this.fileName}
</sp-action-button>
`;
private onChange(): void {
this.input = 'mock-file';
this.beingDraggedOver = false;
}

private renderUploadButton(): TemplateResult | null {
return this.input === undefined
? null
: html`
<sp-action-button autofocus style="margin-top: 16px;">
Upload ${this.fileName}
</sp-action-button>
`;
private onDragOver(): void {
this.beingDraggedOver = true;
}

private onChange(): void {
this.input = this.fileName;
private onDragLeave(): void {
this.beingDraggedOver = false;
}
}
defineElement('controlled-dropzone', ControlledDropzone);
Expand Down
Loading

0 comments on commit f6b7144

Please sign in to comment.