@heyramzi/ui 2.1.0 → 2.2.0

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 (312) hide show
  1. package/package.json +7 -8
  2. package/scripts/sync-shadcn.mjs +3 -4
  3. package/src/agents/agent-avatar.svelte +604 -575
  4. package/src/agents/agent-cast.svelte +179 -183
  5. package/src/agents/demo.svelte +125 -113
  6. package/src/agents/helpers.ts +23 -17
  7. package/src/agents/index.ts +4 -4
  8. package/src/agents/page-state.ts +6 -6
  9. package/src/agents/types.ts +6 -6
  10. package/src/ai/ai-button/AiButton.svelte +4 -12
  11. package/src/ai/generation-progress/GenerationProgress.svelte +10 -3
  12. package/src/ai/prompt-input/PromptInputTextarea.svelte +1 -2
  13. package/src/ai/response/Response.css +2 -3
  14. package/src/animations/avatar-group-hover.css +2 -16
  15. package/src/animations/card-tilt.css +3 -6
  16. package/src/animations/digit-pop-in.css +2 -15
  17. package/src/animations/dropdown.css +4 -17
  18. package/src/animations/input-clear-dissolve.css +5 -18
  19. package/src/animations/input-shake.css +9 -41
  20. package/src/animations/learn-more-hover.css +17 -9
  21. package/src/animations/like-button.css +2 -4
  22. package/src/animations/page-side-by-side.css +2 -10
  23. package/src/animations/plus-menu-morph.css +2 -5
  24. package/src/animations/shimmer-text.css +5 -18
  25. package/src/animations/spinning-counter.css +2 -6
  26. package/src/animations/success-check.css +2 -15
  27. package/src/animations/thinking-states.css +2 -7
  28. package/src/brand/brand.test.ts +21 -5
  29. package/src/brand/index.ts +4 -10
  30. package/src/canvas/card/card-frame.svelte +43 -39
  31. package/src/canvas/card/resize-handles.svelte +89 -80
  32. package/src/canvas/chrome/chrome-zoom.svelte +101 -100
  33. package/src/canvas/chrome/lock-badge.svelte +8 -8
  34. package/src/canvas/chrome/side-handles.svelte +24 -19
  35. package/src/canvas/chrome/size-chip.svelte +30 -30
  36. package/src/canvas/chrome/snap-guides.svelte +20 -20
  37. package/src/canvas/components/icons/ToolIcon.svelte +8 -8
  38. package/src/canvas/components/shared/svg/PreviewSvg.svelte +19 -19
  39. package/src/canvas/components/shared/svg/ShapeOutline.svelte +71 -48
  40. package/src/canvas/components/shared/svg/StrokeNode.svelte +21 -27
  41. package/src/canvas/components/shared/svg/TextRule.svelte +25 -17
  42. package/src/canvas/edges/bend-handle.svelte +46 -46
  43. package/src/canvas/edges/edge-gradient.svelte +10 -10
  44. package/src/canvas/edges/gradient-edge.svelte +45 -29
  45. package/src/canvas/editor/lock.test.ts +6 -1
  46. package/src/canvas/editor/style.ts +7 -1
  47. package/src/canvas/headless/svg-figure.test.ts +5 -1
  48. package/src/canvas/lod/lod-switch.svelte +111 -106
  49. package/src/canvas/pen/PenField.svelte +87 -81
  50. package/src/canvas/pen/PenOverlay.svelte +127 -127
  51. package/src/canvas/pen/ShapeNode.svelte +31 -32
  52. package/src/canvas/pen/TextNode.svelte +54 -53
  53. package/src/canvas/pen/host-field.test.svelte +7 -7
  54. package/src/canvas/pen/shapes.ts +7 -1
  55. package/src/canvas/screen/GlyphIcon.svelte +22 -17
  56. package/src/canvas/screen/PartView.svelte +138 -72
  57. package/src/canvas/screen/ScreenBody.svelte +81 -60
  58. package/src/canvas/screen/ScreenCard.svelte +20 -20
  59. package/src/canvas/ui/CanvasToolbar.svelte +173 -85
  60. package/src/canvas/ui/FrameLayer.svelte +59 -59
  61. package/src/canvas/ui/PenLayer.svelte +39 -30
  62. package/src/canvas/ui/StylePanel.svelte +119 -102
  63. package/src/canvas/ui/canvas-grid.svelte +137 -129
  64. package/src/charts/animated-value.svelte +1 -1
  65. package/src/charts/area-chart.css +2 -5
  66. package/src/charts/area-chart.svelte +1 -1
  67. package/src/charts/bar-chart.css +2 -3
  68. package/src/charts/bar-chart.svelte +1 -1
  69. package/src/charts/charts.css +5 -17
  70. package/src/charts/crosshair.svelte +1 -1
  71. package/src/charts/dashboard/dashboard-empty.svelte +25 -25
  72. package/src/charts/dashboard/dashboard-section.svelte +24 -24
  73. package/src/charts/dashboard/data-panel.svelte +50 -50
  74. package/src/charts/dashboard/data-sort-head.svelte +56 -56
  75. package/src/charts/dashboard/data-table.svelte +138 -138
  76. package/src/charts/dashboard/panel-grid.svelte +30 -30
  77. package/src/charts/dashboard/period-filter.svelte +25 -25
  78. package/src/charts/dashboard/rating-chip.svelte +19 -19
  79. package/src/charts/dashboard/stat-band.svelte +32 -32
  80. package/src/charts/dashboard/stat-tile.svelte +106 -99
  81. package/src/charts/donut-chart.svelte +1 -1
  82. package/src/charts/edge-fade.svelte +1 -1
  83. package/src/charts/figure.svelte +1 -1
  84. package/src/charts/gauge-chart.css +4 -7
  85. package/src/charts/gauge-chart.svelte +1 -1
  86. package/src/charts/hover-focus.svelte +1 -1
  87. package/src/charts/legend.css +1 -3
  88. package/src/charts/legend.svelte +1 -1
  89. package/src/charts/line-chart.svelte +1 -1
  90. package/src/charts/number-chart.css +6 -9
  91. package/src/charts/number-chart.svelte +1 -1
  92. package/src/charts/reference-line.svelte +19 -19
  93. package/src/charts/reveal.svelte +1 -1
  94. package/src/charts/ring-chart.css +2 -4
  95. package/src/charts/ring-chart.svelte +1 -1
  96. package/src/charts/sparkline.svelte +5 -2
  97. package/src/charts/stat-card.svelte +1 -1
  98. package/src/charts/time-series-chart.css +2 -5
  99. package/src/charts/trend-pill.css +2 -4
  100. package/src/charts/trend-pill.svelte +1 -1
  101. package/src/components/copy/copy-button.svelte +93 -98
  102. package/src/components/copy/copy-button.test.ts +10 -2
  103. package/src/components/data-table/infinite-scroll.svelte +42 -42
  104. package/src/components/data-table/pagination.svelte +34 -22
  105. package/src/components/data-table/row-arrow.svelte +19 -16
  106. package/src/components/data-table/row-context-menu.svelte +52 -52
  107. package/src/components/data-table/sortable-head.svelte +25 -25
  108. package/src/components/data-table/table-skeleton.svelte +41 -36
  109. package/src/components/docs/doc-page.svelte +18 -9
  110. package/src/components/docs/on-this-page.svelte +16 -3
  111. package/src/components/docs/scroll-spy.svelte.ts +2 -3
  112. package/src/components/field-row/field-row.svelte +10 -8
  113. package/src/components/hold-to-confirm/hold-to-confirm.svelte +5 -1
  114. package/src/components/icon/icon.svelte +14 -14
  115. package/src/components/language-flag/language-flag.svelte +3 -1
  116. package/src/components/list-page/detail-empty.svelte +34 -34
  117. package/src/components/list-page/detail-header.svelte +55 -47
  118. package/src/components/list-page/detail-panel.svelte +51 -59
  119. package/src/components/list-page/detail-row.svelte +19 -19
  120. package/src/components/list-page/detail-stack.svelte +21 -21
  121. package/src/components/list-page/empty-state.svelte +30 -30
  122. package/src/components/list-page/filter-item.svelte +20 -20
  123. package/src/components/list-page/filter-popover.svelte +60 -55
  124. package/src/components/list-page/grouped-list.svelte +4 -2
  125. package/src/components/list-page/index.ts +5 -1
  126. package/src/components/list-page/list-page-shell.svelte +2 -5
  127. package/src/components/list-page/master-detail.svelte +87 -88
  128. package/src/components/list-page/notice-bar.svelte +38 -38
  129. package/src/components/list-page/prev-next.svelte +63 -63
  130. package/src/components/list-page/rail-body.svelte +18 -18
  131. package/src/components/list-page/rail-empty.svelte +23 -30
  132. package/src/components/list-page/rail-head.svelte +24 -24
  133. package/src/components/list-page/rail-row.svelte +77 -73
  134. package/src/components/list-page/section-host.ts +2 -3
  135. package/src/components/locale-switch/locale-switch.svelte +41 -41
  136. package/src/components/mark/mark.svelte +34 -38
  137. package/src/components/open-in/index.ts +1 -5
  138. package/src/components/open-in/open-in.svelte +40 -40
  139. package/src/components/picker/mark-picker.svelte +49 -49
  140. package/src/components/picker/picker.svelte +5 -3
  141. package/src/components/section-header/section-header.test.ts +7 -1
  142. package/src/components/section-header/section-label.svelte +20 -20
  143. package/src/components/segmented/animated-tabs.svelte +31 -2
  144. package/src/components/segmented/collapse.test.ts +2 -1
  145. package/src/components/segmented/index.ts +2 -0
  146. package/src/components/segmented/segment.svelte +52 -49
  147. package/src/components/segmented/segmented-filter.svelte +79 -80
  148. package/src/components/segmented/segmented-nav.svelte +34 -40
  149. package/src/components/segmented/segmented-overflow.svelte +53 -50
  150. package/src/components/segmented/segmented-track.svelte +62 -46
  151. package/src/components/segmented/segmented.ts +2 -3
  152. package/src/components/star-rating-input/star-rating-input.svelte +103 -103
  153. package/src/components/svg/svg.svelte +4 -4
  154. package/src/components/table-view/table-view.svelte +17 -2
  155. package/src/components/table-view/table-view.test.ts +7 -1
  156. package/src/components/table-view/types.ts +11 -11
  157. package/src/components/tags-input/index.ts +13 -0
  158. package/src/components/tags-input/tags-input.svelte +305 -0
  159. package/src/components/tags-input/tags.test.ts +64 -0
  160. package/src/components/tags-input/tags.ts +142 -0
  161. package/src/components/theme/index.ts +2 -4
  162. package/src/components/theme/theme-provider.svelte +1 -3
  163. package/src/components/toolbar/toolbar-search.svelte +25 -25
  164. package/src/components/toolbar/toolbar.svelte +11 -7
  165. package/src/components/toolbar/toolbar.test.ts +10 -1
  166. package/src/design/index.css +21 -78
  167. package/src/design/polish.css +26 -35
  168. package/src/editor/editor-toolbar.svelte +104 -99
  169. package/src/editor/editor.svelte +296 -266
  170. package/src/editor/image-toolbar.svelte +20 -22
  171. package/src/editor/index.ts +1 -4
  172. package/src/editor/inline-editor.svelte +280 -238
  173. package/src/editor/markdown.ts +15 -15
  174. package/src/editor/renderer.svelte +71 -71
  175. package/src/editor/slash-menu.svelte +24 -27
  176. package/src/effects/animated-beam/diagrams/BeamSvg.svelte +1 -1
  177. package/src/effects/image-comparison/ImageComparison.svelte +11 -1
  178. package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +59 -46
  179. package/src/effects/magic-card/MagicCard.css +14 -7
  180. package/src/effects/marquee/Marquee.svelte +3 -5
  181. package/src/effects/reveal/observe.ts +0 -3
  182. package/src/effects/spotlight/Spotlight.svelte +1 -1
  183. package/src/effects/theme-toggle/ThemeToggle.css +25 -22
  184. package/src/effects/theme-toggle/ThemeToggle.svelte +6 -7
  185. package/src/gallery.test.ts +14 -4
  186. package/src/inbox/README.md +1 -3
  187. package/src/inbox/inbox.test.ts +181 -138
  188. package/src/inbox/index.ts +20 -20
  189. package/src/inbox/logic.ts +114 -111
  190. package/src/inbox/thread-inbox.svelte +227 -151
  191. package/src/inbox/types.ts +130 -108
  192. package/src/lib/theme-transition.ts +2 -4
  193. package/src/lib/tone.ts +2 -4
  194. package/src/lib/utils.ts +2 -2
  195. package/src/modules.test.ts +79 -69
  196. package/src/onboarding/define-tours.test.ts +55 -40
  197. package/src/onboarding/define-tours.ts +23 -23
  198. package/src/onboarding/demo.svelte +24 -5
  199. package/src/onboarding/index.ts +1 -8
  200. package/src/onboarding/onboarding-provider.svelte +19 -7
  201. package/src/onboarding/onboarding.svelte.ts +16 -16
  202. package/src/onboarding/pick.test.ts +61 -52
  203. package/src/onboarding/pick.ts +16 -13
  204. package/src/onboarding/stores.test.ts +80 -80
  205. package/src/onboarding/stores.ts +41 -39
  206. package/src/onboarding/tour-card.svelte +30 -5
  207. package/src/onboarding/tour-runner.svelte +12 -3
  208. package/src/onboarding/types.ts +20 -12
  209. package/src/onboarding/wait.ts +22 -22
  210. package/src/panel/side-panel.svelte +94 -93
  211. package/src/record/demo-data.ts +291 -225
  212. package/src/record/field-section.svelte +38 -34
  213. package/src/record/fields.ts +148 -96
  214. package/src/record/format.ts +63 -56
  215. package/src/record/index.ts +49 -35
  216. package/src/record/info-list.svelte +145 -114
  217. package/src/record/kinds.ts +31 -31
  218. package/src/record/logic.ts +216 -214
  219. package/src/record/next-up.svelte +45 -34
  220. package/src/record/project-list.svelte +56 -50
  221. package/src/record/record-demo.svelte +130 -110
  222. package/src/record/record-header.svelte +37 -28
  223. package/src/record/record-shell.svelte +54 -54
  224. package/src/record/record-stats.svelte +25 -25
  225. package/src/record/record-timeline.svelte +134 -114
  226. package/src/record/record.test.ts +430 -309
  227. package/src/record/steps-rail.svelte +225 -216
  228. package/src/record/types.ts +234 -215
  229. package/src/record/where-we-are.svelte +62 -58
  230. package/src/shadcn/button/button.svelte +1 -1
  231. package/src/shadcn/card/card-title.svelte +1 -5
  232. package/src/shadcn/hooks/use-highlighted-code.svelte.ts +2 -13
  233. package/src/shadcn/sheet/sheet-content.svelte +2 -4
  234. package/src/shadcn/table/table-cell.svelte +2 -3
  235. package/src/shadcn/utilities.css +3 -8
  236. package/src/slides/Controls.svelte +150 -124
  237. package/src/slides/Deck.svelte +243 -238
  238. package/src/slides/Fragment.svelte +64 -57
  239. package/src/slides/Overview.svelte +106 -101
  240. package/src/slides/Presenter.svelte +300 -266
  241. package/src/slides/Slide.svelte +185 -170
  242. package/src/slides/SlideList.svelte +16 -12
  243. package/src/slides/ambient.d.ts +1 -1
  244. package/src/slides/bridges.ts +42 -23
  245. package/src/slides/deck-controller.svelte.ts +47 -35
  246. package/src/slides/demo-slides.svelte +330 -306
  247. package/src/slides/demo.svelte +164 -160
  248. package/src/slides/export/capture.ts +20 -16
  249. package/src/slides/export/ffmpeg.ts +43 -38
  250. package/src/slides/export/index.ts +5 -5
  251. package/src/slides/export/launch.ts +3 -1
  252. package/src/slides/export/pdf.ts +30 -27
  253. package/src/slides/export/types.ts +10 -8
  254. package/src/slides/index.ts +11 -11
  255. package/src/slides/labels.ts +22 -19
  256. package/src/slides/layout.ts +9 -2
  257. package/src/slides/model.ts +4 -4
  258. package/src/slides/navigation.ts +43 -31
  259. package/src/slides/theme.css +5 -7
  260. package/src/slides/types.ts +9 -10
  261. package/src/status/define-statuses.ts +17 -24
  262. package/src/status/index.ts +5 -5
  263. package/src/status/status-badge.svelte +3 -1
  264. package/src/status/status-dot.svelte +1 -3
  265. package/src/status/status-icon.svelte +1 -1
  266. package/src/status/status-types.ts +21 -21
  267. package/src/tasks/board-order.ts +2 -4
  268. package/src/tasks/demo.svelte +189 -31
  269. package/src/tasks/detail/detail-demo.svelte +73 -13
  270. package/src/tasks/detail/detail-types.ts +45 -45
  271. package/src/tasks/detail/task-detail.svelte +40 -10
  272. package/src/tasks/detail/task-property.svelte +8 -2
  273. package/src/tasks/detail/task-thread.svelte +53 -12
  274. package/src/tasks/gantt/gantt-bar.svelte +17 -6
  275. package/src/tasks/gantt/gantt-grid.svelte +40 -9
  276. package/src/tasks/gantt/gantt-group-row.svelte +8 -2
  277. package/src/tasks/gantt/gantt-header.svelte +9 -3
  278. package/src/tasks/gantt/gantt-task-row.svelte +26 -6
  279. package/src/tasks/gantt/gantt.css +2 -1
  280. package/src/tasks/gantt/gantt.test.ts +3 -1
  281. package/src/tasks/gantt/logic.test.ts +110 -20
  282. package/src/tasks/gantt/logic.ts +42 -6
  283. package/src/tasks/inbox/inbox-card.svelte +13 -5
  284. package/src/tasks/inbox/inbox-draft.svelte +1 -1
  285. package/src/tasks/inbox/inbox-logic.ts +6 -40
  286. package/src/tasks/inbox/inbox-statuses.ts +23 -23
  287. package/src/tasks/inbox/inbox-trace.svelte +9 -3
  288. package/src/tasks/inbox/inbox-types.ts +54 -58
  289. package/src/tasks/inbox/index.ts +22 -21
  290. package/src/tasks/index.ts +49 -52
  291. package/src/tasks/kanban-board.svelte +16 -12
  292. package/src/tasks/kanban-types.ts +2 -3
  293. package/src/tasks/presets/sales.ts +6 -6
  294. package/src/tasks/task-gantt.svelte +28 -8
  295. package/src/tasks/task-list.svelte +41 -17
  296. package/src/tasks/time/duration.ts +40 -40
  297. package/src/tasks/time/time-chip.svelte +9 -2
  298. package/src/tasks/time/time-dot.svelte +1 -1
  299. package/src/tasks/time/time-ring.svelte +11 -3
  300. package/src/tasks/time/time-tracker.svelte +57 -15
  301. package/src/tasks/time/time-types.ts +57 -57
  302. package/src/tasks/use-kanban-dnd.svelte.ts +2 -3
  303. package/src/thread/index.ts +7 -7
  304. package/src/thread/logic.ts +36 -33
  305. package/src/thread/thread.svelte +82 -16
  306. package/src/thread/thread.test.ts +58 -47
  307. package/src/thread/types.ts +68 -68
  308. package/src/tokens/craft.css +17 -53
  309. package/src/tokens/index.css +3 -13
  310. package/src/tokens/palette.css +13 -11
  311. package/src/tokens/primitives.css +10 -23
  312. package/src/tasks/inbox/inbox.svelte +0 -203
