@@ -410,73 +410,148 @@ export function App() {
410410
411411 const emptyBecauseFilters = data . projects . length > 0 && visibleProjects . length === 0 ;
412412
413+
413414 return (
414415 < div className = "app-shell" >
415416 < header className = "app-header" >
416- < div className = "brand" >
417- < span className = "brand__mark" > < Icon name = "code" /> </ span >
418- < span > < strong > Code Deck</ strong > < small > Local Developer Cockpit</ small > </ span >
419- </ div >
420- < div className = "global-search" >
421- < Icon name = "search" />
422- < input ref = { searchRef } value = { search } onChange = { ( event ) => setSearch ( event . target . value ) } placeholder = "Projekte, Tags, Frameworks oder Pfade durchsuchen…" />
423- < kbd > ⌘ K</ kbd >
424- </ div >
425- < div className = "header-actions" >
426- < button className = "header-button" type = "button" onClick = { ( ) => setWorkspacesOpen ( true ) } > < Icon name = "layers" /> < span > Workspaces</ span > </ button >
427- < button className = "header-button" type = "button" onClick = { ( ) => setProcessesOpen ( true ) } > < Icon name = "terminal" /> < span > Prozesse</ span > { activeProcesses . length > 0 && < b > { activeProcesses . length } </ b > } </ button >
428- < button className = "header-button" type = "button" onClick = { ( ) => setSettingsOpen ( true ) } > < Icon name = "settings" /> < span > Einstellungen</ span > </ button >
417+ < div className = "app-header__bar" >
418+ { /* <div className="brand" aria-label="CodeDeck">
419+ <img src="/icon.png" alt="" className="brand__mark" />
420+ <strong>CodeDeck</strong>
421+ </div> */ }
422+
423+ < nav className = "main-nav" aria-label = "Hauptnavigation" >
424+ < button className = "main-nav__item active" type = "button" aria-current = "page" >
425+ < Icon name = "folder" />
426+ < span > Projekte</ span >
427+ </ button >
428+ < button className = "main-nav__item" type = "button" onClick = { ( ) => setWorkspacesOpen ( true ) } >
429+ < Icon name = "layers" />
430+ < span > Workspaces</ span >
431+ { data . workspaces . length > 0 && < small > { data . workspaces . length } </ small > }
432+ </ button >
433+ < button className = "main-nav__item" type = "button" onClick = { ( ) => setProcessesOpen ( true ) } >
434+ < Icon name = "terminal" />
435+ < span > Prozesse</ span >
436+ { activeProcesses . length > 0 && < small className = "main-nav__badge" > { activeProcesses . length } </ small > }
437+ </ button >
438+ </ nav >
439+
440+ < div className = "app-header__actions" >
441+ < button
442+ className = "icon-button"
443+ type = "button"
444+ onClick = { ( ) => setSettingsOpen ( true ) }
445+ title = "Einstellungen"
446+ aria-label = "Einstellungen öffnen"
447+ >
448+ < Icon name = "settings" />
449+ </ button >
450+ < button className = "button button--primary" type = "button" onClick = { ( ) => setCreateOpen ( true ) } >
451+ < Icon name = "plus" />
452+ < span > Projekt hinzufügen</ span >
453+ </ button >
454+ </ div >
429455 </ div >
430- </ header >
431456
432- < main className = "home-page" >
433- < section className = "home-hero" >
434- < div >
435- < p className = "eyebrow" > Dein lokales Cockpit</ p >
457+ < div className = "app-toolbar" >
458+ < div className = "app-toolbar__title" >
436459 < h1 > Projekte</ h1 >
437- < p > { data . projects . filter ( ( project ) => ! project . archived ) . length } aktiv · { data . projects . filter ( ( project ) => project . favorite && ! project . archived ) . length } Favoriten · { activeProcesses . length } Prozesse </ p >
460+ < span > { visibleProjects . length } von { data . projects . filter ( ( project ) => showArchived || ! project . archived ) . length } </ span >
438461 </ div >
439- < div className = "hero-actions" >
440- < button className = "button button--secondary" type = "button" onClick = { ( ) => setScanOpen ( true ) } > < Icon name = "search" /> Ordner scannen</ button >
441- < button className = "button button--primary" type = "button" onClick = { ( ) => setCreateOpen ( true ) } > < Icon name = "plus" /> Neues Projekt</ button >
462+ < div className = "global-search" >
463+ < Icon name = "search" />
464+ < input
465+ ref = { searchRef }
466+ value = { search }
467+ onChange = { ( event ) => setSearch ( event . target . value ) }
468+ placeholder = "Name, Pfad, Tag oder Framework"
469+ aria-label = "Projekte durchsuchen"
470+ />
471+ < kbd > Ctrl K</ kbd >
442472 </ div >
443- </ section >
473+ < button className = "button button--secondary" type = "button" onClick = { ( ) => setScanOpen ( true ) } >
474+ < Icon name = "search" />
475+ < span > Ordner scannen</ span >
476+ </ button >
477+ </ div >
478+ </ header >
444479
445- < section className = "filter-bar" >
446- < button className = { `filter-chip ${ favoriteOnly ? "active" : "" } ` } type = "button" onClick = { ( ) => setFavoriteOnly ( ( value ) => ! value ) } > < Icon name = "star" /> Favoriten</ button >
447- < select aria-label = "Nach Tag filtern" value = { selectedTag } onChange = { ( event ) => setSelectedTag ( event . target . value ) } > < option value = "" > Alle Tags & Frameworks </ option > { allTags . map ( ( tag ) => < option value = { tag } key = { tag } > { tag } </ option > ) } </ select >
448- < label className = "filter-checkbox" > < input type = "checkbox" checked = { showArchived } onChange = { ( event ) => setShowArchived ( event . target . checked ) } /> < span > Archivierte anzeigen</ span > </ label >
449- { ( search || favoriteOnly || selectedTag || showArchived ) && < button className = "text-button filter-reset" type = "button" onClick = { ( ) => { setSearch ( "" ) ; setFavoriteOnly ( false ) ; setSelectedTag ( "" ) ; setShowArchived ( false ) ; } } > < Icon name = "x" /> Filter zurücksetzen</ button > }
480+ < main className = "home-page" >
481+ < section className = "filter-bar" aria-label = "Projektfilter" >
482+ < div className = "filter-bar__left" >
483+ < button className = { `filter-chip ${ favoriteOnly ? "active" : "" } ` } type = "button" onClick = { ( ) => setFavoriteOnly ( ( value ) => ! value ) } >
484+ < Icon name = "star" />
485+ < span > Favoriten</ span >
486+ </ button >
487+ < select aria-label = "Nach Tag filtern" value = { selectedTag } onChange = { ( event ) => setSelectedTag ( event . target . value ) } >
488+ < option value = "" > Alle Tags und Frameworks</ option >
489+ { allTags . map ( ( tag ) => < option value = { tag } key = { tag } > { tag } </ option > ) }
490+ </ select >
491+ < label className = "filter-checkbox" >
492+ < input type = "checkbox" checked = { showArchived } onChange = { ( event ) => setShowArchived ( event . target . checked ) } />
493+ < span > Archivierte anzeigen</ span >
494+ </ label >
495+ </ div >
496+ { ( search || favoriteOnly || selectedTag || showArchived ) && (
497+ < button className = "text-button filter-reset" type = "button" onClick = { ( ) => { setSearch ( "" ) ; setFavoriteOnly ( false ) ; setSelectedTag ( "" ) ; setShowArchived ( false ) ; } } >
498+ < Icon name = "x" />
499+ < span > Zurücksetzen</ span >
500+ </ button >
501+ ) }
450502 </ section >
451503
452504 { visibleProjects . length ? (
453- < section className = "project-grid" >
454- { visibleProjects . map ( ( project ) => (
455- < ProjectCard
456- key = { project . id }
457- project = { project }
458- editor = { editorById . get ( project . preferredEditorId ?? "" ) }
459- onOpenDetails = { ( ) => setSelectedProjectId ( project . id ) }
460- onOpenEditor = { ( ) => void openProjectEditor ( project ) }
461- onRunCommand = { ( command ) => void runProjectCommand ( project , command ) }
462- onToggleFavorite = { ( ) => updateProject ( { ...project , favorite : ! project . favorite , updatedAt : new Date ( ) . toISOString ( ) } ) }
463- />
464- ) ) }
505+ < section className = "project-list" aria-label = "Projektliste" >
506+ < div className = "project-list__header" aria-hidden = "true" >
507+ < span > Projekt</ span >
508+ < span > Tags</ span >
509+ < span > Git</ span >
510+ < span > Zuletzt genutzt</ span >
511+ < span > Aktionen</ span >
512+ </ div >
513+ < div className = "project-list__body" >
514+ { visibleProjects . map ( ( project ) => (
515+ < ProjectCard
516+ key = { project . id }
517+ project = { project }
518+ editor = { editorById . get ( project . preferredEditorId ?? "" ) }
519+ onOpenDetails = { ( ) => setSelectedProjectId ( project . id ) }
520+ onOpenEditor = { ( ) => void openProjectEditor ( project ) }
521+ onRunCommand = { ( command ) => void runProjectCommand ( project , command ) }
522+ onToggleFavorite = { ( ) => updateProject ( { ...project , favorite : ! project . favorite , updatedAt : new Date ( ) . toISOString ( ) } ) }
523+ />
524+ ) ) }
525+ </ div >
465526 </ section >
466527 ) : (
467528 < section className = "home-empty" >
468- < div className = "home-empty__art" > < Icon name = { emptyBecauseFilters ? "search" : "layers " } /> </ div >
469- < h2 > { emptyBecauseFilters ? "Keine passenden Projekte" : "Dein Deck ist noch leer " } </ h2 >
470- < p > { emptyBecauseFilters ? "Passe Suche oder Filter an, um deine Projekte wiederzufinden ." : "Füge einen lokalen Projektordner hinzu oder scanne einen Basisordner nach Git-Repositories und bekannten Projektdateien ." } </ p >
529+ < div className = "home-empty__art" > < Icon name = { emptyBecauseFilters ? "search" : "folder " } /> </ div >
530+ < h2 > { emptyBecauseFilters ? "Keine passenden Projekte" : "Noch keine Projekte " } </ h2 >
531+ < p > { emptyBecauseFilters ? "Ändere die Suche oder setze die Filter zurück ." : "Füge einen vorhandenen Ordner hinzu oder erstelle ein neues Projekt aus einer Vorlage ." } </ p >
471532 < div className = "button-row" >
472- { emptyBecauseFilters ? < button className = "button button--secondary" type = "button" onClick = { ( ) => { setSearch ( "" ) ; setFavoriteOnly ( false ) ; setSelectedTag ( "" ) ; setShowArchived ( false ) ; } } > < Icon name = "refresh" /> Filter zurücksetzen</ button > : < > < button className = "button button--secondary" type = "button" onClick = { ( ) => setScanOpen ( true ) } > < Icon name = "search" /> Ordner scannen</ button > < button className = "button button--primary" type = "button" onClick = { ( ) => setCreateOpen ( true ) } > < Icon name = "plus" /> Erstes Projekt hinzufügen</ button > </ > }
533+ { emptyBecauseFilters ? (
534+ < button className = "button button--secondary" type = "button" onClick = { ( ) => { setSearch ( "" ) ; setFavoriteOnly ( false ) ; setSelectedTag ( "" ) ; setShowArchived ( false ) ; } } >
535+ < Icon name = "refresh" />
536+ < span > Filter zurücksetzen</ span >
537+ </ button >
538+ ) : (
539+ < >
540+ < button className = "button button--secondary" type = "button" onClick = { ( ) => setScanOpen ( true ) } >
541+ < Icon name = "search" />
542+ < span > Ordner scannen</ span >
543+ </ button >
544+ < button className = "button button--primary" type = "button" onClick = { ( ) => setCreateOpen ( true ) } >
545+ < Icon name = "plus" />
546+ < span > Projekt hinzufügen</ span >
547+ </ button >
548+ </ >
549+ ) }
473550 </ div >
474551 </ section >
475552 ) }
476553 </ main >
477554
478- < button className = "floating-add" type = "button" onClick = { ( ) => setCreateOpen ( true ) } > < Icon name = "plus" /> < span > Neues Projekt</ span > </ button >
479-
480555 < ProjectCreateModal
481556 open = { createOpen }
482557 editors = { data . editors }
0 commit comments