Exosphere is a set of small, modular, self-hostable community tools built on the AT Protocol. app.exosphere.site
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

ui: rework kanban task card layout for consistency with feature requests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Hugo ad9a45c2 0025ecd3

+54 -51
+54 -51
packages/kanban/src/ui/pages/task.tsx
··· 557 557 </div> 558 558 ) : ( 559 559 <> 560 - <div class={ui.metaRow}> 561 - <span class={ui.muted}>#{task.number}</span> 562 - {task.assigneeHandle && <span class={ui.muted}>@{task.assigneeHandle}</span>} 563 - <span class={ui.muted}>{formatDate(task.createdAt, fullDateOpts)}</span> 564 - </div> 565 - <h2 class={ui.cardTitle}>{task.title}</h2> 566 - <div class={ui.metaRow}> 567 - <span class={ui.muted}>by {task.authorHandle ?? task.authorDid}</span> 568 - {canEdit && ( 569 - <button class={ui.buttonInline} onClick={startEdit}> 570 - Edit 571 - </button> 572 - )} 573 - {(isAuthor || canManage.value) && ( 574 - <button class={ui.buttonDangerInline} onClick={handleDelete}> 575 - Delete 576 - </button> 577 - )} 578 - {canModerate.value && !isAuthor && ( 579 - <button class={ui.buttonDangerInline} onClick={handleHide}> 580 - Hide 581 - </button> 582 - )} 583 - </div> 584 - 585 - <div class={ui.metaRow}> 586 - <span class={ui.muted}>Status:</span> 587 - {canChangeStatus.value ? ( 588 - <select 589 - class={kbUi.statusSelect} 590 - value={localStatus.value ?? task.status} 591 - onChange={(e) => handleStatusChange((e.target as HTMLSelectElement).value)} 592 - > 593 - {cols.map((col) => ( 594 - <option key={col.slug} value={col.slug}> 595 - {col.label} 596 - </option> 597 - ))} 598 - </select> 599 - ) : ( 600 - <span class={ui.badge}> 601 - {statusLabel(localStatus.value ?? task.status, cols)} 602 - </span> 603 - )} 560 + <div class={ui.row}> 561 + <h2 class={ui.cardTitle}> 562 + <span class={ui.muted}>#{task.number}</span> {task.title} 563 + </h2> 564 + <div class={ui.cluster}> 565 + {canEdit && ( 566 + <button class={ui.buttonInline} onClick={startEdit}> 567 + Edit 568 + </button> 569 + )} 570 + {(isAuthor || canManage.value) && ( 571 + <button class={ui.buttonDangerInline} onClick={handleDelete}> 572 + Delete 573 + </button> 574 + )} 575 + {canModerate.value && !isAuthor && ( 576 + <button class={ui.buttonDangerInline} onClick={handleHide}> 577 + Hide 578 + </button> 579 + )} 580 + {canChangeStatus.value ? ( 581 + <select 582 + class={kbUi.statusSelect} 583 + value={localStatus.value ?? task.status} 584 + onChange={(e) => 585 + handleStatusChange((e.target as HTMLSelectElement).value) 586 + } 587 + > 588 + {cols.map((col) => ( 589 + <option key={col.slug} value={col.slug}> 590 + {col.label} 591 + </option> 592 + ))} 593 + </select> 594 + ) : ( 595 + <span class={ui.badge}> 596 + {statusLabel(localStatus.value ?? task.status, cols)} 597 + </span> 598 + )} 599 + </div> 604 600 </div> 605 601 606 602 {canManage.value && availableLabels.value.length > 0 ? ( ··· 610 606 onToggle={handleLabelToggle} 611 607 /> 612 608 ) : task.labels.length > 0 ? ( 613 - <div class={ui.metaRow}> 614 - <span class={ui.muted}>Labels</span> 615 - <div class={ui.cluster}> 616 - {task.labels.map((label) => ( 617 - <LabelBadge key={label.id} label={label} /> 618 - ))} 619 - </div> 609 + <div class={ui.cluster}> 610 + {task.labels.map((label) => ( 611 + <LabelBadge key={label.id} label={label} /> 612 + ))} 620 613 </div> 621 614 ) : null} 615 + 616 + <div class={ui.metaRow}> 617 + <span class={ui.muted}> 618 + {task.authorHandle ? `@${task.authorHandle}` : task.authorDid} 619 + </span> 620 + {task.assigneeHandle && ( 621 + <span class={ui.muted}>→ @{task.assigneeHandle}</span> 622 + )} 623 + <span class={ui.muted}>{formatDate(task.createdAt, fullDateOpts)}</span> 624 + </div> 622 625 </> 623 626 )} 624 627 </div>