MorseCode Card Style Adjustment 设计规格
日期:2026-07-18
状态:已确认
关联:GitHub issue #15
背景
Card#15 已完成首轮模板渲染、三阶段纵向工作区、实时 Preview、图片上传、分享与导出,并经过多轮布局和交互调整。当前 Style Adjustment 仍以第一版模板验证需求为中心:三个模板分别验证纯摩斯码、原文与摩斯码、背景和图标图片槽位,用户只能切换少量配色、字体、背景和可见性设置。
本轮把这些分散能力整合为更完整的主题自定义体验。核心变化是把 Minimal Signal 和 Photo Signal 合并为一个 Default 主题,同时让用户控制文字、背景和独立图标图层。Text and Signal 继续作为第二个独立主题存在。
目标
- 在 Style Adjustment 标题右侧提供当前主题全量 Reset。
- 将
Minimal Signal与Photo Signal合并为Default主题。 - 保留
Text and Signal主题,并让两个主题使用同一套基础自定义能力。 - 摩斯码始终展示,只允许用户开关原文。
- 关闭原文时让摩斯码在内容区域居中;开启时让原文位于摩斯码上方。
- 允许统一修改原文和摩斯码的字体、字号和颜色。
- 提供快捷配色,但不保留与自定义颜色竞争的独立 palette 状态。
- 支持可编辑双端点线性渐变、纯色或图片三种互斥背景模式。
- 图片背景支持裁切位置和模糊,不支持不透明度。
- 支持一个位于背景上、文字下的用户图标图层,并可调整位置、大小和不透明度。
- 品牌使用项目现有
favicon.svg,图标紧邻morsecodes.net左侧。 - 把设置面板改为更清晰的快捷配色条和四个职责单一的折叠分组。
- 保持 SVG 为唯一渲染模型,Preview、PNG 和 SVG 导出继续共享同一场景。
- 保持所有上传与渲染在浏览器本地完成。
非目标
- 不兼容
signal-minimal、signal-photo或其旧分享链接。 - 不缓存或恢复用户在不同主题中的独立调整。
- 不允许直接在 Preview 中拖拽、缩放或旋转图标。
- 不实现多色标渐变编辑器、径向渐变或任意 CSS 渐变字符串。
- 不支持背景图片不透明度。
- 不支持用户上传 SVG、字体或外部 URL 图片。
- 不增加自由图层排序、图层面板或通用画布编辑器。
- 不允许关闭摩斯码或关闭固定品牌。
- 不在
CardGenerator中放置 SEO 内容。 - 本轮不把现有 Card SEO 文案迁移到 Markdown 或其他组件;SEO 将在后续任务统一调整。
核心产品决策
主题集合
主题列表调整为:
signal-default,界面名称为Default。signal-dual,继续使用本地化名称Text and Signal。
signal-default 替换 signal-minimal 和 signal-photo,并成为 defaultTemplateId。删除的模板 ID 不设 alias,也不迁移旧配置。查询参数包含未知模板时,继续使用现有的通用未知模板回退行为,并显示本地化提示。
两个主题都开放文字、渐变/纯色/图片背景和用户图标能力。signal-dual 保留标签、分隔线和 Show labels 控件,因此仍然是独立视觉布局,而不是 signal-default 的配色变体。
Default 初始状态
signal-default 的主题默认值为:
- 原文关闭。
- 摩斯码在主要内容区域水平和垂直居中。
- 背景使用双端点蒸汽波线性渐变。
- 不包含用户背景图片或用户图标。
- 品牌固定显示在底部。
用户打开原文后,场景切换到双内容布局:原文在上,摩斯码在下,二者共用用户选择的字体、首选字号和文字颜色。
固定图层顺序
所有主题使用固定绘制顺序:
基础背景或背景图片
↓
用户图标
↓
原文与摩斯码、主题标签和分隔线
↓
favicon.svg + morsecodes.net用户不能改变该顺序。图标不能遮盖文字,品牌始终位于顶层。
Style Adjustment 信息架构
标题与 Reset
<h2 id="style"> 继续作为 VitePress Outline 和阶段导航目标。标题右侧增加 Lucide RotateCcw 图标按钮,尺寸、边框和交互密度与 Theme Gallery 的展开按钮一致。
Reset 按钮要求:
- 使用本地化
aria-label和 tooltip,不增加冗长的可见说明文字。 - 当前主题没有任何 override 或上传媒体时禁用。
- 点击后打开可访问的确认对话框。
- 确认后恢复当前主题的全部默认值,包含原文/标签可见性、文字、背景、上传图片、图标和所有媒体参数。
- 取消确认时不改变状态。
- Reset 期间使尚未完成的图片读取失效,晚到的异步结果不能重新写回已重置状态。
快捷配色条
快捷配色位于四个折叠组之前,因为它会同时修改文字与背景,不能错误归入“文字”或“背景”。
- 每个 swatch 是一组受信任的结构化文字颜色和背景值。
- 点击 swatch 直接把值写入当前 overrides,不保存
paletteId。 - 只有当前文字和背景全部匹配该预设时,swatch 才显示 pressed 状态。
- 用户随后修改任一相关值时,pressed 状态自动消失。
- 至少提供默认蒸汽波预设;其他预设数量保持精简,由模板声明。
四个设置组
设置面板按以下顺序显示:
- Content
- Text
- Background
- Icon
桌面端沿用当前默认展开行为,移动端沿用当前默认折叠行为。每个组独立展开和收起,Style Editor 继续作为第三阶段的内部滚动所有者。
设置行为
Content
两个主题都提供 Show original text。
signal-default默认关闭。signal-dual默认开启。- 关闭时隐藏原文及只服务于原文的标签或装饰,并切换到仅摩斯码布局。
- 开启时切换到原文在上、摩斯码在下的主题布局。
signal-dual 额外保留 Show labels。如果原文关闭,即使 Show labels 开启,原文标签也必须隐藏;摩斯码标签仍按 Show labels 决定是否显示。
删除所有主题中的 Show Morse code。摩斯码节点不存在 visibility override,也不能通过 URL 隐藏。
Text
原文和摩斯码共用一套文字设置:
- 字体。
- 首选字号。
- 文字颜色。
主题声明允许选择的安全字体栈、字号的最小值、最大值、步长和默认值。用户不上传字体。字号使用 1080 基准画布中的数值,UI 同时提供 range 和数值输入;两个输入始终同步并限制到主题范围。
用户字号是排版算法的首选最大字号,不取消现有自动适配。Renderer 仍可为了内容容纳而缩小实际字号,并在主题允许的最小字号仍无法容纳时返回现有 text overflow 错误。
文字颜色只接受规范化的安全十六进制颜色。主题标签、分隔线和品牌使用主题自己的固定样式,不受这组三项文字 override 影响。
Background
背景使用 Gradient / Solid / Image 三段控件,三种模式互斥渲染。设置组只显示当前模式的字段。
Gradient
第一版自定义渐变固定为两个色标:
- 起始颜色,offset 固定为 0。
- 结束颜色,offset 固定为 1。
- 角度,范围 0 到 359 度。
不允许增加色标、修改 offset 或输入 CSS。signal-default 的默认背景是模板声明的蒸汽波渐变。
Solid
纯色模式只提供一个安全十六进制颜色。进入纯色模式时使用当前主题声明的纯色默认值;用户此前在当前主题会话中调整过的纯色值可以恢复。
Image
图片模式接受 PNG、JPEG 和 WebP,并沿用现有文件大小、像素数和解码限制。提供:
- 上传、替换和移除。
- 图片位置 X/Y,用于控制
cover裁切焦点。 - 模糊,范围由主题声明,第一版为 0 到 40 个画布单位。
图片背景不提供不透明度。Blur 通过受控 SVG filter 实现,并对图片绘制区域做足够 overscan 和画布裁切,避免模糊后露出透明边缘。
首次选择 Image 且没有已加载图片时打开文件选择器。只有图片成功校验和解码后才提交 Image 模式;取消选择或加载失败时保留此前背景模式。切换到 Gradient 或 Solid 不立即销毁已上传背景图片,用户在同一主题会话内切回 Image 时可以继续使用;Reset、移除图片或切换主题会清除它。
Icon
Icon 组始终提供上传入口,只接受 PNG、JPEG 和 WebP。成功上传后才显示:
- 水平位置 X。
- 垂直位置 Y。
- 大小。
- 不透明度。
X/Y 表示图标中心相对画布的百分比。大小表示相对画布较短边的百分比。主题声明各项范围和默认值;位置根据当前大小动态 clamp,保证完整图标留在画布内。图标保持原始宽高比并使用 contain,不强制圆形 mask。
上传后的初始不透明度使用主题声明的低干扰默认值,使图标作为文字下方的水印层出现。Reset、移除图标或切换主题会清除图片和全部参数。
模板与状态模型
Schema v2
模板 schema 升级为 v2。新 schema 必须继续是可序列化纯数据,不包含函数、Vue 组件或原始 CSS。
TemplateCustomization 明确声明:
- visibility 控件及各自默认值。
- 共享 typography 控件、默认值和范围。
- 快捷配色 bundles。
- 背景允许模式、各模式默认值和范围。
- 背景图片能力。
- 图标槽位能力及几何范围。
模板另外声明基于已解析 visibility 的布局 variants。variant 只覆盖受影响元素的 frame 或受控排版属性。例如 signal-default 在原文关闭时为摩斯码使用居中 frame,在原文开启时使用下方 frame。
Scene resolver 根据通用条件选择 variant,不允许通过 template.id === 'signal-default' 之类的分支硬编码布局。
CardState
CardState 保留输入内容和当前模板 ID,并把自定义状态拆成职责清晰的结构化字段:
- visibility overrides。
- typography override。
- active background mode 及各模式的会话值。
- 用户背景图片及图片位置、模糊。
- 用户图标及位置、大小、不透明度。
主题默认值只存在于模板中。状态层对写入值做规范化:如果用户值等于主题默认值,就移除对应 override。这样 dirty 判断和 Reset 不需要复制一份默认状态,也不会因对象表示不同而误判。
主题切换
切换主题时:
- 保留输入模式、原文和摩斯码。
- 使当前图片读取请求失效。
- 清除 visibility、typography、background 和 icon 的全部 overrides 与上传媒体。
- 应用新主题默认值。
- 不缓存离开主题前的调整。
该行为与 Reset 使用同一个状态重置入口,区别仅在于目标模板不同。
渲染与资源边界
Scene 解析
Scene 解析顺序为:
- 读取模板默认值。
- 规范化并应用 CardState overrides。
- 解析 visibility。
- 选择匹配的 layout variant。
- 展开 generated 元素。
- 对原文和摩斯码应用共享 typography。
- 解析背景模式、图片 filter 和图标 geometry。
- 校验最终标准场景节点。
CardSettings 和 CardRenderer 都不根据模板 ID 决定功能。Settings 从 customization schema 生成控件,Renderer 只消费解析后的标准节点和受控资源。
favicon.svg
品牌不再使用 brand.mark 生成器。模板改用项目现有 docs/public/favicon.svg,并把图标与 morsecodes.net 放在同一水平品牌行中,favicon 紧邻文字左侧。
为了保持 SVG 下载独立可用,构建时把该受信任资源读取并内联到场景,而不是在导出 SVG 中留下站内相对 URL。Renderer 只对模板声明的受信任内置资源开放该路径;用户图片仍必须经过现有 raster Data URL 校验,不能借此上传或注入 SVG。
图片模糊
Renderer 为实际使用 blur 的背景节点创建稳定、实例隔离的 SVG filter ID。Filter 参数必须是有限且经过范围限制的数字。没有 blur 时不输出多余 filter。
Preview、序列化 SVG、SVG 下载和 Canvas PNG 栅格化继续使用同一份 filter 与节点几何,不能维护独立的 CSS Preview blur。
查询、分享与隐私
新查询格式只支持本轮 schema;不解析或迁移被删除模板的旧配置。
URL 可以保存:
- 输入模式和有效内容。
- 当前模板。
- visibility overrides,包括默认关闭但被用户打开的原文。
- 字体、首选字号和文字颜色。
- Gradient 或 Solid 背景模式及其安全值。
所有新增字符串和数值都必须有明确格式、长度和范围校验。查询参数继续使用独立的结构化 key,不接收任意 JSON、Data URL、Blob URL 或 CSS。
URL 不保存:
- 背景图片及其位置、模糊或 Image 模式。
- 用户图标及其位置、大小、不透明度。
- 快捷配色 ID,因为快捷配色不是持久状态。
当当前卡片使用 Image 背景时,生成的配置链接省略背景 override,接收者使用该主题默认背景;其余可序列化文字和 visibility 设置照常恢复。用户图标同样从配置链接中省略。
PNG、SVG 下载和系统图片分享包含当前已加载的背景图片、图标、模糊与全部视觉调整。上传数据仍只存在于浏览器内存,不写入 URL、存储或远端服务。
组件职责
CardGenerator
继续作为页面级编排器,负责:
- 唯一 CardState。
- 主题切换和全量 Reset。
- 渲染 Style 标题行及其 Reset 图标按钮。
- Reset 确认对话框状态。
- 图片请求竞态失效。
- Preview revision、下载和分享。
移除 CardSeo 的 import 和渲染。CardGenerator 的 DOM 在 Style 阶段结束后不追加 SEO prose。
CardSettings
负责:
- 快捷配色条。
- Content、Text、Background、Icon 四组控件。
- 根据 schema 和当前状态条件显示字段。
- 发出结构化意图事件,不直接解析模板场景元素。
为了避免单文件继续膨胀,可以按现有 card 组件风格把 Background 和 Icon 的字段组提取为小型、无业务状态的子组件;是否提取以实现时的实际复杂度为准,不预先建立通用表单框架。
useCardGenerator 与 scene
状态 composable 负责规范化写入、dirty 判断、主题默认恢复和查询应用。scene.ts 负责 visibility、layout variant、文字和媒体节点解析。Renderer 不承担表单状态规则。
CardSeo
删除无引用的 CardSeo.vue。九个 Card Markdown 页面保留现有 frontmatter 和 H1,本轮不补充、移动或重写 SEO 正文与本地化消息;相关统一调整另开任务。
错误与可访问性
- Reset 使用有标题、说明、确认和取消按钮的模态对话框,Escape 等价于取消,并把焦点还给 Reset 按钮。
- 所有图标按钮提供本地化 accessible name 和 tooltip。
- Background 使用真正的单选或 segmented-control 语义,不能只靠颜色表达当前模式。
- 快捷配色 swatch 提供本地化名称和 pressed 状态。
- Range 同时配套可编辑数值字段和可见标签;两者共享错误和范围约束。
- 颜色输入同时提供原生色板和规范化 hex 值。
- 图片加载失败不改变此前有效背景或图标状态,并显示现有风格的槽位内错误。
- Image 模式首次选择被取消时不产生空白或不可导出状态。
- 所有动态条件控件在隐藏后退出 tab 顺序。
- RTL locale 使用逻辑 CSS 属性;X/Y 数值继续表示画布坐标,不随界面方向镜像。
测试策略
单元测试
- 模板集合只包含
signal-default和signal-dual,默认模板正确。 - 两个主题的 customization schema、默认值和范围通过校验。
- 默认隐藏原文与默认显示原文都能产生正确 visibility override。
- 原文开关选择正确 layout variant,摩斯码始终存在。
- typography 同时应用于原文和摩斯码,不影响标签和品牌。
- 快捷配色匹配、失配和 override 规范化。
- 三种背景模式、双端点渐变、角度和 blur 范围。
- 图标 position/size clamp 和图层顺序。
- dirty、Reset、主题切换与异步图片请求失效。
- 新查询参数的往返、边界、非法输入拒绝和媒体省略。
- 删除的模板 ID 按未知模板处理,不做兼容映射。
组件测试
- Style 标题 Reset 按钮的 disabled、dialog、确认、取消和焦点恢复。
- 快捷配色位于四组之外,并正确更新背景和文字控件。
- Content 中没有
Show Morse code。 - Background 三段控件只显示当前模式字段。
- 选择 Image 取消或加载失败时保留此前背景。
- 图片模式没有 opacity,保留位置和 blur。
- Icon 上传前隐藏参数,上传后显示 X/Y、大小和不透明度。
favicon.svg与品牌文字同一行且顺序正确。CardGenerator不 import 或渲染CardSeo。
Renderer 与导出测试
- source off/on 的 SVG geometry 与居中行为。
- 背景图片 cover、裁切位置、blur filter ID 隔离和边缘覆盖。
- 图标始终位于文字之前、背景之后。
- 内联 favicon 不留下站内相对资源引用。
- SVG 下载独立包含所有当前视觉资源。
- PNG 栅格化与 Preview 使用相同渐变、blur、图标和品牌布局。
端到端测试
- Default 初始为居中摩斯码和蒸汽波渐变。
- 打开原文后切换为上原文、下摩斯码。
- 快捷配色、自定义文字、三种背景和图标调整实时更新 Preview。
- Reset 全量恢复并移除媒体。
- 切换主题不保留离开主题的调整。
- 下载、分享准备和配置 URL 在有无媒体时行为正确。
- 桌面和移动 Style Editor 可滚动、无重叠,Reset 始终可到达。
- RTL locale 的折叠组、Reset、数值控件和 Preview 不发生方向性错位。
完成标准
- Theme Gallery 只展示 Default 与 Text and Signal。
- Default 初始不显示原文,摩斯码居中。
- 所有主题始终展示摩斯码。
- Style Adjustment 使用全局快捷配色和四个确认的设置组。
- Reset 能完整、可确认地回到当前主题默认值。
- 用户能统一调整内容文字的字体、字号和颜色。
- 用户能选择并编辑双端点渐变、纯色或图片背景。
- 图片背景没有 opacity,具备位置和 blur。
- 用户图标可调整 X/Y、大小和不透明度,且图层正确。
- 品牌使用内联
favicon.svg并紧邻文字左侧。 - 主题切换清空视觉调整和上传媒体。
- 配置链接不包含任何上传数据,且不兼容已删除模板链接。
- CardGenerator 不包含 SEO 内容。
- 聚焦单元、组件、Renderer、导出和 E2E 测试全部通过。