From 3127bf17f3fa7eade7d7c97ff7e314c364acde9e Mon Sep 17 00:00:00 2001 From: Brian Love Date: Mon, 9 Nov 2026 10:01:01 -0800 Subject: [PATCH] feat(react): support compact message action icons --- .../api/react/chat/MessageAction-ui79k6.json | 85 ++++- .../api/react/chat/MessageActions-szwf67.json | 4 +- .../chat/MessageActionsProps-e1ki9v.json | 12 +- .../react/chat/components/chat-message.mdx | 33 +- .../native/e2e/inline-source-previews.spec.ts | 12 + .../chat/native/e2e/message-actions.spec.ts | 39 +++ .../native/e2e/message-presentation.spec.ts | 39 +++ .../native/react/src/copy-answer.spec.tsx | 31 ++ .../chat/native/react/src/copy-answer.tsx | 22 +- .../runtime/message-action-types.tsx | 55 +++ .../react-message-action-icons-styled.tsx | 2 + .../runtime/react-message-action-icons.tsx | 50 +++ libs/react/README.md | 61 +++- libs/react/src/chat/message-actions.spec.tsx | 328 ++++++++++++++++++ libs/react/src/chat/message-actions.tsx | 47 ++- .../src/chat/message-actions.type-test.tsx | 94 ++++- libs/react/src/chat/styles.css | 28 ++ .../src/markdown/inline-preview.spec.tsx | 127 +++++++ libs/react/src/markdown/inline-preview.tsx | 33 +- scripts/react-parity/baseline.json | 22 +- scripts/react-parity/dispositions.json | 20 +- scripts/react-parity/runtime-consumer.mjs | 187 +++++++++- .../react-parity/runtime-consumer.spec.mjs | 20 +- .../verify-langgraph-candidate.mjs | 10 +- 24 files changed, 1280 insertions(+), 81 deletions(-) create mode 100644 fixtures/react-parity/runtime/message-action-types.tsx create mode 100644 fixtures/react-parity/runtime/react-message-action-icons-styled.tsx create mode 100644 fixtures/react-parity/runtime/react-message-action-icons.tsx diff --git a/apps/website/content/api/react/chat/MessageAction-ui79k6.json b/apps/website/content/api/react/chat/MessageAction-ui79k6.json index 322bcfd8b..eaa41d831 100644 --- a/apps/website/content/api/react/chat/MessageAction-ui79k6.json +++ b/apps/website/content/api/react/chat/MessageAction-ui79k6.json @@ -60,7 +60,80 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 8 + "line": 10 + }, + "isReadonly": true, + "isOptional": true + }, + { + "name": "icon", + "kind": "PropertySignature", + "canonicalReference": "@threadplane/react!MessageAction#icon:member", + "excerptTokens": [ + { + "kind": "Content", + "text": "readonly icon?: " + }, + { + "kind": "Reference", + "text": "ReactNode", + "canonicalReference": "@types/react!React.ReactNode:type" + }, + { + "kind": "Content", + "text": ";" + } + ], + "docs": { + "summary": "App-authored noninteractive decorative content; nullish and boolean values omit the icon.", + "remarks": "", + "deprecated": "", + "returns": "", + "examples": [], + "see": [], + "params": [], + "typeParams": [] + }, + "members": [], + "source": { + "path": "libs/react/src/chat/message-actions.tsx", + "line": 12 + }, + "isReadonly": true, + "isOptional": true + }, + { + "name": "iconOnly", + "kind": "PropertySignature", + "canonicalReference": "@threadplane/react!MessageAction#iconOnly:member", + "excerptTokens": [ + { + "kind": "Content", + "text": "readonly iconOnly?: " + }, + { + "kind": "Content", + "text": "boolean" + }, + { + "kind": "Content", + "text": ";" + } + ], + "docs": { + "summary": "Visually hides the label with opt-in styles when true and an icon is supplied.", + "remarks": "", + "deprecated": "", + "returns": "", + "examples": [], + "see": [], + "params": [], + "typeParams": [] + }, + "members": [], + "source": { + "path": "libs/react/src/chat/message-actions.tsx", + "line": 14 }, "isReadonly": true, "isOptional": true @@ -96,7 +169,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 5 + "line": 7 }, "isReadonly": true, "isOptional": false @@ -132,7 +205,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 6 + "line": 8 }, "isReadonly": true, "isOptional": false @@ -168,7 +241,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 7 + "line": 9 }, "isReadonly": true, "isOptional": false @@ -176,12 +249,12 @@ ], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 4 + "line": 6 } } ], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 4 + "line": 6 } } diff --git a/apps/website/content/api/react/chat/MessageActions-szwf67.json b/apps/website/content/api/react/chat/MessageActions-szwf67.json index 0b1a6ac79..4ab64ad4c 100644 --- a/apps/website/content/api/react/chat/MessageActions-szwf67.json +++ b/apps/website/content/api/react/chat/MessageActions-szwf67.json @@ -58,7 +58,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 20 + "line": 26 }, "overloadIndex": 1, "parameters": [ @@ -87,6 +87,6 @@ ], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 20 + "line": 26 } } diff --git a/apps/website/content/api/react/chat/MessageActionsProps-e1ki9v.json b/apps/website/content/api/react/chat/MessageActionsProps-e1ki9v.json index 52a0b2cd9..bc0b3c7cf 100644 --- a/apps/website/content/api/react/chat/MessageActionsProps-e1ki9v.json +++ b/apps/website/content/api/react/chat/MessageActionsProps-e1ki9v.json @@ -70,7 +70,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 13 + "line": 19 }, "isReadonly": true, "isOptional": false @@ -106,7 +106,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 16 + "line": 22 }, "isReadonly": true, "isOptional": true @@ -142,7 +142,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 14 + "line": 20 }, "isReadonly": true, "isOptional": true @@ -178,7 +178,7 @@ "members": [], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 15 + "line": 21 }, "isReadonly": true, "isOptional": true @@ -186,12 +186,12 @@ ], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 12 + "line": 18 } } ], "source": { "path": "libs/react/src/chat/message-actions.tsx", - "line": 12 + "line": 18 } } diff --git a/apps/website/content/docs/react/chat/components/chat-message.mdx b/apps/website/content/docs/react/chat/components/chat-message.mdx index c7e702a2b..9f2c63710 100644 --- a/apps/website/content/docs/react/chat/components/chat-message.mdx +++ b/apps/website/content/docs/react/chat/components/chat-message.mdx @@ -11,6 +11,7 @@ This experimental, private React source-build component presents one message. It import type { MessageRow } from '@threadplane/content/messages'; import { ChatMessage, + MessageActions, MessageList, Reasoning, Citations, @@ -19,7 +20,10 @@ import { import { Markdown } from '@threadplane/react/markdown'; import '@threadplane/react/chat/styles.css'; -export function StandaloneMessage({ onCopy }: { readonly onCopy: () => void }) { +export function StandaloneMessage({ onCopy, copyPending = false }: { + readonly onCopy: () => void; + readonly copyPending?: boolean; +}) { return ( void }) { beforeContent={

Message context

} afterContent={} controls={ - +