Selector-UI: Anlegen und Öffnen #8

Closed
opened 2026-08-27 12:33:42 +00:00 by RDietermann · 1 comment
Owner

Part of #1

Question

Wie sehen die beiden Selector-Screens konkret aus?

layout.css gibt den Rahmen bereits vor: zentriert, .workspace-selector-links als Reiterleiste, darunter .workspace-selector-view als Karte mit max. 34rem Breite. Die beiden Routen NewWorkspace und OpenWorkspace sind heute leere divs.

Zu klären ist, was in die Karte gehört:

  • Öffnen: Wie sieht ein Eintrag in der Workspace-Liste aus — Name, Pfad, beides? Was zeigt der Screen, wenn die Liste leer ist (Erststart)? Wie kommt man von hier an einen Ordner, der noch nicht in der Liste steht?
  • Anlegen: Nur ein Knopf, der den nativen Dialog öffnet — oder davor noch ein Namensfeld? Was passiert nach dem Anlegen: direkt in den Editor oder zurück in die Liste?

Als HITL-Prototyp gedacht: eine grobe, wegwerfbare Fassung über das /prototype-Skill, an der sich entscheiden lässt, wie es sich anfühlt. Die vorhandenen Komponenten CustomButton, CustomInput und CustomLink sind da.

Zielgröße: ein Prototyp, verlinkt an diesem Ticket, plus die daran getroffenen Entscheidungen.

Part of #1 ## Question Wie sehen die beiden Selector-Screens konkret aus? `layout.css` gibt den Rahmen bereits vor: zentriert, `.workspace-selector-links` als Reiterleiste, darunter `.workspace-selector-view` als Karte mit max. 34rem Breite. Die beiden Routen `NewWorkspace` und `OpenWorkspace` sind heute leere `div`s. Zu klären ist, was in die Karte gehört: - **Öffnen:** Wie sieht ein Eintrag in der Workspace-Liste aus — Name, Pfad, beides? Was zeigt der Screen, wenn die Liste leer ist (Erststart)? Wie kommt man von hier an einen Ordner, der noch nicht in der Liste steht? - **Anlegen:** Nur ein Knopf, der den nativen Dialog öffnet — oder davor noch ein Namensfeld? Was passiert nach dem Anlegen: direkt in den Editor oder zurück in die Liste? Als HITL-Prototyp gedacht: eine grobe, wegwerfbare Fassung über das `/prototype`-Skill, an der sich entscheiden lässt, wie es sich anfühlt. Die vorhandenen Komponenten `CustomButton`, `CustomInput` und `CustomLink` sind da. Zielgröße: ein Prototyp, verlinkt an diesem Ticket, plus die daran getroffenen Entscheidungen.
RDietermann added the wayfinder:prototype label 2026-08-27 12:33:42 +00:00
RDietermann added a new dependency 2026-08-27 12:36:05 +00:00
RDietermann added a new dependency 2026-08-27 12:36:06 +00:00
RDietermann self-assigned this 2026-08-28 06:37:07 +00:00
Author
Owner

Antwort

Variante B gewinnt: ein Bildschirm, die Liste führt, das Hinzufügen ist Nebenaktion.

Drei Varianten standen zur Wahl — A (Reiter, wie der heutige Code sie anlegt), B (eine Ansicht, Liste dominiert), C (zweispaltiger Startbildschirm nach Art von JetBrains/VS Code). Prototyp und Umschalter liegen auf dem Branch prototype/selector-ui.

Der Aufbau

┌──────────────────────────────────────────────┐
│  Workspace öffnen                 5 bekannt  │
├──────────────────────────────────────────────┤
│  Notizen                                     │
│  C:\Users\marvin\Notizen                     │
│  DioNotes-Testdaten                          │
│  D:\Projekte\DioNotes-Testdaten              │
│  Archiv 2024            [nicht erreichbar]   │
│  E:\Backup\Archiv 2024                       │
│  …                                           │
├──────────────────────────────────────────────┤
│  Ein Workspace ist ein Ordner mit Notizen.   │
│                    [ Workspace hinzufügen… ] │
└──────────────────────────────────────────────┘

Maximal 40rem breit, zentriert. Die Liste scrollt, Kopf- und Fußzeile stehen fest.

Listeneintrag: Name (der Ordnername) in der ersten Zeile, vollständiger Pfad darunter in der Code-Schrift und gedämpft, rechts bei Bedarf das Statusabzeichen. Der Pfad wird bei Überlänge links gekürzt (direction: rtl), weil das Ende eines Pfades mehr aussagt als sein Anfang.