@@ -50,14 +50,91 @@
50
50
  const on = (days: number) => addDays(today, days);
51
51
 
52
52
  let tasks = $state<Task[]>([
53
- { id: "t1", status: "done", title: "Set up analytics", assignee: "Bo", priority: "low", boardOrder: "a0", start: on(-12), end: on(-8) },
54
- { id: "t2", status: "done", title: "Interview five customers", assignee: "Cleo", priority: "medium", boardOrder: "a1", start: on(-10), end: on(-4) },
55
- { id: "t3", status: "review", title: "Write the pricing page", assignee: "Ada", priority: "high", boardOrder: "a0", start: on(-5), end: on(1), dependsOn: ["t2"] },
56
- { id: "t4", status: "doing", title: "Build the onboarding flow", assignee: "Dana", priority: "high", boardOrder: "a0", start: on(-3), end: on(5), dependsOn: ["t1"] },
57
- { id: "t5", status: "doing", title: "Draft the launch email", assignee: "Bo", priority: "medium", boardOrder: "a1", start: on(0), end: on(3), dependsOn: ["t3"] },
58
- { id: "t6", status: "todo", title: "Record the demo video", assignee: "Cleo", priority: "medium", boardOrder: "a0", start: on(4), end: on(8), dependsOn: ["t4"] },
59
- { id: "t7", status: "todo", title: "Pick a shipping date", assignee: "Ada", priority: "low", boardOrder: "a1", start: on(6), end: on(6) },
60
- { id: "t8", status: "todo", title: "Launch on Product Hunt", assignee: "Dana", priority: "high", boardOrder: "a2", start: on(10), end: on(11), dependsOn: ["t5", "t6"] },
53
+ {
54
+ id: "t1",
55
+ status: "done",
56
+ title: "Set up analytics",
57
+ assignee: "Bo",
58
+ priority: "low",
59
+ boardOrder: "a0",
60
+ start: on(-12),
61
+ end: on(-8),
62
+ },
63
+ {
64
+ id: "t2",
65
+ status: "done",
66
+ title: "Interview five customers",
67
+ assignee: "Cleo",
68
+ priority: "medium",
69
+ boardOrder: "a1",
70
+ start: on(-10),
71
+ end: on(-4),
72
+ },
73
+ {
74
+ id: "t3",
75
+ status: "review",
76
+ title: "Write the pricing page",
77
+ assignee: "Ada",
78
+ priority: "high",
79
+ boardOrder: "a0",
80
+ start: on(-5),
81
+ end: on(1),
82
+ dependsOn: ["t2"],
83
+ },
84
+ {
85
+ id: "t4",
86
+ status: "doing",
87
+ title: "Build the onboarding flow",
88
+ assignee: "Dana",
89
+ priority: "high",
90
+ boardOrder: "a0",
91
+ start: on(-3),
92
+ end: on(5),
93
+ dependsOn: ["t1"],
94
+ },
95
+ {
96
+ id: "t5",
97
+ status: "doing",
98
+ title: "Draft the launch email",
99
+ assignee: "Bo",
100
+ priority: "medium",
101
+ boardOrder: "a1",
102
+ start: on(0),
103
+ end: on(3),
104
+ dependsOn: ["t3"],
105
+ },
106
+ {
107
+ id: "t6",
108
+ status: "todo",
109
+ title: "Record the demo video",
110
+ assignee: "Cleo",
111
+ priority: "medium",
112
+ boardOrder: "a0",
113
+ start: on(4),
114
+ end: on(8),
115
+ dependsOn: ["t4"],
116
+ },
117
+ {
118
+ id: "t7",
119
+ status: "todo",
120
+ title: "Pick a shipping date",
121
+ assignee: "Ada",
122
+ priority: "low",
123
+ boardOrder: "a1",
124
+ start: on(6),
125
+ end: on(6),
126
+ },
127
+ {
128
+ id: "t8",
129
+ status: "todo",
130
+ title: "Launch on Product Hunt",
131
+ assignee: "Dana",
132
+ priority: "high",
133
+ boardOrder: "a2",
134
+ start: on(10),
135
+ end: on(11),
136
+ dependsOn: ["t5", "t6"],
137
+ },
61
138
  ]);
