@deernova/style 0.3.1 → 0.3.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deernova/style",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
package/skill/SKILL.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: deernova-style
3
- description: Deernova 的界面设计语言:只用黑白灰,内容放在不透明纸面上,原生端的操作层用系统 Liquid Glass,Web 应用用不透明平面加 1px 线;界面和 AI 回答用无衬线,衬线只给大标题和长文;按场景(Web 应用、macOS、iOS、iPadOS、官网与文档)切换密度。在 Deernova 的应用或网站里新建、修改或审查界面时使用,包括颜色、字体、间距、圆角、线条、阴影、按钮、输入框、侧边栏、顶栏、列表、卡片、弹窗、空状态、AI 对话和任务清单,以及对应的 CSS、Tailwind 或 SwiftUI 实现。
3
+ description: Deernova 的界面设计语言:只用黑白灰,内容放在不透明纸面上,原生端的操作层用系统 Liquid Glass,Web 应用用不透明平面加 1px 线;界面和 AI 回答用无衬线,衬线只给大标题和长文;按场景(Web 应用、macOS、iOS、iPadOS、官网与文档)切换密度。在 Deernova 的应用或网站里新建、修改或审查界面时使用,包括颜色、字体、间距、圆角、线条、阴影、按钮、输入框、菜单与下拉选择、侧边栏、顶栏、列表、卡片、弹窗、tooltip、空状态、AI 对话和任务清单,以及对应的 CSS、Tailwind 或 SwiftUI 实现。
4
4
  ---
5
5
 
6
6
  # Deernova 设计语言
@@ -56,6 +56,7 @@ description: Deernova 的界面设计语言:只用黑白灰,内容放在不
56
56
  5. **层次靠字号和灰度,少用粗体。** 600 只给真正的标题(`display`、`title`、`headline`)。分组标题、会话名、说明、时间戳用常规字重,靠 `ink-secondary`、`ink-tertiary` 和小一号的字区分层级。
57
57
  6. **控件高度由 token 决定,点击区域单独补。** 按钮、输入框、列表行的可见高度直接用 `button-height-*`、`field-height`、`row-height`,上下内边距为 0,不让页面行高把它撑高。可见尺寸小于 `hit-min` 时,用透明的命中区补足,不加大可见的控件。
58
58
  7. **间距成组。** 间距走 4pt 网格。组内用 `gap-stack`,组与组之间用 `gap-group`(至少 2 倍);内容区里段落、工具调用、卡片之间 `space-4`。用细线和少量留白分组,不靠大块空白和外框。
59
+ 9. **对齐按内容选。** 单行的控件和行在固定高度里垂直居中;图标和文字按中线,不同字号的文字按基线;三行以上的内容,图标和头像对齐第一行;空状态放在略高于正中的位置。不用内边距或 `top` 微调去凑居中。内容栏限宽并在主内容区里居中,见 [布局与对齐](references/foundations/layout.md)。
59
60
  8. **原生端用系统控件,Web 端用同一套自绘组件。** SwiftUI 端的导航结构、侧边栏、工具栏、菜单、表单、弹窗直接用系统控件和系统尺寸,只通过颜色和字体让它们融入;自己画的内容区(对话、卡片、输入区、任务清单)用 token。Web 应用没有系统控件可借,按组件说明里的规格画,骨架见 [Web 应用](references/scenes/web.md)。
60
61
 
61
62
  ## 读什么
@@ -72,11 +73,11 @@ description: Deernova 的界面设计语言:只用黑白灰,内容放在不
72
73
 
73
74
  ### 基础
74
75
 
75
- [颜色](references/foundations/color.md) · [字体](references/foundations/typography.md) · [间距与布局](references/foundations/spacing.md) · [圆角](references/foundations/radius.md) · [线条](references/foundations/stroke.md) · [层级与阴影](references/foundations/elevation.md) · [玻璃](references/foundations/glass.md) · [动效](references/foundations/motion.md) · [图标](references/foundations/iconography.md) · [文案](references/foundations/writing.md) · [无障碍](references/foundations/accessibility.md)
76
+ [颜色](references/foundations/color.md) · [字体](references/foundations/typography.md) · [间距](references/foundations/spacing.md) · [布局与对齐](references/foundations/layout.md) · [圆角](references/foundations/radius.md) · [线条](references/foundations/stroke.md) · [层级与阴影](references/foundations/elevation.md) · [玻璃](references/foundations/glass.md) · [动效](references/foundations/motion.md) · [图标](references/foundations/iconography.md) · [文案](references/foundations/writing.md) · [无障碍](references/foundations/accessibility.md)
76
77
 
