Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added File Upload Component #512

Merged
merged 10 commits into from
Nov 3, 2024
114 changes: 114 additions & 0 deletions apps/docs/src/examples/file-upload.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
.fileUpload {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
min-height: 300px;
row-gap: 5px;
}

.fileUpload__label {
color: white;
font-size: 14px;
font-weight: 500;
user-select: none;
}

.fileUpload__dropzone {
padding: 20px;
display: flex;
flex-direction: column;
row-gap: 10px;
align-items: center;
justify-content: center;
border: 1px dashed rgb(42, 42, 40);
width: 100%;
min-height: 200px;
color: #ccc;
border-radius: 6px;
}

.fileUpload__trigger {
background-color: hsl(201 96% 32%);
color: white;
padding: 5px 10px;
border-radius: 4px;
}

.fileUpload__itemGroup {
display: flex;
flex-direction: column;
gap: 3px;
width: 100%;
}

.fileUpload__item {
width: 100%;
display: grid;
padding: 16px;
column-gap: 10px;
border-radius: 6px;
grid-template-columns: auto 1fr auto;
grid-template-areas:
"preview name delete"
"preview size delete";
column-gap: 5px;
border: 1px solid rgb(42, 42, 40);
padding: 10px;
}

.fileUpload__itemPreview {
grid-area: preview;
}

.fileUpload__itemPreviewImage {
width: 50px;
object-fit: scale-down;
height: auto;
aspect-ratio: 1;
}

.fileUpload__itemName {
grid-area: name;
font-size: 14px;
color: #fff;
}

.fileUpload__itemSize {
grid-area: size;
font-size: 14px;
color: rgb(181, 179, 173);
}

.fileUpload__itemDeleteTrigger {
grid-area: delete;
cursor: pointer;
background-color: #a23434;
color: white;
padding: 2px 8px;
border-radius: 4px;
height: max-content;
align-self: center;
}

.formContainer {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
row-gap: 5px;
}

.formContainer > .fileUpload__dropzone {
min-height: 200px;
}

.submit-btn {
background-color: hsl(201 96% 32%);
color: white;
padding: 5px 10px;
border-radius: 4px;
align-self: flex-end;
}
131 changes: 131 additions & 0 deletions apps/docs/src/examples/file-upload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { FileUpload } from "@kobalte/core/file-upload";
import { For } from "solid-js";

import style from "./file-upload.module.css";

export function BasicExample() {
return (
<FileUpload
class={style.fileUpload}
multiple
maxFiles={5}
onFileAccept={(data) => console.log("data", data)}
onFileReject={(data) => console.log("data", data)}
onFileChange={(data) => console.log("data", data)}
>
<FileUpload.Label class={style.fileUpload__label}>
File Upload
</FileUpload.Label>
<FileUpload.DropZone class={style.fileUpload__dropzone}>
Drop your files here...
<FileUpload.Trigger class={style.fileUpload__trigger}>
Choose files!
</FileUpload.Trigger>
</FileUpload.DropZone>
<FileUpload.HiddenInput />
<FileUpload.ItemGroup class={style.fileUpload__itemGroup}>
<FileUpload.Context>
{(context) => {
return (
<For each={context.acceptedFiles}>
{(file) => (
<FileUpload.Item file={file} class={style.fileUpload__item}>
<FileUpload.ItemPreview
type="image/*"
class={style.fileUpload__itemPreview}
>
<FileUpload.ItemPreviewImage
class={style.fileUpload__itemPreviewImage}
/>
</FileUpload.ItemPreview>
<FileUpload.ItemName class={style.fileUpload__itemName} />
<FileUpload.ItemSize class={style.fileUpload__itemSize} />
<FileUpload.ItemDeleteTrigger
class={style.fileUpload__itemDeleteTrigger}
>
Delete
</FileUpload.ItemDeleteTrigger>
</FileUpload.Item>
)}
</For>
);
}}
</FileUpload.Context>
</FileUpload.ItemGroup>
</FileUpload>
);
}

export function HTMLFormExample() {
let formRef: HTMLFormElement | undefined;

const onSubmit = (event: SubmitEvent) => {
event.preventDefault();
event.stopPropagation();

const formData = new FormData(formRef);
const uploadedFiles = formData.getAll("uploaded-files");

const fileNames = uploadedFiles
.filter((file): file is File => file instanceof File)
.map((file) => file.name);

alert(JSON.stringify(fileNames, null, 2));
};

return (
<form class={style.formContainer} ref={formRef} onSubmit={onSubmit}>
<FileUpload
class={style.fileUpload}
multiple
maxFiles={5}
onFileAccept={(data) => console.log("data", data)}
onFileReject={(data) => console.log("data", data)}
onFileChange={(data) => console.log("data", data)}
>
<FileUpload.Label class={style.fileUpload__label}>
File Upload
</FileUpload.Label>
<FileUpload.DropZone class={style.fileUpload__dropzone}>
Drop your files here...
<FileUpload.Trigger class={style.fileUpload__trigger}>
Choose files!
</FileUpload.Trigger>
</FileUpload.DropZone>
<FileUpload.HiddenInput name="uploaded-files" />
<FileUpload.ItemGroup class={style.fileUpload__itemGroup}>
<FileUpload.Context>
{(context) => {
return (
<For each={context.acceptedFiles}>
{(file) => (
<FileUpload.Item file={file} class={style.fileUpload__item}>
<FileUpload.ItemPreview
type="image/*"
class={style.fileUpload__itemPreview}
>
<FileUpload.ItemPreviewImage
class={style.fileUpload__itemPreviewImage}
/>
</FileUpload.ItemPreview>
<FileUpload.ItemName class={style.fileUpload__itemName} />
<FileUpload.ItemSize class={style.fileUpload__itemSize} />
<FileUpload.ItemDeleteTrigger
class={style.fileUpload__itemDeleteTrigger}
>
Delete
</FileUpload.ItemDeleteTrigger>
</FileUpload.Item>
)}
</For>
);
}}
</FileUpload.Context>
</FileUpload.ItemGroup>
</FileUpload>
<button type="submit" class={style["submit-btn"]}>
Submit Files
</button>
</form>
);
}
4 changes: 4 additions & 0 deletions apps/docs/src/routes/docs/core.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ const CORE_NAV_SECTIONS: NavSection[] = [
title: "Dropdown Menu",
href: "/docs/core/components/dropdown-menu",
},
{
title: "File Upload",
href: "/docs/core/components/file-upload",
},
{
title: "Hover Card",
href: "/docs/core/components/hover-card",
Expand Down
Loading
Loading