diff --git a/app/components/ui/button/index.ts b/app/components/ui/button/index.ts
index 8fe0323..337cbce 100644
--- a/app/components/ui/button/index.ts
+++ b/app/components/ui/button/index.ts
@@ -4,7 +4,7 @@ import { cva } from "class-variance-authority"
export { default as Button } from "./Button.vue"
export const buttonVariants = cva(
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive cursor-pointer",
{
variants: {
variant: {
diff --git a/app/components/ui/file-upload/FileUpload.vue b/app/components/ui/file-upload/FileUpload.vue
new file mode 100644
index 0000000..eff2bf7
--- /dev/null
+++ b/app/components/ui/file-upload/FileUpload.vue
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ file.name }}
+
+
+ {{ (file.size / (1024 * 1024)).toFixed(2) }} MB
+
+
+
+
+
+ {{ file.type || "unknown type" }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/components/ui/file-upload/FileUploadGrid.vue b/app/components/ui/file-upload/FileUploadGrid.vue
new file mode 100644
index 0000000..124eff3
--- /dev/null
+++ b/app/components/ui/file-upload/FileUploadGrid.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
diff --git a/app/components/ui/file-upload/index.ts b/app/components/ui/file-upload/index.ts
new file mode 100644
index 0000000..d170849
--- /dev/null
+++ b/app/components/ui/file-upload/index.ts
@@ -0,0 +1,2 @@
+export { default as FileUpload } from "./FileUpload.vue";
+export { default as FileUploadGrid } from "./FileUploadGrid.vue";
diff --git a/app/layouts/clear.vue b/app/layouts/clear.vue
index 3dc77bc..d692ee1 100644
--- a/app/layouts/clear.vue
+++ b/app/layouts/clear.vue
@@ -17,6 +17,7 @@
diff --git a/app/layouts/default.vue b/app/layouts/default.vue
index ec2def5..86b4174 100644
--- a/app/layouts/default.vue
+++ b/app/layouts/default.vue
@@ -1,6 +1,6 @@
-
+
@@ -25,5 +25,6 @@ import { useSlots } from 'vue'
import 'vue-sonner/style.css'
import AppSidebar from '~/components/ui/sidebar/AppSidebar.vue';
+import Sonner from '~/components/ui/sonner/Sonner.vue';
const slots = useSlots()
diff --git a/app/pages/import.vue b/app/pages/import.vue
index 197f7a3..2955d52 100644
--- a/app/pages/import.vue
+++ b/app/pages/import.vue
@@ -8,11 +8,14 @@ import EmptyMedia from '@/components/ui/empty/EmptyMedia.vue';
import EmptyTitle from '@/components/ui/empty/EmptyTitle.vue';
import EmptyDescription from '@/components/ui/empty/EmptyDescription.vue';
-import { Download, MegaphoneOff, Play } from 'lucide-vue-next';
+import { MegaphoneOff, Play } from 'lucide-vue-next';
import type { EventSourceListener } from '~/composeables/api/event-source';
import type { StreamProgress200Item } from '~/composeables/api/models';
import { streamProgress } from '~/composeables/api/progress-sse-controller/progress-sse-controller';
import { useCurrentPlaylistStore } from '~/stores/use-current-playlist-store';
+import FileUpload from '@/components/ui/file-upload/FileUpload.vue';
+import FileUploadGrid from '@/components/ui/file-upload/FileUploadGrid.vue';
+import Button from '@/components/ui/button/Button.vue';
const currentPlaylistStore = useCurrentPlaylistStore();
const progressEntries = ref
-
-
-
- Drag and drop your audio files
-
-
- or
-
-
-
+
+
+
+
+
+
+ Drag and drop your audio files
+
+
+ or
+
+
+
+
Uploaded files
diff --git a/bun.lock b/bun.lock
index 2770cdd..d1bc6da 100644
--- a/bun.lock
+++ b/bun.lock
@@ -19,6 +19,7 @@
"dotenv": "^17.2.3",
"eventsource": "^4.1.0",
"lucide-vue-next": "^0.548.0",
+ "motion-v": "^1.8.1",
"nuxt": "^4.2.0",
"oidc-client-ts": "^3.3.0",
"pinia": "^3.0.4",
@@ -1051,6 +1052,8 @@
"fraction.js": ["fraction.js@4.3.7", "", {}, "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew=="],
+ "framer-motion": ["framer-motion@12.26.2", "", { "dependencies": { "motion-dom": "^12.26.2", "motion-utils": "^12.24.10", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-lflOQEdjquUi9sCg5Y1LrsZDlsjrHw7m0T9Yedvnk7Bnhqfkc89/Uha10J3CFhkL+TCZVCRw9eUGyM/lyYhXQA=="],
+
"fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
"fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
@@ -1125,6 +1128,8 @@
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
+ "hey-listen": ["hey-listen@1.0.8", "", {}, "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q=="],
+
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
"http-errors": ["http-errors@2.0.0", "", { "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", "statuses": "2.0.1", "toidentifier": "1.0.1" } }, "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ=="],
@@ -1403,6 +1408,12 @@
"mocked-exports": ["mocked-exports@0.1.1", "", {}, "sha512-aF7yRQr/Q0O2/4pIXm6PZ5G+jAd7QS4Yu8m+WEeEHGnbo+7mE36CbLSDQiXYV8bVL3NfmdeqPJct0tUlnjVSnA=="],
+ "motion-dom": ["motion-dom@12.26.2", "", { "dependencies": { "motion-utils": "^12.24.10" } }, "sha512-KLMT1BroY8oKNeliA3JMNJ+nbCIsTKg6hJpDb4jtRAJ7nCKnnpg/LTq/NGqG90Limitz3kdAnAVXecdFVGlWTw=="],
+
+ "motion-utils": ["motion-utils@12.24.10", "", {}, "sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww=="],
+
+ "motion-v": ["motion-v@1.8.1", "", { "dependencies": { "framer-motion": "^12.25.0", "hey-listen": "^1.0.8", "motion-dom": "^12.23.23" }, "peerDependencies": { "@vueuse/core": ">=10.0.0", "vue": ">=3.0.0" } }, "sha512-OS6ve/vdNlrKTmCAHy+lxujIVTggjs9nbzl1auWiewy49FthkpCs5Wwpf40+55Ko3mbTajlKadkTlQYysrnL4A=="],
+
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
diff --git a/package.json b/package.json
index 366d5f8..0004fab 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"dotenv": "^17.2.3",
"eventsource": "^4.1.0",
"lucide-vue-next": "^0.548.0",
+ "motion-v": "^1.8.1",
"nuxt": "^4.2.0",
"oidc-client-ts": "^3.3.0",
"pinia": "^3.0.4",