From 82801f107714567a85a1567a0985e1cd9c3a6838 Mon Sep 17 00:00:00 2001 From: Rami Yushuvaev Date: Tue, 5 May 2026 09:32:16 +0300 Subject: [PATCH] Fix: keyboard accessible snippet import (drag and drop zone) --- src/css/import/_upload.scss | 24 +++++++- .../SelectFiles/DragDropUploadArea.tsx | 59 ++++++++++++------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/css/import/_upload.scss b/src/css/import/_upload.scss index a521c8de..9d0062eb 100644 --- a/src/css/import/_upload.scss +++ b/src/css/import/_upload.scss @@ -29,9 +29,9 @@ $type-colors: ( text-align: center; cursor: pointer; background-color: #fafafa; - margin-block-end: 20px; transition: all 0.3s ease; opacity: 1; + display: block; @media (prefers-reduced-motion: reduce) { transition-duration: 0.01s; @@ -70,12 +70,30 @@ $type-colors: ( color: #666; font-size: 14px; } +} + +.upload-drop-zone-wrapper { + position: relative; + margin-block-end: 20px; - + input[type='file'] { - display: none; + &:focus-within .upload-drop-zone:not(.disabled) { + box-shadow: 0 0 0 2px #fff, 0 0 0 4px #2271b1; } } +.upload-drop-zone-file-input { + position: absolute; + inline-size: 1px; + block-size: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + clip-path: inset(50%); + white-space: nowrap; +} + .import-result-display-card { > div { display: flex; diff --git a/src/js/components/ImportMenu/UploadForm/SelectFiles/DragDropUploadArea.tsx b/src/js/components/ImportMenu/UploadForm/SelectFiles/DragDropUploadArea.tsx index 7525c23e..1d2260af 100644 --- a/src/js/components/ImportMenu/UploadForm/SelectFiles/DragDropUploadArea.tsx +++ b/src/js/components/ImportMenu/UploadForm/SelectFiles/DragDropUploadArea.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useId, useState } from 'react' import classnames from 'classnames' import { __ } from '@wordpress/i18n' import type { DragEventHandler, RefObject } from 'react' @@ -9,56 +9,73 @@ export interface DragDropUploadAreaProps { disabled?: boolean } -export const DragDropUploadArea: React.FC = ({ fileInputRef, onFileSelect, disabled }) => { +const useDragDropZone = ( + disabled: boolean | undefined, + onFileSelect: (files: FileList | undefined) => void +) => { const [dragOver, setDragOver] = useState(false) const handleDragOver: DragEventHandler = event => { + if (disabled) { + return + } + event.preventDefault() setDragOver(true) } const handleDragLeave: DragEventHandler = event => { + if (disabled) { + return + } + event.preventDefault() setDragOver(false) } - const handleFiles = (files: FileList) => { - if (0 < files.length) { - onFileSelect(files) + const handleDrop: DragEventHandler = event => { + if (disabled) { + return } - } - const handleClick = () => { - if (!disabled) { - fileInputRef.current?.click() + handleDragLeave(event) + if (0 < event.dataTransfer.files.length) { + onFileSelect(event.dataTransfer.files) } } + return { dragOver, handleDragOver, handleDragLeave, handleDrop } +} + +export const DragDropUploadArea: React.FC = ({ fileInputRef, onFileSelect, disabled }) => { + const fileInputId = useId() + const { dragOver, handleDragOver, handleDragLeave, handleDrop } = useDragDropZone(disabled, onFileSelect) + return ( - <> -
+
- + onFileSelect(event.target.files ?? undefined)} disabled={disabled} /> - + ) }