Skip to content

Commit 1b2b242

Browse files
committed
chore(dropzone): full fidelity
1 parent 4ababe0 commit 1b2b242

8 files changed

Lines changed: 392 additions & 26 deletions

File tree

2nd-gen/packages/core/components/dropzone/Dropzone.base.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
import { property } from 'lit/decorators.js';
1414

1515
import { SpectrumElement } from '@spectrum-web-components/core/element/index.js';
16+
import { SizedMixin } from '@spectrum-web-components/core/mixins/index.js';
1617

1718
import {
1819
DROP_EFFECTS,
1920
type DropEffect,
21+
DROPZONE_VALID_SIZES,
22+
type DropzoneSize,
2023
SWC_DROPZONE_DRAGLEAVE_EVENT,
2124
SWC_DROPZONE_DRAGOVER_EVENT,
2225
SWC_DROPZONE_DROP_EVENT,
@@ -41,7 +44,11 @@ import {
4144
* @fires swc-dropzone-drop - Fired when files are dropped on the zone. `element.dragged`
4245
* is still `true` when this event fires; it transitions to `false` after dispatch.
4346
*/
44-
export abstract class DropzoneBase extends SpectrumElement {
47+
export abstract class DropzoneBase extends SizedMixin(SpectrumElement, {
48+
validSizes: DROPZONE_VALID_SIZES,
49+
}) {
50+
declare public size: DropzoneSize;
51+
4552
// ──────────────────────────
4653
// SHARED API
4754
// ──────────────────────────

2nd-gen/packages/core/components/dropzone/Dropzone.types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,18 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13+
// ──────────────────
14+
// SIZES
15+
// ──────────────────
16+
17+
export type DropzoneSize = 's' | 'm' | 'l';
18+
19+
export const DROPZONE_VALID_SIZES = [
20+
's',
21+
'm',
22+
'l',
23+
] as const satisfies readonly DropzoneSize[];
24+
1325
// ──────────────────
1426
// DROP EFFECT
1527
// ──────────────────
@@ -40,6 +52,9 @@ export const SWC_DROPZONE_DRAGLEAVE_EVENT = 'swc-dropzone-dragleave';
4052
/** Fired when files are dropped on the drop zone. */
4153
export const SWC_DROPZONE_DROP_EVENT = 'swc-dropzone-drop';
4254

55+
/** Type alias retained for consumers who imported `DropzoneEventDetail` from the 1st-gen package. */
56+
export type DropzoneEventDetail = DragEvent;
57+
4358
declare global {
4459
interface GlobalEventHandlersEventMap {
4560
[SWC_DROPZONE_SHOULD_ACCEPT_EVENT]: CustomEvent<DragEvent>;

2nd-gen/packages/swc/.storybook/preview.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ const preview = {
408408
'Dropzone',
409409
[
410410
'Accessibility migration analysis',
411+
'Migration plan',
411412
'Rendering and styling migration analysis',
412413
],
413414
'Field group',

2nd-gen/packages/swc/components/dropzone/Dropzone.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ import styles from './dropzone.css';
3737
* @fires swc-dropzone-drop - Fired when files are dropped on the zone. Set `filled` in
3838
* your handler to transition the zone to its filled state.
3939
*
40-
* @cssprop --swc-dropzone-background-color - Background color of the drop zone.
41-
* @cssprop --swc-dropzone-border-color - Border color in the default state.
42-
* @cssprop --swc-dropzone-border-color-dragged - Border color when files are dragged over.
43-
* @cssprop --swc-dropzone-border-width - Border width.
44-
* @cssprop --swc-dropzone-corner-radius - Corner radius.
45-
* @cssprop --swc-dropzone-padding - Padding inside the drop zone.
40+
* @cssprop --swc-dropzone-background-color - Background color of the drop zone. Transparent by default; overridden to a subtle accent tint in the dragged state.
41+
* @cssprop --swc-dropzone-border-color - Dashed border color in the default state. Defaults to the gray-300 token.
42+
* @cssprop --swc-dropzone-border-color-dragged - Solid border color when files are dragged over the zone. Defaults to the accent visual color token.
43+
* @cssprop --swc-dropzone-border-width - Border width. Defaults to the border-width-200 token (2px).
44+
* @cssprop --swc-dropzone-corner-radius - Corner radius. Defaults to the corner-radius-400 token.
45+
* @cssprop --swc-dropzone-padding - Padding inside the drop zone. Defaults vary by size: spacing-300 (s), spacing-400 (m), spacing-600 (l).
4646
*/
4747
export class Dropzone extends DropzoneBase {
4848
public static override get styles(): CSSResultArray {
@@ -99,13 +99,13 @@ export class Dropzone extends DropzoneBase {
9999
* Called synchronously when drag state changes so the status region is updated
100100
* before the next Lit render cycle completes.
101101
*
102-
* @param _isDragged - `true` when drag enters; `false` when it leaves or a drop occurs.
102+
* @param isDragged - `true` when drag enters; `false` when it leaves or a drop occurs.
103103
* @internal
104104
*/
105-
protected override _onDragStateChange(_isDragged: boolean): void {
105+
protected override _onDragStateChange(isDragged: boolean): void {
106106
const el = this._statusEl;
107107
if (el) {
108-
el.textContent = this._statusText(_isDragged, this.filled);
108+
el.textContent = this._statusText(isDragged, this.filled);
109109
}
110110
}
111111

@@ -157,8 +157,10 @@ export class Dropzone extends DropzoneBase {
157157

158158
protected override render(): TemplateResult {
159159
return html`
160-
<div role="status" aria-live="polite" class="visually-hidden"></div>
161-
<slot></slot>
160+
<div class="swc-Dropzone">
161+
<div role="status" aria-live="polite" class="swc-Dropzone-status"></div>
162+
<slot></slot>
163+
</div>
162164
`;
163165
}
164166
}

2nd-gen/packages/swc/components/dropzone/dropzone.css

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,106 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
/* Phase 5 (Styling): migrate Spectrum CSS tokens here. */
14-
1513
:host {
1614
display: block;
1715
}
1816

19-
.visually-hidden {
17+
* {
18+
box-sizing: border-box;
19+
}
20+
21+
/* ─────────────────────────────────────
22+
Base wrapper — default (medium) size
23+
───────────────────────────────────── */
24+
25+
.swc-Dropzone {
26+
--_swc-dropzone-border-width: var(--swc-dropzone-border-width, token("border-width-200"));
27+
--_swc-dropzone-corner-radius: var(--swc-dropzone-corner-radius, token("corner-radius-400"));
28+
--_swc-dropzone-padding: var(--swc-dropzone-padding, token("spacing-400"));
29+
--_swc-dropzone-border-color: var(--swc-dropzone-border-color, token("gray-300"));
30+
31+
display: flex;
32+
position: relative;
33+
flex-direction: column;
34+
align-items: center;
35+
justify-content: center;
36+
padding: var(--_swc-dropzone-padding);
37+
background: var(--swc-dropzone-background-color, transparent);
38+
border: var(--_swc-dropzone-border-width) dashed var(--_swc-dropzone-border-color);
39+
border-radius: var(--_swc-dropzone-corner-radius);
40+
}
41+
42+
/* ─────────────────────────────────────
43+
Sizes
44+
───────────────────────────────────── */
45+
46+
:host([size="s"]) .swc-Dropzone {
47+
--_swc-dropzone-padding: var(--swc-dropzone-padding, token("spacing-300"));
48+
}
49+
50+
:host([size="l"]) .swc-Dropzone {
51+
--_swc-dropzone-padding: var(--swc-dropzone-padding, token("spacing-600"));
52+
}
53+
54+
/* ─────────────────────────────────────
55+
Dragged state
56+
───────────────────────────────────── */
57+
58+
:host([dragged]) .swc-Dropzone {
59+
--_swc-dropzone-border-color: var(--swc-dropzone-border-color-dragged, token("accent-visual-color"));
60+
61+
background: var(--swc-dropzone-background-color, token("accent-subtle-background-color-default"));
62+
border-style: solid;
63+
}
64+
65+
/* Cascade accent illustration color into any slotted swc-illustrated-message. */
66+
:host([dragged]) {
67+
--swc-illustrated-message-illustration-color: token("accent-visual-color");
68+
}
69+
70+
/* ─────────────────────────────────────
71+
Filled state
72+
───────────────────────────────────── */
73+
74+
:host([filled]) ::slotted(swc-illustrated-message) {
75+
display: none;
76+
}
77+
78+
/* ─────────────────────────────────────
79+
Filled + dragged (replace) state
80+
───────────────────────────────────── */
81+
82+
:host([filled][dragged]) .swc-Dropzone {
83+
--_swc-dropzone-border-color: var(--swc-dropzone-border-color-dragged, token("accent-visual-color"));
84+
85+
background: var(--swc-dropzone-background-color, token("accent-subtle-background-color-default"));
86+
border-style: solid;
87+
}
88+
89+
/* ─────────────────────────────────────
90+
Visually-hidden status region
91+
───────────────────────────────────── */
92+
93+
.swc-Dropzone-status {
2094
position: absolute;
2195
inline-size: 1px;
2296
block-size: 1px;
2397
white-space: nowrap;
2498
overflow: hidden;
2599
clip-path: inset(50%);
26100
}
101+
102+
/* ─────────────────────────────────────
103+
Forced colors
104+
───────────────────────────────────── */
105+
106+
@media (forced-colors: active) {
107+
.swc-Dropzone {
108+
border-color: ButtonText;
109+
}
110+
111+
:host([dragged]) .swc-Dropzone {
112+
background: Canvas;
113+
border-color: Highlight;
114+
}
115+
}

0 commit comments

Comments
 (0)