77
78
  ### 组件
78
79
 
79
- [按钮](references/components/button.md) · [顶栏与侧面板](references/components/toolbar.md) · [玻璃操作层](references/components/glass-controls.md) · [分段控件](references/components/segmented.md) · [文本框](references/components/text-field.md) · [Composer](references/components/composer.md) · [侧边栏](references/components/sidebar.md) · [分组列表](references/components/list.md) · [卡片](references/components/card.md) · [标签](references/components/tag.md) · [代码块](references/components/code-block.md) · [任务清单](references/components/task-list.md) · [空状态](references/components/empty-state.md) · [横幅与轻提示](references/components/banner.md) · [弹窗](references/components/sheet.md) · [消息](references/components/message.md) · [工具调用与执行步骤](references/components/step-row.md)
80
+ [按钮](references/components/button.md) · [顶栏与侧面板](references/components/toolbar.md) · [玻璃操作层](references/components/glass-controls.md) · [分段控件](references/components/segmented.md) · [文本框](references/components/text-field.md) · [菜单与下拉](references/components/menu.md) · [Composer](references/components/composer.md) · [侧边栏](references/components/sidebar.md) · [分组列表](references/components/list.md) · [卡片](references/components/card.md) · [标签](references/components/tag.md) · [代码块](references/components/code-block.md) · [任务清单](references/components/task-list.md) · [空状态](references/components/empty-state.md) · [横幅与轻提示](references/components/banner.md) · [弹窗与 popover](references/components/sheet.md) · [Tooltip 与悬停浮层](references/components/tooltip.md) · [消息](references/components/message.md) · [工具调用与执行步骤](references/components/step-row.md)
80
81
 
81
82
  ### 场景
82
83
 
@@ -96,7 +97,7 @@ description: Deernova 的界面设计语言:只用黑白灰,内容放在不
96
97
  - 在 SwiftUI 端给系统工具栏、侧边栏加实色背景盖掉玻璃;在 Web 应用里用模糊效果模仿玻璃。
97
98
  - 给卡片加阴影;在玻璃上放正文或列表。
98
99
  - 给界面文字、AI 回答或按钮用衬线;到处用粗体。
99
- - 用上下内边距撑出按钮高度;为了凑 44 点击区域把可见的按钮做大。
100
+ - 用上下内边距撑出按钮高度;为了凑 44 点击区域把可见的按钮做大;用 `padding-top`、`top: 1px` 或等高的 `line-height` 凑垂直居中。
100
101
  - 把官网的大按钮、大字号搬进应用界面;把桌面端的尺寸直接搬到触屏上。
101
102
  - 一屏出现两个主按钮;用「确定」「OK」当按钮文字。
102
103
  - 只靠颜色表达状态。
