diff --git a/v2/pink-sb/src/lib/upload/Box.svelte b/v2/pink-sb/src/lib/upload/Box.svelte index 7211dc582a..6b955e94fd 100644 --- a/v2/pink-sb/src/lib/upload/Box.svelte +++ b/v2/pink-sb/src/lib/upload/Box.svelte @@ -22,6 +22,7 @@ size?: number; extension?: string; error?: string; + progress?: number; status?: 'failed' | 'pending' | 'success'; })[] = []; @@ -67,75 +68,100 @@
{#each files as file} {@const fileSize = file?.size ? humanFileSize(file.size) : false} + {@const hasProgress = typeof file?.progress === 'number' && file.progress > 0} + {@const clampedProgress = hasProgress + ? Math.round(Math.min(Math.max(file.progress ?? 0, 0), 100)) + : 0} + {@const isError = !!file?.error || file?.status === 'failed'}
- - - - - - {file.name} - - {#if fileSize} - - - ({fileSize.value} - {fileSize.unit}) - + + + + + + + {file.name} - {/if} + {#if fileSize} + + + ({fileSize.value} + {fileSize.unit}) + + + {/if} + - - - {#if file?.status === 'success'} - - {:else} - {#if file?.error} - - - - {:else if file?.status === 'pending'} - - + + + {:else if hasProgress} + + {clampedProgress}% + + {:else if file?.status === 'pending'} + + + + {/if} + {/if} - - {/if} + + {#if hasProgress && file?.status !== 'success'} +
+
+
+ {/if}
{/each} @@ -171,4 +197,23 @@ flex-shrink: 1; } } + + .upload-progress-bar { + height: 4px; + width: 100%; + border-radius: var(--border-radius-XS, 4px); + background: var(--bgcolor-neutral-secondary, hsl(0 0% 90%)); + overflow: hidden; + + &-fill { + height: 100%; + border-radius: inherit; + background: var(--bgcolor-accent); + transition: width 0.3s ease; + } + + &.is-error &-fill { + background: var(--bgcolor-error, hsl(0 70% 55%)); + } + } diff --git a/v2/pink-sb/src/stories/upload/Box.stories.svelte b/v2/pink-sb/src/stories/upload/Box.stories.svelte index 86419fb66f..70288f5844 100644 --- a/v2/pink-sb/src/stories/upload/Box.stories.svelte +++ b/v2/pink-sb/src/stories/upload/Box.stories.svelte @@ -28,6 +28,38 @@ status: 'pending' } ]; + + let filesWithProgress = [ + { + name: 'uploading-file.png', + extension: 'png', + size: 15728640, + status: 'pending', + progress: 45 + }, + { + name: 'almost-done.pdf', + extension: 'pdf', + size: 8388608, + status: 'pending', + progress: 92 + }, + { + name: 'completed-file.jpg', + extension: 'jpg', + size: 41024, + status: 'success', + progress: 100 + }, + { + name: 'failed-upload.zip', + extension: 'zip', + size: 52428800, + status: 'failed', + error: 'File exceeds size limit', + progress: 60 + } + ];