Skip to content

Commit eb26bb7

Browse files
author
b45632
committed
feat: redesign application interface
1 parent f28d6c6 commit eb26bb7

15 files changed

Lines changed: 1730 additions & 1556 deletions

File tree

CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,23 @@ The project follows [Semantic Versioning](https://semver.org/).
1414

1515
### Security
1616

17+
## [0.2.1]
18+
19+
### Changed
20+
21+
- Redesigned the application interface
22+
- Reworked the main navigation
23+
- Improved project cards and action layouts
24+
- Fixed duplicate process and settings navigation
25+
- Improved button sizing, text alignment and responsive behavior
26+
- Added the Code Deck application icon to the interface
27+
28+
### Fixed
29+
30+
- Fixed clipped and wrapped button labels
31+
- Fixed inconsistent spacing across dialogs and pages
32+
- Fixed duplicate navigation entries
33+
1734
## [0.2.0]
1835

1936
### Added
@@ -57,6 +74,6 @@ The project follows [Semantic Versioning](https://semver.org/).
5774
- Imported commands are never started automatically.
5875
- Project inspection does not modify project source files.
5976

60-
[Unreleased]: https://github.com/JadnK/CodeDeck/compare/v0.2.0...HEAD
77+
[0.2.1]: https://github.com/JadnK/CodeDeck/compare/v0.2.0...v0.2.1
6178
[0.2.0]: https://github.com/JadnK/CodeDeck/compare/v0.1.0...v0.2.0
6279
[0.1.0]: https://github.com/JadnK/CodeDeck/releases/tag/v0.1.0

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The current interface is in German. This README uses the exact German button nam
3232
Download the latest version from
3333
[GitHub Releases](../../releases/latest).
3434

35-
__Dont forget giving the Star :)__
35+
__If CodeDeck saves you time, consider starring the repository.__
3636

3737
## Where everything is
3838

index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/png" href="/icon.png" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7-
<meta name="theme-color" content="#090d17" />
7+
<meta name="theme-color" content="#111315" />
88
<meta name="description" content="Code Deck – lokales Developer-Cockpit für Projekte, IDEs, Commands und Workspaces." />
9-
<title>Code Deck</title>
9+
<title>CodeDeck</title>
1010
</head>
1111
<body>
1212
<div id="root"></div>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "code-deck",
33
"private": true,
4-
"version": "0.2.0",
4+
"version": "0.2.1",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "code-deck"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
description = "Local developer project cockpit"
55
authors = ["Code Deck Contributors"]
66
edition = "2021"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "Code Deck",
4-
"version": "0.2.0",
4+
"version": "0.2.1",
55
"identifier": "dev.codedeck.app",
66
"build": {
77
"beforeDevCommand": "pnpm dev",

src/app/App.tsx

Lines changed: 121 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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}

src/features/onboarding/Onboarding.tsx

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,25 @@ export function Onboarding({
2222
const [step, setStep] = useState(0);
2323
const steps = [
2424
{
25-
icon: "layers" as const,
26-
eyebrow: "Willkommen",
27-
title: "Deine Projekte. Ein Deck.",
28-
text: "Code Deck bündelt lokale Entwicklungsprojekte, IDEs, Commands und Workspaces in einer schnellen Desktop-App.",
29-
action: "Loslegen",
25+
title: "Willkommen bei CodeDeck",
26+
text: "Verwalte lokale Projekte, öffne sie in der passenden IDE und starte wiederkehrende Commands an einem Ort.",
27+
action: "Einrichtung starten",
3028
run: () => setStep(1),
3129
},
3230
{
33-
icon: "code" as const,
34-
eyebrow: "Schritt 1 von 2",
35-
title: "IDE konfigurieren",
31+
title: "IDE prüfen",
3632
text: hasEditors
37-
? "VS Code und Cursor sind bereits als Vorlagen angelegt. Du kannst sie prüfen oder weitere Editoren hinzufügen."
38-
: "Lege mindestens eine IDE mit einem Command-Template an, zum Beispiel code \"{projectPath}\".",
33+
? "Mindestens eine IDE ist bereits eingerichtet. Du kannst die Einträge später jederzeit in den Einstellungen ändern."
34+
: "Lege eine IDE mit einem Command-Template an, zum Beispiel code \"{projectPath}\".",
3935
action: hasEditors ? "Weiter" : "Einstellungen öffnen",
4036
run: () => hasEditors ? setStep(2) : onOpenSettings(),
4137
},
4238
{
43-
icon: "folder" as const,
44-
eyebrow: "Schritt 2 von 2",
45-
title: "Erstes Projekt hinzufügen",
39+
title: "Projekt hinzufügen",
4640
text: hasProjects
47-
? "Dein erstes Projekt ist bereits angelegt. Du kannst Code Deck jetzt vollständig nutzen."
48-
: "Erstelle ein neues Node-, React-, Spring-, Python- oder Rust-Grundgerüst – oder füge einen vorhandenen Ordner hinzu. Code Deck erkennt Git, Frameworks und Scripts automatisch.",
49-
action: hasProjects ? "Code Deck öffnen" : "Projekt erstellen oder hinzufügen",
41+
? "Ein Projekt ist bereits vorhanden. Die Einrichtung ist abgeschlossen."
42+
: "Füge einen vorhandenen Ordner hinzu oder erstelle ein Grundgerüst für Node.js, React, Spring Boot, Python oder Rust.",
43+
action: hasProjects ? "CodeDeck öffnen" : "Projekt hinzufügen",
5044
run: () => hasProjects ? onComplete() : onAddProject(),
5145
},
5246
];
@@ -55,14 +49,23 @@ export function Onboarding({
5549
return (
5650
<Modal open={open} onClose={onComplete} size="small">
5751
<div className="onboarding">
58-
<div className="onboarding__brand"><span><Icon name="code" /></span>CODE DECK</div>
59-
<div className="onboarding__visual"><Icon name={current.icon} /></div>
60-
<p className="eyebrow">{current.eyebrow}</p>
52+
<div className="onboarding__brand">
53+
<img src="/icon.png" alt="" />
54+
<div><strong>CodeDeck</strong><span>Ersteinrichtung</span></div>
55+
</div>
56+
<div className="onboarding__progress" aria-label={`Schritt ${step + 1} von ${steps.length}`}>
57+
{steps.map((_, index) => <span key={index} className={index <= step ? "active" : ""} />)}
58+
</div>
59+
<p className="onboarding__step">Schritt {step + 1} von {steps.length}</p>
6160
<h2>{current.title}</h2>
62-
<p>{current.text}</p>
63-
<div className="onboarding__dots">{steps.map((_, index) => <span key={index} className={index === step ? "active" : ""} />)}</div>
64-
<button className="button button--primary button--full" type="button" onClick={current.run}>{current.action}<Icon name="external" /></button>
65-
<button className="text-button" type="button" onClick={onComplete}>Onboarding überspringen</button>
61+
<p className="onboarding__text">{current.text}</p>
62+
<div className="onboarding__actions">
63+
<button className="button button--primary button--full" type="button" onClick={current.run}>
64+
<span>{current.action}</span>
65+
<Icon name="external" />
66+
</button>
67+
<button className="text-button" type="button" onClick={onComplete}>Überspringen</button>
68+
</div>
6669
</div>
6770
</Modal>
6871
);

src/features/processes/ProcessesPanel.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export function ProcessesPanel({
3434
const finished = processes.filter((process) => !["starting", "running", "stopping"].includes(process.status));
3535

3636
return (
37-
<Modal open={open} onClose={onClose} title="Prozesse" eyebrow={`${active.length} aktiv`} size="large">
37+
<Modal open={open} onClose={onClose} title={`Prozesse · ${active.length} aktiv`} size="large">
3838
<div className="processes-panel">
3939
{processes.length === 0 ? (
4040
<div className="empty-state"><Icon name="terminal" /><h3>Keine Prozesse</h3><p>Gestartete Commands erscheinen hier mit Live-Logs und Stop-Funktion.</p></div>

0 commit comments

Comments
 (0)