Skip to content

Commit

Permalink
feat: add file upload component (#55)
Browse files Browse the repository at this point in the history
  • Loading branch information
petermakowski authored Jan 5, 2024
1 parent a08f01d commit bc9f4c2
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 4 deletions.
42 changes: 40 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@
"classnames": "^2.3.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-dropzone": "14.2.3",
"react-router-dom": "^6.0.0",
"vanilla-framework": "^4.3.0"
}
Expand Down
21 changes: 21 additions & 0 deletions src/lib/components/FileUpload/FileUpload.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@import "vanilla-framework";
@include vf-base;
@include vf-p-buttons;

.file-upload {
background: linear-gradient(to right, $color-mid-light 50%, transparent 50%) 0 0,
linear-gradient(to right, $color-mid-light 50%, transparent 50%) 0 100%,
linear-gradient(to bottom, $color-mid-light 50%, transparent 50%) 0 0,
linear-gradient(to bottom, $color-mid-light 50%, transparent 50%) 100% 0;
background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
background-size: 10px $input-border-thickness, 10px $input-border-thickness, $input-border-thickness 10px, $input-border-thickness 10px;
}

.file-upload__button {
@extend .p-button--link;

text-align: left;
width: 100%;
padding: $spv--x-small $sph--small $sph--x-large $spv--small;
margin-bottom: 0;
}
20 changes: 20 additions & 0 deletions src/lib/components/FileUpload/FileUpload.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Meta } from "@storybook/react";

import { FileUpload } from "@/lib/components/FileUpload";

const meta: Meta<typeof FileUpload> = {
title: "components/FileUpload",
component: FileUpload,
tags: ["autodocs"],
parameters: {},
};

export default meta;

export const Example = {
args: {
onFileUpload: (files: File[]) => {
alert(files.map((file) => file.name).join(", ") + " received");
},
},
};
47 changes: 47 additions & 0 deletions src/lib/components/FileUpload/FileUpload.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { vi } from "vitest";

import { FileUpload } from "./FileUpload";
beforeEach(() => {});

function createDataTransfer(file: File) {
return {
files: [file],
items: [
{
kind: "file",
type: file.type,
getAsFile: () => file,
},
],
types: ["Files"],
};
}

it("renders without crashing", () => {
render(<FileUpload onFileUpload={vi.fn()} />);
expect(
screen.getByText("Drag and drop files here or click to upload"),
).toBeInTheDocument();
});

it("calls onFileUpload when files are dropped", async () => {
const mockOnFileUpload = vi.fn();
render(<FileUpload onFileUpload={mockOnFileUpload} />);
const file = new File(["hello"], "hello.png", { type: "image/png" });
const dropEvent = await fireEvent.drop(
screen.getByText("Drag and drop files here or click to upload"),
{
dataTransfer: createDataTransfer(file),
},
);

expect(dropEvent).toMatchInlineSnapshot("false");
await waitFor(() =>
expect(mockOnFileUpload).toHaveBeenCalledWith(
[file],
expect.anything(),
expect.anything(),
),
);
});
23 changes: 23 additions & 0 deletions src/lib/components/FileUpload/FileUpload.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { useDropzone, DropzoneOptions } from "react-dropzone";

export interface FileUploadProps {
onFileUpload: NonNullable<DropzoneOptions["onDrop"]>;
}

import "./FileUpload.scss";

export const FileUpload: React.FC<FileUploadProps> = ({
onFileUpload,
}: FileUploadProps) => {
const { getRootProps } = useDropzone({
onDrop: onFileUpload,
});

return (
<div {...getRootProps()} className="file-upload" data-testid="file-upload">
<button className="file-upload__button">
Drag and drop files here or click to upload
</button>
</div>
);
};
1 change: 1 addition & 0 deletions src/lib/components/FileUpload/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./FileUpload";
3 changes: 1 addition & 2 deletions src/lib/components/Stepper/Stepper.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
@import "vanilla-framework";
@include vf-b-grid-definitions;
@include vf-b-placeholders;
@include vf-base;
@include vf-p-lists;
@include vf-p-stepped-list;

Expand Down
2 changes: 2 additions & 0 deletions src/lib/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from "./NestedFormGroup";
export * from "./Pagination";
export * from "./Stepper";

export * from "./FileUpload";

0 comments on commit bc9f4c2

Please sign in to comment.