@@ -168,6 +168,20 @@ public enum Deernova {
168
168
  public static let opacitySolidHover: Double = 0.88
169
169
  /// 对话栏和长文阅读栏的最大宽度。
170
170
  public static let contentMax: CGFloat = 680
171
+ /// 表单页、设置页内容栏的最大宽度。
172
+ public static let formMax: CGFloat = 560
173
+ /// 表格、看板和官网内容的最大宽度。
174
+ public static let wideMax: CGFloat = 1120
175
+ /// 菜单最大宽度;放不下的文字用省略号。
176
+ public static let menuMaxWidth: CGFloat = 320
177
+ /// 底部弹窗顶部拖拽条的宽度。
178
+ public static let sheetGrabberWidth: CGFloat = 36
179
+ /// 拖拽条的高度。
180
+ public static let sheetGrabberHeight: CGFloat = 5
181
+ /// tooltip 和触发它的控件之间的距离。
182
+ public static let tooltipOffset: CGFloat = 8
183
+ /// tooltip 最大宽度,超过时折行,最多两行。
184
+ public static let tooltipMaxWidth: CGFloat = 240
171
185
 
172
186
  // 按密度取值的尺寸:macOS 是 desktop(只用于自己画的内容区),iOS 和 iPadOS 是 touch。
173
187
  #if os(macOS)
@@ -177,7 +191,11 @@ public enum Deernova {
177
191
  public static let pageMargin: CGFloat = 32
178
192
  public static let hitMin: CGFloat = 24
179
193
  public static let sidebarWidth: CGFloat = 288
194
+ public static let sidebarWidthMin: CGFloat = 200
195
+ public static let sidebarWidthMax: CGFloat = 400
196
+ public static let paneWidth: CGFloat = 320
180
197
  public static let toolbarHeight: CGFloat = 44
198
+ public static let gridGutter: CGFloat = 24
181
199
  public static let buttonHeightSm: CGFloat = 24
182
200
  public static let buttonHeightMd: CGFloat = 28
183
201
  public static let buttonHeightLg: CGFloat = 32
@@ -226,8 +244,24 @@ public enum Deernova {
226
244
  public static let emptyIconSize: CGFloat = 32
227
245
  public static let toastHeight: CGFloat = 36
228
246
  public static let bannerRadius: CGFloat = 10
229
- public static let sheetRadius: CGFloat = 12
247
+ public static let menuItemHeight: CGFloat = 28
248
+ public static let menuItemPaddingX: CGFloat = 8
249
+ public static let menuFontSize: CGFloat = 14
250
+ public static let menuPadding: CGFloat = 4
230
251
  public static let menuRadius: CGFloat = 8
252
+ public static let menuOffset: CGFloat = 4
253
+ public static let menuMinWidth: CGFloat = 160
254
+ public static let sheetWidthSm: CGFloat = 360
255
+ public static let sheetWidthMd: CGFloat = 480
256
+ public static let sheetWidthLg: CGFloat = 720
257
+ public static let sheetPadding: CGFloat = 20
258
+ public static let sheetMargin: CGFloat = 32
259
+ public static let sheetRadius: CGFloat = 12
260
+ public static let popoverPadding: CGFloat = 12
261
+ public static let tooltipHeight: CGFloat = 24
262
+ public static let tooltipPaddingX: CGFloat = 8
263
+ public static let tooltipFontSize: CGFloat = 12
264
+ public static let tooltipRadius: CGFloat = 6
231
265
  public static let messageFontSize: CGFloat = 15
232
266
  public static let messageActionSize: CGFloat = 24
233
267
  public static let iconSizeSm: CGFloat = 14
@@ -240,7 +274,11 @@ public enum Deernova {
240
274
  public static let pageMargin: CGFloat = 16
241
275
  public static let hitMin: CGFloat = 44
242
276
  public static let sidebarWidth: CGFloat = 320
277
+ public static let sidebarWidthMin: CGFloat = 260
278
+ public static let sidebarWidthMax: CGFloat = 400
279
+ public static let paneWidth: CGFloat = 360
243
280
  public static let toolbarHeight: CGFloat = 44
281
+ public static let gridGutter: CGFloat = 16
244
282
  public static let buttonHeightSm: CGFloat = 30
245
283
  public static let buttonHeightMd: CGFloat = 36
246
284
  public static let buttonHeightLg: CGFloat = 46
@@ -289,8 +327,24 @@ public enum Deernova {
289
327
  public static let emptyIconSize: CGFloat = 36
290
328
  public static let toastHeight: CGFloat = 40
291
329
  public static let bannerRadius: CGFloat = 12
292
- public static let sheetRadius: CGFloat = 24
330
+ public static let menuItemHeight: CGFloat = 44
331
+ public static let menuItemPaddingX: CGFloat = 10
332
+ public static let menuFontSize: CGFloat = 17
333
+ public static let menuPadding: CGFloat = 6
293
334
  public static let menuRadius: CGFloat = 12
335
+ public static let menuOffset: CGFloat = 8
336
+ public static let menuMinWidth: CGFloat = 220
337
+ public static let sheetWidthSm: CGFloat = 360
338
+ public static let sheetWidthMd: CGFloat = 540
339
+ public static let sheetWidthLg: CGFloat = 720
340
+ public static let sheetPadding: CGFloat = 20
341
+ public static let sheetMargin: CGFloat = 8
342
+ public static let sheetRadius: CGFloat = 24
343
+ public static let popoverPadding: CGFloat = 16
344
+ public static let tooltipHeight: CGFloat = 28
345
+ public static let tooltipPaddingX: CGFloat = 10
346
+ public static let tooltipFontSize: CGFloat = 13
347
+ public static let tooltipRadius: CGFloat = 8
294
348
  public static let messageFontSize: CGFloat = 15
295
349
  public static let messageActionSize: CGFloat = 32
296
350
  public static let iconSizeSm: CGFloat = 17
@@ -148,6 +148,7 @@
148
148
  --z-dropdown: 100;
149
149
  --z-overlay: 1000;
150
150
  --z-toast: 1100;
151
+ --z-tooltip: 1200;
151
152
  --duration-instant: 120ms;
152
153
  --duration-base: 200ms;
153
154
  --duration-slow: 320ms;
@@ -157,6 +158,15 @@
157
158
  --glass-blur: 16px;
158
159
  --glass-saturate: 1.4;
159
160
  --content-max: 680px;
161
+ --form-max: 560px;
162
+ --wide-max: 1120px;
163
+ --menu-max-width: 320px;
164
+ --sheet-grabber-width: 36px;
165
+ --sheet-grabber-height: 5px;
166
+ --tooltip-offset: 8px;
167
+ --tooltip-max-width: 240px;
168
+ --tooltip-delay: 500ms;
169
+ --tooltip-skip-window: 300ms;
160
170
  --icon-stroke: 1.75px;
161
171
  }
162
172
 
@@ -195,7 +205,11 @@
195
205
  --page-margin: 32px;
196
206
  --hit-min: 24px;
197
207
  --sidebar-width: 288px;
208
+ --sidebar-width-min: 200px;
209
+ --sidebar-width-max: 400px;
210
+ --pane-width: 320px;
198
211
  --toolbar-height: 44px;
212
+ --grid-gutter: 24px;
199
213
  --button-height-sm: 24px;
200
214
  --button-height-md: 28px;
201
215
  --button-height-lg: 32px;
@@ -244,8 +258,24 @@
244
258
  --empty-icon-size: 32px;
245
259
  --toast-height: 36px;
246
260
  --banner-radius: 10px;
247
- --sheet-radius: 12px;
261
+ --menu-item-height: 28px;
262
+ --menu-item-padding-x: 8px;
263
+ --menu-font-size: 14px;
264
+ --menu-padding: 4px;
248
265
  --menu-radius: 8px;
266
+ --menu-offset: 4px;
267
+ --menu-min-width: 160px;
268
+ --sheet-width-sm: 360px;
269
+ --sheet-width-md: 480px;
270
+ --sheet-width-lg: 720px;
271
+ --sheet-padding: 20px;
272
+ --sheet-margin: 32px;
273
+ --sheet-radius: 12px;
274
+ --popover-padding: 12px;
275
+ --tooltip-height: 24px;
276
+ --tooltip-padding-x: 8px;
277
+ --tooltip-font-size: 12px;
278
+ --tooltip-radius: 6px;
249
279
  --message-font-size: 15px;
250
280
  --message-action-size: 24px;
251
281
  --icon-size-sm: 14px;
@@ -288,7 +318,11 @@
288
318
  --page-margin: 16px;
289
319
  --hit-min: 44px;
290
320
  --sidebar-width: 320px;
321
+ --sidebar-width-min: 260px;
322
+ --sidebar-width-max: 400px;
323
+ --pane-width: 360px;
291
324
  --toolbar-height: 44px;
325
+ --grid-gutter: 16px;
292
326
  --button-height-sm: 30px;
293
327
  --button-height-md: 36px;
294
328
  --button-height-lg: 46px;
@@ -337,8 +371,24 @@
337
371
  --empty-icon-size: 36px;
338
372
  --toast-height: 40px;
339
373
  --banner-radius: 12px;
340
- --sheet-radius: 24px;
374
+ --menu-item-height: 44px;
375
+ --menu-item-padding-x: 10px;
376
+ --menu-font-size: 17px;
377
+ --menu-padding: 6px;
341
378
  --menu-radius: 12px;
379
+ --menu-offset: 8px;
380
+ --menu-min-width: 220px;
381
+ --sheet-width-sm: 360px;
382
+ --sheet-width-md: 540px;
383
+ --sheet-width-lg: 720px;
384
+ --sheet-padding: 20px;
385
+ --sheet-margin: 8px;
386
+ --sheet-radius: 24px;
387
+ --popover-padding: 16px;
388
+ --tooltip-height: 28px;
389
+ --tooltip-padding-x: 10px;
390
+ --tooltip-font-size: 13px;
391
+ --tooltip-radius: 8px;
342
392
  --message-font-size: 15px;
343
393
  --message-action-size: 32px;
344
394
  --icon-size-sm: 17px;
@@ -381,7 +431,11 @@
381
431
  --page-margin: 16px;
382
432
  --hit-min: 44px;
383
433
  --sidebar-width: 320px;
434
+ --sidebar-width-min: 260px;
435
+ --sidebar-width-max: 400px;
436
+ --pane-width: 360px;
384
437
  --toolbar-height: 44px;
438
+ --grid-gutter: 16px;
385
439
  --button-height-sm: 30px;
386
440
  --button-height-md: 36px;
387
441
  --button-height-lg: 46px;
@@ -430,8 +484,24 @@
430
484
  --empty-icon-size: 36px;
431
485
  --toast-height: 40px;
432
486
  --banner-radius: 12px;
433
- --sheet-radius: 24px;
487
+ --menu-item-height: 44px;
488
+ --menu-item-padding-x: 10px;
489
+ --menu-font-size: 17px;
490
+ --menu-padding: 6px;
434
491
  --menu-radius: 12px;
492
+ --menu-offset: 8px;
493
+ --menu-min-width: 220px;
494
+ --sheet-width-sm: 360px;
495
+ --sheet-width-md: 540px;
496
+ --sheet-width-lg: 720px;
497
+ --sheet-padding: 20px;
498
+ --sheet-margin: 8px;
499
+ --sheet-radius: 24px;
500
+ --popover-padding: 16px;
501
+ --tooltip-height: 28px;
502
+ --tooltip-padding-x: 10px;
503
+ --tooltip-font-size: 13px;
504
+ --tooltip-radius: 8px;
435
505
  --message-font-size: 15px;
436
506
  --message-action-size: 32px;
437
507
  --icon-size-sm: 17px;
@@ -473,7 +543,11 @@
473
543
  --page-margin: 32px;
474
544
  --hit-min: 24px;
475
545
  --sidebar-width: 260px;
546
+ --sidebar-width-min: 200px;
547
+ --sidebar-width-max: 320px;
548
+ --pane-width: 320px;
476
549
  --toolbar-height: 52px;
550
+ --grid-gutter: 32px;
477
551
  --button-height-sm: 32px;
478
552
  --button-height-md: 36px;
479
553
  --button-height-lg: 44px;
@@ -522,8 +596,24 @@
522
596
  --empty-icon-size: 40px;
523
597
  --toast-height: 40px;
524
598
  --banner-radius: 12px;
525
- --sheet-radius: 16px;
599
+ --menu-item-height: 36px;
600
+ --menu-item-padding-x: 10px;
601
+ --menu-font-size: 15px;
602
+ --menu-padding: 6px;
526
603
  --menu-radius: 12px;
604
+ --menu-offset: 8px;
605
+ --menu-min-width: 200px;
606
+ --sheet-width-sm: 400px;
607
+ --sheet-width-md: 560px;
608
+ --sheet-width-lg: 800px;
609
+ --sheet-padding: 24px;
610
+ --sheet-margin: 32px;
611
+ --sheet-radius: 16px;
612
+ --popover-padding: 16px;
613
+ --tooltip-height: 28px;
614
+ --tooltip-padding-x: 10px;
615
+ --tooltip-font-size: 13px;
616
+ --tooltip-radius: 8px;
527
617
  --message-font-size: 15px;
528
618
  --message-action-size: 28px;
529
619
  --icon-size-sm: 16px;
@@ -938,6 +938,12 @@
938
938
  "value": 1100,
939
939
  "swift": false,
940
940
  "usage": "轻提示,压在弹窗之上。"
941
+ },
942
+ {
943
+ "name": "z-tooltip",
944
+ "value": 1200,
945
+ "swift": false,
946
+ "usage": "tooltip 和悬停卡片,压在所有层之上。"
941
947
  }
942
948
  ]
943
949
  },
@@ -1011,6 +1017,16 @@
1011
1017
  "value": "680px",
1012
1018
  "usage": "对话栏和长文阅读栏的最大宽度。"
1013
1019
  },
