selectTheme(t.id)} style={{ cursor: 'pointer', padding: 8, borderRadius: 6, border: themeId === t.id ? '2px solid #4a9eff' : '1px solid #3a3a4a', background: t.params.bgPrimary, color: t.params.textPrimary, fontSize: 11, minHeight: 48, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
+
selectTheme(t.id)} style={{ cursor: 'pointer', padding: 8, borderRadius: 6, border: themeId === t.id ? '2px solid var(--accent)' : '1px solid var(--control-border)', background: t.params.bgPrimary, color: t.params.textPrimary, fontSize: 11, minHeight: 48, display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
{t.name}
{t.desc}
))}
@@ -43,13 +43,13 @@ export function AppearancePanel({ onClose }: { onClose: () => void }) {
{ const f = e.target.files?.[0]; if (f) compressImage(f).then(d => setBgImage(d)); e.target.value = ''; }} />
fileRef.current?.click()} style={{ ...btn }}>选择图片
- {bgImage && <>
setBgImage(null)} style={{ ...btn }}>移除 >}
- {!bgImage &&
未设置 }
+ {bgImage && <>
setBgImage(null)} style={{ ...btn }}>移除 >}
+ {!bgImage &&
未设置 }
鼠标特效
{EFFECTS.map(([t, label]) => (
- setEffect(t)} style={{ padding: '8px', fontSize: 12, borderRadius: 4, cursor: 'pointer', border: effect === t ? '2px solid #4a9eff' : '1px solid #3a3a4a', background: effect === t ? '#2a2a3a' : 'transparent', color: effect === t ? '#9cf' : '#aaa' }}>{label}
+ setEffect(t)} style={{ padding: '8px', fontSize: 12, borderRadius: 4, cursor: 'pointer', border: effect === t ? '2px solid var(--accent)' : '1px solid var(--control-border)', background: effect === t ? 'var(--control-border)' : 'transparent', color: effect === t ? 'var(--accent-text)' : 'var(--text-secondary)' }}>{label}
))}
revert()} style={btn}>恢复(取消改动)
@@ -73,4 +73,4 @@ function normalizeColor(c: string): string {
if (c === 'transparent' || c.startsWith('rgba')) return '#1a1a2a';
return c;
}
-const btn: React.CSSProperties = { padding: '6px 14px', border: '1px solid #3a3a4a', background: 'transparent', color: '#aaa', borderRadius: 4, cursor: 'pointer', fontSize: 13 };
+const btn: React.CSSProperties = { padding: '6px 14px', border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-secondary)', borderRadius: 4, cursor: 'pointer', fontSize: 13 };
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/dialog/InputDialog.tsx b/apps/desktop/src/renderer/features/dialog/InputDialog.tsx
index 6cc25a1..180b5fa 100644
--- a/apps/desktop/src/renderer/features/dialog/InputDialog.tsx
+++ b/apps/desktop/src/renderer/features/dialog/InputDialog.tsx
@@ -16,21 +16,21 @@ export function InputDialog() {
return (
{ if (e.target === e.currentTarget) close(null); }} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.5)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000 }}>
-
-
{title}
+
+
{title}
{mode === 'confirm' ? (
{message}
) : (
setValue(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter') submit(); if (e.key === 'Escape') close(null); }}
- placeholder={placeholder} style={{ width: '100%', background: '#15151f', border: '1px solid #3a3a4a', color: '#ddd', borderRadius: 4, padding: '8px 12px', fontSize: 14, outline: 'none' }} />
+ placeholder={placeholder} style={{ width: '100%', background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '8px 12px', fontSize: 14, outline: 'none' }} />
)}
close(null)} style={btn}>取消
- {mode === 'confirm' ? '确认删除' : '确定'}
+ {mode === 'confirm' ? '确认删除' : '确定'}
);
}
-const btn: React.CSSProperties = { padding: '6px 16px', border: '1px solid #3a3a4a', background: 'transparent', color: '#aaa', borderRadius: 4, cursor: 'pointer', fontSize: 13 };
+const btn: React.CSSProperties = { padding: '6px 16px', border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-secondary)', borderRadius: 4, cursor: 'pointer', fontSize: 13 };
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx b/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx
index 77203a1..9b2c100 100644
--- a/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx
+++ b/apps/desktop/src/renderer/features/dialog/NotifyLayer.tsx
@@ -1,6 +1,6 @@
import { useNotify } from './notify-store';
export function NotifyLayer() { const { items, remove } = useNotify();
return
{items.map(n => (
-
remove(n.id)} style={{ padding: '10px 16px', borderRadius: 6, fontSize: 13, cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,0.3)', background: n.type === 'success' ? '#2a4a3a' : n.type === 'error' ? '#4a2a2a' : '#2a2a3a', color: n.type === 'success' ? '#9fc' : n.type === 'error' ? '#f88' : '#9cf' }}>{n.msg}
+
remove(n.id)} style={{ padding: '10px 16px', borderRadius: 6, fontSize: 13, cursor: 'pointer', boxShadow: '0 4px 12px rgba(0,0,0,0.3)', background: n.type === 'success' ? '#2a4a3a' : n.type === 'error' ? '#4a2a2a' : 'var(--control-border)', color: n.type === 'success' ? '#9fc' : n.type === 'error' ? '#f88' : 'var(--accent-text)' }}>{n.msg}
))}
;
-}
+}
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx b/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx
index e361217..f6c9263 100644
--- a/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx
+++ b/apps/desktop/src/renderer/features/doc-info/DocInfoPanel.tsx
@@ -21,7 +21,7 @@ export function DocInfoPanel() {
{title}
- toggleStar()} title="星标" style={{ cursor: 'pointer', background: 'none', border: 'none', fontSize: 16, color: meta.star ? '#ffd54a' : '#888' }}>
+ toggleStar()} title="星标" style={{ cursor: 'pointer', background: 'none', border: 'none', fontSize: 16, color: meta.star ? 'var(--accent)' : 'var(--text-tertiary)' }}>
{meta.star ? '★' : '☆'}
@@ -33,7 +33,7 @@ export function DocInfoPanel() {
{(meta.tags ?? []).map(t => (
-
+
{t} removeTag(t)}>×
))}
@@ -75,5 +75,5 @@ export function DocInfoPanel() {
function Section({ title, children }: { title: string; children: React.ReactNode }) {
return ();
}
-const inp: React.CSSProperties = { background: '#222', border: '1px solid #444', color: '#ddd', borderRadius: 4, padding: '3px 8px', fontSize: 13, flex: 1 };
-const btn: React.CSSProperties = { minWidth: 28, height: 26, border: '1px solid #444', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4 };
+const inp: React.CSSProperties = { background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '3px 8px', fontSize: 13, flex: 1 };
+const btn: React.CSSProperties = { minWidth: 28, height: 26, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4 };
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx b/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx
index 08e65f5..f6b56b8 100644
--- a/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx
+++ b/apps/desktop/src/renderer/features/editor/CodeBlockView.tsx
@@ -29,12 +29,12 @@ export function CodeBlockView({ node, updateAttributes, selected }: NodeViewProp
const language = (node.attrs.language as string) || '';
const codeClass = language ? `language-${language} hljs` : 'hljs';
return (
-
-
+
+
updateAttributes({ language: e.target.value })}
- style={{ background: '#222', color: '#ccc', border: '1px solid #444', borderRadius: 4, fontSize: 12, padding: '1px 4px', cursor: 'pointer' }}
+ style={{ background: 'var(--bg-secondary)', color: 'var(--text-primary)', border: '1px solid var(--control-border)', borderRadius: 4, fontSize: 12, padding: '1px 4px', cursor: 'pointer' }}
>
{LANGS.map(l => {l.label} )}
@@ -44,4 +44,4 @@ export function CodeBlockView({ node, updateAttributes, selected }: NodeViewProp
);
-}
+}
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/Editor.tsx b/apps/desktop/src/renderer/features/editor/Editor.tsx
index 0e822d3..42c35d7 100644
--- a/apps/desktop/src/renderer/features/editor/Editor.tsx
+++ b/apps/desktop/src/renderer/features/editor/Editor.tsx
@@ -20,7 +20,7 @@ export function Editor() {
}
return (
-
+
{title} {currentPath}
{saveLabel(saveState)}
diff --git a/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx b/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx
index 51d8306..ac08a88 100644
--- a/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx
+++ b/apps/desktop/src/renderer/features/editor/EditorToolbar.tsx
@@ -5,7 +5,7 @@ import { useDialog } from '../dialog/dialog-store';
import { invoke } from '../../ipc-client';
import { IPC } from '@hunter/shared';
-const btn: React.CSSProperties = { minWidth: 30, height: 28, border: '1px solid #444', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4, fontSize: 13 };
+const btn: React.CSSProperties = { minWidth: 30, height: 28, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4, fontSize: 13 };
function T({ onClick, title, children, disabled }: { onClick: () => void; title: string; children: React.ReactNode; disabled?: boolean }) {
return
{children} ;
@@ -35,29 +35,29 @@ export function EditorToolbar() {
editor.chain().focus().setImage({ src: url }).run();
};
return (
-
+
e.chain().focus().undo().run())} disabled={d}>↶
e.chain().focus().redo().run())} disabled={d}>↷
-
+
e.chain().focus().toggleBold().run())} disabled={d}>B
e.chain().focus().toggleItalic().run())} disabled={d}>I
e.chain().focus().toggleStrike().run())} disabled={d}>S
e.chain().focus().toggleCode().run())} disabled={d}>code
e.chain().focus().unsetAllMarks().run())} disabled={d}>T×
e.chain().focus().toggleBlockquote().run())} disabled={d}>❝
-
+
e.chain().focus().toggleHeading({ level: 1 }).run())} disabled={d}>H1
e.chain().focus().toggleHeading({ level: 2 }).run())} disabled={d}>H2
e.chain().focus().toggleHeading({ level: 3 }).run())} disabled={d}>H3
-
+
e.chain().focus().toggleBulletList().run())} disabled={d}>•
e.chain().focus().toggleOrderedList().run())} disabled={d}>1.
e.chain().focus().toggleCodeBlock().run())} disabled={d}>{'>'}
e.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run())} disabled={d}>▦
-
+
{ void link(); }} disabled={d}>链接
{ void pickImage(); }} disabled={d}>图片
{ void imageUrl(); }} disabled={d}>网图
);
-}
+}
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/FindReplace.tsx b/apps/desktop/src/renderer/features/editor/FindReplace.tsx
index 7317966..1108245 100644
--- a/apps/desktop/src/renderer/features/editor/FindReplace.tsx
+++ b/apps/desktop/src/renderer/features/editor/FindReplace.tsx
@@ -80,7 +80,7 @@ export function FindReplace() {
};
return (
-
+
setFind(e.target.value)} placeholder="查找" onKeyDown={e => e.key === 'Enter' && doFind()} style={inp} />
setReplace(e.target.value)} placeholder="替换" style={inp} />
Aa
@@ -95,6 +95,6 @@ export function FindReplace() {
);
}
-const inp: React.CSSProperties = { background: '#222', border: '1px solid #444', color: '#ddd', borderRadius: 4, padding: '3px 8px', width: 110, fontSize: 13 };
-const btn: React.CSSProperties = { minWidth: 30, height: 26, border: '1px solid #444', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4, fontSize: 12 };
-const lab: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 3, fontSize: 12, color: '#aaa', cursor: 'pointer' };
+const inp: React.CSSProperties = { background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '3px 8px', width: 110, fontSize: 13 };
+const btn: React.CSSProperties = { minWidth: 30, height: 26, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4, fontSize: 12 };
+const lab: React.CSSProperties = { display: 'flex', alignItems: 'center', gap: 3, fontSize: 12, color: 'var(--text-secondary)', cursor: 'pointer' };
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx b/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx
index 4ec265c..fef287a 100644
--- a/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx
+++ b/apps/desktop/src/renderer/features/editor/LinkBubbleMenu.tsx
@@ -17,12 +17,12 @@ export function LinkBubbleMenu({ editor }: { editor: Editor }) {
const remove = () => editor.chain().focus().extendMarkRange('link').unsetLink().run();
return (
editor.isActive('link')} className="link-bubble"
- style={{ display: 'flex', gap: 4, alignItems: 'center', background: '#1e1e2a', border: '1px solid #3a3a4a', borderRadius: 6, padding: 4, boxShadow: '0 4px 16px rgba(0,0,0,0.4)' }}>
+ style={{ display: 'flex', gap: 4, alignItems: 'center', background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', borderRadius: 6, padding: 4, boxShadow: '0 4px 16px rgba(0,0,0,0.4)' }}>
setHref(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); apply(); } }}
- placeholder="链接地址" style={{ width: 180, background: '#15151f', border: '1px solid #3a3a4a', color: '#ddd', borderRadius: 4, padding: '3px 8px', fontSize: 13, outline: 'none' }} />
+ placeholder="链接地址" style={{ width: 180, background: 'var(--bg-secondary)', border: '1px solid var(--control-border)', color: 'var(--text-primary)', borderRadius: 4, padding: '3px 8px', fontSize: 13, outline: 'none' }} />
更新
移除
);
}
-const btn: React.CSSProperties = { padding: '3px 10px', border: '1px solid #3a3a4a', background: 'transparent', color: '#ccc', borderRadius: 4, cursor: 'pointer', fontSize: 12 };
+const btn: React.CSSProperties = { padding: '3px 10px', border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', borderRadius: 4, cursor: 'pointer', fontSize: 12 };
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/MathBlock.tsx b/apps/desktop/src/renderer/features/editor/MathBlock.tsx
index e9fa531..e21aa3a 100644
--- a/apps/desktop/src/renderer/features/editor/MathBlock.tsx
+++ b/apps/desktop/src/renderer/features/editor/MathBlock.tsx
@@ -19,9 +19,9 @@ const MathBlockView = (props: NodeViewProps) => {
const tex = props.node.textContent;
const html = renderLatex(tex, true);
return (
-
+
-
+
);
};
@@ -82,4 +82,4 @@ export const InlineMath = Node.create({
insertInlineMath: (tex: string) => ({ chain }: { chain: () => any }) => chain().insertContent({ type: 'inlineMath', attrs: { tex } }).run(),
} as any;
},
-});
+});
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/MoreActions.tsx b/apps/desktop/src/renderer/features/editor/MoreActions.tsx
index 631c296..b93cd4c 100644
--- a/apps/desktop/src/renderer/features/editor/MoreActions.tsx
+++ b/apps/desktop/src/renderer/features/editor/MoreActions.tsx
@@ -15,7 +15,7 @@ export function MoreActions() {
setOpen(o => !o)} style={btn} title="更多操作">⋯
{open && (
-
+
- 复制 Markdown
- 打印 / 另存为 PDF
- 在文件管理器中显示
@@ -26,7 +26,7 @@ export function MoreActions() {
);
}
function Item({ children, onClick }: { children: React.ReactNode; onClick: () => void }) {
- return
(e.currentTarget.style.background = '#2a2a3a')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
;
+ return
(e.currentTarget.style.background = 'var(--control-border)')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
;
}
-const btn: React.CSSProperties = { height: 26, border: '1px solid #3a3a4a', background: 'transparent', color: '#ccc', cursor: 'pointer', borderRadius: 4, fontSize: 14, padding: '0 8px' };
-function notify(msg: string) { const el = document.createElement('div'); el.textContent = msg; el.style.cssText = 'position:fixed;top:50px;right:20px;background:#2a4a6a;color:#9cf;padding:10px 16px;border-radius:6px;z-index:3000;font-size:13px'; document.body.appendChild(el); setTimeout(() => el.remove(), 2500); }
+const btn: React.CSSProperties = { height: 26, border: '1px solid var(--control-border)', background: 'transparent', color: 'var(--text-primary)', cursor: 'pointer', borderRadius: 4, fontSize: 14, padding: '0 8px' };
+function notify(msg: string) { const el = document.createElement('div'); el.textContent = msg; el.style.cssText = 'position:fixed;top:50px;right:20px;background:var(--accent);color:var(--accent-text);padding:10px 16px;border-radius:6px;z-index:3000;font-size:13px'; document.body.appendChild(el); setTimeout(() => el.remove(), 2500); }
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/editor/SlashMenu.tsx b/apps/desktop/src/renderer/features/editor/SlashMenu.tsx
index cc43324..e4e8280 100644
--- a/apps/desktop/src/renderer/features/editor/SlashMenu.tsx
+++ b/apps/desktop/src/renderer/features/editor/SlashMenu.tsx
@@ -50,9 +50,9 @@ export function SlashMenu() {
setOpen(false);
};
return (
-
+
{items.length === 0 &&
无匹配
}
- {items.map(it =>
pick(it)} style={{ padding: '6px 10px', cursor: 'pointer', borderRadius: 4, fontSize: 13 }} onMouseEnter={e => (e.currentTarget.style.background = '#2a2a3a')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{it.label}
)}
+ {items.map(it =>
pick(it)} style={{ padding: '6px 10px', cursor: 'pointer', borderRadius: 4, fontSize: 13 }} onMouseEnter={e => (e.currentTarget.style.background = 'var(--control-border)')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{it.label}
)}
);
-}
+}
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/file-tree/FileTree.tsx b/apps/desktop/src/renderer/features/file-tree/FileTree.tsx
index 4e806ab..5d69deb 100644
--- a/apps/desktop/src/renderer/features/file-tree/FileTree.tsx
+++ b/apps/desktop/src/renderer/features/file-tree/FileTree.tsx
@@ -73,7 +73,7 @@ export function FileTree() {
{isRenaming ? (
setRenameVal(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter') { setRenaming(null); invoke(IPC.fileRename, { from: n.path, toName: renameVal }).then(r => { useTabs.getState().renamePath(n.path, r.path); syncCurrentPath(n.path, r.path); loadTree(); }); } if (e.key === 'Escape') setRenaming(null); }}
- onBlur={() => setRenaming(null)} style={{ flex: 1, background: '#15151f', border: '1px solid #4a6a8a', color: '#ddd', borderRadius: 3, padding: '1px 4px', fontSize: 13 }} />
+ onBlur={() => setRenaming(null)} style={{ flex: 1, background: 'var(--bg-secondary)', border: '1px solid #4a6a8a', color: 'var(--text-primary)', borderRadius: 3, padding: '1px 4px', fontSize: 13 }} />
) : (
{n.name}
)}
@@ -98,7 +98,7 @@ export function FileTree() {
{roots.map(n => renderNode(n, 0))}
{tree.length === 0 && !treeLoading &&
空库,点击上方「+ 新建文档」开始
}
{menu && menuNode && (
-
e.stopPropagation()}>
+
e.stopPropagation()}>
{menuNode.type === 'doc' &&
{ openDoc(menuNode.path); setMenu(null); }}>打开 }
{menuNode.type === 'folder' && <>
{ doCreate(menuNode.path, false); setMenu(null); }}>新建文档
@@ -111,8 +111,8 @@ export function FileTree() {
);
}
-const miniBtn: React.CSSProperties = { border: 'none', background: 'transparent', color: '#888', cursor: 'pointer', padding: '0 3px', fontSize: 12 };
+const miniBtn: React.CSSProperties = { border: 'none', background: 'transparent', color: 'var(--text-tertiary)', cursor: 'pointer', padding: '0 3px', fontSize: 12 };
function MenuItem({ children, onClick, danger }: { children: React.ReactNode; onClick: () => void; danger?: boolean }) {
- return
(e.currentTarget.style.background = '#2a2a3a')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
;
+ return
(e.currentTarget.style.background = 'var(--control-border)')} onMouseLeave={e => (e.currentTarget.style.background = 'transparent')}>{children}
;
}
\ No newline at end of file
diff --git a/apps/desktop/src/renderer/features/graph/GraphView.tsx b/apps/desktop/src/renderer/features/graph/GraphView.tsx
index 19ad424..5189cc9 100644
--- a/apps/desktop/src/renderer/features/graph/GraphView.tsx
+++ b/apps/desktop/src/renderer/features/graph/GraphView.tsx
@@ -46,7 +46,7 @@ const MARKMAP_OPTIONS = {
const t = node.payload?.type as NodeType | undefined;
if (t === 'doc') return '#9aa0aa';
if (t === 'folder') return '#5db0ff';
- return '#4a9eff';
+ return 'var(--accent)';
},
};
@@ -92,15 +92,15 @@ function MindmapTree() {
}, [tree]);
return (
-