From 76b9e978945bb2f36e3240b8fb9b97b0c0862362 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 3 Feb 2026 13:19:04 -0500 Subject: [PATCH] feat(hosted-files): enhance download component with style variants and robust progress states - refactor(ae_comp__hosted_files_download_button): add 'variant' (tonal, filled, outline, ghost) and 'color' props. - fix(ae_comp__hosted_files_download_button): ensure Tailwind bundles variant classes using a literal lookup map. - fix(ae_comp__hosted_files_download_button): prevent premature "Failed to download" message during initialization. - feat(testing): add comprehensive Hosted Files testing dashboard at /testing/hosted_files with large file progress trials. - chore: remove legacy v1 download button component. --- ..._comp__hosted_files_download_button.svelte | 62 ++++- ...mp__hosted_files_download_button_v1.svelte | 156 ------------- src/routes/testing/hosted_files/+page.svelte | 217 ++++++++++++++++++ 3 files changed, 276 insertions(+), 159 deletions(-) delete mode 100644 src/lib/ae_core/ae_comp__hosted_files_download_button_v1.svelte create mode 100644 src/routes/testing/hosted_files/+page.svelte diff --git a/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte b/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte index 62f6a795..5d098e42 100644 --- a/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte +++ b/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte @@ -24,6 +24,8 @@ download_complete?: null | boolean; download_percent?: number; download_status_msg?: string; + variant?: 'tonal' | 'filled' | 'outline' | 'ghost'; + color?: 'primary' | 'secondary' | 'tertiary' | 'success' | 'warning' | 'error' | 'surface'; classes?: string; label?: import('svelte').Snippet; } @@ -40,10 +42,64 @@ download_complete = $bindable(), download_percent = $bindable(), download_status_msg = $bindable('Not started'), - classes = 'btn btn-sm lg:btn-md preset-tonal-primary border border-primary-500 hover:preset-filled-primary-500 min-w-48', + variant = 'tonal', + color = 'primary', + classes = '', label }: Props = $props(); + // Map variant/color to classes using literal strings so Tailwind can find them + const color_map: Record> = { + primary: { + tonal: 'preset-tonal-primary border border-primary-500/30 hover:preset-filled-primary-500', + filled: 'preset-filled-primary-500 hover:preset-filled-primary-600', + outline: 'border border-primary-500 hover:preset-tonal-primary', + ghost: 'hover:preset-tonal-primary' + }, + secondary: { + tonal: 'preset-tonal-secondary border border-secondary-500/30 hover:preset-filled-secondary-500', + filled: 'preset-filled-secondary-500 hover:preset-filled-secondary-600', + outline: 'border border-secondary-500 hover:preset-tonal-secondary', + ghost: 'hover:preset-tonal-secondary' + }, + tertiary: { + tonal: 'preset-tonal-tertiary border border-tertiary-500/30 hover:preset-filled-tertiary-500', + filled: 'preset-filled-tertiary-500 hover:preset-filled-tertiary-600', + outline: 'border border-tertiary-500 hover:preset-tonal-tertiary', + ghost: 'hover:preset-tonal-tertiary' + }, + success: { + tonal: 'preset-tonal-success border border-success-500/30 hover:preset-filled-success-500', + filled: 'preset-filled-success-500 hover:preset-filled-success-600', + outline: 'border border-success-500 hover:preset-tonal-success', + ghost: 'hover:preset-tonal-success' + }, + warning: { + tonal: 'preset-tonal-warning border border-warning-500/30 hover:preset-filled-warning-500', + filled: 'preset-filled-warning-500 hover:preset-filled-warning-600', + outline: 'border border-warning-500 hover:preset-tonal-warning', + ghost: 'hover:preset-tonal-warning' + }, + error: { + tonal: 'preset-tonal-error border border-error-500/30 hover:preset-filled-error-500', + filled: 'preset-filled-error-500 hover:preset-filled-error-600', + outline: 'border border-error-500 hover:preset-tonal-error', + ghost: 'hover:preset-tonal-error' + }, + surface: { + tonal: 'preset-tonal-surface border border-surface-500/30 hover:preset-filled-surface-500', + filled: 'preset-filled-surface-500 hover:preset-filled-surface-600', + outline: 'border border-surface-500 hover:preset-tonal-surface', + ghost: 'hover:preset-tonal-surface' + } + }; + + let variant_classes = $derived.by(() => { + const base = 'btn btn-sm lg:btn-md min-w-48 transition-all'; + const style = color_map[color]?.[variant] || color_map.primary.tonal; + return `${base} ${style} ${classes}`.trim(); + }); + $effect(() => { if (log_lvl) { console.log( @@ -69,9 +125,9 @@ -{:else} - -{/if} diff --git a/src/routes/testing/hosted_files/+page.svelte b/src/routes/testing/hosted_files/+page.svelte new file mode 100644 index 00000000..fec4738b --- /dev/null +++ b/src/routes/testing/hosted_files/+page.svelte @@ -0,0 +1,217 @@ + + + +
+
+
+
+

+ Hosted Files Testing +

+

Testing the AE_Comp_Hosted_Files_Download_Button component

+
+
+ + +
+
+

+ Large File Progress Test +

+ Testing Percentage +
+ +

+ Use this file to verify the percentage counter and loading spinner. + This file is ~100MB+, which should provide ample time to observe the progress state. +

+ + {#if large_file_obj} +
+
+
+ +
+
+

{large_file_obj.filename}

+

ID: {LARGE_FILE_ID}

+
+
+ +
+ +
+
+ {/if} +
+ +
+

Style & Variant Trials

+ + {#if loading} +
+ + Loading test metadata gallery... +
+ {:else} +
+ {#each hosted_files as file} +
+
+
+

{file.filename}

+

ID: {file.id}

+
+ {file.extension} +
+ +
+
+

Variant: Tonal

+ +
+ +
+

Variant: Filled

+ +
+ +
+

Variant: Outline

+ +
+ +
+

Variant: Ghost

+ +
+
+ +
+

Custom Label Snippet:

+ + {#snippet label()} + + Download Source + {/snippet} + +
+
+ {/each} +
+ {/if} +
+ +
+

+ Edge Case: Missing Metadata +

+

+ Testing the component when hosted_file_id or hosted_file_obj is missing. +

+
+ +
+
+
+