Unify markdown on one engine (Milkdown Crepe)
Replace the two-engine setup (MDXEditor for editing + react-markdown for display) with a single Crepe-based component used for both. Editing is inline WYSIWYG with full GFM that actually works — task lists, tables, and code blocks via type-to-create / the slash menu — and read-only mode renders the exact same way, so write and read can no longer drift (the root cause of the heading/list/table/checkbox bugs). - markdown-editor.tsx: Crepe wrapper supporting edit + readOnly, themed to the glass card via --crepe-* variable overrides (scoped to .milkdown so they win over frame-dark's own definitions). - text-particle-view.tsx: render the message card with the read-only editor; drop the react-markdown component map. - Remove now-unused deps: @mdxeditor/editor, react-markdown, remark-gfm, rehype-highlight, highlight.js. The compose immersive mode (short, centered plain text) is unchanged. https://claude.ai/code/session_019DU6V5z6Nr4Vu7b1fBDnq4
This commit is contained in:
@@ -1,155 +1,49 @@
|
||||
/* Blend MDXEditor into the compose glass card, and restore prose typography.
|
||||
*
|
||||
* MDXEditor renders real <h1>/<ul>/<blockquote> elements and leans on the
|
||||
* browser's default styles for their look — it ships no heading/list
|
||||
* typography of its own. Tailwind's Preflight resets those defaults
|
||||
* (headings -> `font-size: inherit`, lists -> `list-style: none`), which would
|
||||
* otherwise make a heading or bullet look identical to body text. So we style
|
||||
* the content elements explicitly here, mirroring the rendered display in
|
||||
* text-particle-view.tsx so "write" and "read" match. */
|
||||
/* Theme Milkdown Crepe to blend into the app's translucent "glass" surfaces.
|
||||
* Crepe's frame-dark theme is a grayscale palette driven by --crepe-* custom
|
||||
* properties; we override those to white-on-transparent with a blue accent so
|
||||
* the editor (and the read-only display, which uses the same engine) sits on
|
||||
* top of the existing card instead of painting its own opaque background. */
|
||||
|
||||
.llink-mdxeditor {
|
||||
--baseBg: transparent;
|
||||
--basePageBg: transparent;
|
||||
/* Override the palette on `.milkdown` itself — frame-dark defines these vars
|
||||
* there, so a lower-specificity ancestor selector would be ignored. */
|
||||
.llink-crepe .milkdown {
|
||||
--crepe-color-background: transparent;
|
||||
--crepe-color-on-background: rgb(255 255 255 / 0.92);
|
||||
--crepe-color-surface: rgb(255 255 255 / 0.06);
|
||||
--crepe-color-surface-low: rgb(255 255 255 / 0.1);
|
||||
--crepe-color-on-surface: #ffffff;
|
||||
--crepe-color-on-surface-variant: rgb(255 255 255 / 0.6);
|
||||
--crepe-color-outline: rgb(255 255 255 / 0.25);
|
||||
--crepe-color-primary: #60a5fa;
|
||||
--crepe-color-secondary: rgb(96 165 250 / 0.25);
|
||||
--crepe-color-on-secondary: #ffffff;
|
||||
--crepe-color-inverse: #ffffff;
|
||||
--crepe-color-on-inverse: #0b0b0b;
|
||||
--crepe-color-inline-code: #fca5a5;
|
||||
--crepe-color-inline-area: rgb(255 255 255 / 0.1);
|
||||
--crepe-color-error: #f87171;
|
||||
--crepe-color-hover: rgb(255 255 255 / 0.08);
|
||||
--crepe-color-selected: rgb(96 165 250 / 0.25);
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.llink-mdxeditor [class*="_editorRoot_"] {
|
||||
background: transparent;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.llink-mdx-content {
|
||||
padding: 0 !important;
|
||||
.llink-crepe .milkdown .ProseMirror {
|
||||
padding: 0;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/* Editing context: fill the compose card and scroll internally so a long
|
||||
* message stays inside the card rather than growing the whole overlay. */
|
||||
.llink-crepe--fill,
|
||||
.llink-crepe--fill .milkdown {
|
||||
height: 100%;
|
||||
color: rgb(255 255 255 / 0.92);
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* Headings */
|
||||
.llink-mdx-content h1,
|
||||
.llink-mdx-content h2,
|
||||
.llink-mdx-content h3,
|
||||
.llink-mdx-content h4,
|
||||
.llink-mdx-content h5,
|
||||
.llink-mdx-content h6 {
|
||||
color: #fff;
|
||||
line-height: 1.25;
|
||||
}
|
||||
.llink-mdx-content h1 {
|
||||
font-size: 1.875rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
.llink-mdx-content h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.llink-mdx-content h3 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.llink-mdx-content h4 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.llink-mdx-content h5 {
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.llink-mdx-content h6 {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.25rem;
|
||||
.llink-crepe--fill .milkdown {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Block spacing */
|
||||
.llink-mdx-content p {
|
||||
margin-bottom: 0.75rem;
|
||||
line-height: 1.625;
|
||||
}
|
||||
.llink-mdx-content > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Inline emphasis */
|
||||
.llink-mdx-content strong {
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
.llink-mdx-content em {
|
||||
font-style: italic;
|
||||
}
|
||||
.llink-mdx-content a {
|
||||
color: #60a5fa;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Lists — Preflight strips the marker and indentation, so restore both */
|
||||
.llink-mdx-content ul,
|
||||
.llink-mdx-content ol {
|
||||
margin-bottom: 0.75rem;
|
||||
padding-left: 1.25rem;
|
||||
}
|
||||
.llink-mdx-content ul {
|
||||
list-style: disc;
|
||||
}
|
||||
.llink-mdx-content ol {
|
||||
list-style: decimal;
|
||||
}
|
||||
.llink-mdx-content li {
|
||||
margin-bottom: 0.25rem;
|
||||
line-height: 1.625;
|
||||
}
|
||||
/* Task-list items draw their own checkbox — no disc bullet. */
|
||||
.llink-mdx-content li[class*="_listItem"] {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/* Blockquote */
|
||||
.llink-mdx-content blockquote {
|
||||
margin-bottom: 0.75rem;
|
||||
padding-left: 1rem;
|
||||
border-left: 2px solid rgb(255 255 255 / 0.3);
|
||||
font-style: italic;
|
||||
color: rgb(255 255 255 / 0.7);
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
.llink-mdx-content code {
|
||||
border-radius: 0.25rem;
|
||||
background: rgb(255 255 255 / 0.1);
|
||||
padding: 0.1rem 0.375rem;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
/* Horizontal rule */
|
||||
.llink-mdx-content hr {
|
||||
margin: 1rem 0;
|
||||
border: none;
|
||||
border-top: 1px solid rgb(255 255 255 / 0.1);
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
.llink-mdx-content table {
|
||||
margin-bottom: 0.75rem;
|
||||
border-collapse: collapse;
|
||||
width: auto;
|
||||
}
|
||||
.llink-mdx-content th,
|
||||
.llink-mdx-content td {
|
||||
border: 1px solid rgb(255 255 255 / 0.2);
|
||||
padding: 0.375rem 0.625rem;
|
||||
text-align: left;
|
||||
}
|
||||
.llink-mdx-content th {
|
||||
background: rgb(255 255 255 / 0.08);
|
||||
font-weight: 600;
|
||||
.llink-crepe--fill .milkdown .ProseMirror {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user