UnSinnlos commited on
Commit
fa5264e
·
verified ·
1 Parent(s): 9edf840

ERGÄNZUNG: Mobile‑Optimierung für Android‑Smartphones

Browse files

Bitte achte zusätzlich explizit auf eine sehr gute Bedienbarkeit auf Android‑Smartphones:

Responsives Layout

Verwende ein vollständig responsives Layout (CSS Flexbox oder Grid).
Nutze sinnvolle Breakpoints (z. B. bei ca. 480 px und 768 px Breite).
Auf schmalen Displays (Smartphones) soll die Seite einspaltig sein:
Die Monate werden untereinander dargestellt.
Jeder Monat kann auf- und zugeklappt werden (Accordion‑Stil), um Scrollen zu reduzieren.




Bedienung per Touch optimieren

Alle interaktiven Elemente (Buttons, Checkboxen, Icons) sollen:
eine ausreichende Größe haben (mind. ca. 40×40 px),
genug Abstand zueinander haben, damit man sie mit dem Finger gut trifft.


Keine Funktionen, die nur per Hover erreichbar sind (kein „nur bei Maus‑Hover sichtbar“).
Inline‑Bearbeitung von Aufgaben soll auch per Tap gut funktionieren.


Typografie & Lesbarkeit

Auf Smartphones:
Mindest‑Schriftgröße ~ 14–16 px,
Zeilenhöhe ausreichend groß (line-height ~ 1.4–1.6),
gute Kontraste (Text klar lesbar gegen den Hintergrund).


Lange Texte automatisch umbrechen; kein horizontales Scrollen.


Navigation & Scrollverhalten

Kein horizontales Scrollen auf mobilen Geräten.
Monate klar getrennt und gut erkennbar.
Optional: Ein fixierter Button oben oder unten, um schnell nach oben zu springen.
Beim Öffnen eines Monats kann automatisch leicht nach unten gescrollt werden, damit der Inhalt sichtbar ist.


Eingabefelder & Buttons

Eingabefelder (z. B. „Aufgabe hinzufügen“) auf Smartphones:
volle Breite oder fast volle Breite nutzen,
ausreichend Innenabstand (padding),
gut lesbare Platzhaltertexte.


Buttons mit klarer Beschriftung in Deutsch (z. B. „Aufgabe hinzufügen“, „Löschen“).


Technische Details für Mobile

Im <head> unbedingt ein passendes Viewport‑Meta‑Tag setzen, z. B.:<meta name="viewport" content="width=device-width, initial-scale=1.0">

Keine Desktop‑spezifischen Elemente verwenden, die auf Mobile nicht funktionieren (z. B. komplexe Drag‑&‑Drop‑Aktionen).
Stelle sicher, dass die Seite ohne externe Build‑Schritte auch auf einem einfachen Android‑Browser (Chrome/Firefox) funktioniert, wenn sie z. B. auf einem kleinen Server oder lokal läuft.


Test & Feinschliff

Erzeuge das CSS so, dass die Seite in der Mobile‑Ansicht der Browser‑Devtools (z. B. Chrome DevTools, Gerät „Pixel 5“ oder ähnlich) gut benutzbar und übersichtlich ist.
Achte besonders darauf, dass:
Aufgabenlisten nicht zu gedrängt wirken,
Buttons und Checkboxen eindeutig erkennbar sind,
kein Inhalt über den Bildschirmrand hinausläuft.





Passe HTML & CSS entsprechend an, damit die gesamte Web‑App sowohl auf Desktop als auch auf Android‑Smartphones einfach, klar und intuitiv nutzbar ist.

Files changed (6) hide show
  1. README.md +8 -5
  2. components/month-accordion.js +131 -0
  3. components/navbar.js +55 -0
  4. index.html +52 -19
  5. script.js +84 -0
  6. style.css +34 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Touchtask Mobile First Todo App
