Task modal
Source: atrium/frontend/src/components/TaskModal.jsx Category: Composite component
Task modal — the full-task view opened from a kanban card. Sections are tabbed (details / comments / history / raw) rather than stacked, because a task file frequently has hundreds of lines of comment history and you don’t want to scroll past it to edit the title.
What it is
Section titled “What it is”A modal (or right-side panel depending on the viewport) with a task header and four tabs. Each tab owns a chunk of the task’s state; switching tabs doesn’t refetch. Edits in any tab save on blur or on an explicit save button (tab-dependent).
Why it exists
Section titled “Why it exists”The card shows a task at a glance. The modal is for doing real work on it. Historically Atrium had one big scrolling view that crammed the activity log under the description; once a task accumulated 30+ comments it became unusable. Tabs split the concerns.
Add light mode toggle to portfolio website. Respect prefers-color-scheme on first load. Persist user choice in localStorage. No flash of wrong theme on page load (inline script in head).
- Details — description, tags, assignee, files_affected, priority. Inline-editable.
- Comments — the structured nested-bullet comments from agents, plus a markdown editor for new comments.
- History — reverse-chronological
activity_logentries. Read-only. - Raw — the underlying YAML frontmatter, formatted. Read-only. Useful for debugging.
Code sketch
Section titled “Code sketch”const tabs = ['details', 'comments', 'history', 'raw'];
export default function TaskModal({ task, onSave, onClose }) { const [active, setActive] = useState('details'); return ( <Modal onClose={onClose}> <Header task={task} /> <Tabs tabs={tabs} active={active} onChange={setActive} /> <Body> {active === 'details' && <DetailsTab task={task} onSave={onSave} />} {active === 'comments' && <CommentsTab task={task} onSave={onSave} />} {active === 'history' && <HistoryTab task={task} />} {active === 'raw' && <RawTab task={task} />} </Body> </Modal> );}How it’s used
Section titled “How it’s used”- Atrium — click a task card to open; URL-routed at
/task/:idso links work - Pattern generalizes to any record-with-history editor (bookmarks, invoices, support tickets)
Gotchas
Section titled “Gotchas”- Tab state belongs to the modal, not the URL. Putting the active tab in the URL sounds nice but makes the back button behave weirdly (open modal → switch tabs → back exits the modal) unless you’re careful with history state.
- Save on blur + unsaved-changes warning. Users expect changes to persist silently. Warn only if they close the modal with dirty fields.
- Comments tab is a markdown editor, not an input. Agent comments have structure (nested bullets). A plain
<textarea>is fine; a WYSIWYG editor is a trap if the underlying format is markdown. - History is capped by virtualization. Very long activity logs slow initial render. Render the most recent N entries, with “show older” to load the rest.
- Raw tab is debug-only. Don’t make it editable — the backend invariants (see agent-task-board-protocol) assume the frontmatter is API-managed, not user-hand-edited.
- Modal vs side panel. On desktop, a right-side panel sits next to the board. On mobile, it’s a full-screen modal. One component handling both requires careful CSS; two components share most of their guts.
See also
Section titled “See also”- components/task-card — the entry point to this modal
- components/board — the container
- patterns/activity-log-in-yaml-frontmatter — what the History tab renders