1020
+ {
1021
+ "name": "form-max",
1022
+ "value": "560px",
1023
+ "usage": "表单页、设置页内容栏的最大宽度。"
1024
+ },
1025
+ {
1026
+ "name": "wide-max",
1027
+ "value": "1120px",
1028
+ "usage": "表格、看板和官网内容的最大宽度。"
1029
+ },
1014
1030
  {
1015
1031
  "name": "breakpoint-sm",
1016
1032
  "value": "760px",
@@ -1047,6 +1063,33 @@
1047
1063
  },
1048
1064
  "usage": "侧边栏默认宽度。iPhone 没有侧边栏;macOS 用系统侧边栏,宽度只作参考。"
1049
1065
  },
1066
+ {
1067
+ "name": "sidebar-width-min",
1068
+ "values": {
1069
+ "desktop": 200,
1070
+ "touch": 260,
1071
+ "comfortable": 200
1072
+ },
1073
+ "usage": "侧边栏拖动时的最小宽度。"
1074
+ },
1075
+ {
1076
+ "name": "sidebar-width-max",
1077
+ "values": {
1078
+ "desktop": 400,
1079
+ "touch": 400,
1080
+ "comfortable": 320
1081
+ },
1082
+ "usage": "侧边栏拖动时的最大宽度。"
1083
+ },
1084
+ {
1085
+ "name": "pane-width",
1086
+ "values": {
1087
+ "desktop": 320,
1088
+ "touch": 360,
1089
+ "comfortable": 320
1090
+ },
1091
+ "usage": "列表加详情里列表栏的默认宽度,也是右侧 inspector 的默认宽度。"
1092
+ },
1050
1093
  {
1051
1094
  "name": "toolbar-height",
1052
1095
  "values": {
@@ -1055,6 +1098,15 @@
1055
1098
  "comfortable": 52
1056
1099
  },
1057
1100
  "usage": "Web 应用顶栏、侧面板标签头的高度。macOS 用系统工具栏。"
1101
+ },
1102
+ {
1103
+ "name": "grid-gutter",
1104
+ "values": {
1105
+ "desktop": 24,
1106
+ "touch": 16,
1107
+ "comfortable": 32
1108
+ },
1109
+ "usage": "官网和文档 12 栏网格的栏间距。应用里的卡片网格用 card-gap。"
1058
1110
  }