3
- emoji: 📈
4
- colorFrom: red
5
- colorTo: gray
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: TouchTask - Mobile-First Todo App 📱
3
+ colorFrom: blue
4
+ colorTo: pink
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/month-accordion.js ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class MonthAccordion extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.isOpen = false;
5
+ }
6
+
7
+ connectedCallback() {
8
+ this.attachShadow({ mode: 'open' });
9
+ this.render();
10
+ this.addEventListener('click', this.toggle.bind(this));
11
+ }
12
+
13
+ toggle() {
14
+ this.isOpen = !this.isOpen;
15
+ this.render();
16
+ }
17
+
18
+ render() {
19
+ const month = this.getAttribute('month') || 'Monat';
20
+
21
+ this.shadowRoot.innerHTML = `
22
+ <style>
23
+ :host {
24
+ display: block;
25
+ margin-bottom: 0.5rem;
26
+ border-radius: 0.5rem;
27
+ overflow: hidden;
28
+ background-color: white;
29
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
30
+ }
31
+ .header {
32
+ display: flex;
33
+ justify-content: space-between;
34
+ align-items: center;
35
+ padding: 1rem;
36
+ cursor: pointer;
37
+ user-select: none;
38
+ }
39
+ .header:hover {
40
+ background-color: rgba(0, 0, 0, 0.02);
41
+ }
42
+ .month-name {
43
+ font-weight: 600;
44
+ font-size: 1.1rem;
45
+ color: #1f2937;
46
+ }
47
+ .task-count {
48
+ background-color: #e5e7eb;
49
+ color: #4b5563;
50
+ padding: 0.25rem 0.5rem;
51
+ border-radius: 9999px;
52
+ font-size: 0.75rem;
53
+ }
54
+ .content {
55
+ padding: 0 1rem;
56
+ max-height: 0;
57
+ overflow: hidden;
58
+ transition: max-height 0.3s ease-out;
59
+ }
60
+ .content.open {
61
+ max-height: 500px;
62
+ padding-bottom: 1rem;
63
+ }
64
+ .task-list {
65
+ margin-top: 0.5rem;
66
+ }
67
+ .add-task-form {
68
+ display: flex;
69
+ margin-top: 1rem;
70
+ }
71
+ .add-task-input {
72
+ flex: 1;
73
+ padding: 0.75rem;
74
+ border: 1px solid #e5e7eb;
75
+ border-radius: 0.375rem;
76
+ margin-right: 0.5rem;
77
+ font-size: 1rem;
78
+ }
79
+ .add-task-btn {
80
+ background-color: #3b82f6;
81
+ color: white;
82
+ border: none;
83
+ border-radius: 0.375rem;
84
+ padding: 0 1rem;
85
+ cursor: pointer;
86
+ }
87
+ .add-task-btn:hover {
88
+ background-color: #2563eb;
89
+ }
90
+ .chevron {
91
+ transition: transform 0.2s ease;
92
+ }
93
+ .chevron.open {
94
+ transform: rotate(180deg);
95
+ }
96
+ </style>
97
+ <div class="header">
98
+ <div class="flex items-center">
99
+ <span class="month-name">${month}</span>
100
+ <span class="task-count ml-2">5 Aufgaben</span>
101
+ </div>
102
+ <div>
103
+ <i data-feather="chevron-down" class="chevron ${this.isOpen ? 'open' : ''}"></i>
104
+ </div>
105
+ </div>
106
+ <div class="content ${this.isOpen ? 'open' : ''}">
107
+ <div class="task-list">
108
+ <div class="task-item flex items-center p-4 border-b border-gray-200">
109
+ <div class="flex items-center flex-1">
110
+ <input type="checkbox" class="task-checkbox w-6 h-6 rounded border-gray-300 text-blue-500 mr-3">
111
+ <span class="text-gray-800">Einkaufen gehen</span>
112
+ </div>
113
+ <button class="delete-task text-gray-400 hover:text-red-500 p-2">
114
+ <i data-feather="trash-2" class="w-5 h-5"></i>
115
+ </button>
116
+ </div>
117
+ </div>
118
+ <form class="add-task-form" data-month="${month}">
119
+ <input type="text" class="add-task-input" placeholder="Neue Aufgabe..." required>
120
+ <button type="submit" class="add-task-btn">Hinzufügen</button>
121
+ </form>
122
+ </div>
123
+ `;
124
+
125
+ if (this.shadowRoot.querySelector('[data-feather]')) {
126
+ feather.replace();
127
+ }
128
+ }
129
+ }
130
+
131
+ customElements.define('custom-month-accordion', MonthAccordion);
components/navbar.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ nav {
7
+ background-color: #ffffff;
8
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
9
+ padding: 1rem;
10
+ }
11
+ .container {
12
+ display: flex;
13
+ justify-content: space-between;
14
+ align-items: center;
15
+ max-width: 1200px;
16
+ margin: 0 auto;
17
+ }
18
+ .logo {
19
+ font-weight: bold;
20
+ font-size: 1.25rem;
21
+ color: #1e40af;
22
+ }
23
+ .nav-links {
24
+ display: flex;
25
+ gap: 1.5rem;
26
+ }
27
+ .nav-link {
28
+ color: #4b5563;
29
+ text-decoration: none;
30
+ font-weight: 500;
31
+ }
32
+ .nav-link:hover {
33
+ color: #1e40af;
34
+ }
35
+ @media (max-width: 640px) {
36
+ .nav-links {
37
+ gap: 1rem;
38
+ }
39
+ }
40
+ </style>
41
+ <nav>
42
+ <div class="container">
43
+ <div class="logo">TouchTask</div>
44
+ <div class="nav-links">
45
+ <a href="#" class="nav-link"><i data-feather="home"></i></a>
46
+ <a href="#" class="nav-link"><i data-feather="calendar"></i></a>
47
+ <a href="#" class="nav-link"><i data-feather="settings"></i></a>
48
+ </div>
49
+ </div>
50
+ </nav>
51
+ `;
52
+ }
53
+ }
54
+
55
+ customElements.define('custom-navbar', CustomNavbar);
index.html CHANGED
@@ -1,19 +1,52 @@
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="de">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>TouchTask - Mobile Todo App</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script src="components/navbar.js"></script>
12
+ <script src="components/month-accordion.js"></script>
13
+ </head>
14
+ <body class="bg-gray-50 min-h-screen">
15
+ <custom-navbar></custom-navbar>
16
+
17
+ <main class="container mx-auto px-4 py-6">
18
+ <div class="mb-8">
19
+ <h1 class="text-3xl font-bold text-gray-800 mb-2">Meine Aufgaben</h1>
20
+ <p class="text-gray-600">Verwalte deine Aufgaben nach Monaten</p>
21
+ </div>
22
+
23
+ <div class="space-y-4">
24
+ <custom-month-accordion month="Januar"></custom-month-accordion>
25
+ <custom-month-accordion month="Februar"></custom-month-accordion>
26
+ <custom-month-accordion month="März"></custom-month-accordion>
27
+ <custom-month-accordion month="April"></custom-month-accordion>
28
+ </div>
29
+
30
+ <div class="fixed bottom-6 right-6">
31
+ <button class="bg-blue-500 hover:bg-blue-600 text-white rounded-full p-4 shadow-lg transition-colors">
32
+ <i data-feather="plus"></i>
33
+ </button>
34
+ </div>
35
+ </main>
36
+
37
+ <script src="script.js"></script>
38
+ <script>
39
+ feather.replace();
40
+ document.addEventListener('DOMContentLoaded', function() {
41
+ // Initialize accordion functionality
42
+ const accordions = document.querySelectorAll('custom-month-accordion');
43
+ accordions.forEach(acc => {
44
+ acc.addEventListener('click', function() {
45
+ this.toggle();
46
+ });
47
+ });
48
+ });
49
+ </script>
50
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
51
+ </body>
52
+ </html>
script.js ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Main app functionality
2
+ class TodoApp {
3
+ constructor() {
4
+ this.tasks = JSON.parse(localStorage.getItem('tasks')) || {};
5
+ this.initEventListeners();
6
+ }
7
+
8
+ initEventListeners() {
9
+ // Add task form submission
10
+ document.addEventListener('submit', (e) => {
11
+ if (e.target.classList.contains('add-task-form')) {
12
+ e.preventDefault();
13
+ const input = e.target.querySelector('input');
14
+ if (input.value.trim()) {
15
+ this.addTask(input.value.trim(), e.target.dataset.month);
16
+ input.value = '';
17
+ }
18
+ }
19
+ });
20
+
21
+ // Task completion toggle
22
+ document.addEventListener('click', (e) => {
23
+ if (e.target.classList.contains('task-checkbox')) {
24
+ const taskId = e.target.dataset.taskId;
25
+ const month = e.target.dataset.month;
26
+ this.toggleTaskCompletion(taskId, month);
27
+ }
28
+ });
29
+ }
30
+
31
+ addTask(text, month) {
32
+ if (!this.tasks[month]) {
33
+ this.tasks[month] = [];
34
+ }
35
+
36
+ const newTask = {
37
+ id: Date.now().toString(),
38
+ text,
39
+ completed: false,
40
+ createdAt: new Date().toISOString()
41
+ };
42
+
43
+ this.tasks[month].push(newTask);
44
+ this.saveTasks();
45
+ this.renderTask(newTask, month);
46
+ }
47
+
48
+ toggleTaskCompletion(taskId, month) {
49
+ const task = this.tasks[month].find(t => t.id === taskId);
50
+ if (task) {
51
+ task.completed = !task.completed;
52
+ this.saveTasks();
53
+ }
54
+ }
55
+
56
+ saveTasks() {
57
+ localStorage.setItem('tasks', JSON.stringify(this.tasks));
58
+ }
59
+
60
+ renderTask(task, month) {
61
+ const taskList = document.querySelector(`custom-month-accordion[month="${month}"] .task-list`);
62
+ if (taskList) {
63
+ const taskElement = document.createElement('div');
64
+ taskElement.className = 'task-item flex items-center p-4 border-b border-gray-200';
65
+ taskElement.innerHTML = `
66
+ <div class="flex items-center flex-1">
67
+ <input type="checkbox" data-task-id="${task.id}" data-month="${month}"
68
+ class="task-checkbox w-6 h-6 rounded border-gray-300 text-blue-500 mr-3">
69
+ <span class="${task.completed ? 'line-through text-gray-400' : 'text-gray-800'}">${task.text}</span>
70
+ </div>
71
+ <button class="delete-task text-gray-400 hover:text-red-500 p-2">
72
+ <i data-feather="trash-2" class="w-5 h-5"></i>
73
+ </button>
74
+ `;
75
+ taskList.appendChild(taskElement);
76
+ feather.replace();
77
+ }
78
+ }
79
+ }
80
+
81
+ // Initialize the app
82
+ document.addEventListener('DOMContentLoaded', () => {
83
+ const app = new TodoApp();
84
+ });
style.css CHANGED
@@ -1,28 +1,44 @@
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
 
 
 
 
 
 
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Base styles */
2
  body {
3
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
4
+ line-height: 1.6;
5
  }
6
 
7
+ /* Touch-friendly elements */
8
+ button, [role="button"] {
9
+ min-width: 44px;
10
+ min-height: 44px;
11
+ touch-action: manipulation;
12
  }
13
 
14
+ /* Task item styles */
15
+ .task-item {
16
+ transition: all 0.2s ease;
 
 
17
  }
18
 
19
+ .task-item:hover {
20
+ background-color: rgba(0, 0, 0, 0.02);
 
 
 
 
21
  }
22
 
23
+ /* Mobile-first adjustments */
24
+ @media (max-width: 480px) {
25
+ html {
26
+ font-size: 16px;
27
+ }
28
+
29
+ .container {
30
+ padding-left: 1rem;
31
+ padding-right: 1rem;
32
+ }
33
  }
34
+
35
+ /* Accessibility focus styles */
36
+ button:focus, input:focus {
37
+ outline: 2px solid #3b82f6;
38
+ outline-offset: 2px;
39
+ }
40
+
41
+ /* Scroll behavior */
42
+ html {
43
+ scroll-behavior: smooth;
44
+ }