62
139
 
63
140
  const views = [
@@ -76,7 +153,11 @@
76
153
 
77
154
  const sortKeys = [
78
155
  { id: "title", label: "Title", compare: (a: Task, b: Task) => a.title.localeCompare(b.title) },
79
- { id: "assignee", label: "Assignee", compare: (a: Task, b: Task) => a.assignee.localeCompare(b.assignee) },
156
+ {
157
+ id: "assignee",
158
+ label: "Assignee",
159
+ compare: (a: Task, b: Task) => a.assignee.localeCompare(b.assignee),
160
+ },
80
161
  { id: "due", label: "Due date", compare: (a: Task, b: Task) => a.end.localeCompare(b.end) },
81
162
  ];
82
163
 
@@ -93,7 +174,11 @@
93
174
  Dana: "oklch(0.72 0.13 20)",
94
175
  };
95
176
 
96
- const dueFormat = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", timeZone: "UTC" });
177
+ const dueFormat = new Intl.DateTimeFormat("en-US", {
178
+ month: "short",
179
+ day: "numeric",
180
+ timeZone: "UTC",
181
+ });
97
182
 
98
183
  function due(task: Task): { label: string; late: boolean } {
99
184
  const late = task.status !== "done" && dayNumber(task.end) < dayNumber(today);
@@ -113,7 +198,14 @@
113
198
  }
