jojonocode commited on
Commit
0c45221
·
verified ·
1 Parent(s): 5157def

Crée pour moi le frontend complet d’une application web appelée BucketMaster.

Browse files

Cette app permet à un utilisateur de :

créer un compte

créer des projets

créer des buckets dans chaque projet

envoyer, télécharger, visualiser et supprimer des fichiers

gérer les clés API

voir des dashboards simples sur l’espace utilisé

🎨 Charte graphique

Utilise les couleurs suivantes :

Jaune soleil (#F7D348)

Gris métallique (#6E6E6E)

Noir profond (#000000)

Blanc pur (#FFFFFF)

Style moderne, minimal, très propre, inspiré des dashboards pro (Linear, Supabase, Stripe).

🖥️ Pages à générer

Page Login / Register

Dashboard général

Page “Projects”

liste des projets

création d’un projet

Page “Project Detail”

liste des buckets

bouton “Créer un bucket”

Page “Bucket Detail”

upload de fichiers

aperçu des images

actions : télécharger, supprimer

Page “API Keys”

afficher, créer, supprimer une clé

Page “Settings”

🧠 Logique frontend

State global (store) pour : user, projects, buckets, files, API keys

Composants très modulaires

Système de notifications (success/error)

Composants réutilisables :

Button

Card

Modal

FileUploader

EmptyState

Table

NavBar + Sidebar

🪄 Attente

Génère :

les pages

les composants

la navigation

un design cohérent

une UI complète prête à connecter à un backend REST

Files changed (7) hide show
  1. README.md +8 -5
  2. components/sidebar.js +25 -0
  3. index.html +58 -19
  4. scripts/main.js +93 -0
  5. scripts/router.js +232 -0
  6. scripts/store.js +88 -0
  7. styles/main.css +67 -0
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Bucketmaster Cloud Storage Wizardry
3
- emoji: 🐨
4
- colorFrom: pink
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: BucketMaster - Cloud Storage Wizardry 🪄
3
+ colorFrom: red
4
+ colorTo: green
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/sidebar.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CloudVaultSidebar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ :host {
7
+ display: block;
8
+ width: 280px;
9
+ background-color: white;
10
+ border-right: 1px solid #E4E7EB;
11
+ height: 100vh;
12
+ }
13
+
14
+ .sidebar-item {
15
+ transition: all 0.2s ease;
16
+ }
17
+
18
+ .sidebar-item:hover {
19
+ background-color: #FFF2CC;
20
+ }
21
+
22
+ .sidebar-item.active {
23
+ background-color: #FFE699;
24
+ border-left: 4px solid #FFC000;
25
+ }
index.html CHANGED
@@ -1,19 +1,58 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>BucketMaster - Cloud Storage</title>
7
+ <link rel="stylesheet" href="styles/main.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script>
10
+ tailwind.config = {
11
+ theme: {
12
+ extend: {
13
+ colors: {
14
+ sun: '#F7D348',
15
+ metal: '#6E6E6E',
16
+ deep: '#000000',
17
+ pure: '#FFFFFF'
18
+ }
19
+ }
20
+ }
21
+ }
22
+ </script>
23
+ </head>
24
+ <body class="bg-pure text-deep min-h-screen">
25
+ <div id="app">
26
+ <!-- Auth pages will be rendered here initially -->
27
+ <div id="auth-container"></div>
28
+
29
+ <!-- Main app container (hidden until auth) -->
30
+ <div id="app-container" class="hidden">
31
+ <bucketmaster-navbar></bucketmaster-navbar>
32
+ <div class="flex">
33
+ <bucketmaster-sidebar></bucketmaster-sidebar>
34
+ <main class="flex-1 p-8">
35
+ <div id="page-content"></div>
36
+ </main>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <!-- Components -->
42
+ <script src="components/navbar.js"></script>
43
+ <script src="components/sidebar.js"></script>
44
+ <script src="components/button.js"></script>
45
+ <script src="components/card.js"></script>
46
+ <script src="components/modal.js"></script>
47
+ <script src="components/file-uploader.js"></script>
48
+ <script src="components/empty-state.js"></script>
49
+ <script src="components/table.js"></script>
50
+ <script src="components/notification.js"></script>
51
+
52
+ <!-- Scripts -->
53
+ <script src="scripts/store.js"></script>
54
+ <script src="scripts/router.js"></script>
55
+ <script src="scripts/main.js"></script>
56
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
57
+ </body>
58
+ </html>
scripts/main.js ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ```javascript
2
+ import store from './store.js';
3
+ import router from './router.js';
4
+
5
+ document.addEventListener('DOMContentLoaded', () => {
6
+ // Initialize Feather Icons
7
+ if (window.feather) {
8
+ feather.replace();
9
+ }
10
+
11
+ // Check auth state
12
+ if (!store.state.user) {
13
+ window.location.hash = '#/login';
14
+ document.getElementById('app-container').classList.add('hidden');
15
+ document.getElementById('auth-container').classList.remove('hidden');
16
+ } else {
17
+ document.getElementById('app-container').classList.remove('hidden');
18
+ document.getElementById('auth-container').classList.add('hidden');
19
+ }
20
+
21
+ // Set up event listeners
22
+ document.addEventListener('click', (e) => {
23
+ // Handle project clicks
24
+ if (e.target.closest('[data-project-id]')) {
25
+ const projectId = e.target.closest('[data-project-id]').getAttribute('data-project-id');
26
+ window.location.hash = `#/projects/${projectId}`;
27
+ }
28
+
29
+ // Handle bucket clicks
30
+ if (e.target.closest('[data-bucket-id]')) {
31
+ const bucketId = e.target.closest('[data-bucket-id]').getAttribute('data-bucket-id');
32
+ window.location.hash = `#/buckets/${bucketId}`;
33
+ }
34
+
35
+ // Handle file actions
36
+ if (e.target.closest('[data-file-id]')) {
37
+ const fileId = e.target.closest('[data-file-id]').getAttribute('data-file-id');
38
+ const action = e.target.closest('[data-file-id]').getAttribute('data-action');
39
+
40
+ if (action === 'download') {
41
+ store.addNotification({
42
+ id: Date.now(),
43
+ type: 'success',
44
+ message: 'Download started'
45
+ });
46
+ } else if (action === 'delete') {
47
+ store.removeFile(fileId);
48
+ store.addNotification({
49
+ id: Date.now(),
50
+ type: 'success',
51
+ message: 'File deleted'
52
+ });
53
+ }
54
+ }
55
+
56
+ // Handle API key deletion
57
+ if (e.target.closest('[data-key-id]')) {
58
+ const keyId = e.target.closest('[data-key-id]').getAttribute('data-key-id');
59
+ store.removeApiKey(keyId);
60
+ store.addNotification({
61
+ id: Date.now(),
62
+ type: 'success',
63
+ message: 'API key deleted'
64
+ });
65
+ }
66
+
67
+ // Handle create project button
68
+ if (e.target.closest('#create-project-btn')) {
69
+ const modal = document.createElement('bucketmaster-modal');
70
+ modal.setAttribute('title', 'Create Project');
71
+ modal.innerHTML = `
72
+ <form id="create-project-form" class="space-y-4">
73
+ <div>
74
+ <label class="block text-metal mb-1">Project Name</label>
75
+ <input type="text" required class="w-full px-3 py-2 border border-metal-200 rounded">
76
+ </div>
77
+ <div class="pt-2">
78
+ <bucketmaster-button type="submit">Create Project</bucketmaster-button>
79
+ </div>
80
+ </form>
81
+ `;
82
+ document.body.appendChild(modal);
83
+ }
84
+
85
+ // Handle create bucket button
86
+ if (e.target.closest('#create-bucket-btn')) {
87
+ const modal = document.createElement('bucketmaster-modal');
88
+ modal.setAttribute('title', 'Create Bucket');
89
+ modal.innerHTML = `
90
+ <form id="create-bucket-form" class="space-y-4">
91
+ <div>
92
+ <label class="block text-metal mb-1">Bucket Name</label>
93
+ <
scripts/router.js ADDED
@@ -0,0 +1,232 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Router {
2
+ constructor() {
3
+ this.routes = {
4
+ '/login': this.renderLogin,
5
+ '/register': this.renderRegister,
6
+ '/dashboard': this.renderDashboard,
7
+ '/projects': this.renderProjects,
8
+ '/projects/:id': this.renderProjectDetail,
9
+ '/buckets/:id': this.renderBucketDetail,
10
+ '/api-keys': this.renderApiKeys,
11
+ '/settings': this.renderSettings
12
+ };
13
+
14
+ window.addEventListener('hashchange', () => this.handleRoute());
15
+ this.handleRoute();
16
+ }
17
+
18
+ handleRoute() {
19
+ const path = window.location.hash.substring(1) || '/dashboard';
20
+ const route = Object.keys(this.routes).find(r => {
21
+ if (r.includes(':')) {
22
+ const basePath = r.split('/:')[0];
23
+ return path.startsWith(basePath);
24
+ }
25
+ return r === path;
26
+ });
27
+
28
+ if (route) {
29
+ this.routes[route]();
30
+ } else {
31
+ this.renderNotFound();
32
+ }
33
+ }
34
+
35
+ renderLogin() {
36
+ document.getElementById('auth-container').innerHTML = `
37
+ <bucketmaster-auth type="login"></bucketmaster-auth>
38
+ `;
39
+ }
40
+
41
+ renderRegister() {
42
+ document.getElementById('auth-container').innerHTML = `
43
+ <bucketmaster-auth type="register"></bucketmaster-auth>
44
+ `;
45
+ }
46
+
47
+ renderDashboard() {
48
+ document.getElementById('page-content').innerHTML = `
49
+ <h1 class="text-2xl font-bold mb-6">Dashboard</h1>
50
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
51
+ <bucketmaster-card title="Projects" value="${store.state.projects.length}" icon="folder"></bucketmaster-card>
52
+ <bucketmaster-card title="Buckets" value="${store.state.buckets.length}" icon="database"></bucketmaster-card>
53
+ <bucketmaster-card title="Storage Used" value="2.5 GB" icon="hard-drive"></bucketmaster-card>
54
+ </div>
55
+ `;
56
+ }
57
+
58
+ renderProjects() {
59
+ document.getElementById('page-content').innerHTML = `
60
+ <div class="flex justify-between items-center mb-6">
61
+ <h1 class="text-2xl font-bold">Projects</h1>
62
+ <bucketmaster-button id="create-project-btn" icon="plus">New Project</bucketmaster-button>
63
+ </div>
64
+ ${store.state.projects.length > 0 ? `
65
+ <bucketmaster-table>
66
+ ${store.state.projects.map(project => `
67
+ <tr class="hover:bg-sun/10 transition-200 cursor-pointer" data-project-id="${project.id}">
68
+ <td>${project.name}</td>
69
+ <td>${project.buckets.length} buckets</td>
70
+ <td>${new Date(project.createdAt).toLocaleDateString()}</td>
71
+ </tr>
72
+ `).join('')}
73
+ </bucketmaster-table>
74
+ ` : `
75
+ <bucketmaster-empty-state
76
+ title="No projects yet"
77
+ description="Get started by creating your first project"
78
+ action-text="Create Project"
79
+ action-id="create-project-btn"
80
+ icon="folder-plus">
81
+ </bucketmaster-empty-state>
82
+ `}
83
+ `;
84
+ }
85
+
86
+ renderProjectDetail() {
87
+ const projectId = window.location.hash.split('/')[2];
88
+ store.setCurrentProject(projectId);
89
+
90
+ document.getElementById('page-content').innerHTML = `
91
+ <div class="flex justify-between items-center mb-6">
92
+ <h1 class="text-2xl font-bold">${store.state.currentProject?.name || 'Project'}</h1>
93
+ <bucketmaster-button id="create-bucket-btn" icon="plus">New Bucket</bucketmaster-button>
94
+ </div>
95
+ ${store.state.currentProject?.buckets.length > 0 ? `
96
+ <bucketmaster-table>
97
+ ${store.state.currentProject.buckets.map(bucket => `
98
+ <tr class="hover:bg-sun/10 transition-200 cursor-pointer" data-bucket-id="${bucket.id}">
99
+ <td>${bucket.name}</td>
100
+ <td>${bucket.files.length} files</td>
101
+ <td>${bucket.size}</td>
102
+ <td>${new Date(bucket.createdAt).toLocaleDateString()}</td>
103
+ </tr>
104
+ `).join('')}
105
+ </bucketmaster-table>
106
+ ` : `
107
+ <bucketmaster-empty-state
108
+ title="No buckets yet"
109
+ description="Create your first bucket to start uploading files"
110
+ action-text="Create Bucket"
111
+ action-id="create-bucket-btn"
112
+ icon="database">
113
+ </bucketmaster-empty-state>
114
+ `}
115
+ `;
116
+ }
117
+
118
+ renderBucketDetail() {
119
+ const bucketId = window.location.hash.split('/')[2];
120
+ store.setCurrentBucket(bucketId);
121
+
122
+ document.getElementById('page-content').innerHTML = `
123
+ <div class="flex justify-between items-center mb-6">
124
+ <h1 class="text-2xl font-bold">${store.state.currentBucket?.name || 'Bucket'}</h1>
125
+ <bucketmaster-button id="upload-file-btn" icon="upload">Upload File</bucketmaster-button>
126
+ </div>
127
+ ${store.state.currentBucket?.files.length > 0 ? `
128
+ <bucketmaster-table>
129
+ ${store.state.currentBucket.files.map(file => `
130
+ <tr>
131
+ <td class="flex items-center">
132
+ <i data-feather="${file.icon}" class="file-icon file-icon-${file.type.toLowerCase()}"></i>
133
+ ${file.name}
134
+ </td>
135
+ <td>${file.size}</td>
136
+ <td>${file.type}</td>
137
+ <td>${new Date(file.uploadedAt).toLocaleDateString()}</td>
138
+ <td class="text-right">
139
+ <div class="flex space-x-2">
140
+ <button class="text-metal hover:text-sun transition-200" data-file-id="${file.id}" data-action="download">
141
+ <i data-feather="download"></i>
142
+ </button>
143
+ <button class="text-metal hover:text-red-500 transition-200" data-file-id="${file.id}" data-action="delete">
144
+ <i data-feather="trash-2"></i>
145
+ </button>
146
+ </div>
147
+ </td>
148
+ </tr>
149
+ `).join('')}
150
+ </bucketmaster-table>
151
+ ` : `
152
+ <bucketmaster-empty-state
153
+ title="No files yet"
154
+ description="Upload your first file to this bucket"
155
+ action-text="Upload File"
156
+ action-id="upload-file-btn"
157
+ icon="file">
158
+ </bucketmaster-empty-state>
159
+ `}
160
+ `;
161
+ }
162
+
163
+ renderApiKeys() {
164
+ document.getElementById('page-content').innerHTML = `
165
+ <div class="flex justify-between items-center mb-6">
166
+ <h1 class="text-2xl font-bold">API Keys</h1>
167
+ <bucketmaster-button id="create-api-key-btn" icon="plus">New API Key</bucketmaster-button>
168
+ </div>
169
+ ${store.state.apiKeys.length > 0 ? `
170
+ <bucketmaster-table>
171
+ ${store.state.apiKeys.map(key => `
172
+ <tr>
173
+ <td>${key.name}</td>
174
+ <td>${key.key.substring(0, 8)}...</td>
175
+ <td>${new Date(key.createdAt).toLocaleDateString()}</td>
176
+ <td class="text-right">
177
+ <button class="text-metal hover:text-red-500 transition-200" data-key-id="${key.id}">
178
+ <i data-feather="trash-2"></i>
179
+ </button>
180
+ </td>
181
+ </tr>
182
+ `).join('')}
183
+ </bucketmaster-table>
184
+ ` : `
185
+ <bucketmaster-empty-state
186
+ title="No API Keys"
187
+ description="Create your first API key to access the BucketMaster API"
188
+ action-text="Create API Key"
189
+ action-id="create-api-key-btn"
190
+ icon="key">
191
+ </bucketmaster-empty-state>
192
+ `}
193
+ `;
194
+ }
195
+
196
+ renderSettings() {
197
+ document.getElementById('page-content').innerHTML = `
198
+ <h1 class="text-2xl font-bold mb-6">Settings</h1>
199
+ <div class="bg-pure rounded-lg shadow p-6 max-w-2xl">
200
+ <h2 class="text-xl font-semibold mb-4">Account</h2>
201
+ <form id="account-form" class="space-y-4">
202
+ <div>
203
+ <label class="block text-metal mb-1">Name</label>
204
+ <input type="text" value="${store.state.user?.name || ''}" class="w-full px-3 py-2 border border-metal-200 rounded">
205
+ </div>
206
+ <div>
207
+ <label class="block text-metal mb-1">Email</label>
208
+ <input type="email" value="${store.state.user?.email || ''}" class="w-full px-3 py-2 border border-metal-200 rounded">
209
+ </div>
210
+ <div class="pt-4">
211
+ <bucketmaster-button type="submit">Save Changes</bucketmaster-button>
212
+ </div>
213
+ </form>
214
+ </div>
215
+ `;
216
+ }
217
+
218
+ renderNotFound() {
219
+ document.getElementById('page-content').innerHTML = `
220
+ <bucketmaster-empty-state
221
+ title="Page Not Found"
222
+ description="The page you're looking for doesn't exist"
223
+ action-text="Go to Dashboard"
224
+ action-id="go-to-dashboard"
225
+ icon="alert-circle">
226
+ </bucketmaster-empty-state>
227
+ `;
228
+ }
229
+ }
230
+
231
+ const router = new Router();
232
+ export default router;
scripts/store.js ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Store {
2
+ constructor() {
3
+ this.state = {
4
+ user: null,
5
+ projects: [],
6
+ currentProject: null,
7
+ buckets: [],
8
+ currentBucket: null,
9
+ files: [],
10
+ apiKeys: [],
11
+ notifications: []
12
+ };
13
+ }
14
+
15
+ setUser(user) {
16
+ this.state.user = user;
17
+ this.save();
18
+ }
19
+
20
+ addProject(project) {
21
+ this.state.projects.push(project);
22
+ this.save();
23
+ }
24
+
25
+ setCurrentProject(projectId) {
26
+ this.state.currentProject = this.state.projects.find(p => p.id === projectId);
27
+ this.save();
28
+ }
29
+
30
+ addBucket(bucket) {
31
+ this.state.buckets.push(bucket);
32
+ this.save();
33
+ }
34
+
35
+ setCurrentBucket(bucketId) {
36
+ this.state.currentBucket = this.state.buckets.find(b => b.id === bucketId);
37
+ this.save();
38
+ }
39
+
40
+ addFile(file) {
41
+ this.state.files.push(file);
42
+ this.save();
43
+ }
44
+
45
+ removeFile(fileId) {
46
+ this.state.files = this.state.files.filter(f => f.id !== fileId);
47
+ this.save();
48
+ }
49
+
50
+ addApiKey(apiKey) {
51
+ this.state.apiKeys.push(apiKey);
52
+ this.save();
53
+ }
54
+
55
+ removeApiKey(keyId) {
56
+ this.state.apiKeys = this.state.apiKeys.filter(k => k.id !== keyId);
57
+ this.save();
58
+ }
59
+
60
+ addNotification(notification) {
61
+ this.state.notifications.push(notification);
62
+ setTimeout(() => {
63
+ this.removeNotification(notification.id);
64
+ }, 3000);
65
+ this.save();
66
+ }
67
+
68
+ removeNotification(id) {
69
+ this.state.notifications = this.state.notifications.filter(n => n.id !== id);
70
+ this.save();
71
+ }
72
+
73
+ save() {
74
+ localStorage.setItem('bucketmaster-state', JSON.stringify(this.state));
75
+ }
76
+
77
+ load() {
78
+ const saved = localStorage.getItem('bucketmaster-state');
79
+ if (saved) {
80
+ this.state = JSON.parse(saved);
81
+ }
82
+ }
83
+ }
84
+
85
+ const store = new Store();
86
+ store.load();
87
+
88
+ export default store;
styles/main.css ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import 'tailwindcss/base';
2
+ @import 'tailwindcss/components';
3
+ @import 'tailwindcss/utilities';
4
+
5
+ /* Base styles */
6
+ body {
7
+ font-family: 'Inter', sans-serif;
8
+ }
9
+
10
+ /* Custom scrollbar */
11
+ ::-webkit-scrollbar {
12
+ width: 6px;
13
+ height: 6px;
14
+ }
15
+
16
+ ::-webkit-scrollbar-track {
17
+ background: #f1f1f1;
18
+ }
19
+
20
+ ::-webkit-scrollbar-thumb {
21
+ background: #F7D348;
22
+ border-radius: 3px;
23
+ }
24
+
25
+ /* Animations */
26
+ @keyframes fadeIn {
27
+ from { opacity: 0; }
28
+ to { opacity: 1; }
29
+ }
30
+
31
+ .fade-in {
32
+ animation: fadeIn 0.3s ease;
33
+ }
34
+
35
+ /* Transitions */
36
+ .transition-200 {
37
+ transition: all 0.2s ease;
38
+ }
39
+
40
+ /* File icons */
41
+ .file-icon {
42
+ @apply w-5 h-5 mr-2;
43
+ }
44
+
45
+ .file-icon-image {
46
+ color: #38A169;
47
+ }
48
+
49
+ .file-icon-pdf {
50
+ color: #E53E3E;
51
+ }
52
+
53
+ .file-icon-video {
54
+ color: #805AD5;
55
+ }
56
+
57
+ .file-icon-audio {
58
+ color: #3182CE;
59
+ }
60
+
61
+ .file-icon-zip {
62
+ color: #DD6B20;
63
+ }
64
+
65
+ .file-icon-default {
66
+ color: #6E6E6E;
67
+ }