1059
1111
  ]
1060
1112
  },
@@ -1590,11 +1642,131 @@
1590
1642
  }
1591
1643
  ]
1592
1644
  },
1645
+ {
1646
+ "id": "menu",
1647
+ "title": "菜单与下拉",
1648
+ "reference": "references/components/menu.md",
1649
+ "tokens": [
1650
+ {
1651
+ "name": "menu-item-height",
1652
+ "values": {
1653
+ "desktop": 28,
1654
+ "touch": 44,
1655
+ "comfortable": 36
1656
+ },
1657
+ "usage": "菜单项和下拉选项的高度。"
1658
+ },
1659
+ {
1660
+ "name": "menu-item-padding-x",
1661
+ "values": {
1662
+ "desktop": 8,
1663
+ "touch": 10,
1664
+ "comfortable": 10
1665
+ },
1666
+ "usage": "菜单项左右内边距。"
1667
+ },
1668
+ {
1669
+ "name": "menu-font-size",
1670
+ "values": {
1671
+ "desktop": 14,
1672
+ "touch": 17,
1673
+ "comfortable": 15
1674
+ },
1675
+ "usage": "菜单项字号。"
1676
+ },
1677
+ {
1678
+ "name": "menu-padding",
1679
+ "values": {
1680
+ "desktop": 4,
1681
+ "touch": 6,
1682
+ "comfortable": 6
1683
+ },
1684
+ "usage": "菜单面板的内边距,也是分隔线上下的间距。"
1685
+ },
1686
+ {
1687
+ "name": "menu-radius",
1688
+ "values": {
1689
+ "desktop": 8,
1690
+ "touch": 12,
1691
+ "comfortable": 12
1692
+ },
1693
+ "usage": "菜单和 popover 的圆角;菜单项的圆角 = 它减去 menu-padding。"
1694
+ },
1695
+ {
1696
+ "name": "menu-offset",
1697
+ "values": {
1698
+ "desktop": 4,
1699
+ "touch": 8,
1700
+ "comfortable": 8
1701
+ },
1702
+ "usage": "菜单和触发它的控件之间的距离。"
1703
+ },
1704
+ {
1705
+ "name": "menu-min-width",
1706
+ "values": {
1707
+ "desktop": 160,
1708
+ "touch": 220,
1709
+ "comfortable": 200
1710
+ },
1711
+ "usage": "菜单最小宽度;同时不窄于触发器。"
1712
+ },
1713
+ {
1714
+ "name": "menu-max-width",
1715
+ "value": "320px",
1716
+ "usage": "菜单最大宽度;放不下的文字用省略号。"
1717
+ }
1718
+ ]
1719
+ },
1593
1720
  {
1594
1721
  "id": "sheet",
1595
- "title": "弹窗与底部弹窗",
1722
+ "title": "弹窗、底部弹窗与 popover",
1596
1723
  "reference": "references/components/sheet.md",
1597
1724
  "tokens": [
1725
+ {
1726
+ "name": "sheet-width-sm",
1727
+ "values": {
1728
+ "desktop": 360,
1729
+ "touch": 360,
1730
+ "comfortable": 400
1731
+ },
1732
+ "usage": "确认弹窗、只有一两句话的提示。"
1733
+ },
1734
+ {
1735
+ "name": "sheet-width-md",
1736
+ "values": {
1737
+ "desktop": 480,
1738
+ "touch": 540,
1739
+ "comfortable": 560
1740
+ },
1741
+ "usage": "默认宽度:短表单、选择分享方式这类短任务。"
1742
+ },
1743
+ {
1744
+ "name": "sheet-width-lg",
1745
+ "values": {
1746
+ "desktop": 720,
1747
+ "touch": 720,
1748
+ "comfortable": 800
1749
+ },
1750
+ "usage": "预览、较长的设置,或分两栏的内容。"
1751
+ },
1752
+ {
1753
+ "name": "sheet-padding",
1754
+ "values": {
1755
+ "desktop": 20,
1756
+ "touch": 20,
1757
+ "comfortable": 24
1758
+ },
1759
+ "usage": "弹窗内边距;标题、内容和按钮区都和它对齐。"
1760
+ },
1761
+ {
1762
+ "name": "sheet-margin",
1763
+ "values": {
1764
+ "desktop": 32,
1765
+ "touch": 8,
1766
+ "comfortable": 32
1767
+ },
1768
+ "usage": "弹窗离窗口边缘的最小距离;触控端底部弹窗悬浮时离屏幕边缘的距离。"
1769
+ },
1598
1770
  {
1599
1771
  "name": "sheet-radius",
1600
1772
  "values": {
@@ -1605,13 +1777,92 @@
1605
1777
  "usage": "弹窗和底部弹窗的圆角。"
1606
1778
  },
1607
1779
  {
1608
- "name": "menu-radius",
1780
+ "name": "sheet-grabber-width",
1781
+ "value": "36px",
1782
+ "usage": "底部弹窗顶部拖拽条的宽度。"
1783
+ },
1784
+ {
1785
+ "name": "sheet-grabber-height",
1786
+ "value": "5px",
1787
+ "usage": "拖拽条的高度。"
1788
+ },
1789
+ {
1790
+ "name": "popover-padding",
1791
+ "values": {
1792
+ "desktop": 12,
1793
+ "touch": 16,
1794
+ "comfortable": 16
1795
+ },
1796
+ "usage": "popover 的内边距;圆角用 menu-radius,宽度不超过 sheet-width-sm。"
1797
+ }
1798
+ ]
1799
+ },
1800
+ {
1801
+ "id": "tooltip",
1802
+ "title": "Tooltip 与悬停浮层",
1803
+ "reference": "references/components/tooltip.md",
1804
+ "tokens": [
1805
+ {
1806
+ "name": "tooltip-height",
1807
+ "values": {
1808
+ "desktop": 24,
1809
+ "touch": 28,
1810
+ "comfortable": 28
1811
+ },
1812
+ "usage": "单行 tooltip 的高度;折成两行时随内容长高。"
1813
+ },
1814
+ {
1815
+ "name": "tooltip-padding-x",
1609
1816
  "values": {
1610
1817
  "desktop": 8,
1611
- "touch": 12,
1612
- "comfortable": 12
1818
+ "touch": 10,
1819
+ "comfortable": 10
1820
+ },
1821
+ "usage": "tooltip 左右内边距。"
1822
+ },
1823
+ {
1824
+ "name": "tooltip-font-size",
1825
+ "values": {
1826
+ "desktop": 12,
1827
+ "touch": 13,
1828
+ "comfortable": 13
1613
1829
  },
1614
- "usage": "弹出菜单、popover 的圆角。"
1830
+ "usage": "tooltip 字号。"
1831
+ },
1832
+ {
1833
+ "name": "tooltip-radius",
1834
+ "values": {
1835
+ "desktop": 6,
1836
+ "touch": 8,
1837
+ "comfortable": 8
1838
+ },
1839
+ "usage": "tooltip 圆角。"
1840
+ },
1841
+ {
1842
+ "name": "tooltip-offset",
1843
+ "value": "8px",
1844
+ "usage": "tooltip 和触发它的控件之间的距离。"
1845
+ },
1846
+ {
1847
+ "name": "tooltip-max-width",
1848
+ "value": "240px",
1849
+ "usage": "tooltip 最大宽度,超过时折行,最多两行。"
1850
+ },
1851
+ {
1852
+ "name": "tooltip-delay",
1853
+ "value": "500ms",
1854
+ "platforms": [
1855
+ "web"
1856
+ ],
1857
+ "usage": "指针停留多久后显示 tooltip 和悬停卡片。SwiftUI 的 .help() 用系统的时间。"
1858
+ },
1859
+ {
1860
+ "name": "tooltip-skip-window",
1861
+ "value": "300ms",
1862
+ "platforms": [
1863
+ "web"
1864
+ ],
1865
+ "usage": "一个 tooltip 刚关闭的这段时间里,移到相邻控件立即显示,不再等待。"
1615
1866
  }
1616
1867
  ]
1617
1868
  },
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "0.3.1",
3
- "sourceHash": "a584ab2e77ab9517da74f2f0d5b16dc45951f4fbc2b2263a27a8981e70278705"
2
+ "version": "0.3.3",
3
+ "sourceHash": "2de047daa5254886378ff8fbc726f160de3f3817e9347e52d8a0b0aee55e68dc"
4
4
  }