114
199
 
115
200
  // ---- time tracking, an option the host turns on
116
- type Entry = { id: string; taskId: string; person: string; day: string; minutes: number; note?: string };
201
+ type Entry = {
202
+ id: string;
203
+ taskId: string;
204
+ person: string;
205
+ day: string;
206
+ minutes: number;
207
+ note?: string;
208
+ };
117
209
 
118
210
  const estimates: Record<string, number> = { t3: 360, t4: 480, t5: 180, t6: 240 };
119
211
 
@@ -121,9 +213,30 @@
121
213
  let timeTaskId = $state("t4");
122
214
  let nextEntry = 100;
123
215
  let entries = $state<Entry[]>([
124
- { id: "e1", taskId: "t4", person: "Dana", day: on(-3), minutes: 150, note: "Signup and email step" },
125
- { id: "e2", taskId: "t4", person: "Ada", day: on(-2), minutes: 95, note: "Copy for the welcome screen" },
126
- { id: "e3", taskId: "t4", person: "Dana", day: on(-2), minutes: 125, note: "Progress bar and empty states" },
216
+ {
217
+ id: "e1",
218
+ taskId: "t4",
219
+ person: "Dana",
220
+ day: on(-3),
221
+ minutes: 150,
222
+ note: "Signup and email step",
223
+ },
224
+ {
225
+ id: "e2",
226
+ taskId: "t4",
227
+ person: "Ada",
228
+ day: on(-2),
229
+ minutes: 95,
230
+ note: "Copy for the welcome screen",
231
+ },
232
+ {
233
+ id: "e3",
234
+ taskId: "t4",
235
+ person: "Dana",
236
+ day: on(-2),
237
+ minutes: 125,
238
+ note: "Progress bar and empty states",
239
+ },
127
240
  { id: "e4", taskId: "t4", person: "Dana", day: on(-1), minutes: 80 },
128
241
  { id: "e5", taskId: "t3", person: "Ada", day: on(-5), minutes: 210, note: "First draft" },
129
242
  { id: "e6", taskId: "t3", person: "Bo", day: on(-3), minutes: 95, note: "Pricing table" },
@@ -158,7 +271,8 @@
158
271
  timer = null;
159
272
  }
160
273
 
161
- const listGrid = "grid grid-cols-[minmax(0,1fr)_7rem_5.5rem_4.5rem] items-center gap-3 max-sm:grid-cols-[minmax(0,1fr)_4.5rem]";
274
+ const listGrid =
275
+ "grid grid-cols-[minmax(0,1fr)_7rem_5.5rem_4.5rem] items-center gap-3 max-sm:grid-cols-[minmax(0,1fr)_4.5rem]";
162
276
  </script>
163
277
 
164
278
  {#snippet avatar(name: string)}
@@ -176,12 +290,23 @@
176
290
  <div class="flex flex-wrap items-center gap-2">
177
291
  <SegmentedFilter options={views} bind:value={view} ariaLabel="Task view" block={false} />
178
292
  <div class="ml-auto flex items-center gap-3">
179
- <label class="flex cursor-pointer items-center gap-1.5 text-xs font-medium text-muted-foreground">
180
- <input type="checkbox" bind:checked={tracking} class="size-3.5 accent-[var(--tone-accent,var(--color-primary))]" />
293
+ <label
294
+ class="flex cursor-pointer items-center gap-1.5 text-xs font-medium text-muted-foreground"
295
+ >
296
+ <input
297
+ type="checkbox"
298
+ bind:checked={tracking}
299
+ class="size-3.5 accent-[var(--tone-accent,var(--color-primary))]"
300
+ />
181
301
  Time tracking
182
302
  </label>
183
303
  {#if view === "gantt"}
184
- <SegmentedFilter options={scales} bind:value={scale} ariaLabel="Timeline scale" block={false} />
304
+ <SegmentedFilter
305
+ options={scales}
306
+ bind:value={scale}
307
+ ariaLabel="Timeline scale"
308
+ block={false}
309
+ />
185
310
  {:else}
186
311
  <label for="tasks-sort" class="text-xs font-medium text-muted-foreground">Sort</label>
187
312
  <select
@@ -213,15 +338,27 @@
213
338
  >
214
339
  {#snippet renderCard(task)}
215
340
  {@const d = due(task)}
216
- <article class="rounded-xl border border-border bg-card p-2.5 text-card-foreground shadow-sm">
341
+ <article
342
+ class="rounded-xl border border-border bg-card p-2.5 text-card-foreground shadow-sm"
343
+ >
217
344
  <p class="text-sm leading-snug">{task.title}</p>
218
345
  <div class="mt-2.5 flex items-center gap-2 text-xs">
219
346
  {@render avatar(task.assignee)}
220
- <span class={d.late ? "font-medium text-destructive" : "text-muted-foreground"}>{d.label}</span>
347
+ <span class={d.late ? "font-medium text-destructive" : "text-muted-foreground"}
348
+ >{d.label}</span
349
+ >
221
350
  {#if tracking}
222
- <TimeChip minutes={minutesByTask[task.id] ?? 0} estimate={estimates[task.id]} running={timer?.taskId === task.id} />
351
+ <TimeChip
352
+ minutes={minutesByTask[task.id] ?? 0}
353
+ estimate={estimates[task.id]}
354
+ running={timer?.taskId === task.id}
355
+ />
223
356
  {/if}
224
- <span class="ml-auto rounded-full px-1.5 py-0.5 font-medium capitalize {priorityClass[task.priority]}">
357
+ <span
358
+ class="ml-auto rounded-full px-1.5 py-0.5 font-medium capitalize {priorityClass[
359
+ task.priority
360
+ ]}"
361
+ >
225
362
  {task.priority}
226
363
  </span>
227
364
  </div>
@@ -252,13 +389,21 @@
252
389
  <div class="{listGrid} h-10 px-2 text-sm">
253
390
  <span class="flex min-w-0 items-center gap-2.5">
254
391
  {#key task.status}
255
- <StatusDot statuses={statuses} status={task.status} />
392
+ <StatusDot {statuses} status={task.status} />
256
393
  {/key}
257
- <span class="truncate" class:text-muted-foreground={task.status === "done"} class:line-through={task.status === "done"}>
394
+ <span
395
+ class="truncate"
396
+ class:text-muted-foreground={task.status === "done"}
397
+ class:line-through={task.status === "done"}
398
+ >
258
399
  {task.title}
259
400
  </span>
260
401
  {#if tracking}
261
- <TimeChip minutes={minutesByTask[task.id] ?? 0} estimate={estimates[task.id]} running={timer?.taskId === task.id} />
402
+ <TimeChip
403
+ minutes={minutesByTask[task.id] ?? 0}
404
+ estimate={estimates[task.id]}
405
+ running={timer?.taskId === task.id}
406
+ />
262
407
  {/if}
263
408
  </span>
264
409
  <span class="flex min-w-0 items-center gap-2 text-muted-foreground max-sm:hidden">
@@ -266,11 +411,19 @@
266
411
  <span class="truncate">{task.assignee}</span>
267
412
  </span>
268
413
  <span class="max-sm:hidden">
269
- <span class="rounded-full px-1.5 py-0.5 text-xs font-medium capitalize {priorityClass[task.priority]}">
414
+ <span
415
+ class="rounded-full px-1.5 py-0.5 text-xs font-medium capitalize {priorityClass[
416
+ task.priority
417
+ ]}"
418
+ >
270
419
  {task.priority}
271
420
  </span>
272
421
  </span>
273
- <span class="text-right text-xs tabular-nums {d.late ? 'font-medium text-destructive' : 'text-muted-foreground'}">
422
+ <span
423
+ class="text-right text-xs tabular-nums {d.late
424
+ ? 'font-medium text-destructive'
425
+ : 'text-muted-foreground'}"
426
+ >
274
427
  {d.label}
275
428
  </span>
276
429
  </div>
@@ -293,7 +446,7 @@
293
446
  {onChange}
294
447
  >
295
448
  {#snippet renderLabel(task)}
296
- <StatusDot statuses={statuses} status={task.status} />
449
+ <StatusDot {statuses} status={task.status} />
297
450
  <span class="min-w-0 flex-1 truncate">{task.title}</span>
298
451
  {@render avatar(task.assignee)}
299
452
  {/snippet}
@@ -316,7 +469,9 @@
316
469
  {#if tracking}
317
470
  <section class="flex flex-col gap-3 border-t border-border pt-4">
318
471
  <div class="flex items-center justify-between gap-3">
319
- <h3 class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Task time</h3>
472
+ <h3 class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
473
+ Task time
474
+ </h3>
320
475
  <select
321
476
  bind:value={timeTaskId}
322
477
  aria-label="Task"
@@ -350,7 +505,9 @@
350
505
  {/if}
351
506
 
352
507
  <section class="flex flex-col gap-2 border-t border-border pt-4">
353
- <h3 class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">Status badges</h3>
508
+ <h3 class="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
509
+ Status badges
510
+ </h3>
354
511
  <div class="flex flex-wrap items-center gap-2">
355
512
  {#each salesStatuses.ids as id (id)}
356
513
  <StatusBadge statuses={salesStatuses} status={id} />
@@ -370,7 +527,8 @@
370
527
  <style>
371
528
  /* Switching views: the new one rises in with a touch of blur, the old one is gone at once. */
372
529
  .tasks-view {
373
- animation: tasks-view-in var(--duration-fast, 250ms) var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)) backwards;
530
+ animation: tasks-view-in var(--duration-fast, 250ms)
531
+ var(--ease-smooth-out, cubic-bezier(0.22, 1, 0.36, 1)) backwards;
374
532
  }
375
533
 
376
534
  @keyframes tasks-view-in {
@@ -9,7 +9,15 @@
9
9
  import type { TaskComment } from "./detail-types.js";
10
10
  import type { TimeLogInput, TimeStopInfo } from "../time/time-types.js";
11
11
 
12
- type Scenario = "default" | "long" | "emptyDescription" | "unassigned" | "running" | "busy" | "closed" | "loading";
12
+ type Scenario =
13
+ | "default"
14
+ | "long"
15
+ | "emptyDescription"
16
+ | "unassigned"
17
+ | "running"
18
+ | "busy"
19
+ | "closed"
20
+ | "loading";
13
21
 
14
22
  const statuses = defineStatuses({
15
23
  todo: { label: "To do", tone: "neutral", variant: "open" },
@@ -34,15 +42,35 @@
34
42
  const stamp = (agoHours: number) => new Date(now - agoHours * hour).toISOString();
35
43
 
36
44
  const seed: TaskComment[] = [
37
- { id: "c1", author: "Ada Lovelace", body: "Calls with Yoan: the format that sold the template was simple. A board on why, then the system, then the demo.", createdAt: stamp(30) },
38
- { id: "c2", author: "Planner", agent: true, body: "Reused that shape for the outline. Three sections, the demo last, one call to action at the end.", createdAt: stamp(26) },
39
- { id: "c3", author: "Bo Chen", body: "Looks right. I'll record Thursday.", createdAt: stamp(5), edited: true },
45
+ {
46
+ id: "c1",
47
+ author: "Ada Lovelace",
48
+ body: "Calls with Yoan: the format that sold the template was simple. A board on why, then the system, then the demo.",
49
+ createdAt: stamp(30),
50
+ },
51
+ {
52
+ id: "c2",
53
+ author: "Planner",
54
+ agent: true,
55
+ body: "Reused that shape for the outline. Three sections, the demo last, one call to action at the end.",
56
+ createdAt: stamp(26),
57
+ },
58
+ {
59
+ id: "c3",
60
+ author: "Bo Chen",
61
+ body: "Looks right. I'll record Thursday.",
62
+ createdAt: stamp(5),
63
+ edited: true,
64
+ },
40
65
  ];
41
66
  const crowd: TaskComment[] = Array.from({ length: 24 }, (_, i) => ({
42
67
  id: `b${i}`,
43
- author: i % 4 === 1 ? "Planner" : people[i % people.length] ?? "Ada Lovelace",
68
+ author: i % 4 === 1 ? "Planner" : (people[i % people.length] ?? "Ada Lovelace"),
44
69
  agent: i % 4 === 1,
45
- body: i % 5 === 0 ? "Pushed the second cut. The intro runs 40 seconds, so I trimmed the first example and kept the one with numbers." : "Noted, moving on to the next step.",
70
+ body:
71
+ i % 5 === 0
72
+ ? "Pushed the second cut. The intro runs 40 seconds, so I trimmed the first example and kept the one with numbers."
73
+ : "Noted, moving on to the next step.",
46
74
  createdAt: stamp(60 - i * 2),
47
75
  }));
48
76
 
@@ -59,7 +87,13 @@
59
87
  let done = $state(false);
60
88
  let timer = $state<{ startedAt: number } | null>(null);
61
89
  let entries = $state([
62
- { id: "e1", minutes: 90, day: new Date(now - 24 * hour).toISOString().slice(0, 10), person: "Ada Lovelace", note: "Outline" },
90
+ {
91
+ id: "e1",
92
+ minutes: 90,
93
+ day: new Date(now - 24 * hour).toISOString().slice(0, 10),
94
+ person: "Ada Lovelace",
95
+ note: "Outline",
96
+ },
63
97
  ]);
64
98
 
65
99
  $effect(() => {
@@ -76,7 +110,16 @@
76
110
  let statusLabel = $derived(statuses.label(status));
77
111
 
78
112
  function onLog(input: TimeLogInput) {
79
- entries = [{ id: `e${entries.length + 1}`, minutes: input.minutes, day: input.day, person: "Ada Lovelace", note: input.note ?? "" }, ...entries];
113
+ entries = [
114
+ {
115
+ id: `e${entries.length + 1}`,
116
+ minutes: input.minutes,
117
+ day: input.day,
118
+ person: "Ada Lovelace",
119
+ note: input.note ?? "",
120
+ },
121
+ ...entries,
122
+ ];
80
123
  return true;
81
124
  }
82
125
 
@@ -86,7 +129,15 @@
86
129
  }
87
130
 
88
131
  function onSend(body: string) {
89
- thread = [...thread, { id: `n${thread.length}`, author: "Ada Lovelace", body, createdAt: new Date().toISOString() }];
132
+ thread = [
133
+ ...thread,
134
+ {
135
+ id: `n${thread.length}`,
136
+ author: "Ada Lovelace",
137
+ body,
138
+ createdAt: new Date().toISOString(),
139
+ },
140
+ ];
90
141
  }
91
142
  </script>
92
143
 
@@ -112,7 +163,10 @@
112
163
  </button>
113
164
  </div>
114
165
 
115
- <div class="mx-auto w-full overflow-hidden rounded-xl border border-border bg-background" style:max-width={narrow ? "390px" : "none"}>
166
+ <div
167
+ class="mx-auto w-full overflow-hidden rounded-xl border border-border bg-background"
168
+ style:max-width={narrow ? "390px" : "none"}
169
+ >
116
170
  <TaskDetail
117
171
  {title}
118
172
  onTitleChange={(next) => {
@@ -139,15 +193,21 @@
139
193
  {/snippet}
140
194
  {#snippet properties()}
141
195
  <TaskProperty label="Status">
142
- <TaskChip aria-label="Status: {statusLabel}"><StatusDot {statuses} {status} size={14} animate={false} />{statusLabel}</TaskChip>
196
+ <TaskChip aria-label="Status: {statusLabel}"
197
+ ><StatusDot {statuses} {status} size={14} animate={false} />{statusLabel}</TaskChip
198
+ >
143
199
  </TaskProperty>
144
200
  <TaskProperty label="Priority">
145
- <TaskChip><Flag weight="fill" class="text-destructive" aria-hidden="true" />High</TaskChip>
201
+ <TaskChip><Flag weight="fill" class="text-destructive" aria-hidden="true" />High</TaskChip
202
+ >
146
203
  </TaskProperty>
147
204
  <TaskProperty label="Assignee">
148
205
  {#if assignee}
149
206
  <TaskChip>
150
- <span class="grid size-4 place-items-center rounded-full bg-muted text-[0px]" aria-hidden="true"><User /></span>
207
+ <span
208
+ class="grid size-4 place-items-center rounded-full bg-muted text-[0px]"
209
+ aria-hidden="true"><User /></span
210
+ >
151
211
  {assignee}
152
212
  </TaskChip>
153
213
  {:else}
@@ -1,54 +1,54 @@
1
1
  /** One entry in a task's thread. The host resolves the author's name. */
2
2
  export type TaskComment = {
3
- id: string;
4
- author: string;
5
- body: string;
6
- /** ISO timestamp. */
7
- createdAt: string;
8
- /** An agent wrote it: the thread draws the agent avatar and an "AI" label. */
9
- agent?: boolean;
10
- /** Set when the body changed after posting. */
11
- edited?: boolean;
3
+ id: string;
4
+ author: string;
5
+ body: string;
6
+ /** ISO timestamp. */
7
+ createdAt: string;
8
+ /** An agent wrote it: the thread draws the agent avatar and an "AI" label. */
9
+ agent?: boolean;
10
+ /** Set when the body changed after posting. */
11
+ edited?: boolean;
12
12
  };
13
13
 
14
14
  export type TaskDetailLabels = {
15
- markComplete: string;
16
- markIncomplete: string;
17
- editTitle: string;
18
- description: string;
19
- addDescription: string;
20
- editDescription: string;
21
- save: string;
22
- saving: string;
23
- cancel: string;
24
- comments: string;
25
- commentPlaceholder: string;
26
- commentSend: string;
27
- commentEdit: string;
28
- commentDelete: string;
29
- commentEdited: string;
30
- commentsEmpty: string;
31
- ai: string;
32
- properties: string;
15
+ markComplete: string;
16
+ markIncomplete: string;
17
+ editTitle: string;
18
+ description: string;
19
+ addDescription: string;
20
+ editDescription: string;
21
+ save: string;
22
+ saving: string;
23
+ cancel: string;
24
+ comments: string;
25
+ commentPlaceholder: string;
26
+ commentSend: string;
27
+ commentEdit: string;
28
+ commentDelete: string;
29
+ commentEdited: string;
30
+ commentsEmpty: string;
31
+ ai: string;
32
+ properties: string;
33
33
  };
34
34
 
35
35
  export const DEFAULT_TASK_DETAIL_LABELS: TaskDetailLabels = {
36
- markComplete: "Mark complete",
37
- markIncomplete: "Mark incomplete",
38
- editTitle: "Edit title",
39
- description: "Description",
40
- addDescription: "Add a description",
41
- editDescription: "Edit description",
42
- save: "Save",
43
- saving: "Saving",
44
- cancel: "Cancel",
45
- comments: "Activity",
46
- commentPlaceholder: "Leave a comment",
47
- commentSend: "Comment",
48
- commentEdit: "Edit comment",
49
- commentDelete: "Delete comment",
50
- commentEdited: "edited",
51
- commentsEmpty: "No comments yet",
52
- ai: "AI",
53
- properties: "Properties",
36
+ markComplete: "Mark complete",
37
+ markIncomplete: "Mark incomplete",
38
+ editTitle: "Edit title",
39
+ description: "Description",
40
+ addDescription: "Add a description",
41
+ editDescription: "Edit description",
42
+ save: "Save",
43
+ saving: "Saving",
44
+ cancel: "Cancel",
45
+ comments: "Activity",
46
+ commentPlaceholder: "Leave a comment",
47
+ commentSend: "Comment",
48
+ commentEdit: "Edit comment",
49
+ commentDelete: "Delete comment",
50
+ commentEdited: "edited",
51
+ commentsEmpty: "No comments yet",
52
+ ai: "AI",
53
+ properties: "Properties",
54
54
  };
@@ -2,7 +2,11 @@
2
2
  import type { Snippet } from "svelte";
3
3
  import { Circle, CheckCircle, PencilSimple } from "phosphor-svelte";
4
4
  import { cn } from "../../lib/utils.js";
5
- import { DEFAULT_TASK_DETAIL_LABELS, type TaskComment, type TaskDetailLabels } from "./detail-types.js";
5
+ import {
6
+ DEFAULT_TASK_DETAIL_LABELS,
7
+ type TaskComment,
8
+ type TaskDetailLabels,
9
+ } from "./detail-types.js";
6
10
  import TaskThread from "./task-thread.svelte";
7
11
 
8
12
  interface Props {
@@ -119,7 +123,10 @@
119
123
  onclick={onToggleDone}
120
124
  disabled={!onToggleDone}
121
125
  aria-label={done ? labels.markIncomplete : labels.markComplete}
122
- class={cn("tk-icon mt-px", done ? "text-success" : "text-muted-foreground/60 hover:text-foreground")}
126
+ class={cn(
127
+ "tk-icon mt-px",
128
+ done ? "text-success" : "text-muted-foreground/60 hover:text-foreground",
129
+ )}
123
130
  >
124
131
  {#if done}
125
132
  <CheckCircle class="size-5" weight="fill" aria-hidden="true" />
@@ -139,7 +146,9 @@
139
146
  class="-mx-2 -my-1 min-w-0 flex-1 resize-none rounded-md border border-input bg-transparent px-2 py-1 text-2xl leading-tight font-semibold tracking-tight outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
140
147
  ></textarea>
141
148
  {:else}
142
- <h1 class="min-w-0 flex-1 text-2xl leading-tight font-semibold tracking-tight text-balance break-words">
149
+ <h1
150
+ class="min-w-0 flex-1 text-2xl leading-tight font-semibold tracking-tight text-balance break-words"
151
+ >
143
152
  <button
144
153
  type="button"
145
154
  onclick={startTitle}
@@ -153,14 +162,19 @@
153
162
  >
154
163
  {title}
155
164
  {#if onTitleChange}
156
- <PencilSimple class="ms-1.5 inline size-3.5 align-middle text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100" aria-hidden="true" />
165
+ <PencilSimple
166
+ class="ms-1.5 inline size-3.5 align-middle text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100"
167
+ aria-hidden="true"
168
+ />
157
169
  {/if}
158
170
  </button>
159
171
  </h1>
160
172
  {/if}
161
173
  </div>
162
174
  {#if meta}
163
- <div class="mt-2 flex min-h-5 flex-wrap items-center gap-x-3 gap-y-1 ps-9 text-xs text-muted-foreground">
175
+ <div
176
+ class="mt-2 flex min-h-5 flex-wrap items-center gap-x-3 gap-y-1 ps-9 text-xs text-muted-foreground"
177
+ >
164
178
  {@render meta()}
165
179
  </div>
166
180
  {/if}
@@ -171,10 +185,14 @@
171
185
  class="px-4 pt-3 @3xl:col-start-2 @3xl:row-span-2 @3xl:row-start-1 @3xl:border-s @3xl:border-border @3xl:px-5 @3xl:pt-6"
172
186
  aria-label={labels.properties}
173
187
  >
174
- <div class="flex flex-wrap items-center gap-1 @3xl:sticky @3xl:top-0 @3xl:flex-col @3xl:items-stretch @3xl:gap-0.5">
188
+ <div
189
+ class="flex flex-wrap items-center gap-1 @3xl:sticky @3xl:top-0 @3xl:flex-col @3xl:items-stretch @3xl:gap-0.5"
190
+ >
175
191
  {@render properties?.()}
176
192
  {#if railFooter}
177
- <div class="mt-2 hidden w-full border-t border-border/60 pt-3 @3xl:block">{@render railFooter()}</div>
193
+ <div class="mt-2 hidden w-full border-t border-border/60 pt-3 @3xl:block">
194
+ {@render railFooter()}
195
+ </div>
178
196
  {/if}
179
197
  </div>
180
198
  </aside>
@@ -185,7 +203,12 @@
185
203
  <div class="flex h-7 items-center justify-between">
186
204
  <h2 class="text-xs font-medium text-muted-foreground">{labels.description}</h2>
187
205
  {#if !editingDescription && description && onDescriptionChange}
188
- <button type="button" class="tk-icon" onclick={startDescription} aria-label={labels.editDescription}>
206
+ <button
207
+ type="button"
208
+ class="tk-icon"
209
+ onclick={startDescription}
210
+ aria-label={labels.editDescription}
211
+ >
189
212
  <PencilSimple class="size-3.5" aria-hidden="true" />
190
213
  </button>
191
214
  {/if}
@@ -200,8 +223,15 @@
200
223
  class="w-full resize-y rounded-md border border-input bg-transparent px-3 py-2 text-sm leading-relaxed outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50"
201
224
  ></textarea>
202
225
  <div class="mt-1 flex justify-end gap-1.5">
203
- <button type="button" class="tk-button" onclick={() => (editingDescription = false)}>{labels.cancel}</button>
204
- <button type="button" class="tk-button tk-primary" onclick={saveDescription} disabled={savingDescription}>
226
+ <button type="button" class="tk-button" onclick={() => (editingDescription = false)}
227
+ >{labels.cancel}</button
228
+ >
229
+ <button
230
+ type="button"
231
+ class="tk-button tk-primary"
232
+ onclick={saveDescription}
233
+ disabled={savingDescription}
234
+ >
205
235
  {savingDescription ? labels.saving : labels.save}
206
236
  </button>
207
237
  </div>