{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "datei-upload-ablage",
 "name": "Datei-Ablage mit Vorschau und Prüfung",
 "name_en": "File upload drop zone with previews and validation",
 "kurz": "Schadensfoto zur Anfrage: echtes Dateifeld in einer Ablagefläche, Vorschau-Karten mit Entfernen, Fehler mit Dateiname am Feld und Verkleinern auf 2000 px im Browser.",
 "kategorie": "Sektionen & Funktionen",
 "kategorie_slug": "sektionen",
 "kategorie_nr": 16,
 "bau_chat": "D",
 "prioritaet": "D",
 "trendstatus": "etabliert",
 "belegstatus": "teilbelegt",
 "website_belege": 1,
 "stimmung": [
  "ruhig",
  "präzise"
 ],
 "stimmung_roh": [
  "ruhig",
  "präzise"
 ],
 "technik": [
  "form",
  "vanilla-js",
  "canvas"
 ],
 "technik_gruppen": [
  "css",
  "js",
  "canvas"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Ein Feld „Fotos oder Dateien“ mit großer Ablagefläche: Dateien hineinziehen oder tippen und auswählen, auf dem Telefon auch direkt fotografieren. Jede Datei erscheint als kleine Karte mit Vorschaubild, Name, Größe und Knopf „Entfernen“. Zu große oder falsche Dateien zeigen sofort eine klare Meldung am Feld. Fotos werden vor dem Senden im Browser verkleinert.",
  "warum_es_wirkt": "Ein Foto vom Wasserschaden, vom Kratzer am Auto oder die Zeichnung zur Anfrage spart dem Betrieb einen Rückruf. Das Standard-Dateifeld wirkt dagegen technisch und verrät nicht, ob alles angekommen ist.",
  "wann_einsetzen": "Anfrage beim Handwerker, Schadensmeldung in der Werkstatt, Kurzbewerbung mit Lebenslauf, Anfrage mit Zeichnung im Mittelstand, Objektfotos für eine Bewertung.",
  "wann_nicht": "Wenn die Datei nicht wirklich gebraucht wird. Bei Gesundheitsunterlagen (Praxis, Pflege) und Mandantendokumenten: Dort gehört ein sicherer Kanal statt eines Formulars hin. Kein Pflichtfeld daraus machen, wenn es auch ohne geht.",
  "varianten": [
   "foto: nur Bilder, accept=\"image/*\", Kamera-Hinweis auf dem Telefon, Verkleinern auf etwa 2000 px",
   "dokument: PDF und Office, Größengrenze sichtbar, keine Vorschau außer Dateityp",
   "kompakt-mobil: nur ein Knopf „Foto aufnehmen oder wählen“ plus Liste"
  ],
  "umsetzung": "1. label umschließt input type=file (multiple, accept); das Input bleibt fokussierbar und wird nur visuell versteckt, nie display: none. 2. dragenter, dragover und drop auf der Fläche; dragover auch auf window abbrechen, damit ein Fehlwurf nicht die Seite verlässt. 3. Dateien in einen DataTransfer sammeln und dem Input zuweisen, damit das Formular normal sendet. 4. Prüfen nach Endung und Typ (file.type kann leer sein) und Größe; Fehler per setCustomValidity am Feld wie validierung-nach-interaktion. 5. Bilder mit createImageBitmap und Canvas.toBlob auf etwa 2000 px verkleinern; das entfernt auch Ortsdaten. 6. Liste der Dateien als ul mit aria-live=\"polite\"; der Entfernen-Knopf nennt den Dateinamen. 7. Fallback: Ohne JS bleibt das native Dateifeld mit Text zu Typ und Größe. Upload-Ziel, Speicherdauer und Datenschutzhinweis am Feld vom Kunden prüfen lassen.",
  "mobil": "Ablagefläche entfällt, ein großer Knopf; Kamera über accept=\"image/*\".",
  "reduzierte_bewegung": "Hervorhebung nur über Rahmenfarbe, keine Skalierung.",
  "barrierefreiheit": "Echtes Input per Tastatur erreichbar und beschriftet; Zustand und Fehler über aria-live; der Fehlertext nennt Datei und Grund; Fokus sichtbar auf der Fläche. 320 px: einspaltige Liste. 200 % Zoom: Karten brechen um. Kontrast 4,5:1 für Hinweise zu Typ und Größe. Bei langen Formularen formular-fehlerzusammenfassung."
 },
 "messwerte": {
  "easing": "Token des Rezepts",
  "dauer_ms": "Hervorhebung der Fläche beim Darüberziehen 150–200; neue Karte erscheint ohne Layoutsprung",
  "stagger_ms": "",
  "distanz": "",
  "sonstiges": "Verkleinern auf etwa 2000 px lange Kante, JPEG-Qualität etwa 0,8",
  "herkunft": "eigene Festlegung",
  "quelle": "eigene Festlegung"
 },
 "kurve": {
  "bezier": [
   0.0,
   0.0,
   0.38,
   0.9
  ],
  "css": "cubic-bezier(0, 0, 0.38, 0.9)",
  "name": "eigene Kurve",
  "dauer_ms": 150
 },
 "gesehen_bei": [
  {
   "seite": "WeTransfer: Drag and drop file upload",
   "url": "https://wetransfer.com/resources/drag-drop-file-upload/documents",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 03.11.2026: Ablagefläche mit „Drag & drop to start transferring“, darunter „or click to browse“, auf dem Telefon „Tap to start transferring“. Seite lud nur teilweise.",
   "art": "website"
  },
  {
   "seite": "GOV.UK Design System: File upload",
   "url": "https://design-system.service.gov.uk/components/file-upload",
   "auszeichnung": "",
   "beobachtung": "Abgerufen 03.11.2026: Ablagefläche immer sichtbar, per JS ergänzt; Fehlertexte wie „The selected file must be smaller than 2MB“; Hinweis, dass Sprachsteuerung native Dateifelder schwer auslösen kann; multiple seit v5.13.0. Nur fragen, wenn nötig.",
   "art": "artikel"
  }
 ],
 "tutorials": [
  {
   "titel": "MDN: File drag and drop",
   "url": "https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop"
  },
  {
   "titel": "web.dev: Read files in JavaScript",
   "url": "https://web.dev/articles/read-files"
  }
 ],
 "kombinierbar_mit": [
  "kontakt-anfrage-formular",
  "stellen-karriere",
  "mehrschritt-anfrage",
  "validierung-nach-interaktion",
  "formular-fehlerzusammenfassung",
  "fortschrittsring"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/sektionen/datei-upload-ablage/",
  "meta": "https://cecodesign.de/lab/fundus/sektionen/datei-upload-ablage/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/sektionen/datei-upload-ablage/demo"
 },
 "herkunft": {
  "quelldateien": [
   "Techniken-Recherche 03.11.2026"
  ],
  "pruefnotizen": [
   "Ein Website-Beleg (WeTransfer, Seite lud nur teilweise); einen zweiten im Browser nachholen.",
   "Dass Neukodieren EXIF und GPS entfernt, ist aus Wissen, nicht am 03.11.2026 geprüft.",
   "Datenschutz: Upload-Ziel, Speicherdauer und Hinweis am Formular vom Kunden prüfen lassen, keine Rechtsberatung.",
   "kontakt-anfrage-formular und stellen-karriere nennen den Upload nur als Feld; dieses Muster liefert den Baustein dafür."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Schadensfoto zur Anfrage: echtes Dateifeld in einer Ablagefläche, Vorschau-Karten mit Entfernen, Fehler mit Dateiname am Feld und Verkleinern auf 2000 px im Browser.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "Eintritt cubic-bezier(0, 0, 0.38, 0.9), Austritt cubic-bezier(0.2, 0, 1, 0.9) (token-tech-praezise aus dem Rezept handwerk)",
   "dauer_ms": "Hover 150; Fläche beim Darüberziehen 180 (Rahmen, Grund, Symbol); Karte 240 ein, 160 aus; Ladebalken 900; Ergebnis nach 500",
   "stagger_ms": "",
   "distanz": "Karte y 4 px → 0; Symbol beim Darüberziehen y -4 px",
   "feld": "label umschließt input type=file multiple accept; Input absolut über der Fläche mit opacity 0, fokussierbar; Fokusring an der Fläche über :has(input:focus-visible)",
   "ablegen": "dragenter/dragover/dragleave/drop an der Fläche mit Zähler gegen Flackern; dragover und drop auf window abgebrochen",
   "sammeln": "gültige Dateien in einen DataTransfer, input.files = dt.files",
   "pruefung": "Endung plus file.type (leer erlaubt); foto: jpg, jpeg, png, heic, heif, webp, je 15 MB, höchstens 6; dokument: pdf, doc, docx, odt, je 5 MB, höchstens 3",
   "fehler": "ungültige Datei bleibt als rote Karte mit Grund; setCustomValidity mit Dateiname und Grund, aria-invalid, Text unter der Fläche; beim Senden Fehlerzusammenfassung mit Links zu den Feldern",
   "verkleinern": "createImageBitmap, Canvas auf lange Kante 2000 px, toBlob image/jpeg 0,8; Anzeige „4032 × 3024 → 2000 × 1500 px · 616 KB → 152 KB“; ohne Decoder (z. B. HEIC) unverändert",
   "live": "ul aria-live=\"polite\" für neue Karten, Statuszeile für „… entfernt. 1 von 6 Fotos.“; Entfernen nennt den Dateinamen und gibt den Fokus an den nächsten Eintrag",
   "senden": "Demo: preventDefault, kein Upload, Erfolg mit Anzahl der Dateien; Datenschutzhinweis als markierter Platzhalter"
  },
  "ausloeser": "ziehen",
  "touch": "Ohne Hover heißt die Fläche „Foto aufnehmen oder auswählen“; accept=image/* bietet die Kamera an. Variante kompakt-mobil: nur ein 56 px hoher Knopf, Fotos als Kacheln (3 bzw. 2 Spalten) mit runden 44-px-Entfernen-Knöpfen.",
  "reduziert": "Karten erscheinen und verschwinden ohne Weg und Überblendung, die Fläche wechselt nur Rahmen und Grund, das Symbol bewegt sich nicht.",
  "korrekturen": {},
  "geprueft": "03.11.2026",
  "notiz": "foto und kompakt-mobil: Rezept handwerk-werkstatt-klartext, erfundene Brennholt Haustechnik aus Solingen, Schadensmeldung mit Rückruf. dokument: Rezept arbeitgeber-karriere, erfundene Lindemann Elektrotechnik aus Plön, Kurzbewerbung mit Lebenslauf als PDF (optional), Tannengrün-Spalte mit Gehalt und Stunden. Eine Kurve für die ganze Demo (Handwerk). Beispieldateien erzeugt die Demo selbst: zwei Fotos aus medien/handwerk-*.webp auf 4032 × 3024 hochgerechnet, dazu eine .mov mit 24 MB bzw. eine .pages und ein 8,4-MB-PDF als Fehlerfälle. Vorführung: Fläche hervorheben, ablegen, verkleinern, Fehlerkarten entfernen, Namen eintragen, senden, Erfolg. Datenschutz, Upload-Ziel und Speicherdauer vom Kunden prüfen lassen. Selbsturteil 4.",
  "varianten": [
   {
    "id": "foto",
    "name": "Schadensfoto zur Anfrage",
    "wann": "Handwerk, Kfz-Werkstatt, Hausverwaltung, Gutachter: Fotos sparen den Rückruf.",
    "werte": {
     "rezept": "handwerk-werkstatt-klartext",
     "accept": "image/jpeg, image/png, image/heic, image/heif, image/webp",
     "grenzen": "6 Fotos, je 15 MB",
     "verkleinern": "2000 px, JPEG 0,8"
    }
   },
   {
    "id": "dokument",
    "name": "Lebenslauf als PDF",
    "wann": "Kurzbewerbung, Anfrage mit Zeichnung oder Leistungsverzeichnis im Mittelstand.",
    "werte": {
     "rezept": "arbeitgeber-karriere",
     "accept": ".pdf, .doc, .docx, .odt",
     "grenzen": "3 Dateien, je 5 MB",
     "vorschau": "nur Dateityp als Kachel (PDF rot, Word/ODT blau)"
    }
   },
   {
    "id": "kompakt-mobil",
    "name": "Ein Knopf und Kacheln",
    "wann": "Mobile Schadensmeldung, Kurzformular auf dem Telefon, Einsatz vor Ort.",
    "werte": {
     "rezept": "handwerk-werkstatt-klartext",
     "knopf": "56 px hoch, volle Breite, „Foto aufnehmen oder wählen“",
     "liste": "Kacheln 1:1, 3 Spalten (2 unter 560 px), Entfernen 44 px rund"
    }
   }
  ]
 }
}
