fix(web): refine theme contrast and color system
This commit is contained in:
1 parent
adcee97f78
commit
0bb405aeb7
17 files changed
+326
-194
No files matched your search
@@ -46,19 +46,18 @@ export const LoginScreen = ({ error, instanceUrl: initialInstanceUrl, isSubmitti
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="flex h-[100dvh] items-center justify-center bg-gradient-to-tr from-emerald-50/70 via-emerald-50 to-emerald-100 px-4 py-8 text-slate-950">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_right,rgb(var(--brand-green-rgb)/0.06),transparent_45%)] pointer-events-none" />
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_bottom_left,rgb(var(--brand-green-rgb)/0.04),transparent_55%)] pointer-events-none" />
|
||||
<GitHubRepositoryLink className="absolute right-4 top-[max(1rem,env(safe-area-inset-top))] z-10 h-10 w-10 justify-center rounded-full border border-slate-200 bg-white/85 text-slate-600 shadow-sm backdrop-blur transition hover:bg-white hover:text-slate-950 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/70" iconClassName="h-5 w-5" />
|
||||
<main className="flex h-[100dvh] items-center justify-center bg-[var(--workspace-canvas)] px-4 py-8 text-slate-950">
|
||||
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(circle_at_50%_15%,rgb(var(--brand-green-rgb)/0.045),transparent_42%)]" />
|
||||
<GitHubRepositoryLink className="absolute right-4 top-[max(1rem,env(safe-area-inset-top))] z-10 h-10 w-10 justify-center rounded-full border border-slate-200 bg-white/85 text-slate-600 shadow-[0_4px_16px_rgb(var(--slate-900-rgb)/0.05)] backdrop-blur transition hover:border-slate-300 hover:bg-white hover:text-slate-950 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/60" iconClassName="h-5 w-5" />
|
||||
|
||||
<section className="relative w-full max-w-[400px] rounded-2xl border border-emerald-500/15 bg-white/95 p-8 shadow-[0_20px_50px_rgb(var(--brand-green-rgb)/0.08)] backdrop-blur-md transition-all duration-300 hover:shadow-[0_24px_60px_rgb(var(--brand-green-rgb)/0.12)]">
|
||||
<section className="relative w-full max-w-[400px] rounded-2xl border border-slate-200 bg-white/95 p-8 shadow-[0_20px_50px_rgb(var(--slate-900-rgb)/0.08)] backdrop-blur-md">
|
||||
<div className="mb-8 flex items-center gap-4">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-gradient-to-br from-emerald-500 to-emerald-600 text-white shadow-[0_8px_16px_-4px_rgb(var(--brand-green-rgb)/0.35)]">
|
||||
<div className="flex h-12 w-12 items-center justify-center rounded-xl bg-emerald-500 text-white shadow-[0_8px_18px_-8px_rgb(var(--brand-green-rgb)/0.45)]">
|
||||
<LockKeyhole className="h-5.5 w-5.5" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<h1 className="text-xl font-bold leading-tight tracking-tight text-slate-900">{t("login.title")}</h1>
|
||||
<p className="mt-1 text-xs font-medium uppercase tracking-wider text-slate-400">{t("login.subtitle")}</p>
|
||||
<p className="mt-1 text-xs font-medium tracking-wide text-slate-500">{t("login.subtitle")}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -85,7 +84,7 @@ export const LoginScreen = ({ error, instanceUrl: initialInstanceUrl, isSubmitti
|
||||
<span className="mb-2 block text-sm font-semibold text-slate-700">{t("login.desktopInstanceUrl")}</span>
|
||||
<Input
|
||||
autoComplete="url"
|
||||
className="h-11 rounded-lg bg-slate-50/50 px-3.5 focus-visible:bg-white focus-visible:ring-4 focus-visible:ring-emerald-500/10"
|
||||
className="h-11 rounded-lg bg-slate-50/50 px-3.5 focus-visible:bg-white focus-visible:ring-2 focus-visible:ring-emerald-500/20"
|
||||
placeholder={t("login.instanceUrlPlaceholder")}
|
||||
required
|
||||
type="url"
|
||||
@@ -99,7 +98,7 @@ export const LoginScreen = ({ error, instanceUrl: initialInstanceUrl, isSubmitti
|
||||
<span className="mb-2 block text-sm font-semibold text-slate-700">{t("login.username")}</span>
|
||||
<Input
|
||||
autoComplete="username"
|
||||
className="h-11 rounded-lg bg-slate-50/50 px-3.5 focus-visible:bg-white focus-visible:ring-4 focus-visible:ring-emerald-500/10"
|
||||
className="h-11 rounded-lg bg-slate-50/50 px-3.5 focus-visible:bg-white focus-visible:ring-2 focus-visible:ring-emerald-500/20"
|
||||
required
|
||||
value={username}
|
||||
onChange={(event) => setUsername(event.target.value)}
|
||||
@@ -110,7 +109,7 @@ export const LoginScreen = ({ error, instanceUrl: initialInstanceUrl, isSubmitti
|
||||
<span className="mb-2 block text-sm font-semibold text-slate-700">{t("login.password")}</span>
|
||||
<Input
|
||||
autoComplete="current-password"
|
||||
className="h-11 rounded-lg bg-slate-50/50 px-3.5 focus-visible:bg-white focus-visible:ring-4 focus-visible:ring-emerald-500/10"
|
||||
className="h-11 rounded-lg bg-slate-50/50 px-3.5 focus-visible:bg-white focus-visible:ring-2 focus-visible:ring-emerald-500/20"
|
||||
required
|
||||
type="password"
|
||||
value={password}
|
||||
@@ -119,7 +118,7 @@ export const LoginScreen = ({ error, instanceUrl: initialInstanceUrl, isSubmitti
|
||||
</label>
|
||||
|
||||
<Button
|
||||
className="w-full h-11 justify-center rounded-lg bg-emerald-500 hover:bg-emerald-600 text-white font-semibold transition-all duration-200 shadow-[0_8px_20px_-4px_rgb(var(--brand-green-rgb)/0.25)] hover:shadow-[0_12px_24px_-4px_rgb(var(--brand-green-rgb)/0.35)]"
|
||||
className="h-11 w-full justify-center rounded-lg bg-emerald-500 font-semibold text-white shadow-[0_8px_20px_-8px_rgb(var(--brand-green-rgb)/0.35)] transition-colors duration-200 hover:bg-emerald-600"
|
||||
size="md"
|
||||
type="submit"
|
||||
variant="solid"
|
||||
|
||||
@@ -66,16 +66,17 @@ export const MermaidCodeBlock = ({ editor, node }: NodeViewProps) => {
|
||||
let cancelled = false;
|
||||
const timer = window.setTimeout(() => {
|
||||
setRenderState("loading");
|
||||
const palette = MERMAID_THEME_PALETTES[mermaidTheme];
|
||||
|
||||
const renderBeautiful = () => loadBeautifulMermaid()
|
||||
.then(({ renderMermaidSVG, THEMES }) => renderMermaidSVG(source, {
|
||||
...THEMES[mermaidTheme],
|
||||
...palette,
|
||||
transparent: true,
|
||||
font: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
||||
padding: 24,
|
||||
}));
|
||||
const renderOfficial = () => loadMermaid().then(async (mermaid) => {
|
||||
const palette = MERMAID_THEME_PALETTES[mermaidTheme];
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
securityLevel: "strict",
|
||||
|
||||
@@ -34,21 +34,21 @@ export interface MermaidThemePalette {
|
||||
}
|
||||
|
||||
export const MERMAID_THEME_PALETTES: Record<MermaidThemeName, MermaidThemePalette> = {
|
||||
"zinc-light": { bg: "#FFFFFF", fg: "#27272A" },
|
||||
"zinc-dark": { bg: "#18181B", fg: "#FAFAFA" },
|
||||
"tokyo-night": { bg: "#1a1b26", fg: "#a9b1d6", line: "#3d59a1", accent: "#7aa2f7", muted: "#565f89" },
|
||||
"tokyo-night-storm": { bg: "#24283b", fg: "#a9b1d6", line: "#3d59a1", accent: "#7aa2f7", muted: "#565f89" },
|
||||
"tokyo-night-light": { bg: "#d5d6db", fg: "#343b58", line: "#34548a", accent: "#34548a", muted: "#9699a3" },
|
||||
"catppuccin-mocha": { bg: "#1e1e2e", fg: "#cdd6f4", line: "#585b70", accent: "#cba6f7", muted: "#6c7086" },
|
||||
"catppuccin-latte": { bg: "#eff1f5", fg: "#4c4f69", line: "#9ca0b0", accent: "#8839ef", muted: "#9ca0b0" },
|
||||
nord: { bg: "#2e3440", fg: "#d8dee9", line: "#4c566a", accent: "#88c0d0", muted: "#616e88" },
|
||||
"nord-light": { bg: "#eceff4", fg: "#2e3440", line: "#aab1c0", accent: "#5e81ac", muted: "#7b88a1" },
|
||||
dracula: { bg: "#282a36", fg: "#f8f8f2", line: "#6272a4", accent: "#bd93f9", muted: "#6272a4" },
|
||||
"zinc-light": { bg: "#FFFFFF", fg: "#27272A", line: "#a1a1aa", accent: "#52525b", muted: "#71717a" },
|
||||
"zinc-dark": { bg: "#18181B", fg: "#FAFAFA", line: "#52525b", accent: "#a1a1aa", muted: "#a1a1aa" },
|
||||
"tokyo-night": { bg: "#1a1b26", fg: "#a9b1d6", line: "#3d59a1", accent: "#7aa2f7", muted: "#7c85ac" },
|
||||
"tokyo-night-storm": { bg: "#24283b", fg: "#a9b1d6", line: "#3d59a1", accent: "#7aa2f7", muted: "#8991b8" },
|
||||
"tokyo-night-light": { bg: "#d5d6db", fg: "#343b58", line: "#34548a", accent: "#34548a", muted: "#545a71" },
|
||||
"catppuccin-mocha": { bg: "#1e1e2e", fg: "#cdd6f4", line: "#585b70", accent: "#cba6f7", muted: "#9399b2" },
|
||||
"catppuccin-latte": { bg: "#eff1f5", fg: "#4c4f69", line: "#9ca0b0", accent: "#8839ef", muted: "#666a80" },
|
||||
nord: { bg: "#2e3440", fg: "#d8dee9", line: "#4c566a", accent: "#88c0d0", muted: "#97a0b4" },
|
||||
"nord-light": { bg: "#eceff4", fg: "#2e3440", line: "#aab1c0", accent: "#5e81ac", muted: "#5f6a7e" },
|
||||
dracula: { bg: "#282a36", fg: "#f8f8f2", line: "#6272a4", accent: "#bd93f9", muted: "#8894b8" },
|
||||
"github-light": { bg: "#ffffff", fg: "#1f2328", line: "#d1d9e0", accent: "#0969da", muted: "#59636e" },
|
||||
"github-dark": { bg: "#0d1117", fg: "#e6edf3", line: "#3d444d", accent: "#4493f8", muted: "#9198a1" },
|
||||
"solarized-light": { bg: "#fdf6e3", fg: "#657b83", line: "#93a1a1", accent: "#268bd2", muted: "#93a1a1" },
|
||||
"solarized-dark": { bg: "#002b36", fg: "#839496", line: "#586e75", accent: "#268bd2", muted: "#586e75" },
|
||||
"one-dark": { bg: "#282c34", fg: "#abb2bf", line: "#4b5263", accent: "#c678dd", muted: "#5c6370" },
|
||||
"solarized-light": { bg: "#fdf6e3", fg: "#586e75", line: "#93a1a1", accent: "#268bd2", muted: "#5f747b" },
|
||||
"solarized-dark": { bg: "#002b36", fg: "#839496", line: "#586e75", accent: "#268bd2", muted: "#93a1a1" },
|
||||
"one-dark": { bg: "#282c34", fg: "#abb2bf", line: "#4b5263", accent: "#c678dd", muted: "#8f96a3" },
|
||||
};
|
||||
|
||||
export const EDITOR_THEME_NAMES = [
|
||||
@@ -138,8 +138,8 @@ const MERMAID_THEME_STORAGE_KEY = "edgeever.mermaid-theme";
|
||||
const EDITOR_THEME_STORAGE_KEY = "edgeever.editor-theme";
|
||||
const CUSTOM_EDITOR_THEME_STORAGE_KEY = "edgeever.custom-editor-theme";
|
||||
const CUSTOM_EDITOR_THEMES_STORAGE_KEY = "edgeever.custom-editor-themes";
|
||||
const LIGHT_THEME_COLOR = "#f8fafc";
|
||||
const DARK_THEME_COLOR = "#0f172a";
|
||||
const LIGHT_THEME_COLOR = "#f3f5f7";
|
||||
const DARK_THEME_COLOR = "#101311";
|
||||
const AppearanceThemeContext = createContext<AppearanceThemeContextValue | null>(null);
|
||||
const MermaidThemeContext = createContext<MermaidThemeContextValue | null>(null);
|
||||
const EditorThemeContext = createContext<EditorThemeContextValue | null>(null);
|
||||
|
||||
@@ -7,6 +7,27 @@ import {
|
||||
resolveMermaidTheme,
|
||||
} from "../components/ThemeProvider";
|
||||
|
||||
const BUILT_IN_EDITOR_THEMES = [
|
||||
"minimal-emerald",
|
||||
"outline-emerald",
|
||||
"wechat-green",
|
||||
"modern-mint",
|
||||
"marxico",
|
||||
];
|
||||
|
||||
const readDarkThemeTokens = (theme) => {
|
||||
const css = readFileSync(new URL(`../styles/editor-themes/${theme}.css`, import.meta.url), "utf8");
|
||||
const selector = `:root.dark .edgeever-editor[data-editor-theme="${theme}"]:not([data-editor-theme="default"])`;
|
||||
const blockStart = css.indexOf(`${selector} {`);
|
||||
expect(blockStart).toBeGreaterThanOrEqual(0);
|
||||
const blockEnd = css.indexOf("}", blockStart);
|
||||
const block = css.slice(blockStart, blockEnd);
|
||||
const tokens = Object.fromEntries(
|
||||
[...block.matchAll(/--editor-theme-([\w-]+):\s*(#[\da-f]{6}|var\([^;]+\));/gi)].map((match) => [match[1], match[2]])
|
||||
);
|
||||
return { block, css, tokens };
|
||||
};
|
||||
|
||||
describe("dark theme contracts", () => {
|
||||
test("default custom editor themes meet their contrast thresholds", () => {
|
||||
for (const colors of [DEFAULT_CUSTOM_LIGHT_COLORS, DEFAULT_CUSTOM_DARK_COLORS]) {
|
||||
@@ -25,13 +46,39 @@ describe("dark theme contracts", () => {
|
||||
expect(css).toContain('[class~="text-emerald-700"]');
|
||||
});
|
||||
|
||||
test("workspace dark surfaces stay neutral and bundled editor themes blend into the canvas", () => {
|
||||
const css = readFileSync(new URL("../styles/globals.css", import.meta.url), "utf8");
|
||||
|
||||
expect(css).toContain("--workspace-canvas: #101311;");
|
||||
expect(css).toContain("--workspace-sidebar: #121612;");
|
||||
expect(css).toContain("--workspace-memo-list: #151a17;");
|
||||
expect(css).toContain("--workspace-editor: #191e1b;");
|
||||
expect(css).toContain(':not([data-editor-theme="custom"])');
|
||||
expect(css).toContain("--editor-theme-bg: var(--workspace-editor);");
|
||||
expect(contrastRatio("#cad4ce", "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio("#9aa9a0", "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
});
|
||||
|
||||
test("every bundled editor theme has a complete accessible dark palette", () => {
|
||||
for (const theme of BUILT_IN_EDITOR_THEMES) {
|
||||
const { tokens } = readDarkThemeTokens(theme);
|
||||
|
||||
expect(tokens.bg).toBe("var(--workspace-editor)");
|
||||
expect(contrastRatio(tokens.text, "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio(tokens.heading, "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio(tokens.accent, "#191e1b")).toBeGreaterThanOrEqual(3);
|
||||
expect(contrastRatio(tokens.muted, tokens.soft)).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio(tokens["code-text"], tokens["code-bg"])).toBeGreaterThanOrEqual(4.5);
|
||||
}
|
||||
});
|
||||
|
||||
test("Marxico keeps note content legible in dark mode", () => {
|
||||
const css = readFileSync(new URL("../styles/editor-themes/marxico.css", import.meta.url), "utf8");
|
||||
const { css, tokens } = readDarkThemeTokens("marxico");
|
||||
|
||||
expect(css).toContain(':root.dark .edgeever-editor[data-editor-theme="marxico"]');
|
||||
expect(css).toContain("color: var(--editor-theme-text);");
|
||||
expect(contrastRatio("#dce3ea", "#19222b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio("#e7edf2", "#19222b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio(tokens.text, "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio(tokens.heading, "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
});
|
||||
|
||||
test("automatic Mermaid themes follow the resolved appearance", () => {
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { renderMermaidSVG, THEMES } from "beautiful-mermaid";
|
||||
import { MERMAID_THEME_PALETTES } from "../components/ThemeProvider";
|
||||
import { contrastRatio } from "./color-contrast";
|
||||
import { getOfficialMermaidThemeVariables } from "./mermaid-theme";
|
||||
|
||||
const SEQUENCE_SOURCE = `sequenceDiagram
|
||||
participant User as 用户
|
||||
participant App as 客户端
|
||||
User->>App: 保存笔记
|
||||
App-->>User: 保存成功`;
|
||||
|
||||
describe("official Mermaid theme variables", () => {
|
||||
test("maps every built-in theme across flowchart, sequence, and state diagrams", () => {
|
||||
for (const palette of Object.values(MERMAID_THEME_PALETTES)) {
|
||||
@@ -20,13 +28,36 @@ describe("official Mermaid theme variables", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps minimal two-color themes coherent", () => {
|
||||
test("keeps the zinc light theme coherent", () => {
|
||||
const palette = MERMAID_THEME_PALETTES["zinc-light"];
|
||||
const variables = getOfficialMermaidThemeVariables(palette);
|
||||
|
||||
expect(variables.background).toBe(palette.bg);
|
||||
expect(variables.primaryColor).toBe(palette.bg);
|
||||
expect(variables.primaryBorderColor).toBe(palette.fg);
|
||||
expect(variables.signalColor).toBe(palette.fg);
|
||||
expect(variables.primaryBorderColor).toBe(palette.muted);
|
||||
expect(variables.signalColor).toBe(palette.accent);
|
||||
});
|
||||
|
||||
test("keeps primary and secondary diagram text readable in every theme", () => {
|
||||
for (const [theme, palette] of Object.entries(MERMAID_THEME_PALETTES)) {
|
||||
expect(contrastRatio(palette.fg, palette.bg), `${theme} primary text`).toBeGreaterThanOrEqual(4.5);
|
||||
expect(palette.muted, `${theme} secondary text color`).toBeDefined();
|
||||
expect(contrastRatio(palette.muted, palette.bg), `${theme} secondary text`).toBeGreaterThanOrEqual(4.5);
|
||||
}
|
||||
});
|
||||
|
||||
test("applies the accessible text palette when every theme renders a sequence diagram", () => {
|
||||
for (const [theme, palette] of Object.entries(MERMAID_THEME_PALETTES)) {
|
||||
const svg = renderMermaidSVG(SEQUENCE_SOURCE, {
|
||||
...THEMES[theme],
|
||||
...palette,
|
||||
transparent: true,
|
||||
});
|
||||
|
||||
expect(svg, `${theme} rendered SVG`).toContain(`--bg:${palette.bg}`);
|
||||
expect(svg, `${theme} rendered SVG`).toContain(`--fg:${palette.fg}`);
|
||||
expect(svg, `${theme} rendered SVG`).toContain(`--muted:${palette.muted}`);
|
||||
expect(svg, `${theme} message text`).toContain('fill="var(--_text-muted)"');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import hljs from "highlight.js/lib/common";
|
||||
import { renderMermaidSVG, THEMES } from "beautiful-mermaid";
|
||||
import { MERMAID_THEME_PALETTES } from "@/components/ThemeProvider";
|
||||
|
||||
const WINDOWS_RESERVED_NAME = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(?:\.|$)/i;
|
||||
const EXPORT_FONT_FAMILY =
|
||||
@@ -187,6 +188,7 @@ export const renderMermaidBlocksForHtmlExport = async (root: HTMLElement) => {
|
||||
try {
|
||||
const svg = renderMermaidSVG(source, {
|
||||
...THEMES["zinc-light"],
|
||||
...MERMAID_THEME_PALETTES["zinc-light"],
|
||||
transparent: true,
|
||||
font: EXPORT_FONT_FAMILY,
|
||||
padding: 24,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { contrastRatio } from "./color-contrast";
|
||||
|
||||
const globals = readFileSync(new URL("../styles/globals.css", import.meta.url), "utf8");
|
||||
|
||||
describe("application color system", () => {
|
||||
test("uses the same restrained brand green throughout the application", () => {
|
||||
const mobileEditor = readFileSync(new URL("../styles/mobile-markdown-editor.css", import.meta.url), "utf8");
|
||||
|
||||
expect(globals).toContain("--brand-green: #16a06e;");
|
||||
expect(globals).not.toContain("--brand-green: #00a82d;");
|
||||
expect(mobileEditor).toContain("color: #16a06e;");
|
||||
expect(contrastRatio("#11694a", "#f0f8f4")).toBeGreaterThanOrEqual(4.5);
|
||||
});
|
||||
|
||||
test("keeps the light workspace crisp and neutral while preserving text hierarchy", () => {
|
||||
expect(globals).toContain("--workspace-canvas: #f3f5f7;");
|
||||
expect(globals).toContain("--workspace-sidebar: #eff1f4;");
|
||||
expect(globals).toContain("--workspace-memo-list: #f6f7f9;");
|
||||
expect(globals).toContain("--workspace-editor: #ffffff;");
|
||||
expect(contrastRatio("#0f172a", "#ffffff")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio("#64748b", "#ffffff")).toBeGreaterThanOrEqual(4.5);
|
||||
});
|
||||
|
||||
test("keeps dark workspace surfaces distinct without blue-black color casts", () => {
|
||||
expect(globals).toContain("--workspace-canvas: #101311;");
|
||||
expect(globals).toContain("--workspace-sidebar: #121612;");
|
||||
expect(globals).toContain("--workspace-memo-list: #151a17;");
|
||||
expect(globals).toContain("--workspace-editor: #191e1b;");
|
||||
expect(contrastRatio("#cad4ce", "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
expect(contrastRatio("#9aa9a0", "#191e1b")).toBeGreaterThanOrEqual(4.5);
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { Editor } from "@tiptap/react";
|
||||
import { MEMO_CONTENT_STYLE } from "@edgeever/shared";
|
||||
import { marked } from "marked";
|
||||
import { MERMAID_THEME_PALETTES } from "@/components/ThemeProvider";
|
||||
import { copyHtmlToClipboard } from "@/lib/clipboard";
|
||||
import { parseCustomCssToStyles } from "@/lib/css-sandbox";
|
||||
|
||||
@@ -280,6 +281,7 @@ const renderMermaidSvg = async (source: string) => {
|
||||
const { renderMermaidSVG, THEMES } = await import("beautiful-mermaid");
|
||||
return renderMermaidSVG(source, {
|
||||
...THEMES["zinc-light"],
|
||||
...MERMAID_THEME_PALETTES["zinc-light"],
|
||||
transparent: true,
|
||||
font: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif",
|
||||
padding: 24,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Previewer } from "pagedjs";
|
||||
import hljs from "highlight.js/lib/common";
|
||||
import { renderMermaidSVG, THEMES } from "beautiful-mermaid";
|
||||
import { MERMAID_THEME_PALETTES } from "@/components/ThemeProvider";
|
||||
import {
|
||||
NOTE_PRINT_MESSAGE,
|
||||
NOTE_PRINT_READY_MESSAGE,
|
||||
@@ -39,6 +40,7 @@ const renderMermaidBlocks = async (root: HTMLElement) => {
|
||||
try {
|
||||
const svg = renderMermaidSVG(source, {
|
||||
...THEMES["zinc-light"],
|
||||
...MERMAID_THEME_PALETTES["zinc-light"],
|
||||
transparent: true,
|
||||
font: PRINT_FONT_FAMILY,
|
||||
padding: 24,
|
||||
|
||||
@@ -298,17 +298,17 @@
|
||||
* but remap every hard-coded reading color so new and existing notes remain legible.
|
||||
*/
|
||||
:root.dark .edgeever-editor[data-editor-theme="marxico"]:not([data-editor-theme="default"]) {
|
||||
--editor-theme-bg: #19222b;
|
||||
--editor-theme-text: #dce3ea;
|
||||
--editor-theme-muted: #99a7b5;
|
||||
--editor-theme-heading: #e7edf2;
|
||||
--editor-theme-accent: #68b7ff;
|
||||
--editor-theme-soft: #202d38;
|
||||
--editor-theme-border: #344451;
|
||||
--editor-theme-code-bg: #2b2027;
|
||||
--editor-theme-code-text: #f0a6bd;
|
||||
--editor-theme-table-stripe: #1d2832;
|
||||
--editor-theme-table-hover: #24323e;
|
||||
--editor-theme-bg: var(--workspace-editor);
|
||||
--editor-theme-text: #d9e1dc;
|
||||
--editor-theme-muted: #99a7a0;
|
||||
--editor-theme-heading: #eef2ef;
|
||||
--editor-theme-accent: #78b7e8;
|
||||
--editor-theme-soft: #202a25;
|
||||
--editor-theme-border: #39473f;
|
||||
--editor-theme-code-bg: #2a2023;
|
||||
--editor-theme-code-text: #f2b0c2;
|
||||
--editor-theme-table-stripe: #1d2621;
|
||||
--editor-theme-table-hover: #24312a;
|
||||
color-scheme: dark;
|
||||
background: var(--editor-theme-bg) !important;
|
||||
}
|
||||
@@ -336,7 +336,7 @@
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="marxico"]:not([data-editor-theme="default"]) .ProseMirror a:not(.edgeever-attachment-link):hover {
|
||||
color: #9acfff;
|
||||
color: #acd5f4;
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="marxico"]:not([data-editor-theme="default"]) .ProseMirror blockquote {
|
||||
@@ -351,7 +351,13 @@
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="marxico"]:not([data-editor-theme="default"]) .ProseMirror pre {
|
||||
background: #202830;
|
||||
background: #151d19;
|
||||
color: var(--editor-theme-text);
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="marxico"]:not([data-editor-theme="default"]) .ProseMirror .edgeever-code-copy-button {
|
||||
border-color: var(--editor-theme-border);
|
||||
background: #151d19;
|
||||
color: var(--editor-theme-text);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="minimal-emerald"]:not([data-editor-theme="default"]) {
|
||||
--editor-theme-bg: #111827;
|
||||
--editor-theme-text: #d1d5db;
|
||||
--editor-theme-muted: #9ca3af;
|
||||
--editor-theme-heading: #f9fafb;
|
||||
--editor-theme-accent: #34d399;
|
||||
--editor-theme-soft: #1f2937;
|
||||
--editor-theme-border: #374151;
|
||||
--editor-theme-code-bg: #1f2937;
|
||||
--editor-theme-code-text: #6ee7b7;
|
||||
--editor-theme-bg: var(--workspace-editor);
|
||||
--editor-theme-text: #d8e0db;
|
||||
--editor-theme-muted: #97a59c;
|
||||
--editor-theme-heading: #f0f4f1;
|
||||
--editor-theme-accent: #4fd1a1;
|
||||
--editor-theme-soft: #202923;
|
||||
--editor-theme-border: #314039;
|
||||
--editor-theme-code-bg: #111713;
|
||||
--editor-theme-code-text: #7ee0bc;
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="minimal-emerald"]:not([data-editor-theme="default"]) .ProseMirror {
|
||||
@@ -76,7 +76,7 @@
|
||||
.edgeever-editor[data-editor-theme="minimal-emerald"]:not([data-editor-theme="default"]) .ProseMirror a {
|
||||
color: var(--editor-theme-accent);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgba(5, 150, 105, 0.4);
|
||||
text-decoration-color: color-mix(in srgb, var(--editor-theme-accent) 42%, transparent);
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="modern-mint"]:not([data-editor-theme="default"]) {
|
||||
--editor-theme-bg: #111a18;
|
||||
--editor-theme-text: #cbd5e1;
|
||||
--editor-theme-muted: #8fa39f;
|
||||
--editor-theme-heading: #f1f5f9;
|
||||
--editor-theme-accent: #14b8a6;
|
||||
--editor-theme-soft: #182b26;
|
||||
--editor-theme-border: #24423a;
|
||||
--editor-theme-code-bg: #1e293b;
|
||||
--editor-theme-code-text: #2ee5b5;
|
||||
--editor-theme-bg: var(--workspace-editor);
|
||||
--editor-theme-text: #d2ded9;
|
||||
--editor-theme-muted: #90a49b;
|
||||
--editor-theme-heading: #eff6f3;
|
||||
--editor-theme-accent: #2dc9ac;
|
||||
--editor-theme-soft: #1b2b25;
|
||||
--editor-theme-border: #2f473e;
|
||||
--editor-theme-code-bg: #101916;
|
||||
--editor-theme-code-text: #66e5c7;
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="modern-mint"]:not([data-editor-theme="default"]) .ProseMirror {
|
||||
@@ -77,14 +77,10 @@
|
||||
.edgeever-editor[data-editor-theme="modern-mint"]:not([data-editor-theme="default"]) .ProseMirror a {
|
||||
color: var(--editor-theme-accent);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgba(0, 179, 138, 0.4);
|
||||
text-decoration-color: color-mix(in srgb, var(--editor-theme-accent) 42%, transparent);
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="modern-mint"]:not([data-editor-theme="default"]) .ProseMirror a {
|
||||
text-decoration-color: rgba(20, 184, 166, 0.4);
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="modern-mint"]:not([data-editor-theme="default"]) .ProseMirror blockquote {
|
||||
margin: 1.5rem 0;
|
||||
border-left: 4px solid var(--editor-theme-accent);
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="outline-emerald"]:not([data-editor-theme="default"]) {
|
||||
--editor-theme-bg: #0f172a;
|
||||
--editor-theme-text: #cbd5e1;
|
||||
--editor-theme-muted: #94a3b8;
|
||||
--editor-theme-heading: #f8fafc;
|
||||
--editor-theme-accent: #34d399;
|
||||
--editor-theme-soft: #1e293b;
|
||||
--editor-theme-border: #334155;
|
||||
--editor-theme-code-bg: #020617;
|
||||
--editor-theme-code-text: #e2e8f0;
|
||||
--editor-theme-bg: var(--workspace-editor);
|
||||
--editor-theme-text: #d3dcd6;
|
||||
--editor-theme-muted: #8f9e95;
|
||||
--editor-theme-heading: #f3f6f4;
|
||||
--editor-theme-accent: #66d6ae;
|
||||
--editor-theme-soft: #1d2822;
|
||||
--editor-theme-border: #36463d;
|
||||
--editor-theme-code-bg: #0f1411;
|
||||
--editor-theme-code-text: #dbe6df;
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="outline-emerald"]:not([data-editor-theme="default"]) .ProseMirror {
|
||||
@@ -78,7 +78,7 @@
|
||||
.edgeever-editor[data-editor-theme="outline-emerald"]:not([data-editor-theme="default"]) .ProseMirror a {
|
||||
color: var(--editor-theme-accent);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgba(5, 150, 105, 0.4);
|
||||
text-decoration-color: color-mix(in srgb, var(--editor-theme-accent) 42%, transparent);
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="wechat-green"]:not([data-editor-theme="default"]) {
|
||||
--editor-theme-bg: #121212;
|
||||
--editor-theme-text: #cbd5e1;
|
||||
--editor-theme-muted: #94a3b8;
|
||||
--editor-theme-heading: #fafafa;
|
||||
--editor-theme-accent: #34d399;
|
||||
--editor-theme-soft: #1a241e;
|
||||
--editor-theme-border: #2d3d33;
|
||||
--editor-theme-code-bg: #1e293b;
|
||||
--editor-theme-code-text: #3eb575;
|
||||
--editor-theme-bg: var(--workspace-editor);
|
||||
--editor-theme-text: #d7ded9;
|
||||
--editor-theme-muted: #9aa69e;
|
||||
--editor-theme-heading: #f5f7f5;
|
||||
--editor-theme-accent: #3ecf78;
|
||||
--editor-theme-soft: #1c2a21;
|
||||
--editor-theme-border: #314439;
|
||||
--editor-theme-code-bg: #111a15;
|
||||
--editor-theme-code-text: #70dfa0;
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="wechat-green"]:not([data-editor-theme="default"]) .ProseMirror {
|
||||
@@ -79,20 +79,16 @@
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="wechat-green"]:not([data-editor-theme="default"]) .ProseMirror strong {
|
||||
color: var(--editor-theme-accent);
|
||||
background: rgba(52, 211, 153, 0.15);
|
||||
background: rgb(62 207 120 / 13%);
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="wechat-green"]:not([data-editor-theme="default"]) .ProseMirror a {
|
||||
color: var(--editor-theme-accent);
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgba(7, 193, 96, 0.4);
|
||||
text-decoration-color: color-mix(in srgb, var(--editor-theme-accent) 42%, transparent);
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
:root.dark .edgeever-editor[data-editor-theme="wechat-green"]:not([data-editor-theme="default"]) .ProseMirror a {
|
||||
text-decoration-color: rgba(52, 211, 153, 0.4);
|
||||
}
|
||||
|
||||
.edgeever-editor[data-editor-theme="wechat-green"]:not([data-editor-theme="default"]) .ProseMirror blockquote {
|
||||
margin: 1.5rem 0;
|
||||
border-left: 4px solid var(--editor-theme-accent);
|
||||
|
||||
+112
-96
@@ -90,25 +90,25 @@ html[data-edgeever-environment="demo"] body::after {
|
||||
:root {
|
||||
--background: 80 11% 96%;
|
||||
--foreground: 224 71% 4%;
|
||||
--brand-green: #00a82d;
|
||||
--brand-green-hover: #008f26;
|
||||
--brand-green-muted: #e6f6ea;
|
||||
--brand-green-soft: #f0fbf3;
|
||||
--brand-green-border: #99dcab;
|
||||
--brand-green-text: #00751f;
|
||||
--brand-green-rgb: 0 168 45;
|
||||
--brand-green-hover-rgb: 0 143 38;
|
||||
--brand-green-50-rgb: 230 246 234;
|
||||
--brand-green-100-rgb: 204 237 213;
|
||||
--brand-green-200-rgb: 153 220 171;
|
||||
--brand-green-300-rgb: 102 202 128;
|
||||
--brand-green-400-rgb: 51 185 86;
|
||||
--brand-green-500-rgb: 0 168 45;
|
||||
--brand-green-600-rgb: 0 143 38;
|
||||
--brand-green-700-rgb: 0 117 31;
|
||||
--brand-green-800-rgb: 0 92 25;
|
||||
--brand-green-900-rgb: 0 67 18;
|
||||
--brand-green-950-rgb: 0 43 11;
|
||||
--brand-green: #16a06e;
|
||||
--brand-green-hover: #12845b;
|
||||
--brand-green-muted: #def1e9;
|
||||
--brand-green-soft: #f0f8f4;
|
||||
--brand-green-border: #b8dfd0;
|
||||
--brand-green-text: #11694a;
|
||||
--brand-green-rgb: 22 160 110;
|
||||
--brand-green-hover-rgb: 18 132 91;
|
||||
--brand-green-50-rgb: 240 248 244;
|
||||
--brand-green-100-rgb: 222 241 233;
|
||||
--brand-green-200-rgb: 184 223 208;
|
||||
--brand-green-300-rgb: 125 196 170;
|
||||
--brand-green-400-rgb: 62 174 134;
|
||||
--brand-green-500-rgb: 22 160 110;
|
||||
--brand-green-600-rgb: 18 132 91;
|
||||
--brand-green-700-rgb: 17 105 74;
|
||||
--brand-green-800-rgb: 17 83 60;
|
||||
--brand-green-900-rgb: 15 68 50;
|
||||
--brand-green-950-rgb: 7 37 28;
|
||||
--workspace-canvas: #f3f5f7;
|
||||
--workspace-sidebar: #eff1f4;
|
||||
--workspace-memo-list: #f6f7f9;
|
||||
@@ -140,24 +140,24 @@ html[data-edgeever-environment="demo"] body::after {
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 224 71% 4%;
|
||||
|
||||
--primary: 136 100% 33%;
|
||||
--primary: 158 76% 36%;
|
||||
--primary-foreground: 80 11% 96%;
|
||||
|
||||
--secondary: 136 55% 94%;
|
||||
--secondary-foreground: 136 100% 25%;
|
||||
--secondary: 158 32% 94%;
|
||||
--secondary-foreground: 158 70% 25%;
|
||||
|
||||
--muted: 210 40% 96.1%;
|
||||
--muted-foreground: 215.4 16.3% 46.9%;
|
||||
|
||||
--accent: 136 55% 94%;
|
||||
--accent-foreground: 136 100% 25%;
|
||||
--accent: 158 32% 94%;
|
||||
--accent-foreground: 158 70% 25%;
|
||||
|
||||
--destructive: 0 84.2% 60.2%;
|
||||
--destructive-foreground: 210 40% 98%;
|
||||
|
||||
--border: 220 13% 91%;
|
||||
--input: 220 13% 91%;
|
||||
--ring: 136 100% 33%;
|
||||
--ring: 158 76% 36%;
|
||||
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
@@ -173,42 +173,42 @@ html[data-edgeever-environment="demo"] body::after {
|
||||
|
||||
:root.dark {
|
||||
color-scheme: dark;
|
||||
--background: 210 26% 9%;
|
||||
--foreground: 210 20% 89%;
|
||||
--card: 211 22% 14%;
|
||||
--card-foreground: 210 20% 89%;
|
||||
--popover: 211 23% 15%;
|
||||
--popover-foreground: 210 20% 89%;
|
||||
--background: 150 8% 8%;
|
||||
--foreground: 144 9% 88%;
|
||||
--card: 150 10% 13%;
|
||||
--card-foreground: 144 9% 88%;
|
||||
--popover: 150 10% 14%;
|
||||
--popover-foreground: 144 9% 88%;
|
||||
--primary: 160 76% 36%;
|
||||
--primary-foreground: 150 33% 97%;
|
||||
--secondary: 210 20% 18%;
|
||||
--secondary: 150 10% 18%;
|
||||
--secondary-foreground: 160 35% 72%;
|
||||
--muted: 210 17% 18%;
|
||||
--muted-foreground: 210 12% 62%;
|
||||
--accent: 210 18% 20%;
|
||||
--muted: 150 8% 18%;
|
||||
--muted-foreground: 145 8% 62%;
|
||||
--accent: 150 10% 20%;
|
||||
--accent-foreground: 160 40% 75%;
|
||||
--destructive: 0 72% 51%;
|
||||
--destructive-foreground: 210 20% 96%;
|
||||
--border: 210 16% 24%;
|
||||
--input: 210 16% 24%;
|
||||
--destructive-foreground: 144 12% 96%;
|
||||
--border: 150 10% 23%;
|
||||
--input: 150 10% 23%;
|
||||
--ring: 160 76% 36%;
|
||||
--workspace-canvas: #10161c;
|
||||
--workspace-sidebar: #131a21;
|
||||
--workspace-memo-list: #161e26;
|
||||
--workspace-editor: #19222b;
|
||||
--workspace-divider: #2a3540;
|
||||
--workspace-selection: #23323c;
|
||||
--slate-50-rgb: 16 22 28;
|
||||
--slate-100-rgb: 23 31 39;
|
||||
--slate-200-rgb: 39 50 61;
|
||||
--slate-300-rgb: 56 69 82;
|
||||
--slate-400-rgb: 80 95 110;
|
||||
--slate-500-rgb: 136 151 165;
|
||||
--slate-600-rgb: 174 187 199;
|
||||
--slate-700-rgb: 200 210 219;
|
||||
--slate-800-rgb: 220 227 234;
|
||||
--slate-900-rgb: 235 240 244;
|
||||
--dark-surface-rgb: 25 34 43;
|
||||
--workspace-canvas: #101311;
|
||||
--workspace-sidebar: #121612;
|
||||
--workspace-memo-list: #151a17;
|
||||
--workspace-editor: #191e1b;
|
||||
--workspace-divider: #2a312d;
|
||||
--workspace-selection: #1d3028;
|
||||
--slate-50-rgb: 15 20 17;
|
||||
--slate-100-rgb: 21 28 24;
|
||||
--slate-200-rgb: 38 49 43;
|
||||
--slate-300-rgb: 55 68 61;
|
||||
--slate-400-rgb: 78 92 84;
|
||||
--slate-500-rgb: 137 150 142;
|
||||
--slate-600-rgb: 182 195 187;
|
||||
--slate-700-rgb: 202 212 206;
|
||||
--slate-800-rgb: 221 229 224;
|
||||
--slate-900-rgb: 233 239 235;
|
||||
--dark-surface-rgb: 25 30 27;
|
||||
--brand-green: #16a06e;
|
||||
--brand-green-hover: #24b986;
|
||||
--brand-green-muted: #183a31;
|
||||
@@ -255,10 +255,8 @@ html.edgeever-mobile-native-editing #root {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
background:
|
||||
linear-gradient(180deg, rgba(248, 250, 252, 0.98), rgba(241, 245, 249, 0.98)),
|
||||
#f8fafc;
|
||||
color: #0f172a;
|
||||
background: var(--workspace-canvas);
|
||||
color: hsl(var(--foreground));
|
||||
overscroll-behavior-x: none;
|
||||
overscroll-behavior-y: auto;
|
||||
}
|
||||
@@ -329,6 +327,12 @@ html[data-edgeever-extension-theme] kbd {
|
||||
font-family: var(--edgeever-theme-font-mono, ui-monospace, monospace);
|
||||
}
|
||||
|
||||
/* Keep the strongest text neutral instead of falling back to Tailwind's
|
||||
* blue-black slate-950 literal. Background uses of slate-950 remain intact. */
|
||||
:root [class~="text-slate-950"] {
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 180ms;
|
||||
@@ -447,6 +451,18 @@ html[data-edgeever-extension-theme] .edgeever-workspace-selection {
|
||||
background: var(--workspace-selection) !important;
|
||||
}
|
||||
|
||||
/* Curated reading themes should feel like part of the note canvas in dark
|
||||
* mode. Custom themes keep their explicit background as an intentional user
|
||||
* choice, while bundled themes contribute typography and semantic colors. */
|
||||
:root.dark .edgeever-editor[data-editor-theme]:not([data-editor-theme="default"]):not([data-editor-theme="custom"]) {
|
||||
--editor-theme-bg: var(--workspace-editor);
|
||||
}
|
||||
|
||||
/* Repeated memo rows need less separation than the three workspace panes. */
|
||||
:root.dark .edgeever-workspace-memo-list article {
|
||||
border-color: color-mix(in srgb, var(--workspace-divider) 58%, transparent) !important;
|
||||
}
|
||||
|
||||
:root.dark .ProseMirror {
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
@@ -594,14 +610,14 @@ textarea {
|
||||
gap: 0.2rem;
|
||||
max-width: min(100%, 32rem);
|
||||
padding: 0.03rem 0.32rem 0.05rem;
|
||||
border: 1px solid rgb(110 231 183 / 0.9);
|
||||
border: 1px solid var(--brand-green-border);
|
||||
border-radius: 0.35rem;
|
||||
background: linear-gradient(135deg, rgb(236 253 245), rgb(209 250 229));
|
||||
color: rgb(4 120 87);
|
||||
background: var(--brand-green-soft);
|
||||
color: var(--brand-green-text);
|
||||
font-size: 0.9em;
|
||||
font-weight: 500;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: rgb(52 211 153 / 0.7);
|
||||
text-decoration-color: color-mix(in srgb, var(--brand-green) 55%, transparent);
|
||||
text-underline-offset: 2px;
|
||||
vertical-align: baseline;
|
||||
cursor: pointer;
|
||||
@@ -619,25 +635,25 @@ textarea {
|
||||
|
||||
.ProseMirror a.edgeever-note-link:hover,
|
||||
.ProseMirror a[href^="#memo="]:hover {
|
||||
color: rgb(6 95 70);
|
||||
border-color: rgb(16 185 129);
|
||||
background: rgb(167 243 208);
|
||||
text-decoration-color: rgb(4 120 87);
|
||||
box-shadow: 0 2px 8px rgb(16 185 129 / 0.2);
|
||||
color: var(--brand-green-text);
|
||||
border-color: var(--brand-green);
|
||||
background: var(--brand-green-muted);
|
||||
text-decoration-color: var(--brand-green-text);
|
||||
box-shadow: 0 2px 8px rgb(var(--brand-green-rgb) / 0.1);
|
||||
}
|
||||
|
||||
:root.dark .ProseMirror a.edgeever-note-link,
|
||||
:root.dark .ProseMirror a[href^="#memo="] {
|
||||
border-color: rgb(52 211 153 / 0.7);
|
||||
background: linear-gradient(135deg, rgb(6 78 59), rgb(6 95 70));
|
||||
color: rgb(110 231 183);
|
||||
border-color: var(--brand-green-border);
|
||||
background: var(--brand-green-soft);
|
||||
color: var(--brand-green-text);
|
||||
}
|
||||
|
||||
:root.dark .ProseMirror a.edgeever-note-link:hover,
|
||||
:root.dark .ProseMirror a[href^="#memo="]:hover {
|
||||
border-color: rgb(110 231 183);
|
||||
background: rgb(6 95 70);
|
||||
color: rgb(167 243 208);
|
||||
border-color: var(--brand-green);
|
||||
background: var(--brand-green-muted);
|
||||
color: var(--brand-green-text);
|
||||
}
|
||||
|
||||
.ProseMirror a.edgeever-attachment-link,
|
||||
@@ -647,15 +663,15 @@ textarea {
|
||||
gap: 0.3rem;
|
||||
max-width: min(100%, 30rem);
|
||||
padding: 0.3rem 0.55rem;
|
||||
border: 1px solid rgb(203 213 225 / 0.9);
|
||||
border: 1px solid rgb(var(--slate-300-rgb) / 0.9);
|
||||
border-radius: 0.45rem;
|
||||
background: linear-gradient(135deg, rgb(248 250 252), rgb(241 245 249));
|
||||
color: rgb(30 41 59);
|
||||
background: rgb(var(--slate-50-rgb));
|
||||
color: rgb(var(--slate-800-rgb));
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
text-decoration: none;
|
||||
box-shadow: 0 1px 2px rgb(15 23 42 / 0.06);
|
||||
box-shadow: 0 1px 2px rgb(var(--slate-900-rgb) / 0.04);
|
||||
transition: border-color 160ms ease, background 160ms ease, box-shadow 160ms ease;
|
||||
}
|
||||
|
||||
@@ -672,16 +688,16 @@ textarea {
|
||||
|
||||
.ProseMirror a.edgeever-attachment-link:hover,
|
||||
.ProseMirror a[href*="/api/v1/resources/"]:hover {
|
||||
border-color: rgb(16 185 129 / 0.55);
|
||||
background: linear-gradient(135deg, rgb(236 253 245), rgb(240 253 250));
|
||||
box-shadow: 0 3px 10px rgb(15 118 110 / 0.12);
|
||||
border-color: rgb(var(--brand-green-rgb) / 0.5);
|
||||
background: var(--brand-green-soft);
|
||||
box-shadow: 0 3px 10px rgb(var(--brand-green-rgb) / 0.08);
|
||||
}
|
||||
|
||||
:root.dark .ProseMirror a.edgeever-attachment-link,
|
||||
:root.dark .ProseMirror a[href*="/api/v1/resources/"] {
|
||||
border-color: rgb(71 85 105 / 0.8);
|
||||
background: linear-gradient(135deg, rgb(30 41 59), rgb(15 23 42));
|
||||
color: rgb(226 232 240);
|
||||
border-color: rgb(var(--slate-300-rgb) / 0.8);
|
||||
background: rgb(var(--slate-100-rgb));
|
||||
color: rgb(var(--slate-800-rgb));
|
||||
}
|
||||
|
||||
.ProseMirror ul,
|
||||
@@ -1399,7 +1415,7 @@ textarea {
|
||||
|
||||
:root.dark .ProseMirror tbody tr:hover td,
|
||||
:root.dark .markdown-content tbody tr:hover td {
|
||||
background: #202b3d;
|
||||
background: #202b25;
|
||||
}
|
||||
|
||||
/* Theme-aware surfaces for legacy white utilities and fixed semantic colors. */
|
||||
@@ -1460,19 +1476,19 @@ textarea {
|
||||
:root.dark [class~="bg-slate-900"],
|
||||
:root.dark [class*="bg-slate-900/"] { background-color: rgb(var(--slate-900-rgb)) !important; }
|
||||
|
||||
:root.dark [class~="text-slate-50"] { color: #ebf0f4 !important; }
|
||||
:root.dark [class~="text-slate-100"] { color: #e2e8ed !important; }
|
||||
:root.dark [class~="text-slate-200"] { color: #d4dce3 !important; }
|
||||
:root.dark [class~="text-slate-300"] { color: #c4ced7 !important; }
|
||||
:root.dark [class~="text-slate-350"] { color: #aab7c3 !important; }
|
||||
:root.dark [class~="text-slate-50"] { color: #eef2ef !important; }
|
||||
:root.dark [class~="text-slate-100"] { color: #e5ebe7 !important; }
|
||||
:root.dark [class~="text-slate-200"] { color: #d7dfda !important; }
|
||||
:root.dark [class~="text-slate-300"] { color: #c6d0ca !important; }
|
||||
:root.dark [class~="text-slate-350"] { color: #aebbb3 !important; }
|
||||
:root.dark [class~="text-slate-400"],
|
||||
:root.dark [class*="text-slate-400/"] { color: rgb(130 145 161 / var(--dark-utility-alpha, 1)) !important; }
|
||||
:root.dark [class~="text-slate-500"] { color: #99a7b5 !important; }
|
||||
:root.dark [class*="text-slate-400/"] { color: rgb(132 148 138 / var(--dark-utility-alpha, 1)) !important; }
|
||||
:root.dark [class~="text-slate-500"] { color: #9aa9a0 !important; }
|
||||
:root.dark [class~="text-slate-600"],
|
||||
:root.dark [class~="text-slate-650"] { color: #b7c2cd !important; }
|
||||
:root.dark [class~="text-slate-700"] { color: #c8d2db !important; }
|
||||
:root.dark [class~="text-slate-800"] { color: #dce3ea !important; }
|
||||
:root.dark [class~="text-slate-900"] { color: #e7edf2 !important; }
|
||||
:root.dark [class~="text-slate-650"] { color: #b6c3bb !important; }
|
||||
:root.dark [class~="text-slate-700"] { color: #cad4ce !important; }
|
||||
:root.dark [class~="text-slate-800"] { color: #dde5e0 !important; }
|
||||
:root.dark [class~="text-slate-900"] { color: #e9efeb !important; }
|
||||
|
||||
:root.dark [class~="border-slate-50"],
|
||||
:root.dark [class*="border-slate-50/"] { border-color: rgb(var(--slate-50-rgb)) !important; }
|
||||
|
||||
@@ -495,8 +495,8 @@ input {
|
||||
|
||||
.edgeever-mobile-tiptap-content a:active,
|
||||
.edgeever-mobile-tiptap-content a:hover {
|
||||
color: #00a82d;
|
||||
text-decoration-color: #00a82d;
|
||||
color: #16a06e;
|
||||
text-decoration-color: #16a06e;
|
||||
}
|
||||
|
||||
.edgeever-mobile-tiptap-content a.edgeever-attachment-link,
|
||||
|
||||
@@ -25,7 +25,7 @@ export default {
|
||||
],
|
||||
},
|
||||
boxShadow: {
|
||||
panel: "0 1px 2px rgb(15 23 42 / 0.07), 0 14px 34px rgb(36 56 39 / 0.08)",
|
||||
panel: "0 1px 2px rgb(var(--slate-900-rgb) / 0.05), 0 16px 40px rgb(var(--slate-900-rgb) / 0.07)",
|
||||
},
|
||||
borderRadius: {
|
||||
lg: "var(--radius)",
|
||||
|
||||
Reference in new issue
Block a user