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
@@ -1,12 +1,26 @@
import P from "@moduletrace/twui/layout/P";
import Markdown from "react-markdown";
import remarkBreaks from "remark-breaks";
import remarkGfm from "remark-gfm";
import Stack from "@moduletrace/twui/layout/Stack";
import linkComputerRefs from "@/src/utils/link-computer-refs";
import { UserMarkdownComponents } from "../(data)/user-markdown-components";
import { QuotableAttribute } from "../(hooks)/use-message-selection";
/**
* Ink bubble with paper text; inverts in dark mode.
* Ink bubble with paper text; inverts in dark mode. The text is markdown
* (GFM; raw HTML is never rendered) as the composer writes it, a single
* line break kept as one, so older plain messages read as typed. Bots
* and workspaces it mentions show as chips.
*/
export default function UserBubble({ text }: { text: string }) {
return (
<P noMargin className="max-w-[80%] rounded-default-lg bg-ink text-on-ink px-4 py-3 text-sm leading-5 whitespace-pre-wrap break-words">
{text}
</P>
<Stack
{...{ [QuotableAttribute]: "" }}
className="max-w-[80%] min-w-0 gap-2.5! items-stretch rounded-default-lg bg-ink text-on-ink px-4 py-3 text-sm leading-5 break-words"
>
<Markdown remarkPlugins={[remarkGfm, remarkBreaks]} components={UserMarkdownComponents}>
{linkComputerRefs({ text })}
</Markdown>
</Stack>
);
}