@@ -9,8 +9,8 @@
9
9
  - **主按钮** `is-primary`:`accent` 底、`on-accent` 字。保存、发送、购买这类关键动作,一屏最多一个。
10
10
  - **次按钮**(默认):`fill-selected` 灰底、无描边、无阴影、`ink` 字。半透明的灰底放在任何纸面上都成立。
11
11
  - **文字按钮** `is-plain`:无底,`ink-secondary` 字,悬停时出现 `fill-hover`。工具栏和卡片里的次要操作。
12
- - **危险按钮** `is-danger`:`danger-soft` 底、`danger` 字。只有在最终确认弹窗里,才用实色的危险样式(SwiftUI 的 `role: .destructive`)。
13
- - **图标按钮** `dn-icon-button`:只有图标,无底,`ink-secondary`,必须有无障碍标签。
12
+ - **危险按钮** `is-danger`:`danger-soft` 底、`danger` 字。只有在最终的[危险确认弹窗](sheet.md)里,才用实色的危险样式 `is-primary is-danger`:`danger` 底、`on-accent` 字(SwiftUI 的 `role: .destructive`)。
13
+ - **图标按钮** `dn-icon-button`:只有图标,无底,`ink-secondary`,必须有无障碍标签;指针端用 [tooltip](tooltip.md) 显示它的名称。
14
14
 