Statusabzeichen in den drei Farben des Design-Systems: nicht erreichbar in Warnfarbe, kein Workspace mehr gedämpft, beschädigt in Gefahrfarbe. Der Name betroffener Einträge wird abgeschwächt, der Eintrag bleibt anklickbar — ein Klick versucht es erneut (siehe #6).

Leerer Erststart: Die Liste weicht einem .empty-state („Hier ist noch nichts / Der erste Workspace ist ein Ordner deiner Wahl"), und der Fußzeilenknopf wird zur Primäraktion (.btn-primary). Sonst bleibt er ein normaler .btn. Das ist der einzige Unterschied zwischen den beiden Zuständen — kein eigener Bildschirm.

Rückfrage bei nicht-leerem Ordner als modaler Dialog, wie in #6 festgelegt. Er nennt die Zahl der vorhandenen Dateien und sagt ausdrücklich, dass nur .dionotes/ angelegt und nichts Vorhandenes verändert wird — die Rückfrage soll informieren, nicht beunruhigen.

Warum B

Öffnen ist der Alltagsfall, Hinzufügen passiert pro Workspace genau einmal. Reiter stellen beide gleichrangig nebeneinander und verlangen bei jedem Start eine Entscheidung, die in 95 % der Fälle dieselbe ist. C hat denselben Vorzug wie B, kauft ihn aber mit einer festen zweiten Spalte, die außer einem Knopf und dem Markennamen nichts trägt — viel Fläche für wenig Inhalt bei einem Bildschirm, der laut layout.css „genau eine Aufgabe" hat.

Die Beschriftung

„Workspace hinzufügen…", nicht „Ordner wählen…" oder „Neuen anlegen…".

Der Knopf ist der einzige Weg zu einem Ordner-Dialog und deckt zwei Fälle zugleich ab: einen neuen Workspace anlegen und einen bestehenden wieder aufnehmen, der nicht mehr in der Liste steht — möglich geworden durch #6, wo ein bereits vorhandener Workspace geöffnet statt abgelehnt wird. „Neuen anlegen…" wäre für den zweiten Fall falsch. Gegen „Ordner wählen…" spricht, dass es den mechanischen Zwischenschritt beschreibt statt das Ziel des Nutzers.


Folge für #5: der Selector wird eine einzige Route

Ohne Reiter gibt es keinen Grund mehr für zwei Selector-Routen. NewWorkspace {} und OpenWorkspace {} verschmelzen zu einer Route; die in #5 vorgeschlagene Konstante SELECTOR_TABS entfällt ersatzlos, ebenso die CSS-Klasse .workspace-selector-links und die Tab-Komponente.

Das Routen-Enum aus #5 wird damit zu:

#[derive(Debug, Clone, Routable, PartialEq, EnumMessage)]
#[rustfmt::skip]
pub enum Route {
    #[route("/")]
    Selector {},

    #[nest("/workspace")]
        #[layout(EditorShell)]
            #[route("/")]
            #[strum(message = "Home")]
            Home {},
            #[route("/editor")]
            #[strum(message = "Editor")]
            Editor {},
        #[end_layout]
    #[end_nest]
}

Nebeneffekt: Der Pflegepunkt, den ich in #5 offen ausweisen musste — dass der Compiler nicht erzwingt, eine neue Route ins passende Tab-Array einzutragen — löst sich für den Selector auf. EDITOR_TABS bleibt bestehen und behält den Vorbehalt.

Der Selector braucht auch kein #[layout] mehr: Er ist der Bildschirm, es gibt keinen Outlet-Inhalt, der umschaltet.

## Antwort **Variante B gewinnt: ein Bildschirm, die Liste führt, das Hinzufügen ist Nebenaktion.** Drei Varianten standen zur Wahl — A (Reiter, wie der heutige Code sie anlegt), B (eine Ansicht, Liste dominiert), C (zweispaltiger Startbildschirm nach Art von JetBrains/VS Code). Prototyp und Umschalter liegen auf dem Branch `prototype/selector-ui`. ### Der Aufbau ``` ┌──────────────────────────────────────────────┐ │ Workspace öffnen 5 bekannt │ ├──────────────────────────────────────────────┤ │ Notizen │ │ C:\Users\marvin\Notizen │ │ DioNotes-Testdaten │ │ D:\Projekte\DioNotes-Testdaten │ │ Archiv 2024 [nicht erreichbar] │ │ E:\Backup\Archiv 2024 │ │ … │ ├──────────────────────────────────────────────┤ │ Ein Workspace ist ein Ordner mit Notizen. │ │ [ Workspace hinzufügen… ] │ └──────────────────────────────────────────────┘ ``` Maximal 40rem breit, zentriert. Die Liste scrollt, Kopf- und Fußzeile stehen fest. **Listeneintrag:** Name (der Ordnername) in der ersten Zeile, vollständiger Pfad darunter in der Code-Schrift und gedämpft, rechts bei Bedarf das Statusabzeichen. Der Pfad wird bei Überlänge **links** gekürzt (`direction: rtl`), weil das Ende eines Pfades mehr aussagt als sein Anfang. **Statusabzeichen** in den drei Farben des Design-Systems: `nicht erreichbar` in Warnfarbe, `kein Workspace mehr` gedämpft, `beschädigt` in Gefahrfarbe. Der Name betroffener Einträge wird abgeschwächt, der Eintrag bleibt anklickbar — ein Klick versucht es erneut (siehe #6). **Leerer Erststart:** Die Liste weicht einem `.empty-state` („Hier ist noch nichts / Der erste Workspace ist ein Ordner deiner Wahl"), und der Fußzeilenknopf wird zur Primäraktion (`.btn-primary`). Sonst bleibt er ein normaler `.btn`. Das ist der einzige Unterschied zwischen den beiden Zuständen — kein eigener Bildschirm. **Rückfrage bei nicht-leerem Ordner** als modaler Dialog, wie in #6 festgelegt. Er nennt die Zahl der vorhandenen Dateien und sagt ausdrücklich, dass nur `.dionotes/` angelegt und nichts Vorhandenes verändert wird — die Rückfrage soll informieren, nicht beunruhigen. ### Warum B Öffnen ist der Alltagsfall, Hinzufügen passiert pro Workspace genau einmal. Reiter stellen beide gleichrangig nebeneinander und verlangen bei jedem Start eine Entscheidung, die in 95 % der Fälle dieselbe ist. C hat denselben Vorzug wie B, kauft ihn aber mit einer festen zweiten Spalte, die außer einem Knopf und dem Markennamen nichts trägt — viel Fläche für wenig Inhalt bei einem Bildschirm, der laut `layout.css` „genau eine Aufgabe" hat. ### Die Beschriftung **„Workspace hinzufügen…"**, nicht „Ordner wählen…" oder „Neuen anlegen…". Der Knopf ist der einzige Weg zu einem Ordner-Dialog und deckt zwei Fälle zugleich ab: einen neuen Workspace anlegen und einen bestehenden wieder aufnehmen, der nicht mehr in der Liste steht — möglich geworden durch #6, wo ein bereits vorhandener Workspace geöffnet statt abgelehnt wird. „Neuen anlegen…" wäre für den zweiten Fall falsch. Gegen „Ordner wählen…" spricht, dass es den mechanischen Zwischenschritt beschreibt statt das Ziel des Nutzers. --- ## Folge für #5: der Selector wird eine einzige Route Ohne Reiter gibt es keinen Grund mehr für zwei Selector-Routen. **`NewWorkspace {}` und `OpenWorkspace {}` verschmelzen zu einer Route**; die in #5 vorgeschlagene Konstante `SELECTOR_TABS` entfällt ersatzlos, ebenso die CSS-Klasse `.workspace-selector-links` und die Tab-Komponente. Das Routen-Enum aus #5 wird damit zu: ```rust #[derive(Debug, Clone, Routable, PartialEq, EnumMessage)] #[rustfmt::skip] pub enum Route { #[route("/")] Selector {}, #[nest("/workspace")] #[layout(EditorShell)] #[route("/")] #[strum(message = "Home")] Home {}, #[route("/editor")] #[strum(message = "Editor")] Editor {}, #[end_layout] #[end_nest] } ``` Nebeneffekt: Der Pflegepunkt, den ich in #5 offen ausweisen musste — dass der Compiler nicht erzwingt, eine neue Route ins passende Tab-Array einzutragen — löst sich für den Selector auf. `EDITOR_TABS` bleibt bestehen und behält den Vorbehalt. Der Selector braucht auch kein `#[layout]` mehr: Er *ist* der Bildschirm, es gibt keinen Outlet-Inhalt, der umschaltet.
Sign in to join this conversation.