cdrop — 跨 OS 剪贴板与文件传输服务
Commilitia Drop:自托管的跨设备剪贴板同步与点对点文件传输。 - 后端 Go(chi / SQLite WAL / SSE Hub / WebRTC signaling + 状态机 / Relay ring buffer),编译进单个 distroless 镜像(前端 go:embed)。 - 前端 React + TanStack Router + Zustand,自实现 SSE + WebRTC P2P,NAT 受阻时回退服务端中继;聚珍(Juzhen)CJK 综合排版。 - 桌面端 Wails v2(macOS / Windows),瘦客户端复用 web。 - 鉴权 OIDC PKCE(自建 Casdoor 等),refresh_token 信封加密存系统密钥库;iOS Shortcut 用 HS256 scoped token。 架构文档与变更记录见 docs 分支(PROJECT_BRIEF / FRONTEND_DESIGN / CHANGELOG)。 本次为公开发布初始提交:完整开发历史(含部署细节)留存于私有归档,公开仓库自此干净起步。
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Semantic 层 —— 语义令牌。组件唯一应该消费的颜色 / 阴影变量。
|
||||
*
|
||||
* 主题切换 = 改一个 attribute:document.documentElement.dataset.theme = "dark"。
|
||||
* 自定义主题 = 在 :root[data-theme="custom-x"] 下覆盖同一组变量。
|
||||
*
|
||||
* 系统主题:未设 data-theme 时,跟随 @media (prefers-color-scheme: dark)。
|
||||
*
|
||||
* 2026-05 重塑:
|
||||
* - 表面切到中性灰 5 阶(去紫调),accent 仍是 Dracula Purple。
|
||||
* - 引入 5 色角色:info / success / warn / error / emphasis + 各自 soft 派生。
|
||||
* - 状态编码统一走角色色(Activity 左色条、Badge tone、Callout 等)。
|
||||
*/
|
||||
|
||||
/* ===== Light · 中性灰 + Alucard accent / 角色色(默认) ===== */
|
||||
:root,
|
||||
:root[data-theme="light"]
|
||||
{
|
||||
--bg: var(--c-bg-light-neutral);
|
||||
--surface: var(--c-surface-light-neutral);
|
||||
--surface-raised: var(--c-raised-light-neutral);
|
||||
--surface-sunken: var(--c-sunken-light-neutral);
|
||||
--surface-elev2: var(--c-elev2-light-neutral);
|
||||
--divider: var(--c-divider-light-neutral);
|
||||
--divider-strong: var(--c-divider-strong-light);
|
||||
|
||||
--text: var(--c-foreground-alucard);
|
||||
--text-muted: var(--c-text-muted-light-neutral);
|
||||
|
||||
--accent: var(--c-purple-700);
|
||||
--accent-soft: color-mix(in srgb, var(--accent) 10%, transparent);
|
||||
--accent-softer: color-mix(in srgb, var(--accent) 5%, transparent);
|
||||
--accent-ring: color-mix(in srgb, var(--accent) 26%, transparent);
|
||||
--accent-on: #FFFFFF;
|
||||
|
||||
/* 5 色角色 —— Alucard 调色板深版,作 status 编码主力 */
|
||||
--info: var(--c-cyan-deep); /* #036A96 */
|
||||
--success: var(--c-green-deep); /* #14710A */
|
||||
--warn: var(--c-yellow-deep); /* #846E15 */
|
||||
--error: var(--c-red-deep); /* #CB3A2A */
|
||||
--emphasis: var(--c-pink-deep); /* #A3144D */
|
||||
--orange: var(--c-orange-deep); /* #A34D14,备用 */
|
||||
|
||||
--info-soft: color-mix(in srgb, var(--info) 9%, transparent);
|
||||
--success-soft: color-mix(in srgb, var(--success) 9%, transparent);
|
||||
--warn-soft: color-mix(in srgb, var(--warn) 11%, transparent);
|
||||
--error-soft: color-mix(in srgb, var(--error) 9%, transparent);
|
||||
--emphasis-soft: color-mix(in srgb, var(--emphasis) 9%, transparent);
|
||||
|
||||
/* state-* 是历史 alias,保留兼容现有组件(StateDot 等) */
|
||||
--state-online: var(--success);
|
||||
--state-error: var(--error);
|
||||
--state-warn: var(--warn);
|
||||
|
||||
--shadow-card: 0 1px 2px rgba(17, 17, 20, 0.05),
|
||||
0 2px 6px rgba(17, 17, 20, 0.07);
|
||||
--shadow-raised: 0 8px 20px rgba(17, 17, 20, 0.10),
|
||||
0 2px 6px rgba(17, 17, 20, 0.06);
|
||||
--shadow-overlay: 0 12px 32px rgba(17, 17, 20, 0.18);
|
||||
--shadow-accent: 0 8px 22px rgba(100, 74, 201, 0.24);
|
||||
|
||||
/* 字母头像:浅色主题 白底黑字 */
|
||||
--avatar-bg: #FFFFFF;
|
||||
--avatar-fg: #1F1F1F;
|
||||
|
||||
/* 颜色阶 —— Mantine accent 色板用,10 阶手工对齐 Dracula Purple */
|
||||
--accent-0: #F3F0FF;
|
||||
--accent-1: #E4DEFF;
|
||||
--accent-2: #C9BEFF;
|
||||
--accent-3: #AC9BFE;
|
||||
--accent-4: #9580FF;
|
||||
--accent-5: #8369FB;
|
||||
--accent-6: #7458EE;
|
||||
--accent-7: #644AC9;
|
||||
--accent-8: #523CA8;
|
||||
--accent-9: #3F2D85;
|
||||
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
/* ===== Dark · 中性灰 + Dracula accent / 角色色 =====
|
||||
*
|
||||
* 对比度准则:
|
||||
* - 表面用 c-*-dark-neutral 5 阶,色相 260° 但饱和度 8%,接近中性灰。
|
||||
* 紫色 accent (#AA99FF) 在 #26262E 上对比度 ~8.5:1,胜过原 Dracula 紫底紫前景的 4.2:1。
|
||||
* - --text-muted 用更冷的中性 #9C9CA9,而非 Comment 紫调,避免在中性灰上仍透紫感。
|
||||
* - --accent 用 BrightBlue #AA99FF (Dracula PRO Base 官方"亮紫"),
|
||||
* 按钮背景仍可用,accent-on 是 #1B1A23 强反差。
|
||||
*/
|
||||
:root[data-theme="dark"]
|
||||
{
|
||||
--bg: var(--c-bg-dark-neutral);
|
||||
--surface: var(--c-surface-dark-neutral);
|
||||
--surface-raised: var(--c-raised-dark-neutral);
|
||||
--surface-sunken: var(--c-sunken-dark-neutral);
|
||||
--surface-elev2: var(--c-elev2-dark-neutral);
|
||||
--divider: var(--c-divider-dark-neutral);
|
||||
--divider-strong: var(--c-divider-strong-dark);
|
||||
|
||||
--text: var(--c-foreground-dracula);
|
||||
--text-muted: var(--c-text-muted-dark-neutral);
|
||||
|
||||
--accent: var(--c-purple-400);
|
||||
--accent-soft: color-mix(in srgb, var(--accent) 20%, transparent);
|
||||
--accent-softer: color-mix(in srgb, var(--accent) 10%, transparent);
|
||||
--accent-ring: color-mix(in srgb, var(--accent) 36%, transparent);
|
||||
--accent-on: #1B1A23;
|
||||
|
||||
/* 5 色角色 —— Dracula Pro neon,中性背景下饱和度足够 */
|
||||
--info: var(--c-cyan); /* #80FFEA */
|
||||
--success: var(--c-green); /* #8AFF80 */
|
||||
--warn: var(--c-yellow); /* #FFFF80 */
|
||||
--error: var(--c-red); /* #FF9580 */
|
||||
--emphasis: var(--c-pink); /* #FF80BF */
|
||||
--orange: var(--c-orange); /* #FFCA80 */
|
||||
|
||||
--info-soft: color-mix(in srgb, var(--info) 14%, transparent);
|
||||
--success-soft: color-mix(in srgb, var(--success) 14%, transparent);
|
||||
--warn-soft: color-mix(in srgb, var(--warn) 14%, transparent);
|
||||
--error-soft: color-mix(in srgb, var(--error) 14%, transparent);
|
||||
--emphasis-soft: color-mix(in srgb, var(--emphasis) 14%, transparent);
|
||||
|
||||
--state-online: var(--success);
|
||||
--state-error: var(--error);
|
||||
--state-warn: var(--warn);
|
||||
|
||||
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.45),
|
||||
0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
--shadow-raised: 0 12px 28px rgba(0, 0, 0, 0.55),
|
||||
0 2px 6px rgba(0, 0, 0, 0.4);
|
||||
--shadow-overlay: 0 16px 40px rgba(0, 0, 0, 0.65);
|
||||
--shadow-accent: 0 10px 28px rgba(170, 153, 255, 0.34);
|
||||
|
||||
--avatar-bg: #000000;
|
||||
--avatar-fg: #FFFFFF;
|
||||
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
/* ===== System:未指定 data-theme 时跟随系统 ===== */
|
||||
@media (prefers-color-scheme: dark)
|
||||
{
|
||||
:root:not([data-theme])
|
||||
{
|
||||
--bg: var(--c-bg-dark-neutral);
|
||||
--surface: var(--c-surface-dark-neutral);
|
||||
--surface-raised: var(--c-raised-dark-neutral);
|
||||
--surface-sunken: var(--c-sunken-dark-neutral);
|
||||
--surface-elev2: var(--c-elev2-dark-neutral);
|
||||
--divider: var(--c-divider-dark-neutral);
|
||||
--divider-strong: var(--c-divider-strong-dark);
|
||||
|
||||
--text: var(--c-foreground-dracula);
|
||||
--text-muted: var(--c-text-muted-dark-neutral);
|
||||
|
||||
--accent: var(--c-purple-400);
|
||||
--accent-soft: color-mix(in srgb, var(--accent) 20%, transparent);
|
||||
--accent-softer: color-mix(in srgb, var(--accent) 10%, transparent);
|
||||
--accent-ring: color-mix(in srgb, var(--accent) 36%, transparent);
|
||||
--accent-on: #1B1A23;
|
||||
|
||||
--info: var(--c-cyan);
|
||||
--success: var(--c-green);
|
||||
--warn: var(--c-yellow);
|
||||
--error: var(--c-red);
|
||||
--emphasis: var(--c-pink);
|
||||
--orange: var(--c-orange);
|
||||
|
||||
--info-soft: color-mix(in srgb, var(--info) 14%, transparent);
|
||||
--success-soft: color-mix(in srgb, var(--success) 14%, transparent);
|
||||
--warn-soft: color-mix(in srgb, var(--warn) 14%, transparent);
|
||||
--error-soft: color-mix(in srgb, var(--error) 14%, transparent);
|
||||
--emphasis-soft: color-mix(in srgb, var(--emphasis) 14%, transparent);
|
||||
|
||||
--state-online: var(--success);
|
||||
--state-error: var(--error);
|
||||
--state-warn: var(--warn);
|
||||
|
||||
--shadow-card: 0 1px 2px rgba(0, 0, 0, 0.45),
|
||||
0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
--shadow-raised: 0 12px 28px rgba(0, 0, 0, 0.55),
|
||||
0 2px 6px rgba(0, 0, 0, 0.4);
|
||||
--shadow-overlay: 0 16px 40px rgba(0, 0, 0, 0.65);
|
||||
--shadow-accent: 0 10px 28px rgba(170, 153, 255, 0.34);
|
||||
|
||||
--avatar-bg: #000000;
|
||||
--avatar-fg: #FFFFFF;
|
||||
|
||||
color-scheme: dark;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user