Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions docs/implementation-notes/card-execution-supplement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Card execution supplement

Date: 2026-07-31

## Intent

`jtype-board-react` hosts such as jcode Cloud need to show execution receipts
next to a Card without replacing the native Card editor. The package now exposes
an additive `renderCardSupplement(card)` slot for that purpose.

The host owns the supplement content and data. jtype continues to own Card
title, description, status, properties, relations, comments, save behavior, and
optimistic concurrency.

## Public contract

- `JTypeBoardProps.renderCardSupplement?: (card: BoardViewCard) => ReactNode`
- The slot renders after native Properties and Relations in the built-in
editable Card detail.
- It does not render for the explicit `readOnly` detail.
- It does not render when `onCardOpen` intercepts the built-in detail.
- Omission is a no-op.

The slot flows through the shared component contract:

`JTypeBoard → BoardSurface.renderCardSupplement → BoardPeek.supplement`.

There are no Desktop/Web/Cloud platform conditionals.

## Feature impact matrix

| Surface | Behavior | Verification |
| --- | --- | --- |
| Desktop board | No change when the slot is omitted | Desktop build + shared board tests |
| Web board | No change when the slot is omitted | Web build + shared board tests |
| Editable `jtype-board-react` embed | Native editor plus optional host supplement | Package Playwright fixture |
| Read-only package embed | Existing non-mutating detail; no supplement | Package Playwright fixture |
| `onCardOpen` host | Host callback remains the only detail owner | Package Playwright fixture |
| Package API/artifact | New prop exported in `.d.ts`; bundle and README updated | Package build/typecheck |

## Test cases

1. The editable package detail retains Description and Properties and adds the
host supplement.
2. The read-only package detail does not render the editable supplement.
3. `onCardOpen` interception does not render the supplement.
4. Existing package editor tests continue to cover Card mutations and bounded
host layout.

## Release

Package version: `0.1.2`.
5 changes: 4 additions & 1 deletion packages/board-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ The wrapper fills its container — **give the parent element a height.**
| `live` | `boolean` | `true` | Try the live SSE feed; see *Live updates* below. |
| `pollIntervalMs` | `number` | `30000` | Polling cadence (min 5000). |
| `onCardOpen` | `(card: BoardViewCard) => void` | — | Intercept card opens; replaces the built-in read-only detail panel. |
| `renderCardSupplement` | `(card: BoardViewCard) => ReactNode` | — | Add host-owned content after native Properties and Relations in the built-in editable Card detail. It is not rendered for `readOnly` or intercepted opens. |
| `onConnectionChange` | `(s: 'live' \| 'polling' \| 'error') => void` | — | Observe transport state transitions. |
| `locale` | `'en' \| 'zh' \| 'ja' \| 'ko'` | `'en'` | Board chrome language. The lingui instance is bundle-wide, so multiple boards on one page share the last-set locale. |
| `className`, `style` | | — | Extra class/style for the wrapper element. |
Expand Down Expand Up @@ -142,7 +143,9 @@ read-only card detail, and localized chrome. Editable embeds use the shared
focused quick-create and card-detail dialogs, including description,
properties, relations, and sub-cards. Explicitly read-only embeds keep the
non-mutating detail; a host `onCardOpen` callback still replaces either
built-in path.
built-in path. Hosts that need execution receipts or other contextual data
without replacing the editor can use `renderCardSupplement`. The slot is
additive: jtype retains ownership of Card editing and mutations.
Not yet (flag-gated later): members/assignee options, versions/activity,
ticket badges (the `OCCSV-####` chip — the embed client has no ticket-index
endpoint, so cards never show it even when the board configures `ticketKey`),
Expand Down
8 changes: 7 additions & 1 deletion packages/board-react/dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CSSProperties } from 'react';
import { ReactElement } from 'react';
import { ReactNode } from 'react';

/** Shape of the `.board` JSON config document (mirrors WebBoardView). */
export declare type BoardConfigJSON = BoardDocumentConfig;
Expand Down Expand Up @@ -165,7 +166,7 @@ export declare class JTypeApiError extends Error {
* `client`) plus `workspaceId`+`boardRef` and it renders the same shared
* BoardSurface the jtype desktop + web apps use, backed by the document API.
*/
export declare function JTypeBoard({ workspaceId, boardRef, baseUrl, token, client: injectedClient, readOnly, currentUser, live, pollIntervalMs, onCardOpen, onConnectionChange, locale, className, style, }: JTypeBoardProps): ReactElement;
export declare function JTypeBoard({ workspaceId, boardRef, baseUrl, token, client: injectedClient, readOnly, currentUser, live, pollIntervalMs, onCardOpen, renderCardSupplement, onConnectionChange, locale, className, style, }: JTypeBoardProps): ReactElement;

export declare type JTypeBoardConnection = 'live' | 'polling' | 'error';

Expand Down Expand Up @@ -235,6 +236,11 @@ export declare type JTypeBoardProps = {
pollIntervalMs?: number;
/** Intercept card opens (replaces the built-in editable/read-only detail). */
onCardOpen?: (card: BoardViewCard) => void;
/**
* Add host-owned content after native Properties and Relations without
* replacing jtype's editor. Not rendered for read-only or intercepted opens.
*/
renderCardSupplement?: (card: BoardViewCard) => ReactNode;
/** Observe live/polling/error transitions. */
onConnectionChange?: (state: JTypeBoardConnection) => void;
/** Board chrome locale (default 'en'). Shared across instances (see README). */
Expand Down
Loading
Loading