Replace the composer textarea with a Tiptap markdown editor

The composer now writes markdown with bold, italic, strike, code,
links, quotes and lists, from shortcuts, markdown typing or a bubble
over the selection. @ mentions a bot and # a workspace, shown as chips
and saved as [bot:ID] / [workspace:ID]. Text selected in a message can
be quoted into the composer. User messages render as markdown, and
replies tell the bot who and what the user mentioned.

Adds an ESM stand-in for use-sync-external-store, since bunext keeps
React external in page bundles and the CommonJS original requires it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-20 05:48:23 +01:00
co-authored by Claude Opus 5.5
parent e2093b0df6
commit 1208eac6b7
51 changed files with 1618 additions and 126 deletions
@@ -7,6 +7,7 @@ import type { BotMessageWithAttachments } from "@/src/types";
import linkComputerRefs from "@/src/utils/link-computer-refs";
import { BotMessageActionsContext } from "../(data)/message-actions-context";
import { MessageMarkdownComponents } from "../(data)/message-markdown-components";
import { QuotableAttribute } from "../(hooks)/use-message-selection";
import GroupTimestamp from "./group-timestamp";
import MessageActions from "./message-actions";
import MessageReactions from "./message-reactions";
@@ -29,7 +30,7 @@ type Props = {
* rendered). Computers it names (`computerRef`) show as buttons that
* switch the bot to them. A quoted reply sits above it, its reactions
* below, and a row under it replies, reacts, reads it aloud and shows
* why it needs you.
* why it needs you. Its text can be selected and quoted.
*/
export default function BotMessageLine({ message, bot_name, at }: Props) {
const { onReact } = useContext(BotMessageActionsContext);
@@ -43,7 +44,10 @@ export default function BotMessageLine({ message, bot_name, at }: Props) {
bot_name={bot_name}
/>
) : null}
<Stack className="w-full gap-2.5! items-start break-words">
<Stack
{...{ [QuotableAttribute]: "" }}
className="w-full gap-2.5! items-start break-words"
>
<Markdown
remarkPlugins={[remarkGfm]}
components={MessageMarkdownComponents}