Skip to content

Commit 15af919

Browse files
authored
Merge pull request #87 from filecoin-project/bp/upload-component-compact
[UXIT-3464] Add compact Upload component
2 parents 6cbdefe + b392827 commit 15af919

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

src/components/upload/drag-n-drop.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Root } from '@radix-ui/react-form'
22
import { useState } from 'react'
3+
import { MAX_FILE_SIZE } from '@/constants/files.ts'
34
import { FilePicker } from '../file-picker/index.tsx'
45
import { ButtonBase as Button } from '../ui/button/button-base.tsx'
56

@@ -32,7 +33,7 @@ export default function DragNDrop({ onFileSelected, onUpload, isUploading }: Dra
3233
<Root className="space-y-6" onSubmit={(e) => e.preventDefault()}>
3334
<FilePicker
3435
file={file}
35-
maxSize={200_000_000}
36+
maxSize={MAX_FILE_SIZE}
3637
onChange={(file) => {
3738
setFile(file)
3839
if (file && onFileSelected) {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { FormControl, FormField, FormMessage, Root } from '@radix-ui/react-form'
2+
import { PlusIcon } from 'lucide-react'
3+
import { useRef, useState } from 'react'
4+
import { MAX_FILE_SIZE } from '@/constants/files.ts'
5+
import { formatFileSize } from '@/utils/format-file-size.ts'
6+
import { ButtonBase as Button } from '../ui/button/button-base.tsx'
7+
8+
interface UploadButtonProps {
9+
onUpload: (file: File) => void
10+
isUploading?: boolean
11+
accept?: string[]
12+
maxSize?: number
13+
}
14+
15+
export function UploadButton({
16+
onUpload,
17+
isUploading = false,
18+
accept = ['*'],
19+
maxSize = MAX_FILE_SIZE,
20+
}: UploadButtonProps) {
21+
const fileInputRef = useRef<HTMLInputElement>(null)
22+
const [error, setError] = useState<string | null>(null)
23+
24+
function handleButtonClick() {
25+
fileInputRef.current?.click()
26+
}
27+
28+
function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
29+
const file = e.target.files?.[0]
30+
if (file) {
31+
if (file.size > maxSize) {
32+
setError(`File is too large. Maximum size is ${formatFileSize(maxSize)}.`)
33+
if (fileInputRef.current) fileInputRef.current.value = ''
34+
return
35+
}
36+
37+
setError(null)
38+
onUpload(file)
39+
if (fileInputRef.current) fileInputRef.current.value = ''
40+
}
41+
}
42+
43+
return (
44+
<Root className="flex flex-col gap-2 items-end" onSubmit={(e) => e.preventDefault()}>
45+
<FormField name="file">
46+
<FormControl asChild>
47+
<input
48+
accept={accept.join(',')}
49+
className="hidden"
50+
multiple={false}
51+
onChange={handleFileChange}
52+
ref={fileInputRef}
53+
type="file"
54+
/>
55+
</FormControl>
56+
</FormField>
57+
<div className="w-content">
58+
<Button
59+
disabled={isUploading}
60+
loading={isUploading}
61+
onClick={handleButtonClick}
62+
type="button"
63+
variant="primary"
64+
>
65+
<div className="flex items-center gap-2">
66+
<PlusIcon size={20} />
67+
<span>Add file</span>
68+
</div>
69+
</Button>
70+
</div>
71+
<div className="h-3">
72+
{error && (
73+
<FormField name="file">
74+
<FormMessage className="text-sm text-red-500 mt-1 break-words max-w-full">{error}</FormMessage>
75+
</FormField>
76+
)}
77+
</div>
78+
</Root>
79+
)
80+
}

src/constants/files.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const MAX_FILE_SIZE = 200_000_000

0 commit comments

Comments
 (0)