15
15
  ## 尺寸
16
16
 
@@ -82,6 +82,7 @@
82
82
  .dn-button.is-plain { background: transparent; color: var(--ink-secondary); }
83
83
  .dn-button.is-plain:hover:not(:disabled) { background: var(--fill-hover); color: var(--ink); }
84
84
  .dn-button.is-danger { background: var(--danger-soft); color: var(--danger); }
85
+ .dn-button.is-primary.is-danger { background: var(--danger); color: var(--on-accent); }
85
86
 
86
87
  .dn-button.is-sm { height: var(--button-height-sm); padding: 0 var(--button-padding-x-sm); border-radius: var(--button-radius-sm); font-size: var(--button-font-size-sm); }
87
88
  .dn-button.is-lg { height: var(--button-height-lg); padding: 0 var(--button-padding-x-lg); font-size: var(--button-font-size-lg); }
@@ -13,7 +13,7 @@
13
13
  | `empty-icon-size` | 32 | 36 | 40 | 空状态图标的边长。 |
14
14
  <!-- /tokens -->
15
15
 
16
- - 在可用区域里居中。图标 `empty-icon-size`、细线、`ink-tertiary`;标题用衬线 `empty-title-size`、半粗;正文 `type-body`、`ink-secondary`,最大宽度 320。
16
+ - 在可用区域里视觉居中:水平居中,垂直方向略高于正中(上下留白约 2 : 3),见 [布局与对齐](../foundations/layout.md)。图标 `empty-icon-size`、细线、`ink-tertiary`;标题用衬线 `empty-title-size`、半粗;正文 `type-body`、`ink-secondary`,最大宽度 320。
17
17
  - 按钮用[大号](button.md)。
18
18
  - 搜索没有结果时不放按钮,标题写成「没有找到“关键词”」,正文给出修改建议。
19
19