The board wears a picture — background becomes a mapping, and the window chrome follows it under a thin frost
background is {color:, image:} and only a mapping at every level; the board's image paints the full window under a transparent title bar, with a thin-material frost strip keeping the chrome legible and the standard accommodations intact.
Claude-Session: https://claude.ai/code/session_014PtZdPwqZuqEDLc6wZMtEy
This commit is contained in:
@@ -14,7 +14,7 @@ Lanework is in early development. This list tracks what has actually shipped and
|
||||
- **Live store** — every open board is one shared, watched, in-memory snapshot: an FSEvents folder watcher (debounced, `.git`-filtered, origin-reconciling) drives whole-tree reloads with a generation guard and single-flight coalescing; write brackets suppress self-echo, and a per-board **write-provenance ledger** — in-memory, dying with the session — records a content hash, an absence marker or an old→new pair for every file the app writes, so a landing reload can tell its own echo from an outside edit file by file (final content decides: byte-identical is the app's, one byte different is somebody else's); a file-identity-keyed store registry refcounts stores and watchers across windows and absorbs root renames via bookmark re-resolution (a vanished root locks the board and watches for its return); plus the board registry (recents, bookmarks, cached counts), the banner center's single precedence order, the dirty-buffer guard, and transient UI state.
|
||||
- **Window architecture** — the three window types and their lifecycle: a welcome window (below), one board window per root (per-board frame memory, repositioned onto a live screen), and at-most-one card window per card (last-used size, cascaded, then per-card frame memory once you've placed one; follows its card across lanes; dismisses the moment its card leaves the board — into the trash, with its deleted lane, purged, or moved to another board). Closing a board window or quitting runs one strict close flush — card sessions end, pending work drains, the registry is stamped — before the store tears down; launch restores the boards whose open-now flags survived quit (or crash), a preference gating only whether the flags are consulted. Every open passes through a real loading window — it appears immediately at its saved frame under the registry's cached name, its content a centered spinner behind a ~200 ms grace, while the tree walk runs off the main actor (one walk per board however many windows ask at once), and ⌘W during the walk genuinely cancels it. When an **attended** open refuses, that same content area transforms in place into the **decision surface** — never a sheet, never a chained dialog: the walk's defects grouped by class, each class stating the problem once and listing the affected files with Reveal in Finder and Open in Editor, one class-level choice preselected to its default and a per-file override behind a disclosure. Only honest choices are offered — unparseable frontmatter gets Open in Editor and Re-check (or Skip below the root), a file from a newer Lanework gets Skip alone (and blocks the whole board at the root), a board root with no `index.md` gets a minted index, a root with no `schema` gets a `schema: 1` stamp. Repair and Open applies every chosen fix in one write bracket — ordinary app writes, and on Pro boards a separate heal-authored repair commit — then re-runs the whole walk, opening on a clean result and re-aggregating into the *same* surface otherwise; Re-check re-walks without writing; Cancel (and ⌘W) retires to welcome's row. Skips are per-open consent that rides the session and is never persisted, and the opened board carries a warning-tone notice naming what was left out, each with its own Reveal in Finder. Restoration failures keep the retire-to-welcome-row landing — repair is an attended act, and launch never chains dialogs.
|
||||
- **The board** — every lane always on screen, the window's width dividing across the lanes' width units with no horizontal scroll: cards flow into as many interior masonry columns as a lane is wide, a right-edge drag resizes between whole units by growing the *window* (snapping at the gap with release hysteresis, hard-stopping at the screen with rubber-band feedback), and ⌥⌘→/⌥⌘← re-divide the existing width instead. Lane chrome is a per-lane SF Symbol (unknown names fall back leniently), title or untitled placeholder, a card-count badge that counts exactly what's rendered, and a new-card button — the whole title bar doubling as the drag surface, a plain click selecting the lane and movement carrying it away.
|
||||
- **Card faces** — a card reads as a leading SF Symbol, its title (or a quiet untitled placeholder), and a quiet paperclip when it has attachments — title-only by design, no body excerpt. Colour is an edge accent rather than a fill: `background` paints a stripe down the card's left edge and `iconColor` tints the symbol, both written as a kebab-case palette name (12 icon tints, 12 backgrounds) or a `#RRGGBB[AA]` hex. Everything degrades rather than complains — an unreadable colour simply doesn't paint, and the value stays on disk exactly as written. Each card's snapshot carries its attachment names, listed flat and in Finder order (top-level files only; subfolders, hidden files, and symlinks are preserved but never surfaced). A card has one presentation: selection changes only its styling, never its geometry, so the masonry never reflows on a click — the paperclip chip is the face's whole attachment story, and viewing the files themselves is the card window's job.
|
||||
- **Card faces** — a card reads as a leading SF Symbol, its title (or a quiet untitled placeholder), and a quiet paperclip when it has attachments — title-only by design, no body excerpt. Colour is an edge accent rather than a fill: `background` paints a stripe down the card's left edge and `iconColor` tints the symbol, the colour written either way as a kebab-case palette name (12 icon tints, 12 backgrounds) or a `#RRGGBB[AA]` hex — `background` as a mapping, `{color: fern}`, which is the one shape that field takes. Everything degrades rather than complains — an unreadable colour simply doesn't paint, and the value stays on disk exactly as written. Each card's snapshot carries its attachment names, listed flat and in Finder order (top-level files only; subfolders, hidden files, and symlinks are preserved but never surfaced). A card has one presentation: selection changes only its styling, never its geometry, so the masonry never reflows on a click — the paperclip chip is the face's whole attachment story, and viewing the files themselves is the card window's job.
|
||||
- **Creating and renaming** — New Card (⌘N) files into the selected card's lane immediately after it, a selected lane's bottom, or the last-active lane, opening a focused pseudo-card that exists nowhere on disk until its title commits (Return commits and re-selects the lane, ⌘↩ also opens the card window, Escape or clicking away discards, and a failed create discards rather than waiting for a card that can't arrive). Inline rename — Return on a card, Board ▸ Rename for either kind — tracks its target by UUID, so a foreign move mid-edit is invisible and a target that is trashed or deleted discards the edit silently; committing empty removes the `title` key rather than writing a blank one. New Lane is ⇧⌘N. Every mutating command disables while an editor holds the keyboard and under the read-only lock.
|
||||
|
||||
- **Drag & drop** — cards, in either container, and lanes all travel as real system drag sessions, so a drag crosses window boundaries, shows the system's own copy badge, and carries a full-size replica of what it picked up. A dashed shadow sits at the exact landing spot and the board reflows to make room; the proposal is pure geometry over an analytically reconstructed resting layout — never measured mid-animation frames — so the shadow is stable rather than jittery, and a lane only reflows once the cursor reaches where the dragged run would actually land, holding its last proposal across the ambiguous stretch in between. Dragging any member of a multi-selection drags the whole selection: N contiguous shadows, one insertion point, landing in flatten order. Locality picks the default the way Finder's volumes do — within a board a drag moves, between boards it copies, with ⌥ forcing copy and ⌘ forcing move and the badge tracking live as the cursor crosses a boundary; a lane reordering inside its own board ignores ⌥ entirely, and a lane carries exactly its cards either way, since the trash is board-level and there is nothing lane-nested to strip. Dragging a trash card onto a lane restores it at the drop position — an ordinary move — while dropping it on another board follows the same copy default every cross-board drag does, ⌘ forcing the true restore-move. The same gesture runs the other way: dropping a live card on the shown trash deletes it, exactly as ⌫ would, with the shadow always taking the topmost row — which the rank minting makes honest rather than arbitrary: every arrival really does land above the current top. A lane drag proposes the same delete over the column, and a trashed lane row drags back out to a strip slot the way a trash card drags back into a lane; a foreign board's item isn't deliverable there and neither is ⌥, since copying into the trash isn't a thing. Lanes taller than their viewport autoscroll from either edge, re-resolving the landing spot on every step so a stationary cursor still lands where the shadow shows. A foreign edit mid-drag re-grounds the drag rather than corrupting the drop: the zones re-derive against each new snapshot, a proposal whose lane was deleted withdraws and a release with none simply cancels, and a drag whose items all vanish dissolves itself. At release the board keeps drawing the dropped arrangement until the write round-trips through the watcher, so nothing snaps back for a frame; every drop is one write bracket — one reload, one commit — whatever the set's size. Files dragged in from Finder join the same dispatch: dropped on a card they copy into its `attachments/` (any type, multi-file, Finder-style renames on collision, the card highlighting while hovered), dropped on lane empty space they become one card per file — titled with the filename minus its extension, that file attached, landing at the drop position with a shadow per card. The trash column and its cards are inert to them, and a read-only board or an open inline editor refuses them outright.
|
||||
@@ -23,7 +23,7 @@ Lanework is in early development. This list tracks what has actually shipped and
|
||||
|
||||
- **The clipboard** — ⌘X/⌘C/⌘V move cards *and* lanes, within a board and across boards, so structure transfers without a mouse. It's a hybrid: the pasteboard carries a small manifest plus the titles as plain text, while the real content — whole folders, attachments and strays and all — is snapshotted into Application Support the instant you press ⌘C, so a copy captures the item as it was at that moment and survives the original being deleted, its volume unmounting, or the app quitting and relaunching. The store keeps exactly one snapshot: every copy and every launch sweeps whatever the pasteboard no longer points at. If a snapshot has gone missing by the time you paste, the manifest still carries each item's full `index.md`, so the paste lands with its content intact — and says so out loud, naming exactly what was left behind ("Pasted 'Fix login' without its 2 attachments") rather than leaving you to find an empty `attachments/` later. Cut is Finder-style deferred: the items dim in place and stay put until a paste moves them, voiding if another app takes the pasteboard or the source board closes (the paste then quietly becomes a copy), and voiding *per item* if one is deleted in the meantime — so a paste moves whatever survived, and a cut emptied down to nothing simply does nothing. Paste lands after the anchor card, at a selected lane's bottom, or at the last member of a multi-selection in flatten order — the same anchor ⌘N uses — and a lane payload lands after the anchor lane or at the board's right end, which is one of the two ways out of a board with no lanes at all. Copies keep `created` and take fresh identities throughout; a lane carries exactly its cards, copied or moved, because the trash is board-level and there is nothing lane-nested to strip; pasting a lane back into its own board is the within-board duplicate the drag deliberately doesn't offer. The clipboard works on trash cards like on any card — ⌘C yields a live copy wherever you paste it, and ⌘X in the trash followed by ⌘V is the keyboard-native restore, a card into a lane and a trashed lane row after the anchor lane — while paste never targets the trash itself, and the read-only lock blocks cut without ever blocking copy, because copying out is a read.
|
||||
|
||||
- **Styling** — one style editor serves every anchor: a background grid of the twelve palette wells behind a leading None well that *removes* the key, and a curated grid of five dozen kanban-relevant SF Symbols behind a leading level-default well that does the same. It is selection-aware (the selected cards or lanes; the board with nothing selected) and states the current value per dimension across the whole target set — agreement selects a well, disagreement reads "—", and a hand-written hex or uncurated symbol states itself verbatim outside the grids, replaced by any well you choose. A batch applies as one bracketed commit that skips every target already carrying the value, and the open editor tracks its targets live: one deleted out from under it leaves the set, and the last one closes the editor rather than quietly retargeting the board. Reached from Board ▸ Style… (⌥⌘S) or a card's or lane's context menu, where a compact row of app-wide recent colours recolours in one click and a lane's menu also carries its width stepper. Colour renders at all three levels — a card's `background` as a left-edge stripe, a lane's as a full-width band along its top edge, the board's as the window's content background — each painting nothing at all when the value doesn't resolve, bytes on disk untouched.
|
||||
- **Styling** — one style editor serves every anchor: a background grid of the twelve palette wells behind a leading None well that *removes* the key, and a curated grid of five dozen kanban-relevant SF Symbols behind a leading level-default well that does the same. It is selection-aware (the selected cards or lanes; the board with nothing selected) and states the current value per dimension across the whole target set — agreement selects a well, disagreement reads "—", and a hand-written hex or uncurated symbol states itself verbatim outside the grids, replaced by any well you choose. A batch applies as one bracketed commit that skips every target already carrying the value, and the open editor tracks its targets live: one deleted out from under it leaves the set, and the last one closes the editor rather than quietly retargeting the board. Reached from Board ▸ Style… (⌥⌘S) or a card's or lane's context menu, where a compact row of app-wide recent colours recolours in one click and a lane's menu also carries its width stepper. Colour renders at all three levels — a card's `background` as a left-edge stripe, a lane's as a full-width band along its top edge, the board's as the window's content background — each painting nothing at all when the value doesn't resolve, bytes on disk untouched. **A board can also wear a picture.** `background` is a mapping at every level — `{color: fern}` on a card or a lane — and a board's may name an image beside its colour: `background: {color: "#112233", image: art/sunset.jpg}` paints that image over that colour, scaled to fill, across the **whole window**: the content runs under a transparent title bar with a frosted strip keeping the toolbar and the board-name widget legible on top of it. The path is relative to the board folder, so the picture travels with the document when it is copied, zipped or synced (an absolute path, or one climbing out of the folder, simply paints nothing). Either half may stand alone, the colour shows through while a large photograph decodes off the main thread, and replacing the file in Finder swaps the backdrop live. There is no picker for it — like a hand-written hex, the raw file is the escape hatch — and a board with no background of its own keeps the standard window chrome exactly as before.
|
||||
|
||||
- **The trash** — deleting a card **moves** it: its folder travels into the board's reserved `.trash/`, always landing at the top, and View ▸ Show Trash reveals a trailing column where those cards live. A trashed card is an ordinary card in a special place — the same card face, the same colour stripe, the same attachments chip, the same search, the same selection, the same clipboard — so `.trash/` is self-describing in Finder and to agents, and there is no tombstone flag anywhere. **Lanes delete into the trash too**: the folder travels subtree-intact and shows as one distinct dimmed row carrying its title and held-card count — an opaque unit that never expands, whose cards aren't individually addressable, and which restores whole or purges whole (its confirmation counting the cards it would take with it). The column takes exactly one width unit while shown, so showing it re-divides the window rather than resizing it, and its newest-first order falls out of ordinary ranks with no timestamp sort. There is no Put Back: restore by dragging a card out into any lane at any position, or ⌘X in the trash and ⌘V into a lane — both are ordinary moves, so a restored card lands where you put it. Drop a live card on the column to delete it — the pointer's twin of ⌫, writing the identical move, and its shadow always takes the top row because that is genuinely where the card lands. Delete is one vocabulary staged by place: ⌫/⌘⌫ moves a board card to the trash and deletes a trash card permanently, and ⇧⌘⌫ Empty Trash… purges the whole container — each confirmed where the loss is real, named by count, and Empty Trash always covers the whole trash, never just what a filter is showing. Nothing edit-shaped — Open, Rename, Style…, Finder file drops — applies to a trash selection, and a selection never mixes trashed with live.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user