@deernova/style 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/README.md +19 -9
  2. package/bin/cli.mjs +212 -32
  3. package/package.json +1 -1
  4. package/skill/SKILL.md +90 -22
  5. package/skill/assets/DeernovaTokens.swift +376 -0
  6. package/skill/assets/screens/iphone-button-sizes-dark.png +0 -0
  7. package/skill/assets/screens/iphone-button-sizes-light.png +0 -0
  8. package/skill/assets/screens/iphone-screens-dark.png +0 -0
  9. package/skill/assets/screens/iphone-screens-light.png +0 -0
  10. package/skill/assets/screens/mac-window-dark.png +0 -0
  11. package/skill/assets/screens/mac-window-light.png +0 -0
  12. package/skill/assets/tailwind.css +106 -0
  13. package/skill/assets/tokens.css +533 -0
  14. package/skill/assets/tokens.json +1686 -0
  15. package/skill/manifest.json +2 -22
  16. package/skill/references/components/banner.md +95 -0
  17. package/skill/references/components/button.md +181 -0
  18. package/skill/references/components/card.md +89 -0
  19. package/skill/references/components/code-block.md +77 -0
  20. package/skill/references/components/composer.md +206 -0
  21. package/skill/references/components/empty-state.md +63 -0
  22. package/skill/references/components/glass-controls.md +127 -0
  23. package/skill/references/components/list.md +130 -0
  24. package/skill/references/components/message.md +94 -0
  25. package/skill/references/components/segmented.md +79 -0
  26. package/skill/references/components/sheet.md +84 -0
  27. package/skill/references/components/sidebar.md +139 -0
  28. package/skill/references/components/step-row.md +135 -0
  29. package/skill/references/components/tag.md +86 -0
  30. package/skill/references/components/task-list.md +83 -0
  31. package/skill/references/components/text-field.md +86 -0
  32. package/skill/references/components/toolbar.md +139 -0
  33. package/skill/references/foundations/accessibility.md +27 -0
  34. package/skill/references/foundations/color.md +58 -0
  35. package/skill/references/foundations/elevation.md +17 -0
  36. package/skill/references/foundations/glass.md +36 -0
  37. package/skill/references/foundations/iconography.md +44 -0
  38. package/skill/references/foundations/motion.md +22 -0
  39. package/skill/references/foundations/radius.md +31 -0
  40. package/skill/references/foundations/spacing.md +38 -0
  41. package/skill/references/foundations/stroke.md +35 -0
  42. package/skill/references/foundations/typography.md +54 -0
  43. package/skill/references/foundations/writing.md +10 -0
  44. package/skill/references/review.md +26 -13
  45. package/skill/references/scenes/ios.md +61 -0
  46. package/skill/references/scenes/ipados.md +42 -0
  47. package/skill/references/scenes/macos.md +65 -0
  48. package/skill/references/scenes/swiftui.md +94 -0
  49. package/skill/references/scenes/web-marketing.md +34 -0
  50. package/skill/references/scenes/web.md +83 -0
  51. package/skill/references/tokens.md +441 -74
  52. package/skill/assets/design/README.md +0 -170
  53. package/skill/assets/design/components/Banner/README.md +0 -33
  54. package/skill/assets/design/components/Banner/preview.html +0 -26
  55. package/skill/assets/design/components/Button/README.md +0 -59
  56. package/skill/assets/design/components/Button/preview.html +0 -27
  57. package/skill/assets/design/components/Card/README.md +0 -31
  58. package/skill/assets/design/components/Card/preview.html +0 -24
  59. package/skill/assets/design/components/CodeBlock/README.md +0 -34
  60. package/skill/assets/design/components/CodeBlock/preview.html +0 -16
  61. package/skill/assets/design/components/Composer/README.md +0 -42
  62. package/skill/assets/design/components/Composer/preview.html +0 -28
  63. package/skill/assets/design/components/Cover/preview.html +0 -53
  64. package/skill/assets/design/components/EmptyState/README.md +0 -28
  65. package/skill/assets/design/components/EmptyState/preview.html +0 -16
  66. package/skill/assets/design/components/GlassControls/README.md +0 -43
  67. package/skill/assets/design/components/GlassControls/preview.html +0 -40
  68. package/skill/assets/design/components/ListGroup/README.md +0 -39
  69. package/skill/assets/design/components/ListGroup/preview.html +0 -22
  70. package/skill/assets/design/components/MacWindow/README.md +0 -27
  71. package/skill/assets/design/components/MacWindow/preview.html +0 -70
  72. package/skill/assets/design/components/Message/README.md +0 -31
  73. package/skill/assets/design/components/Message/preview.html +0 -21
  74. package/skill/assets/design/components/PhoneScreen/README.md +0 -25
  75. package/skill/assets/design/components/PhoneScreen/preview.html +0 -74
  76. package/skill/assets/design/components/Segmented/README.md +0 -21
  77. package/skill/assets/design/components/Segmented/preview.html +0 -21
  78. package/skill/assets/design/components/Sheet/README.md +0 -29
  79. package/skill/assets/design/components/Sheet/preview.html +0 -31
  80. package/skill/assets/design/components/Sidebar/README.md +0 -36
  81. package/skill/assets/design/components/Sidebar/preview.html +0 -20
  82. package/skill/assets/design/components/StepRow/README.md +0 -35
  83. package/skill/assets/design/components/StepRow/preview.html +0 -17
  84. package/skill/assets/design/components/Tag/README.md +0 -36
  85. package/skill/assets/design/components/Tag/preview.html +0 -22
  86. package/skill/assets/design/components/TextField/README.md +0 -29
  87. package/skill/assets/design/components/TextField/preview.html +0 -28
  88. package/skill/assets/design/components/bundle.css +0 -189
  89. package/skill/assets/design/design-system.json +0 -25
  90. package/skill/assets/design/images/Banner-dark.png +0 -0
  91. package/skill/assets/design/images/Banner-light.png +0 -0
  92. package/skill/assets/design/images/Button-dark.png +0 -0
  93. package/skill/assets/design/images/Button-light.png +0 -0
  94. package/skill/assets/design/images/Card-dark.png +0 -0
  95. package/skill/assets/design/images/Card-light.png +0 -0
  96. package/skill/assets/design/images/CodeBlock-dark.png +0 -0
  97. package/skill/assets/design/images/CodeBlock-light.png +0 -0
  98. package/skill/assets/design/images/Composer-dark.png +0 -0
  99. package/skill/assets/design/images/Composer-light.png +0 -0
  100. package/skill/assets/design/images/Cover-dark.png +0 -0
  101. package/skill/assets/design/images/Cover-light.png +0 -0
  102. package/skill/assets/design/images/EmptyState-dark.png +0 -0
  103. package/skill/assets/design/images/EmptyState-light.png +0 -0
  104. package/skill/assets/design/images/Example-iOSButtonsInPhone-dark.png +0 -0
  105. package/skill/assets/design/images/Example-iOSButtonsInPhone-light.png +0 -0
  106. package/skill/assets/design/images/GlassControls-dark.png +0 -0
  107. package/skill/assets/design/images/GlassControls-light.png +0 -0
  108. package/skill/assets/design/images/ListGroup-dark.png +0 -0
  109. package/skill/assets/design/images/ListGroup-light.png +0 -0
  110. package/skill/assets/design/images/MacWindow-dark.png +0 -0
  111. package/skill/assets/design/images/MacWindow-light.png +0 -0
  112. package/skill/assets/design/images/Message-dark.png +0 -0
  113. package/skill/assets/design/images/Message-light.png +0 -0
  114. package/skill/assets/design/images/PhoneScreen-dark.png +0 -0
  115. package/skill/assets/design/images/PhoneScreen-light.png +0 -0
  116. package/skill/assets/design/images/Segmented-dark.png +0 -0
  117. package/skill/assets/design/images/Segmented-light.png +0 -0
  118. package/skill/assets/design/images/Sheet-dark.png +0 -0
  119. package/skill/assets/design/images/Sheet-light.png +0 -0
  120. package/skill/assets/design/images/Sidebar-dark.png +0 -0
  121. package/skill/assets/design/images/Sidebar-light.png +0 -0
  122. package/skill/assets/design/images/StepRow-dark.png +0 -0
  123. package/skill/assets/design/images/StepRow-light.png +0 -0
  124. package/skill/assets/design/images/Tag-dark.png +0 -0
  125. package/skill/assets/design/images/Tag-light.png +0 -0
  126. package/skill/assets/design/images/TextField-dark.png +0 -0
  127. package/skill/assets/design/images/TextField-light.png +0 -0
  128. package/skill/assets/design/tokens.css +0 -187
  129. package/skill/assets/design/tokens.json +0 -142
  130. package/skill/references/components.md +0 -648
  131. package/skill/references/foundations.md +0 -170
  132. package/skill/references/native.md +0 -7
  133. package/skill/references/web.md +0 -11
