Skip to content

Commit 5cc627e

Browse files
authored
feat: FileInput (#150)
* feat: FileInput * fix: added icon * feat: cancel upload * fix: remove redundant code * fix: usage docs added and as per requirements ' * fix: moved to framents
1 parent 42be85c commit 5cc627e

File tree

3 files changed

+100
-0
lines changed

3 files changed

+100
-0
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { InputFile } from '..';
2+
3+
export default {
4+
title: 'UI/InputFile',
5+
component: InputFile,
6+
tags: ['autodocs'],
7+
render: (args: { type: string; placeholder: string; helperText: string }) => ({
8+
Component: InputFile,
9+
props: args
10+
})
11+
};
12+
13+
export const Main = {
14+
args: {}
15+
};
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<script lang="ts">
2+
import { Album01Icon } from '@hugeicons/core-free-icons';
3+
import { HugeiconsIcon } from '@hugeicons/svelte';
4+
5+
interface IInputFileProps {
6+
files: FileList | undefined;
7+
accept: string;
8+
label: string;
9+
cancelLabel: string;
10+
oncancel: () => void;
11+
}
12+
13+
let {
14+
files = $bindable(),
15+
accept = 'image/*',
16+
label = 'Click to upload a photo',
17+
cancelLabel = 'Delete upload',
18+
oncancel
19+
}: IInputFileProps = $props();
20+
21+
const uniqueId = Math.random().toString().split('.')[1];
22+
let inputFile: HTMLInputElement | undefined = $state();
23+
</script>
24+
25+
<input id={uniqueId} type="file" bind:files class="hidden" {accept} bind:this={inputFile} />
26+
27+
<label
28+
for={uniqueId}
29+
class="bg-grey text-black-400 font-geist flex h-[158px] w-full items-center justify-center rounded-4xl text-base font-normal"
30+
>
31+
{#if files}
32+
<div class="flex flex-col items-center gap-2">
33+
<HugeiconsIcon size="24px" icon={Album01Icon} color="var(--color-black-600)" />
34+
<h3 class="text-black-800">{files[0].name.slice(0, 10) + '...'}</h3>
35+
<button
36+
type="button"
37+
{oncancel}
38+
class="text-brand-burnt-orange underline decoration-solid"
39+
>
40+
{cancelLabel}
41+
</button>
42+
</div>
43+
{:else}
44+
<div class="flex flex-col items-center gap-2">
45+
<HugeiconsIcon size="24px" icon={Album01Icon} color="var(--color-black-600)" />
46+
{label}
47+
</div>
48+
{/if}
49+
</label>
50+
51+
<!--
52+
@component
53+
export default InputFile;
54+
@description
55+
A styled file input component with a custom label, file preview, and a cancel button.
56+
Supports binding file selection and a cancel handler.
57+
58+
@props
59+
- files: The bound FileList or undefined.
60+
- accept: The accepted file types (default: "image/*").
61+
- label: Label text shown when no file is selected (default: "Click to upload a photo").
62+
- cancelLabel: Text for the cancel button (default: "Delete upload").
63+
- oncancel: Function called when user clicks the cancel button.
64+
65+
@usage
66+
```html
67+
<script lang="ts">
68+
import InputFile from './InputFile.svelte';
69+
let files: FileList | undefined;
70+
71+
function handleCancel() {
72+
files = undefined;
73+
}
74+
</script>
75+
76+
<InputFile
77+
bind:files
78+
accept="image/png, image/jpeg"
79+
label="Upload your profile photo"
80+
cancelLabel="Remove"
81+
oncancel={handleCancel}
82+
/>
83+
```
84+
-->
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export { default as BottomNav } from './BottomNav/BottomNav.svelte';
22
export { default as SettingsNavigationButton } from './SettingsNavigationButton/SettingsNavigationButton.svelte';
3+
export { default as InputFile } from './InputFile/InputFile.svelte';

0 commit comments

Comments
 (0)