akhaliq HF Staff commited on
Commit
57361f3
·
verified ·
1 Parent(s): 18880d1

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. assets/css/styles.css +229 -0
  2. assets/js/script.js +111 -0
  3. index.html +50 -19
assets/css/styles.css ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Base Reset and Typography */
2
+ :root {
3
+ --primary-color: #007bff;
4
+ --secondary-color: #6c757d;
5
+ --success-color: #28a745;
6
+ --danger-color: #dc3545;
7
+ --bg-color: #f8f9fa;
8
+ --card-bg: #ffffff;
9
+ --border-color: #e9ecef;
10
+ --text-color: #343a40;
11
+ --font-family: 'Roboto', sans-serif;
12
+ }
13
+
14
+ *, *::before, *::after {
15
+ box-sizing: border-box;
16
+ margin: 0;
17
+ padding: 0;
18
+ }
19
+
20
+ body {
21
+ font-family: var(--font-family);
22
+ background-color: var(--bg-color);
23
+ color: var(--text-color);
24
+ line-height: 1.6;
25
+ min-height: 100vh;
26
+ display: flex;
27
+ flex-direction: column;
28
+ }
29
+
30
+ /* Header */
31
+ .site-header {
32
+ background-color: var(--primary-color);
33
+ color: white;
34
+ padding: 1rem 0;
35
+ text-align: center;
36
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
37
+ }
38
+
39
+ .site-header h1 {
40
+ margin-bottom: 0.25rem;
41
+ font-size: 1.8rem;
42
+ }
43
+
44
+ .branding {
45
+ font-size: 0.9rem;
46
+ margin-top: 0.5rem;
47
+ }
48
+
49
+ .branding a {
50
+ color: #ffd700; /* Gold color for contrast */
51
+ text-decoration: none;
52
+ font-weight: bold;
53
+ }
54
+
55
+ .branding a:hover {
56
+ text-decoration: underline;
57
+ }
58
+
59
+ /* Main Container (Mobile-first) */
60
+ .container {
61
+ max-width: 90%;
62
+ margin: 20px auto;
63
+ padding: 15px;
64
+ flex-grow: 1;
65
+ }
66
+
67
+ /* Input Form Styling */
68
+ .todo-input {
69
+ margin-bottom: 30px;
70
+ background: var(--card-bg);
71
+ padding: 15px;
72
+ border-radius: 8px;
73
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
74
+ }
75
+
76
+ #todo-form {
77
+ display: flex;
78
+ gap: 10px;
79
+ }
80
+
81
+ #todo-input {
82
+ flex-grow: 1;
83
+ padding: 10px;
84
+ border: 2px solid var(--border-color);
85
+ border-radius: 4px;
86
+ font-size: 1rem;
87
+ transition: border-color 0.2s;
88
+ }
89
+
90
+ #todo-input:focus {
91
+ outline: none;
92
+ border-color: var(--primary-color);
93
+ box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
94
+ }
95
+
96
+ #add-button {
97
+ /* Ensure the button doesn't shrink too much on mobile */
98
+ min-width: 90px;
99
+ padding: 10px 15px;
100
+ background-color: var(--primary-color);
101
+ color: white;
102
+ border: none;
103
+ border-radius: 4px;
104
+ cursor: pointer;
105
+ font-size: 1rem;
106
+ font-weight: 700;
107
+ transition: background-color 0.2s;
108
+ }
109
+
110
+ #add-button:hover {
111
+ background-color: #0056b3;
112
+ }
113
+
114
+ /* Todo List Styling */
115
+ .todo-list-container h2 {
116
+ font-size: 1.5rem;
117
+ margin-bottom: 10px;
118
+ border-bottom: 2px solid var(--border-color);
119
+ padding-bottom: 5px;
120
+ }
121
+
122
+ #todo-list {
123
+ list-style: none;
124
+ padding: 0;
125
+ }
126
+
127
+ .todo-item {
128
+ display: flex;
129
+ justify-content: space-between;
130
+ align-items: center;
131
+ padding: 12px 15px;
132
+ margin-bottom: 8px;
133
+ background-color: var(--card-bg);
134
+ border: 1px solid var(--border-color);
135
+ border-radius: 4px;
136
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
137
+ transition: background-color 0.3s, opacity 0.3s;
138
+ }
139
+
140
+ .todo-item .task-text {
141
+ flex-grow: 1;
142
+ margin-right: 15px;
143
+ word-break: break-word;
144
+ cursor: pointer;
145
+ }
146
+
147
+ /* Completed State */
148
+ .todo-item.completed {
149
+ background-color: #e9ffed; /* Light green background */
150
+ border-left: 5px solid var(--success-color);
151
+ opacity: 0.7;
152
+ }
153
+
154
+ .todo-item.completed .task-text {
155
+ text-decoration: line-through;
156
+ color: var(--secondary-color);
157
+ }
158
+
159
+ /* Actions (Buttons) */
160
+ .todo-actions {
161
+ display: flex;
162
+ gap: 8px;
163
+ }
164
+
165
+ .todo-actions button {
166
+ padding: 8px 12px;
167
+ border: none;
168
+ border-radius: 4px;
169
+ cursor: pointer;
170
+ font-size: 0.9rem;
171
+ transition: opacity 0.2s;
172
+ }
173
+
174
+ .todo-actions button:hover {
175
+ opacity: 0.8;
176
+ }
177
+
178
+ .delete-btn {
179
+ background-color: var(--danger-color);
180
+ color: white;
181
+ }
182
+
183
+ /* Empty State Styling */
184
+ .empty-state {
185
+ text-align: center;
186
+ color: var(--secondary-color);
187
+ font-style: italic;
188
+ border: none;
189
+ box-shadow: none;
190
+ padding: 20px;
191
+ }
192
+
193
+ /* Footer */
194
+ .site-footer {
195
+ padding: 10px;
196
+ text-align: center;
197
+ font-size: 0.8rem;
198
+ color: var(--secondary-color);
199
+ border-top: 1px solid var(--border-color);
200
+ margin-top: auto; /* Push footer to the bottom */
201
+ }
202
+
203
+ /* Responsive adjustments for larger screens */
204
+ @media (min-width: 600px) {
205
+ .container {
206
+ max-width: 600px;
207
+ }
208
+
209
+ .site-header h1 {
210
+ font-size: 2.5rem;
211
+ }
212
+
213
+ #todo-form {
214
+ flex-direction: row;
215
+ }
216
+
217
+ #todo-input {
218
+ padding: 12px;
219
+ font-size: 1.1rem;
220
+ }
221
+
222
+ #add-button {
223
+ padding: 12px 20px;
224
+ }
225
+
226
+ .todo-item {
227
+ padding: 15px 20px;
228
+ }
229
+ }
assets/js/script.js ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const todoForm = document.getElementById('todo-form');
2
+ const todoInput = document.getElementById('todo-input');
3
+ const todoList = document.getElementById('todo-list');
4
+
5
+ // Initialize todos from Local Storage, defaulting to an empty array
6
+ let todos = JSON.parse(localStorage.getItem('todos')) || [];
7
+
8
+ // Function to save todos to Local Storage
9
+ const saveTodos = () => {
10
+ localStorage.setItem('todos', JSON.stringify(todos));
11
+ };
12
+
13
+ // Function to render the entire list
14
+ const renderTodos = () => {
15
+ todoList.innerHTML = ''; // Clear existing list items
16
+
17
+ if (todos.length === 0) {
18
+ const emptyMessage = document.createElement('li');
19
+ emptyMessage.textContent = "Great job! No tasks currently pending.";
20
+ emptyMessage.className = "todo-item empty-state";
21
+ todoList.appendChild(emptyMessage);
22
+ return;
23
+ }
24
+
25
+ todos.forEach((todo, index) => {
26
+ const listItem = document.createElement('li');
27
+ listItem.className = `todo-item ${todo.completed ? 'completed' : ''}`;
28
+ listItem.setAttribute('role', 'listitem');
29
+ listItem.setAttribute('aria-checked', todo.completed);
30
+
31
+ // Task Text (Clickable to toggle completion)
32
+ const taskText = document.createElement('span');
33
+ taskText.className = 'task-text';
34
+ taskText.textContent = todo.text;
35
+ taskText.setAttribute('tabindex', '0'); // Make text focusable for keyboard users
36
+ taskText.addEventListener('click', () => toggleComplete(index));
37
+ taskText.addEventListener('keydown', (e) => {
38
+ if (e.key === 'Enter' || e.key === ' ') {
39
+ e.preventDefault();
40
+ toggleComplete(index);
41
+ }
42
+ });
43
+
44
+ // Actions container
45
+ const actions = document.createElement('div');
46
+ actions.className = 'todo-actions';
47
+
48
+ // Delete Button
49
+ const deleteBtn = document.createElement('button');
50
+ deleteBtn.textContent = 'Delete';
51
+ deleteBtn.className = 'delete-btn';
52
+ deleteBtn.setAttribute('aria-label', `Delete task: ${todo.text}`);
53
+ deleteBtn.addEventListener('click', () => deleteTodo(index));
54
+
55
+ listItem.appendChild(taskText);
56
+ actions.appendChild(deleteBtn);
57
+ listItem.appendChild(actions);
58
+
59
+ todoList.appendChild(listItem);
60
+ });
61
+ };
62
+
63
+ // 1. Add Functionality
64
+ const addTodo = (e) => {
65
+ e.preventDefault();
66
+
67
+ const taskText = todoInput.value.trim();
68
+
69
+ if (taskText === "") {
70
+ // Use standard constraint validation feedback if input is required,
71
+ // but since we prevent default and trim, a simple focus is enough
72
+ alert("Please enter a task.");
73
+ todoInput.focus();
74
+ return;
75
+ }
76
+
77
+ const newTodo = {
78
+ text: taskText,
79
+ completed: false,
80
+ id: Date.now() // Simple unique ID for future scalability if needed
81
+ };
82
+
83
+ todos.push(newTodo);
84
+ saveTodos();
85
+ renderTodos();
86
+
87
+ todoInput.value = ''; // Clear input
88
+ todoInput.focus();
89
+ };
90
+
91
+ // 2. Delete Functionality
92
+ const deleteTodo = (index) => {
93
+ // Optional: add a visual confirmation dialog
94
+ if (confirm(`Are you sure you want to delete "${todos[index].text}"?`)) {
95
+ // Remove 1 element starting at the given index
96
+ todos.splice(index, 1);
97
+ saveTodos();
98
+ renderTodos();
99
+ }
100
+ };
101
+
102
+ // 3. Mark as Complete Functionality (Toggle)
103
+ const toggleComplete = (index) => {
104
+ todos[index].completed = !todos[index].completed;
105
+ saveTodos();
106
+ renderTodos(); // Re-render to apply the completed class and ARIA state
107
+ };
108
+
109
+ // Event Listeners
110
+ document.addEventListener('DOMContentLoaded', renderTodos);
111
+ todoForm.addEventListener('submit', addTodo);
index.html CHANGED
@@ -1,19 +1,50 @@
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
+ <meta name="description" content="A simple, fast, and responsive To-Do application built with vanilla JavaScript.">
7
+ <meta name="keywords" content="todo, list, vanilla js, productivity, front-end">
8
+ <title>Vanilla JS To-Do App</title>
9
+ <link rel="stylesheet" href="assets/css/styles.css">
10
+ <!-- Using Google Fonts for better typography -->
11
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap" rel="stylesheet">
12
+ </head>
13
+ <body>
14
+ <header class="site-header">
15
+ <h1>Vanilla To-Do List</h1>
16
+ <p class="branding">
17
+ Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" rel="noopener noreferrer">anycoder</a>
18
+ </p>
19
+ </header>
20
+
21
+ <main class="container">
22
+ <section class="todo-input">
23
+ <form id="todo-form">
24
+ <input
25
+ type="text"
26
+ id="todo-input"
27
+ placeholder="What needs to be done?"
28
+ aria-label="New To-Do Item"
29
+ required
30
+ maxlength="100"
31
+ >
32
+ <button type="submit" id="add-button">Add Task</button>
33
+ </form>
34
+ </section>
35
+
36
+ <section class="todo-list-container">
37
+ <h2>Tasks</h2>
38
+ <ul id="todo-list" aria-live="polite">
39
+ <!-- To-Do items will be injected here by JavaScript -->
40
+ </ul>
41
+ </section>
42
+ </main>
43
+
44
+ <footer class="site-footer">
45
+ <p>&copy; 2024 Simple To-Do App | All Rights Reserved.</p>
46
+ </footer>
47
+
48
+ <script src="assets/js/script.js"></script>
49
+ </body>
50
+ </html>