@@ -1,43 +0,0 @@
1
- # GlassControls
2
-
3
- 浮在内容之上的玻璃操作层:工具栏按钮组、标签栏、浮动操作按钮。
4
-
5
- **什么时候用**:用户在浏览内容时随时要用到的操作,比如新建、搜索、切换页面、分享。内容本身永远不放在玻璃上。
6
-
7
- **需要提供**:每个按钮的 SF Symbol 和无障碍标签(`accessibilityLabel`)、点击动作;如果是标签栏,还要提供当前选中项。
8
-
9
- **规格**
10
-
11
- - 单个玻璃按钮:圆形,`control-ios`(44)。
12
- - 按钮组:胶囊形,内部按钮 36pt,间距 2pt。相邻的玻璃元素放进同一个 `GlassEffectContainer`,间距 `space-3`。
13
- - 选中项:图标从 `ink-secondary` 变成 `ink`,底色 `fill-selected`。
14
- - 实色玻璃(`accent` 底、`on-accent` 图标,也就是黑底白图标)一屏只用一次,留给主操作,比如「新建」。
15
-
16
- ```swift
17
- // 标准标签栏与工具栏,系统自动渲染为玻璃
18
- TabView {
19
- Tab("笔记", systemImage: "doc.text") { NotesView() }
20
- Tab("收藏", systemImage: "star") { FavoritesView() }
21
- Tab(role: .search) { SearchView() } // 搜索单独成为右侧的圆形玻璃按钮
22
- }
23
- .tabBarMinimizeBehavior(.onScrollDown)
24
- .tint(.brandAccent)
25
-
26
- // 自定义浮动按钮
27
- GlassEffectContainer(spacing: 12) {
28
- HStack(spacing: 12) {
29
- Button("搜索", systemImage: "magnifyingglass") { search() }
30
- .buttonStyle(.glass)
31
- Button("新建", systemImage: "plus") { create() }
32
- .buttonStyle(.glassProminent)
33
- }
34
- .labelStyle(.iconOnly)
35
- }
36
-
37
- // 完全自定义形状时
38
- Image(systemName: "mic")
39
- .frame(width: 44, height: 44)
40
- .glassEffect(.regular.interactive(), in: .circle)
41
- ```
42
-
43
- **不要**:在玻璃上放段落文字或列表;玻璃叠玻璃;给工具栏加实色背景挡住滚动边缘效果;同一屏出现两个实色玻璃。
@@ -1,40 +0,0 @@
1
- <!-- @dsCard group="Actions" height=260 subtitle="浮在内容之上的操作层" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>GlassControls</title>
5
- <style>
6
- .scene { position: relative; height: 260px; overflow: hidden; background: var(--surface); }
7
- .content { position: absolute; inset: 0; padding: var(--space-4); display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-2); }
8
- .content .dn-card { width: auto; }
9
- .bar { position: absolute; left: 0; right: 0; bottom: var(--space-4); display: flex; justify-content: center; align-items: center; gap: var(--space-3); }
10
- .top { position: absolute; top: var(--space-2); right: var(--space-4); display: flex; gap: var(--space-2); }
11
- </style>
12
- </head>
13
- <body>
14
- <div class="scene">
15
- <div class="content" aria-hidden="true">
16
- <div class="dn-card"><p class="dn-card-title">本周回顾</p><p class="dn-card-body">完成 12 条笔记,整理了两个项目的待办。</p><div class="dn-card-meta">今天 09:41</div></div>
17
- <div class="dn-card"><p class="dn-card-title">读书摘录</p><p class="dn-card-body">好的工具会退到背景里,让人只看见自己的工作。</p><div class="dn-card-meta">昨天</div></div>
18
- <div class="dn-card"><p class="dn-card-title">旅行清单</p><p class="dn-card-body">护照、转换插头、两本书、一件薄外套。</p><div class="dn-card-meta">10 月 28 日</div></div>
19
- <div class="dn-card"><p class="dn-card-title">产品想法</p><p class="dn-card-body">一个账号打通所有应用,订阅一次全部可用。</p><div class="dn-card-meta">10 月 26 日</div></div>
20
- <div class="dn-card"><p class="dn-card-title">会议记录</p><p class="dn-card-body">下周三前确定首页的信息层级。</p><div class="dn-card-meta">10 月 25 日</div></div>
21
- <div class="dn-card"><p class="dn-card-title">周末</p><p class="dn-card-body">去山里走走,带上相机。</p><div class="dn-card-meta">10 月 24 日</div></div>
22
- </div>
23
- <div class="top">
24
- <div class="dn-glass dn-glass-group">
25
- <button class="dn-glass-btn" aria-label="分享"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 3v12M8 7l4-4 4 4M5 13v6h14v-6"/></svg></button>
26
- <button class="dn-glass-btn" aria-label="更多"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="6" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="18" cy="12" r="1"/></svg></button>
27
- </div>
28
- </div>
29
- <div class="bar">
30
- <div class="dn-glass dn-glass-group">
31
- <button class="dn-glass-btn is-selected" aria-label="笔记"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M7 3h7l5 5v13H7z"/><path d="M14 3v5h5"/></svg></button>
32
- <button class="dn-glass-btn" aria-label="收藏"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 4l2.4 5 5.6.6-4.2 3.8 1.2 5.5L12 16l-5 2.9 1.2-5.5L4 9.6l5.6-.6z"/></svg></button>
33
- <button class="dn-glass-btn" aria-label="设置"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/></svg></button>
34
- </div>
35
- <button class="dn-glass dn-glass-btn" aria-label="搜索"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="M20 20l-4.5-4.5"/></svg></button>
36
- <button class="dn-glass dn-glass-btn dn-glass-prominent" aria-label="新建"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg></button>
37
- </div>
38
- </div>
39
- </body>
40
- </html>
@@ -1,39 +0,0 @@
1
- # ListGroup
2
-
3
- iOS 分组列表,用于设置页、详情页和各种表单。
4
-
5
- **需要提供**:分组,每个分组可以有页头和页脚说明;每一行提供标题,以及可选的图标、右侧的值、开关或箭头,点击后跳转或执行动作。
6
-
7
- **规格**
8
-
9
- - 页面底色 `canvas`,分组底色 `surface-raised`,`radius-lg`,左右边距 `space-4`,分组之间 `space-5`。
10
- - 每行最小高度 `control-ios`(44),左右内边距 `space-4`,文字 17pt `ink`;右侧的值用 `ink-secondary`,箭头用 `ink-tertiary`。
11
- - 图标放在 28pt 的方块里,`accent-soft` 浅灰底、`ink` 图标、`radius-sm`。整个列表统一用灰色,不要每行一个颜色。
12
- - 分隔线 `stroke-hairline`、`line` 色,从文字起点开始。
13
- - 页头 13pt `ink-secondary`,页脚 13pt `ink-tertiary`,页脚写清楚这个设置会带来什么后果。
14
- - 开关打开时用 `success` 色。不要用黑白色调的开关:深色主题下白色轨道会把白色圆钮吞掉。
15
-
16
- ```swift
17
- Form {
18
- Section("账号") {
19
- NavigationLink { ProfileView() } label: {
20
- LabeledContent { Text("林一") } label: { Label("个人资料", systemImage: "person") }
21
- }
22
- }
23
- Section {
24
- Toggle(isOn: $iCloudSync) { Label("iCloud 同步", systemImage: "icloud") }
25
- .tint(.success)
26
- } header: {
27
- Text("同步")
28
- } footer: {
29
- Text("关闭 iCloud 同步后,新笔记只保存在这台设备上。")
30
- }
31
- }
32
- .scrollContentBackground(.hidden)
33
- .background(.canvas)
34
- .tint(.brandAccent)
35
- ```
36
-
37
- Mac 上的设置窗口同样用 `Form` 加 `.formStyle(.grouped)`,系统会给出对应的 Mac 样式。
38
-
39
- **不要**:每行用不同颜色的图标;页脚写成一大段;在列表行里放主按钮(主按钮放在页面底部)。
@@ -1,22 +0,0 @@
1
- <!-- @dsCard group="Navigation" height=420 subtitle="iOS 分组列表与设置页" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>ListGroup</title></head>
5
- <body>
6
- <div class="dn-stage" style="padding:0">
7
- <div class="dn-listwrap">
8
- <div class="dn-list-head">账号</div>
9
- <div class="dn-list">
10
- <div class="dn-list-row has-icon"><span class="dn-list-icon"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="12" cy="8" r="4"/><path d="M4 20a8 8 0 0 1 16 0"/></svg></span>个人资料<span class="dn-list-value">林一</span><svg class="dn-icon dn-chevron" viewBox="0 0 24 24"><path d="M9 6l6 6-6 6"/></svg></div>
11
- <div class="dn-list-row has-icon"><span class="dn-list-icon"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 4l2.4 5 5.6.6-4.2 3.8 1.2 5.5L12 16l-5 2.9 1.2-5.5L4 9.6l5.6-.6z"/></svg></span>订阅<span class="dn-list-value">全家桶 · 年付</span><svg class="dn-icon dn-chevron" viewBox="0 0 24 24"><path d="M9 6l6 6-6 6"/></svg></div>
12
- </div>
13
- <div class="dn-list-head" style="margin-top:var(--space-6)">同步</div>
14
- <div class="dn-list">
15
- <div class="dn-list-row has-icon"><span class="dn-list-icon"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M7 18a4 4 0 0 1-.5-8 6 6 0 0 1 11.5 1.5A3.5 3.5 0 0 1 17.5 18z"/></svg></span>iCloud 同步<span class="dn-switch" role="img" aria-label="已开启"></span></div>
16
- <div class="dn-list-row has-icon"><span class="dn-list-icon"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M6 16V11a6 6 0 0 1 12 0v5l2 2H4z"/><path d="M10 20h4"/></svg></span>同步完成时通知我<span class="dn-switch is-off" role="img" aria-label="已关闭"></span></div>
17
- </div>
18
- <div class="dn-list-foot">关闭 iCloud 同步后,新笔记只保存在这台设备上。</div>
19
- </div>
20
- </div>
21
- </body>
22
- </html>
@@ -1,27 +0,0 @@
1
- # MacWindow
2
-
3
- Mac 应用窗口的标准结构:左边是悬浮的玻璃侧边栏,右边内容区的上方浮着玻璃工具栏,下方浮着 Composer。
4
-
5
- **结构**
6
-
7
- - 窗口底色 `canvas`。侧边栏是 `NavigationSplitView` 的 sidebar 列,系统会渲染成悬浮的玻璃面板。
8
- - 工具栏用 `.toolbar` 声明,标题用 `mac-headline`;右侧的按钮组由系统渲染成玻璃胶囊。内容从工具栏下面滚过去。
9
- - 内容区居中,阅读栏宽不超过 `content-max`,左右边距 `space-4`。
10
- - 底部的 Composer 悬浮在内容之上,它承载输入的内容,所以是纸面,不是玻璃。用 `.safeAreaInset(edge: .bottom)` 放置,让内容可以滚到它的上方。
11
-
12
- ```swift
13
- NavigationSplitView {
14
- SidebarView()
15
- } detail: {
16
- ScrollView { ThreadView().frame(maxWidth: 680) }
17
- .safeAreaInset(edge: .bottom) { Composer().padding(16) }
18
- .navigationTitle(chat.title)
19
- .toolbar {
20
- ToolbarItemGroup {
21
- ShareLink(item: chat.url)
22
- Menu("更多", systemImage: "ellipsis") { … }
23
- }
24
- }
25
- }
26
- .background(.canvas)
27
- ```
@@ -1,70 +0,0 @@
1
- <!-- @dsCard group="Layouts" height=590 width=960 subtitle="组合示例:Mac 窗口" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>MacWindow</title>
5
- <style>
6
- body { background: var(--surface-sunken); }
7
- .win { position: relative; margin: 16px; height: 528px; border-radius: var(--radius-lg); background: var(--canvas); border: var(--stroke-hairline) solid var(--line); box-shadow: var(--shadow-float); overflow: hidden; display: flex; }
8
- .side.dn-glass { margin: 8px; width: var(--sidebar-mac); flex: none; border-radius: var(--radius-lg); padding: var(--space-2); display: flex; flex-direction: column; gap: 1px; }
9
- .lights { display: flex; gap: 8px; padding: 6px 6px 12px; }
10
- .lights span { width: 12px; height: 12px; border-radius: var(--radius-full); background: var(--line-control); }
11
- .main { flex: 1; position: relative; min-width: 0; }
12
- .toolbar { position: absolute; top: 10px; left: 12px; right: 16px; display: flex; align-items: center; gap: var(--space-2); z-index: 2; }
13
- .toolbar .title { font-size: 13px; font-weight: 600; color: var(--ink); padding-left: var(--space-1); }
14
- .toolbar .dn-glass-group .dn-glass-btn { width: 32px; height: 32px; }
15
- .toolbar .dn-glass-group .dn-icon { width: 16px; height: 16px; }
16
- .scroll { position: absolute; inset: 0; padding: 56px var(--space-4) 0; display: flex; justify-content: center; }
17
- .scroll .dn-thread { max-width: 600px; }
18
- .dock { position: absolute; left: 0; right: 0; bottom: 16px; display: flex; justify-content: center; padding: 0 var(--space-4); }
19
- </style>
20
- </head>
21
- <body>
22
- <div class="win">
23
- <nav class="side dn-glass" aria-label="侧边栏">
24
- <div class="lights" aria-hidden="true"><span></span><span></span><span></span></div>
25
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg><span class="dn-side-text">新建对话</span><span class="dn-count">⌘N</span></div>
26
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="M20 20l-4.5-4.5"/></svg><span class="dn-side-text">搜索</span></div>
27
- <div class="dn-side-head">项目</div>
28
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span class="dn-side-text">工作</span><span class="dn-count">41</span></div>
29
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span class="dn-side-text">生活</span><span class="dn-count">17</span></div>
30
- <div class="dn-side-head">最近</div>
31
- <div class="dn-side-item is-selected"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M5 5h14v10H9l-4 4z"/></svg><span class="dn-side-text">把周报整理成三条要点</span></div>
32
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M5 5h14v10H9l-4 4z"/></svg><span class="dn-side-text">下周去杭州的行程和预算</span></div>
33
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M5 5h14v10H9l-4 4z"/></svg><span class="dn-side-text">订阅页文案改三版</span></div>
34
- </nav>
35
- <section class="main">
36
- <div class="toolbar">
37
- <span class="title">把周报整理成三条要点</span>
38
- <span class="dn-spacer"></span>
39
- <div class="dn-glass dn-glass-group">
40
- <button class="dn-glass-btn" aria-label="分享"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 3v12M8 7l4-4 4 4M5 13v6h14v-6"/></svg></button>
41
- <button class="dn-glass-btn" aria-label="更多"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="6" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="18" cy="12" r="1"/></svg></button>
42
- </div>
43
- </div>
44
- <div class="scroll">
45
- <div class="dn-thread">
46
- <div class="dn-msg-user">帮我把这份周报整理成三条要点</div>
47
- <div class="dn-steps">
48
- <div class="dn-step dn-step-ok"><svg class="dn-icon dn-glyph" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M8 12.5l2.5 2.5L16 9.5"/></svg><span class="dn-step-name">读取</span><span class="dn-step-text">周报草稿.md、10 月数据.csv</span><span class="dn-step-meta">0.4 秒</span></div>
49
- </div>
50
- <div class="dn-msg-assistant">
51
- <p>这周的进展可以归成三件事:</p>
52
- <p><strong>首页改版定稿。</strong>信息层级按「最近、收藏、全部」排列,下周三前交给开发。<br><strong>同步问题修复。</strong>离线编辑后重复保存的问题已经解决。<br><strong>订阅转化提升。</strong>全家桶年付的转化率从 3.1% 升到 4.4%。</p>
53
- </div>
54
- </div>
55
- </div>
56
- <div class="dock">
57
- <div class="dn-composer">
58
- <textarea id="mw" rows="1" aria-label="消息" placeholder="继续追问,或拖入文件"></textarea>
59
- <div class="dn-composer-bar">
60
- <button class="dn-iconbtn" aria-label="添加附件"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg></button>
61
- <button class="dn-chip">标准模式<svg class="dn-icon" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg></button>
62
- <span class="dn-spacer"></span>
63
- <button class="dn-send" disabled aria-label="发送"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 19V5M6 11l6-6 6 6"/></svg></button>
64
- </div>
65
- </div>
66
- </div>
67
- </section>
68
- </div>
69
- </body>
70
- </html>
@@ -1,31 +0,0 @@
1
- # Message
2
-
3
- 对话里的一条消息。用户说的话放在凹下去的气泡里,AI 的回答直接排在纸面上,用衬线字体,像一页文章。
4
-
5
- **需要提供**:发送者(用户或 AI)、内容(Markdown,可以包含代码块、列表、链接)、AI 消息的操作(复制、重新生成),以及生成中的状态。
6
-
7
- **规格**
8
-
9
- - 用户消息:靠右,最大宽度 80%,`surface-sunken` 底,`radius-lg`,内边距上下 6pt、左右 `space-3`;Mac 用 `mac-body`,iOS 用 `ios-callout`。
10
- - AI 消息:靠左,不加气泡,正文用 `mac-prose` 或 `ios-prose`,栏宽不超过 `content-max`。代码块用 CodeBlock,执行步骤用 StepRow。
11
- - 消息之间间距 `space-4`,段落之间 `space-2`。
12
- - 操作按钮放在 AI 消息下方,22pt 图标按钮,`ink-tertiary` 色,Mac 上只在悬停时显示,iOS 上一直显示。
13
- - 链接用 `ink` 色,加 1pt 的 `line-control` 色下划线,下偏移 3pt。
14
- - 生成中:回答末尾显示一个闪烁的光标,Composer 的发送按钮变成「停止」。
15
-
16
- ```swift
17
- // 用户消息
18
- Text(message.text)
19
- .padding(.vertical, 6).padding(.horizontal, 12)
20
- .background(.surfaceSunken, in: .rect(cornerRadius: 12))
21
- .frame(maxWidth: .infinity, alignment: .trailing)
22
-
23
- // AI 消息:用 AttributedString(markdown:) 渲染,或接入 Markdown 渲染库
24
- Text(try AttributedString(markdown: message.text))
25
- .font(.system(.body, design: .serif))
26
- .lineSpacing(4)
27
- .textSelection(.enabled)
28
- .frame(maxWidth: 680, alignment: .leading)
29
- ```
30
-
31
- **不要**:给 AI 回答也加气泡;用头像区分谁在说话(靠位置和字体就够了);在正文里用彩色强调文字(强调用加粗)。
@@ -1,21 +0,0 @@
1
- <!-- @dsCard group="Content" height=290 subtitle="对话:用户气泡与衬线回答" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>Message</title></head>
5
- <body>
6
- <div class="dn-stage" style="justify-content:center">
7
- <div class="dn-thread">
8
- <div class="dn-msg-user">帮我把这份周报整理成三条要点</div>
9
- <div class="dn-msg-assistant">
10
- <p>这周的进展可以归成三件事:</p>
11
- <p><strong>首页改版定稿。</strong>信息层级按「最近、收藏、全部」排列,下周三前交给开发。<br><strong>同步问题修复。</strong>离线编辑后重复保存的问题已经解决,影响了约 2% 的用户。<br><strong>订阅转化提升。</strong>全家桶年付的转化率从 3.1% 升到 4.4%。</p>
12
- <p>需要的话,我可以按 <a href="#">周报模板</a> 再排一次版。</p>
13
- <div class="dn-msg-actions">
14
- <button class="dn-iconbtn" aria-label="复制"><svg class="dn-icon" viewBox="0 0 24 24"><rect x="8" y="8" width="12" height="12" rx="2"/><path d="M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"/></svg></button>
15
- <button class="dn-iconbtn" aria-label="重新生成"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M4 12a8 8 0 1 0 2.3-5.6"/><path d="M4 4v4h4"/></svg></button>
16
- </div>
17
- </div>
18
- </div>
19
- </div>
20
- </body>
21
- </html>
@@ -1,25 +0,0 @@
1
- # PhoneScreen
2
-
3
- iPhone 上的两种典型页面:一个列表页,一个对话页。展示纸面和玻璃在手机上怎么分层。
4
-
5
- **列表页**
6
-
7
- - 衬线大标题(`ios-large-title`),内容是 `radius-lg` 的卡片,左右边距 `space-4`,卡片之间 `space-2`。
8
- - 底部是玻璃标签栏,搜索单独成为右侧的圆形玻璃按钮(`Tab(role: .search)`)。向下滚动时标签栏收起。
9
-
10
- **对话页**
11
-
12
- - 顶部的返回和更多按钮是系统导航栏提供的玻璃圆形按钮,标题用 17pt 半粗。
13
- - 对话内容:AI 回答用 `ios-prose`,用户消息用 `ios-callout`。
14
- - 底部的 Composer 收成单行胶囊(`radius-xl`),用 `.safeAreaInset(edge: .bottom)` 悬浮在内容上方;输入多行时向上增长。
15
-
16
- ```swift
17
- NavigationStack {
18
- ScrollView { ThreadView().padding(.horizontal, 16) }
19
- .safeAreaInset(edge: .bottom) { Composer().padding(.horizontal, 12) }
20
- .navigationTitle("周报整理")
21
- .navigationBarTitleDisplayMode(.inline)
22
- .toolbar { ToolbarItem { Menu("更多", systemImage: "ellipsis") { … } } }
23
- }
24
- .background(.canvas)
25
- ```
@@ -1,74 +0,0 @@
1
- <!-- @dsCard group="Layouts" height=780 width=840 subtitle="组合示例:iPhone 列表页与对话页" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>PhoneScreen</title>
5
- <style>
6
- body { background: var(--surface-sunken); }
7
- .pair { display: flex; gap: 40px; justify-content: center; padding: 30px 20px; }
8
- .phone { position: relative; width: 375px; height: 720px; border-radius: calc(var(--radius-xl) + var(--space-4)); background: var(--canvas); border: var(--stroke-hairline) solid var(--line); box-shadow: var(--shadow-float); overflow: hidden; flex: none; }
9
- .status { height: 50px; padding: 16px 32px 0; font-size: 15px; font-weight: 600; color: var(--ink); }
10
- .large { font-family: var(--font-serif); font-size: 30px; line-height: 36px; font-weight: 600; letter-spacing: -0.01em; margin: 6px 16px 12px; color: var(--ink); }
11
- .cards { display: flex; flex-direction: column; gap: var(--space-2); padding: 0 16px; }
12
- .cards .dn-card { width: auto; border-radius: var(--radius-lg); padding: 14px var(--space-4); }
13
- .cards .dn-card-title { font-size: 17px; line-height: 22px; }
14
- .cards .dn-card-body { font-size: 13px; line-height: 17px; }
15
- .tabs { position: absolute; left: 16px; right: 16px; bottom: 28px; display: flex; align-items: center; gap: var(--space-3); }
16
- .tabbar { flex: 1; display: flex; justify-content: space-around; padding: 4px; }
17
- .tab { display: flex; flex-direction: column; align-items: center; gap: 1px; width: 84px; padding: 5px 0; border-radius: var(--radius-full); font-size: 10px; font-weight: 500; color: var(--ink-secondary); }
18
- .tab .dn-icon { width: 21px; height: 21px; }
19
- .tab.is-selected { background: var(--fill-selected); color: var(--ink); }
20
- .tabs .dn-glass-btn { width: 54px; height: 54px; }
21
- .nav { position: absolute; top: 50px; left: 16px; right: 16px; display: flex; align-items: center; justify-content: space-between; z-index: 2; }
22
- .nav .t { font-size: 15px; font-weight: 600; color: var(--ink); }
23
- .chat { position: absolute; inset: 106px 16px 110px; display: flex; flex-direction: column; gap: var(--space-3); }
24
- .chat .dn-msg-user { font-size: 15px; line-height: 20px; padding: 8px 14px; }
25
- .chat .dn-msg-assistant { font-size: 17px; line-height: 26px; }
26
- .chat .dn-msg-assistant p { margin-bottom: var(--space-2); }
27
- .chat .dn-step { padding: 0; font-size: 13px; }
28
- .bottom { position: absolute; left: 12px; right: 12px; bottom: 28px; }
29
- .bottom .dn-composer { border-radius: var(--radius-xl); padding: var(--space-2) var(--space-2) var(--space-2) var(--space-4); flex-direction: row; align-items: center; }
30
- .bottom textarea { min-height: 0; height: 24px; font-size: 17px; line-height: 24px; padding: 0; }
31
- .bottom .dn-send { width: 32px; height: 32px; }
32
- </style>
33
- </head>
34
- <body>
35
- <div class="pair">
36
- <div class="phone">
37
- <div class="status">9:41</div>
38
- <div class="large">笔记</div>
39
- <div class="cards">
40
- <article class="dn-card"><p class="dn-card-title">本周回顾</p><p class="dn-card-body">完成 12 条笔记,整理了两个项目的待办,下周重点是首页改版。</p><div class="dn-card-meta"><span class="dn-tag dn-tag-success"><span class="dn-dot"></span>已同步</span><span>今天 09:41</span></div></article>
41
- <article class="dn-card"><p class="dn-card-title">读书摘录</p><p class="dn-card-body">好的工具会退到背景里,让人只看见自己的工作。</p><div class="dn-card-meta"><span>昨天</span><span>·</span><span>阅读</span></div></article>
42
- <article class="dn-card"><p class="dn-card-title">旅行清单</p><p class="dn-card-body">护照、转换插头、两本书、一件薄外套。</p><div class="dn-card-meta"><span>10 月 28 日</span></div></article>
43
- </div>
44
- <div class="tabs">
45
- <div class="tabbar dn-glass">
46
- <div class="tab is-selected"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M7 3h7l5 5v13H7z"/><path d="M14 3v5h5"/></svg>笔记</div>
47
- <div class="tab"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M5 5h14v10H9l-4 4z"/></svg>对话</div>
48
- <div class="tab"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M4 7h10M18 7h2M4 17h4M12 17h8"/><circle cx="16" cy="7" r="2"/><circle cx="10" cy="17" r="2"/></svg>设置</div>
49
- </div>
50
- <button class="dn-glass dn-glass-btn" aria-label="搜索"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="M20 20l-4.5-4.5"/></svg></button>
51
- </div>
52
- </div>
53
- <div class="phone">
54
- <div class="status">9:41</div>
55
- <div class="nav">
56
- <button class="dn-glass dn-glass-btn" aria-label="返回"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M15 6l-6 6 6 6"/></svg></button>
57
- <span class="t">周报整理</span>
58
- <button class="dn-glass dn-glass-btn" aria-label="更多"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="6" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="18" cy="12" r="1"/></svg></button>
59
- </div>
60
- <div class="chat">
61
- <div class="dn-msg-user">帮我把这份周报整理成三条要点</div>
62
- <div class="dn-step dn-step-ok"><svg class="dn-icon dn-glyph" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M8 12.5l2.5 2.5L16 9.5"/></svg><span class="dn-step-name">读取</span><span class="dn-step-text">周报草稿.md</span><span class="dn-step-meta">0.4 秒</span></div>
63
- <div class="dn-msg-assistant"><p><strong>首页改版定稿。</strong>下周三前交给开发。</p><p><strong>同步问题修复。</strong>离线编辑后重复保存的问题已解决。</p><p><strong>订阅转化提升。</strong>年付转化率从 3.1% 升到 4.4%。</p></div>
64
- </div>
65
- <div class="bottom">
66
- <div class="dn-composer">
67
- <textarea id="ps" rows="1" aria-label="消息" placeholder="继续追问"></textarea>
68
- <button class="dn-send" disabled aria-label="发送"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 19V5M6 11l6-6 6 6"/></svg></button>
69
- </div>
70
- </div>
71
- </div>
72
- </div>
73
- </body>
74
- </html>
@@ -1,21 +0,0 @@
1
- # Segmented
2
-
3
- 分段控件,在同一份数据的 2–4 种视图或范围之间切换。
4
-
5
- **需要提供**:选项列表(每项 2–4 个字,或者一个 SF Symbol)和绑定的选中值。
6
-
7
- **规格**:底槽 `fill-selected`;选中块 `surface-raised` 加 `shadow-control`;未选中文字 `ink-secondary`,选中文字 `ink`。Mac 上外层 `radius-sm`、内边距 2,内层 `radius-xs`,两层同心;高度 `control-mac-sm`。iOS 上是胶囊形,高 32pt。
8
-
9
- ```swift
10
- Picker("视图", selection: $mode) {
11
- Text("列表").tag(Mode.list)
12
- Text("卡片").tag(Mode.cards)
13
- Text("日历").tag(Mode.calendar)
14
- }
15
- .pickerStyle(.segmented)
16
- .labelsHidden()
17
- ```
18
-
19
- 直接用系统控件就能得到上面的效果,不需要自己画。
20
-
21
- **不要**:选项超过 4 个(改用 Menu 或 Picker);拿它当执行动作的按钮组;文字长短差别太大。
@@ -1,21 +0,0 @@
1
- <!-- @dsCard group="Actions" height=130 subtitle="在 2–4 个视图之间切换" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>Segmented</title></head>
5
- <body>
6
- <div class="dn-stage dn-stack" style="align-items:flex-start">
7
- <div class="dn-row">
8
- <span class="dn-note" style="width:56px">macOS</span>
9
- <div class="dn-seg" role="group" aria-label="视图">
10
- <button aria-pressed="true">列表</button><button aria-pressed="false">卡片</button><button aria-pressed="false">日历</button>
11
- </div>
12
- </div>
13
- <div class="dn-row">
14
- <span class="dn-note" style="width:56px">iOS</span>
15
- <div class="dn-seg dn-seg-ios" role="group" aria-label="范围">
16
- <button aria-pressed="false">今天</button><button aria-pressed="true">本周</button><button aria-pressed="false">本月</button>
17
- </div>
18
- </div>
19
- </div>
20
- </body>
21
- </html>
@@ -1,29 +0,0 @@
1
- # Sheet
2
-
3
- 从底部弹出的面板,用于一个短小、独立的任务:确认购买、编辑一个字段、选择分享方式。
4
-
5
- **需要提供**:标题、一两句说明、内容(短表单或选项)、主操作和取消操作,以及要支持的高度档位。
6
-
7
- **规格**
8
-
9
- - iOS 26 上,系统会把中等高度的弹窗渲染成悬浮的玻璃面板,四周留出间距;拉到全高后变成不透明。直接使用系统样式,不要自己画背景。
10
- - 顶部拖拽条 36×5pt,`line-control` 色。
11
- - 标题用 `ios-title`(衬线),说明用 `ios-callout` `ink-secondary`,下方留 `space-4`。
12
- - 主操作是通栏 46pt 胶囊主按钮(`control-ios-lg`),下面是同尺寸的文字按钮「暂不需要」,两者间距 `space-1`。
13
- - 内容超过一屏,或需要长时间阅读时,改成全高弹窗或推入新页面,背景用 `canvas`。
14
- - Mac 上对应的是附着在窗口上的 sheet 和系统 Alert,同样直接使用系统样式。
15
-
16
- ```swift
17
- .sheet(isPresented: $showPaywall) {
18
- PaywallView()
19
- .presentationDetents([.medium, .large])
20
- .presentationDragIndicator(.visible)
21
- }
22
-
23
- // 确认删除这类二选一的决定,用系统对话框
24
- .confirmationDialog("删除这条笔记?", isPresented: $confirmDelete) {
25
- Button("删除", role: .destructive) { delete() }
26
- }
27
- ```
28
-
29
- **不要**:在弹窗里再弹一个弹窗;把长篇文章放进玻璃弹窗;没有取消方式;把价格之类的关键信息藏在小字里。
@@ -1,31 +0,0 @@
1
- <!-- @dsCard group="Feedback" height=420 subtitle="iOS 底部弹窗,系统玻璃" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>Sheet</title>
5
- <style>
6
- .scene { position: relative; height: 420px; overflow: hidden; background: var(--canvas); display: flex; justify-content: center; }
7
- .under { position: absolute; inset: 0; padding: var(--space-5) var(--space-4); display: flex; flex-direction: column; gap: var(--space-2); align-items: center; }
8
- .under .dn-card { width: 359px; }
9
- .shade { position: absolute; inset: 0; background: var(--scrim); }
10
- .dn-sheet { position: absolute; bottom: 8px; }
11
- </style>
12
- </head>
13
- <body>
14
- <div class="scene">
15
- <div class="under" aria-hidden="true">
16
- <div class="dn-card"><p class="dn-card-title">本周回顾</p><p class="dn-card-body">完成 12 条笔记,整理了两个项目的待办。</p></div>
17
- <div class="dn-card"><p class="dn-card-title">读书摘录</p><p class="dn-card-body">好的工具会退到背景里。</p></div>
18
- </div>
19
- <div class="shade"></div>
20
- <div class="dn-sheet dn-glass" role="dialog" aria-label="开通全家桶">
21
- <div class="dn-grabber"></div>
22
- <h3>开通全家桶</h3>
23
- <p>一次订阅,旗下所有应用的高级功能都可以使用,AI 次数在各应用之间共享。</p>
24
- <div class="dn-stack">
25
- <button class="dn-btn dn-btn-primary dn-btn-ios-lg">¥168 / 年,免费试用 7 天</button>
26
- <button class="dn-btn dn-btn-plain dn-btn-ios-lg" style="font-weight:500">暂不需要</button>
27
- </div>
28
- </div>
29
- </div>
30
- </body>
31
- </html>
@@ -1,36 +0,0 @@
1
- # Sidebar
2
-
3
- macOS 应用的主导航:顶部放全局操作,下面按分组列出各个位置。
4
-
5
- **需要提供**:分组(标题可选)、每一项的 SF Symbol 和名称、可选的计数或快捷键、绑定的选中项。
6
-
7
- **规格**
8
-
9
- - 宽度 `sidebar-mac`(220),用户可以拖动调整。macOS 26 上侧边栏是悬浮的玻璃面板,由 `NavigationSplitView` 自动提供;预览里用 `surface-sunken` 模拟。
10
- - 每项高 `row-mac`(26),`radius-sm`,左右内边距 `space-2`,图标 14pt、颜色 `ink-secondary`,文字 13pt `ink`。
11
- - 悬停时底色 `fill-hover`。选中时底色 `fill-selected`、文字中粗、图标变 `ink`。选中块不用黑色填满,保持安静。
12
- - 分组标题 11pt 半粗 `ink-tertiary`,上方留 `space-3`、下方留 `space-1`。
13
- - 计数和快捷键放在右侧,11pt `ink-tertiary`,用等宽数字。
14
- - 名称太长时在末尾截断,悬停时显示完整内容。
15
-
16
- ```swift
17
- NavigationSplitView {
18
- List(selection: $selection) {
19
- Section("资料库") {
20
- Label("全部笔记", systemImage: "doc.text").badge(128).tag(Item.all)
21
- Label("收藏", systemImage: "star").badge(9).tag(Item.favorites)
22
- }
23
- Section("最近") {
24
- ForEach(recent) { chat in
25
- Label(chat.title, systemImage: "bubble.left").tag(Item.chat(chat.id))
26
- }
27
- }
28
- }
29
- .navigationSplitViewColumnWidth(min: 180, ideal: 220, max: 300)
30
- } detail: {
31
- DetailView(selection: selection)
32
- }
33
- .tint(.brandAccent)
34
- ```
35
-
36
- **不要**:给侧边栏加实色背景(会盖掉系统玻璃);一级导航超过两层;用彩色图标区分每一项(图标一律灰色)。
@@ -1,20 +0,0 @@
1
- <!-- @dsCard group="Navigation" height=320 subtitle="macOS 侧边栏" -->
2
- <!doctype html>
3
- <html lang="zh-CN">
4
- <head><link rel="stylesheet" href="../../tokens.css"><link rel="stylesheet" href="../bundle.css"><script>(function(){function a(){var t=location.hash.slice(1),r=document.documentElement;if(t==="light"||t==="dark")r.setAttribute("data-theme",t);else r.removeAttribute("data-theme");}a();addEventListener("hashchange",a);})();</script><meta charset="utf-8"><title>Sidebar</title></head>
5
- <body>
6
- <div class="dn-stage" style="align-items:flex-start">
7
- <nav class="dn-sidebar" aria-label="侧边栏">
8
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14"/></svg><span class="dn-side-text">新建笔记</span><span class="dn-count">⌘N</span></div>
9
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="M20 20l-4.5-4.5"/></svg><span class="dn-side-text">搜索</span></div>
10
- <div class="dn-side-head">资料库</div>
11
- <div class="dn-side-item is-selected"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M7 3h7l5 5v13H7z"/><path d="M14 3v5h5"/></svg><span class="dn-side-text">全部笔记</span><span class="dn-count">128</span></div>
12
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M12 4l2.4 5 5.6.6-4.2 3.8 1.2 5.5L12 16l-5 2.9 1.2-5.5L4 9.6l5.6-.6z"/></svg><span class="dn-side-text">收藏</span><span class="dn-count">9</span></div>
13
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg><span class="dn-side-text">工作</span><span class="dn-count">41</span></div>
14
- <div class="dn-side-head">最近</div>
15
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M5 5h14v10H9l-4 4z"/></svg><span class="dn-side-text">把周报整理成三条要点</span></div>
16
- <div class="dn-side-item"><svg class="dn-icon" viewBox="0 0 24 24"><path d="M5 5h14v10H9l-4 4z"/></svg><span class="dn-side-text">下周去杭州的行程安排和预算</span></div>
17
- </nav>
18
- </div>
19
- </body>
20
- </html>
@@ -1,35 +0,0 @@
1
- # StepRow
2
-
3
- 一行显示一个执行步骤:做了什么、结果如何、用了多久。点开可以看到细节。用于 AI 的工具调用、导入导出、批量处理这类任务。
4
-
5
- **需要提供**:状态(进行中 / 成功 / 失败)、动作名(2–4 个字的动词)、对象摘要(文件名、参数、结果)、耗时或说明;可选的详细内容,点击后展开。
6
-
7
- **规格**
8
-
9
- - 高 `control-mac`,`radius-sm`,悬停时底色 `fill-hover`。整行默认 `ink-secondary`,让位于正文内容。
10
- - 状态图标 14pt:进行中是 `ink` 色的转圈,成功是 `success` 色,失败是 `danger` 色。失败时摘要要写清楚原因。
11
- - 动作名 12pt 半粗 `ink`;摘要用 11pt 等宽,单行,在末尾截断;右侧耗时 11pt `ink-tertiary`。
12
- - 展开后的详情缩进到和文字对齐,`surface-sunken` 底,`radius-sm`,12pt 等宽。
13
- - 连续 3 步以上全部成功时,合并成一行「完成 5 个步骤」,点击后展开。
14
-
15
- ```swift
16
- DisclosureGroup(isExpanded: $expanded) {
17
- Text(step.detail)
18
- .font(.system(.callout, design: .monospaced))
19
- .foregroundStyle(.inkSecondary)
20
- .padding(.vertical, 6).padding(.horizontal, 8)
21
- .frame(maxWidth: .infinity, alignment: .leading)
22
- .background(.surfaceSunken, in: .rect(cornerRadius: 6))
23
- } label: {
24
- HStack(spacing: 7) {
25
- StatusGlyph(step.status) // ProgressView / checkmark.circle / xmark.circle
26
- Text(step.action).fontWeight(.semibold).foregroundStyle(.ink)
27
- Text(step.summary).font(.callout.monospaced()).lineLimit(1)
28
- Spacer()
29
- Text(step.duration).font(.caption).monospacedDigit().foregroundStyle(.inkTertiary)
30
- }
31
- .foregroundStyle(.inkSecondary)
32
- }
33
- ```
34
-
35
- **不要**:把每一步都做成卡片;成功的步骤也用醒目的颜色;把原始日志直接铺在对话里(放进折叠详情)。