Session notes and tasks
A React block (a whole screen) in Beamline's Clinic app.
A session's note beside its follow-up tasks, each task tied to the exact words it came from: choose a task and its words light in the note or the transcript with the link drawn between them, and the note's margin names the tasks each paragraph is evidence for. Suggested tasks wait to be confirmed or dismissed; a paragraph is edited in place and saved as the note's next version; words the note no longer has are said, with the words the task kept, never replaced by a guess, and new words are chosen by clicking a sentence or selecting any words. The past sessions the next note may draw on are chosen against a limit and sent exactly; All open lists every open task of the client across sessions, each opening in its own session. While a paragraph is edited, saved snippets go in at the caret: a shorthand typed before the caret, or a phrase said through the app, shows the snippet and where it lands before it is inserted; Undo snippet takes out exactly its words while they are unchanged; an unrecognised phrase is said, and a new snippet whose phrase or shorthand another already has is refused. An open task reads its kind, owner (with their picture) and due date as values, each opening its own list or calendar.
Use it for
- Reviewing what an AI or a colleague drafted from a session (a clinical note, a coaching or legal consultation, a research interview) with the follow-ups it proposes, where each follow-up must point at the words that justify it.
- Practitioners finishing a session: confirm, edit and assign follow-ups, check each against its evidence, and choose which earlier sessions the next draft may draw on.
Not for
- A recorded meeting with its summary, chapters and talk time (meeting-review).
- Background work an agent is running (task-rows).
- The chunks an agent retrieved for one answer (context-cards).
- A team's task board by status (project-board).
Anatomy
- header: the client (avatar, name), the open session's title, date, length and place; a session select; the past-sessions button with its slots; Rewrite the note when the chosen past sessions differ from what the note drew on
- drew-on line: what the note was written with ("Written with 1 past session: Thu 22 Oct"), or what the next note will draw on
- source pane: Note and Transcript tabs with the note's version; the note by section, each paragraph with its evidence marked (dashed under a suggested task's words, solid under a confirmed one's) and a margin of tags naming the tasks it is evidence for by kind; a transcript by turn (speaker, time, words) marked the same way; a paragraph whose words a task lost carries the warning edge and its task's tag keeping the kind, dashed in the warning tone
- editing a paragraph: Edit in its margin (shown with attention, always on touch) turns it into a field with Cancel and Save; Save makes the note's next version; a refusal keeps the typed words with the reason and Retry
- link: a line drawn from the chosen task's words to its card (dashed in the warning tone to a paragraph that changed); none at rest without a choice, on a phone or while words are being chosen
- tasks pane: This session and All open with their counts; Suggested (with Confirm and a menu holding Edit and Dismiss), To do (a box to tick off) and Done; each card the task, its kind, owner, due date (Was due when late, the date on the warning tint) and where it came from in a word (the note's section, the transcript's speaker and time, Added by hand, or Evidence changed or removed in amber with the warning icon, or Transcript unavailable, quiet with its own icon); a dismissed suggestion stays as one line with Undo; Add task
- open card: the task's text to edit in place, Kind, Owner and Due, and Where it came from: the words, Show in the note (phone) and Choose new words or Link words
- choosing words: a bar naming the task with Cancel; every sentence a target; a selection of any words offers Link these words beside it
- past sessions: the client's earlier sessions as a checklist with date, length and place; the limit as slots and N of M chosen; a session of another client or whose note can't be used, disabled with its reason; a choice past the limit refused in words; blocked: the reason in place of the list
- snippets (in the paragraph editor): the pending snippet (how it was asked for, the words it lands after, its text, Cancel and Insert), Say a snippet, Undo snippet, New snippet (shorthand, spoken phrase, text, Add) and a hint of how many there are
States
- suggested (dashed under its words, Confirm)
- confirmed (to do, a box to tick)
- done (struck through, in Done)
- dismissed (one line with Undo)
- chosen: words lit, link drawn, card open
- evidence changed (the paragraph is there, the words are not: the warning edge, the task's kind dashed amber in the margin, the dashed amber line to the paragraph, the words the task kept, Choose new words); words that only moved, in their paragraph or whole into another, stay found
- evidence removed (the paragraph is gone)
- editing a paragraph (the field, Cancel, Save; Escape cancels, Ctrl or ⌘ Enter saves)
- note save refused (the typed words kept, the reason, Retry)
- source unavailable (a transcript that wasn't kept: quiet, its own icon, no warning)
- added by hand (no evidence, Link words)
- choosing words (sentences, a selection, Cancel)
- saving (Saving… on the card)
- save refused (the change put back, the reason, Retry)
- past sessions: none chosen, some chosen, limit reached (refused in words), unavailable session, another client's session, blocked
- context changed (the next note's sources said, Rewrite the note)
- writing the note (shaped skeleton, what it draws on, seconds so far; tasks wait)
- rewrite refused (the old note stays, the reason, Try again)
- no tasks (empty state with Add task)
- all open (by session, searchable; no match; nothing open)
- phone: Note and Tasks take turns; Show in the note and Back to the task
- snippet offered by its shorthand (Tab inserts), heard by its phrase (Insert), unrecognised phrase, listening, listening refused
- snippet inserted (Undo snippet), its words edited since (undo by hand)
- new snippet refused: phrase or shorthand already used
Keyboard
- Tab through the header, the panes' tabs and views, the note's margin tags and the task cards
- a margin tag or a card: Enter chooses its task (the card opens; again closes it)
- a paragraph's Edit (in its margin, in the tab order): Enter opens the field; Ctrl or ⌘ Enter saves, Escape cancels
- the divider between the panes: ←/→ resize, Enter folds
- choosing words: Tab to a paragraph, ←/→ (or ↑/↓) step through its sentences (said with their number), Enter links the sentence, Escape cancels
- a selection made with the pointer offers Link these words, a button in the tab order
- past sessions: Space ticks a session; a tick past the limit is refused and said
- in the paragraph editor: Tab inserts the offered snippet, Escape dismisses it (a second Escape cancels the edit)
Motion
A saved edit re-checks every task's words in the frame it lands (a lost task's line turns dashed amber at once). A new choice brings the words and the card into view (a smooth scroll, instant under reduced motion), lights the words on the motion tokens and draws the link in from the words in the considered duration; the link follows a scroll or a resize on the next frame and fades away when the choice ends; cards open in place with a short fade while the others slide to their new places (FLIP); the slots fill on the motion tokens. Nothing runs at rest: no frame loop, timer or observer beyond the room's resize observer.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
client (required) | { id: string; name: string } | — | The client; `photo` is their picture (initials without one). |
sessions (required) | Session[] | — | The client's sessions, newest first. A session of another client (a record linked by mistake) is listed for what it is and never offered as context. |
kinds (required) | TaskKind[] | — | Kinds of task in your app's words; the first is the default for a new task. |
people (required) | Person[] | — | Who a task can be given to. |
sessionId | string | — | The session open on screen. Default: the newest. |
defaultSessionId | string | — | |
onSessionChange | ((id: string) => void) | — | |
tasks | SessionTask[] | — | Every task of the client's sessions (the open session's are shown beside its note; All open lists the rest). |
defaultTasks | SessionTask[] | — | |
onTasksChange | ((tasks: SessionTask[]) => void) | — | The whole list after each change, at once (optimistic); a refused save puts the task back. |
onTaskChange | ((task: SessionTask, previous: SessionTask | null) => void | Promise<unknown>) | — | Saves one task (`previous` null: a task added by hand). Return a promise to show progress; reject (with an Error whose message says why) to refuse: the task goes back and its card says why, with Retry. |
me | string | — | The signed-in person's id: their tasks say You. |
selectedTask | string | null | — | The task open beside the note. |
defaultSelectedTask | string | null | — | |
onSelectedTaskChange | ((id: string | null) => void) | — | |
view | "open" | "session" | — | This session's tasks, or every open task of the client. |
defaultView | "open" | "session" | — | |
onViewChange | ((view: "open" | "session") => void) | — | |
context | string[] | — | The past sessions (ids) the next note of the open session will draw on. Default: what its note drew on. |
defaultContext | string[] | — | |
onContextChange | ((ids: string[]) => void) | — | |
contextLimit | number | — | How many past sessions a note may draw on. Default 3. |
contextBlocked | string | null | — | Why this person can't choose past sessions (their access was removed); omit when they can. |
onRegenerate | ((request: { sessionId: string; contextIds: string[]; }) => void | Promise<unknown>) | — | Rewrite the open session's note with exactly these past sessions. Resolve when the new note (and its suggested tasks) is in `sessions` and `tasks`; reject with the reason to keep the old note and say why. |
generating | boolean | — | The note is being written outside this screen (a note still on its way after the session). |
today | string | — | "2026-10-30": the day late due dates count from. Default: today in the browser. |
className | string | — | Classes on the documented visual root; no override by default. |
style | CSSProperties | — | Inline styles on the documented visual root; no overrides by default. |
ref | Ref<HTMLDivElement> | — | Receives the documented native target or imperative handle; omitted by default. |
onNoteChange | ((change: { sessionId: string; paragraphId: string; text: string; version: number; }) =… | — | Saves an edit of one paragraph of the open session's note as its next version. Resolve once the new note is in `sessions` (every task's words are looked up again in it: a task whose words are gone says Evidence changed); reject with the reason to keep the editor open with the typed words and Retry. Without it the note is read-only. |
snippets | Snippet[] | — | Saved text for the paragraph editor: a shorthand typed then Tab, or a phrase said. |
defaultSnippets | Snippet[] | — | |
onSnippetsChange | ((snippets: Snippet[]) => void) | — | |
onListen | (() => Promise<string>) | — | Listens through the app's speech service and resolves with the phrase heard; reject with the reason. |
Built from
- resizable-panels
- tabs
- segmented-control
- popover
- checkbox
- select
- date-picker
- inline-edit
- dropdown-menu
- search-field
- avatar
- button
- empty-state
- skeleton
- input
Dependencies
lucide-react
Import
import { SessionNotes } from "@beamline/session-notes";
Get it
Session notes and tasks is part of Beamline UI. Install the parts you need in your React app as compiled packages or editable source. Get Beamline · Connect your agent
More in Clinic
- Appointment book: The desk's day with the appointment editor beside it. The appointment being edited is a block on the day like any other, drawn in the accent while it is…
- Book an appointment: A client books an appointment on the practice's own site: a service (length and price beside it), who gives it or anyone free, and where; a day with…
- Services and hours: A practice's services and the hours its practitioners can be booked, one relation seen from both ends. A service reads as values and changes on demand…
- Patient overview: One patient's record on a page. A search finds patients by name, chart number or birth date (recent patients when empty; same names told apart by birth…
- Patient chart: A clinic's chart for one client and their animals. The client's header (phone, email, contact preferences, the balance with what it means and as of when…
- Health questionnaire: A patient's medical history as a versioned questionnaire. Every question takes Yes, No or I don't know, and one not answered says so, never read as No; a…
- Case workspace: A patient's clinical cases and how cases work at the practice. A case shows its status, type, teeth, staff, location and start; its checklist counts…
- Care plan: A client's care plan composed beside what the client will see of it. Every field says who sees it (the care team only, or the client too) and the…
- Treatment plan: A patient's treatment plan in named phases. Each procedure shows its tooth, status and fee beside the patient's and the insurer's estimate (not known…
- Plan templates: Reusable treatment-plan templates. A template reads as words at rest and changes on demand: its name edits in place; the status its procedures start as…
- Plan acceptance: A treatment plan presented for acceptance, from both sides. The practice chooses the agreement (the account's default or this location's own) and how…
- Plan follow-up: The practice's follow-up lists, for the person who turns accepted treatment into booked chairs. Treatment plans lead with what's at stake: the value…
- Note templates: A practitioner's note templates in one library with three ways in. My templates lists their own by kind, favourites first, each with when it was last…
- Probing chart: A periodontal probing chart. Six sites per tooth (three buccal, three lingual) across both arches as you face the patient, each depth in its cell and…
- Procedure picker: Procedures, conditions and bundles put on a patient's teeth from the chair. The mode (existing, planned, completed) is chosen before adding and each…
- Results notebook: A notebook entry's structured results. The entry's text above a bounded results table with typed columns: a sample link, numbers in their unit with their…
- Insurance claims: Insurance claims as a queue: every claim at first, in the order a person works them (rejected by the clearinghouse, denied by the payer, partly paid, not…
- Account ledger: A patient's account. All transactions or the ones needing attention, each dated with its type in a word, its amount and the running balance; entries that…
- Dispensing: Dispensing from the shelf by lot. A product is found with its stock and prices (consumables left out unless asked); the quantity is drawn across its…
- Record sharing: Records sent out of a clinic. Several visits' records and their documents (record, invoice, plan, lab result, image) are chosen separately, with how much…
- Client journal: A client's journal from both ends. The client's side is their home, built around their day: today's goals with how many are done and a mark each, done…