Add a dedicated card view; make card text no longer inline-editable

Clicking a card -- in the "all tasks" list, a kanban column, or the
inbox -- now opens /cards/:id instead of editing the text in place:

- CardRow's text is now plain (its RouterLink wraps the text + status
  badge; the delete button stays a sibling so it isn't nested inside
  the link). KanbanCard is now itself a RouterLink.
- New CardView.vue: header follows the project view's layout, but the
  back link sits inline inside the title (before the card's text)
  rather than off in the actions corner, since it isn't paired with a
  manage menu here. Inbox cards have no project to link back to, so
  they go to the dashboard instead. Below the header, an "Edit text"
  section (styled like the project rename form) replaces the inline
  editing that used to live in the list row, and a delete button in
  the header actions replaces CardRow's per-row delete for cards
  reached via kanban/inbox (which never had one).
- No backend changes: GET/PATCH/DELETE /cards/{id} already existed.
- Renamed .card-row__status to the more general .status-badge, now
  shared by the list row and the card view.
- cards store: dropped setText, now unused now that editing goes
  through a direct PATCH + store refresh in CardView instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-04 23:51:06 +01:00
co-authored by Claude Sonnet 5
parent c2c988d928
commit fb329bf693
7 changed files with 211 additions and 66 deletions
+50 -26
View File
@@ -48,9 +48,7 @@
}
/* No browser focus ring on form controls -- the border colour change is
highlight enough (components with more elaborate focus styles, e.g.
.card-row__text, override this with their own higher-specificity rule).
Specificity is a single pseudo-class + element, (0,0,1,1) -- .field below
highlight enough. Specificity is a single pseudo-class + element, (0,0,1,1) -- .field below
is deliberately a single class with no element in the selector, (0,0,1,0),
so it can never win a specificity tie against this regardless of source
order (a wrapper-class + descendant-element rule, e.g. the old ".form
@@ -550,7 +548,34 @@ h1 {
background: var(--surface);
}
.card-row__status {
/* Wraps the text + status badge -- the whole row is a link to the card's own
view, except the delete button (a sibling, so it isn't nested inside it). */
.card-row__link {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.3rem 0.4rem;
border-radius: var(--radius-sm);
color: inherit;
text-decoration: none;
}
.card-row__link:hover {
background: var(--bg);
}
.card-row__text {
flex: 1;
min-width: 0;
font-size: 1rem;
word-break: break-word;
}
/* A small pill naming a card's status -- the card list row and the card's
own view both show one. */
.status-badge {
flex: none;
padding: 0.15rem 0.55rem;
border-radius: var(--radius-pill);
@@ -562,32 +587,11 @@ h1 {
color: var(--muted);
}
.card-row__status--none {
.status-badge--none {
font-weight: 400;
font-style: italic;
}
.card-row__text {
flex: 1;
min-width: 0;
border: 1px solid transparent;
border-radius: var(--radius-sm);
background: transparent;
color: var(--text);
font-size: 1rem;
padding: 0.3rem 0.4rem;
}
.card-row__text:hover {
border-color: var(--border);
}
.card-row__text:focus {
outline: none;
border-color: var(--accent);
background: var(--bg);
}
.card-row__delete {
flex: none;
border: none;
@@ -649,6 +653,19 @@ h1 {
text-decoration: none;
}
/* The card view's back link sits inside its title, right before the card's
text, rather than up in .project-head__actions like the other views. */
.card-view__back {
display: inline-flex;
margin-right: 0.4rem;
color: var(--muted);
text-decoration: none;
}
.card-view__back:hover {
color: var(--accent);
}
.menu {
position: relative;
flex: none;
@@ -889,14 +906,21 @@ h1 {
}
.kanban-card {
display: block;
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-md);
padding: 0.55rem 0.65rem;
font-size: 0.9rem;
color: inherit;
text-decoration: none;
cursor: grab;
}
.kanban-card:hover {
border-color: var(--accent);
}
.kanban-card--ghost {
opacity: var(--opacity-ghost);
}