@tldraw/commenting 0.0.0-bootstrap → 5.3.0-canary.04044ed9e96d

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 (338) hide show
  1. package/README.md +0 -2
  2. package/commenting.css +1152 -350
  3. package/dist-cjs/canvas/anchor-lifecycle.js +148 -0
  4. package/dist-cjs/canvas/anchor-lifecycle.js.map +7 -0
  5. package/dist-cjs/{ui/avatar.js → canvas/canvas-events.js} +14 -22
  6. package/dist-cjs/canvas/canvas-events.js.map +7 -0
  7. package/dist-cjs/canvas/cluster-badge.js +121 -0
  8. package/dist-cjs/canvas/cluster-badge.js.map +7 -0
  9. package/dist-cjs/canvas/cluster-fade.js +85 -0
  10. package/dist-cjs/canvas/cluster-fade.js.map +7 -0
  11. package/dist-cjs/canvas/cluster-input.js +53 -3
  12. package/dist-cjs/canvas/cluster-input.js.map +2 -2
  13. package/dist-cjs/canvas/cluster-model.js +252 -0
  14. package/dist-cjs/canvas/cluster-model.js.map +7 -0
  15. package/dist-cjs/canvas/comment-body.js +1 -1
  16. package/dist-cjs/canvas/comment-body.js.map +2 -2
  17. package/dist-cjs/canvas/comment-drafts.js +54 -0
  18. package/dist-cjs/canvas/comment-drafts.js.map +7 -0
  19. package/dist-cjs/canvas/comment-mutations.js +152 -0
  20. package/dist-cjs/canvas/comment-mutations.js.map +7 -0
  21. package/dist-cjs/canvas/comment-reactions.js +160 -0
  22. package/dist-cjs/canvas/comment-reactions.js.map +7 -0
  23. package/dist-cjs/canvas/comment-render.js +9 -6
  24. package/dist-cjs/canvas/comment-render.js.map +2 -2
  25. package/dist-cjs/canvas/comment-store.js +19 -9
  26. package/dist-cjs/canvas/comment-store.js.map +2 -2
  27. package/dist-cjs/canvas/comment-tool.js +63 -14
  28. package/dist-cjs/canvas/comment-tool.js.map +2 -2
  29. package/dist-cjs/canvas/comments-filter-menu.js +17 -37
  30. package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
  31. package/dist-cjs/canvas/comments-overflow-menu.js +25 -22
  32. package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
  33. package/dist-cjs/canvas/comments-overlay.js +151 -989
  34. package/dist-cjs/canvas/comments-overlay.js.map +3 -3
  35. package/dist-cjs/canvas/comments-sidebar.js +49 -41
  36. package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
  37. package/dist-cjs/canvas/comments-visibility-toggle.js +45 -0
  38. package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
  39. package/dist-cjs/canvas/context.js +17 -0
  40. package/dist-cjs/canvas/context.js.map +7 -0
  41. package/dist-cjs/canvas/hooks.js +28 -3
  42. package/dist-cjs/canvas/hooks.js.map +2 -2
  43. package/dist-cjs/canvas/license.js.map +1 -1
  44. package/dist-cjs/canvas/mobile-placement.js +91 -0
  45. package/dist-cjs/canvas/mobile-placement.js.map +7 -0
  46. package/dist-cjs/canvas/options.js +57 -2
  47. package/dist-cjs/canvas/options.js.map +2 -2
  48. package/dist-cjs/canvas/pending-composer.js +134 -0
  49. package/dist-cjs/canvas/pending-composer.js.map +7 -0
  50. package/dist-cjs/canvas/pin-stacking.js +81 -0
  51. package/dist-cjs/canvas/pin-stacking.js.map +7 -0
  52. package/dist-cjs/canvas/region-box.js +113 -0
  53. package/dist-cjs/canvas/region-box.js.map +7 -0
  54. package/dist-cjs/canvas/sidebar-filters.js +2 -2
  55. package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
  56. package/dist-cjs/canvas/state.js +28 -14
  57. package/dist-cjs/canvas/state.js.map +2 -2
  58. package/dist-cjs/canvas/thread-pin.js +304 -0
  59. package/dist-cjs/canvas/thread-pin.js.map +7 -0
  60. package/dist-cjs/canvas/thread-preview.js +177 -0
  61. package/dist-cjs/canvas/thread-preview.js.map +7 -0
  62. package/dist-cjs/canvas/thread-stack.js +199 -0
  63. package/dist-cjs/canvas/thread-stack.js.map +7 -0
  64. package/dist-cjs/canvas/thread-state.js +82 -21
  65. package/dist-cjs/canvas/thread-state.js.map +2 -2
  66. package/dist-cjs/canvas/thread-view.js +450 -0
  67. package/dist-cjs/canvas/thread-view.js.map +7 -0
  68. package/dist-cjs/clustering/computeClusterTable.js +6 -6
  69. package/dist-cjs/clustering/computeClusterTable.js.map +2 -2
  70. package/dist-cjs/clustering/replay.js +89 -22
  71. package/dist-cjs/clustering/replay.js.map +3 -3
  72. package/dist-cjs/clustering/runtime.js +126 -7
  73. package/dist-cjs/clustering/runtime.js.map +2 -2
  74. package/dist-cjs/clustering/types.js.map +1 -1
  75. package/dist-cjs/index.d.ts +904 -353
  76. package/dist-cjs/index.js +52 -28
  77. package/dist-cjs/index.js.map +2 -2
  78. package/dist-cjs/ui/byline.js +10 -6
  79. package/dist-cjs/ui/byline.js.map +2 -2
  80. package/dist-cjs/ui/comment-card.js +15 -8
  81. package/dist-cjs/ui/comment-card.js.map +2 -2
  82. package/dist-cjs/ui/comment-composer.js +124 -39
  83. package/dist-cjs/ui/comment-composer.js.map +2 -2
  84. package/dist-cjs/ui/comment-pin.js +11 -2
  85. package/dist-cjs/ui/comment-pin.js.map +2 -2
  86. package/dist-cjs/ui/comment-thread.js +9 -7
  87. package/dist-cjs/ui/comment-thread.js.map +2 -2
  88. package/dist-cjs/ui/comments-list.js +39 -40
  89. package/dist-cjs/ui/comments-list.js.map +2 -2
  90. package/dist-cjs/ui/count-badge.js +3 -2
  91. package/dist-cjs/ui/count-badge.js.map +2 -2
  92. package/dist-cjs/ui/emoji-picker.js +54 -0
  93. package/dist-cjs/ui/emoji-picker.js.map +7 -0
  94. package/dist-cjs/ui/empty-state.js +3 -3
  95. package/dist-cjs/ui/empty-state.js.map +2 -2
  96. package/dist-cjs/ui/format-time.js +16 -1
  97. package/dist-cjs/ui/format-time.js.map +2 -2
  98. package/dist-cjs/ui/icons.js +115 -0
  99. package/dist-cjs/ui/icons.js.map +7 -0
  100. package/dist-cjs/ui/reaction-picker.js +71 -0
  101. package/dist-cjs/ui/reaction-picker.js.map +7 -0
  102. package/dist-cjs/ui/reaction.js +58 -6
  103. package/dist-cjs/ui/reaction.js.map +2 -2
  104. package/dist-cjs/ui/reactions.js +20 -7
  105. package/dist-cjs/ui/reactions.js.map +2 -2
  106. package/dist-cjs/ui/{mention.js → reply-count.js} +9 -11
  107. package/dist-cjs/ui/reply-count.js.map +7 -0
  108. package/dist-cjs/ui/send-button.js +13 -1
  109. package/dist-cjs/ui/send-button.js.map +2 -2
  110. package/dist-cjs/ui/{comment-text.js → visual-viewport.js} +12 -9
  111. package/dist-cjs/ui/visual-viewport.js.map +7 -0
  112. package/dist-esm/canvas/anchor-lifecycle.mjs +128 -0
  113. package/dist-esm/canvas/anchor-lifecycle.mjs.map +7 -0
  114. package/dist-esm/canvas/canvas-events.mjs +15 -0
  115. package/dist-esm/canvas/canvas-events.mjs.map +7 -0
  116. package/dist-esm/canvas/cluster-badge.mjs +106 -0
  117. package/dist-esm/canvas/cluster-badge.mjs.map +7 -0
  118. package/dist-esm/canvas/cluster-fade.mjs +65 -0
  119. package/dist-esm/canvas/cluster-fade.mjs.map +7 -0
  120. package/dist-esm/canvas/cluster-input.mjs +54 -4
  121. package/dist-esm/canvas/cluster-input.mjs.map +2 -2
  122. package/dist-esm/canvas/cluster-model.mjs +236 -0
  123. package/dist-esm/canvas/cluster-model.mjs.map +7 -0
  124. package/dist-esm/canvas/comment-body.mjs +1 -1
  125. package/dist-esm/canvas/comment-body.mjs.map +2 -2
  126. package/dist-esm/canvas/comment-drafts.mjs +34 -0
  127. package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
  128. package/dist-esm/canvas/comment-mutations.mjs +132 -0
  129. package/dist-esm/canvas/comment-mutations.mjs.map +7 -0
  130. package/dist-esm/canvas/comment-reactions.mjs +145 -0
  131. package/dist-esm/canvas/comment-reactions.mjs.map +7 -0
  132. package/dist-esm/canvas/comment-render.mjs +10 -7
  133. package/dist-esm/canvas/comment-render.mjs.map +2 -2
  134. package/dist-esm/canvas/comment-store.mjs +19 -9
  135. package/dist-esm/canvas/comment-store.mjs.map +2 -2
  136. package/dist-esm/canvas/comment-tool.mjs +66 -17
  137. package/dist-esm/canvas/comment-tool.mjs.map +2 -2
  138. package/dist-esm/canvas/comments-filter-menu.mjs +17 -36
  139. package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
  140. package/dist-esm/canvas/comments-overflow-menu.mjs +27 -22
  141. package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
  142. package/dist-esm/canvas/comments-overlay.mjs +157 -1010
  143. package/dist-esm/canvas/comments-overlay.mjs.map +3 -3
  144. package/dist-esm/canvas/comments-sidebar.mjs +53 -46
  145. package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
  146. package/dist-esm/canvas/comments-visibility-toggle.mjs +25 -0
  147. package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
  148. package/dist-esm/canvas/context.mjs +1 -0
  149. package/dist-esm/canvas/context.mjs.map +7 -0
  150. package/dist-esm/canvas/hooks.mjs +35 -5
  151. package/dist-esm/canvas/hooks.mjs.map +2 -2
  152. package/dist-esm/canvas/license.mjs.map +1 -1
  153. package/dist-esm/canvas/mobile-placement.mjs +71 -0
  154. package/dist-esm/canvas/mobile-placement.mjs.map +7 -0
  155. package/dist-esm/canvas/options.mjs +59 -3
  156. package/dist-esm/canvas/options.mjs.map +2 -2
  157. package/dist-esm/canvas/pending-composer.mjs +126 -0
  158. package/dist-esm/canvas/pending-composer.mjs.map +7 -0
  159. package/dist-esm/canvas/pin-stacking.mjs +61 -0
  160. package/dist-esm/canvas/pin-stacking.mjs.map +7 -0
  161. package/dist-esm/canvas/region-box.mjs +93 -0
  162. package/dist-esm/canvas/region-box.mjs.map +7 -0
  163. package/dist-esm/canvas/sidebar-filters.mjs +2 -2
  164. package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
  165. package/dist-esm/canvas/state.mjs +29 -19
  166. package/dist-esm/canvas/state.mjs.map +2 -2
  167. package/dist-esm/canvas/thread-pin.mjs +310 -0
  168. package/dist-esm/canvas/thread-pin.mjs.map +7 -0
  169. package/dist-esm/canvas/thread-preview.mjs +163 -0
  170. package/dist-esm/canvas/thread-preview.mjs.map +7 -0
  171. package/dist-esm/canvas/thread-stack.mjs +189 -0
  172. package/dist-esm/canvas/thread-stack.mjs.map +7 -0
  173. package/dist-esm/canvas/thread-state.mjs +86 -22
  174. package/dist-esm/canvas/thread-state.mjs.map +2 -2
  175. package/dist-esm/canvas/thread-view.mjs +461 -0
  176. package/dist-esm/canvas/thread-view.mjs.map +7 -0
  177. package/dist-esm/clustering/computeClusterTable.mjs +6 -6
  178. package/dist-esm/clustering/computeClusterTable.mjs.map +2 -2
  179. package/dist-esm/clustering/replay.mjs +89 -22
  180. package/dist-esm/clustering/replay.mjs.map +3 -3
  181. package/dist-esm/clustering/runtime.mjs +126 -7
  182. package/dist-esm/clustering/runtime.mjs.map +2 -2
  183. package/dist-esm/index.d.mts +904 -353
  184. package/dist-esm/index.mjs +102 -43
  185. package/dist-esm/index.mjs.map +2 -2
  186. package/dist-esm/ui/byline.mjs +11 -7
  187. package/dist-esm/ui/byline.mjs.map +2 -2
  188. package/dist-esm/ui/comment-card.mjs +15 -8
  189. package/dist-esm/ui/comment-card.mjs.map +2 -2
  190. package/dist-esm/ui/comment-composer.mjs +135 -39
  191. package/dist-esm/ui/comment-composer.mjs.map +2 -2
  192. package/dist-esm/ui/comment-pin.mjs +11 -2
  193. package/dist-esm/ui/comment-pin.mjs.map +2 -2
  194. package/dist-esm/ui/comment-thread.mjs +9 -7
  195. package/dist-esm/ui/comment-thread.mjs.map +2 -2
  196. package/dist-esm/ui/comments-list.mjs +51 -50
  197. package/dist-esm/ui/comments-list.mjs.map +2 -2
  198. package/dist-esm/ui/count-badge.mjs +3 -2
  199. package/dist-esm/ui/count-badge.mjs.map +2 -2
  200. package/dist-esm/ui/emoji-picker.mjs +34 -0
  201. package/dist-esm/ui/emoji-picker.mjs.map +7 -0
  202. package/dist-esm/ui/empty-state.mjs +3 -3
  203. package/dist-esm/ui/empty-state.mjs.map +2 -2
  204. package/dist-esm/ui/format-time.mjs +16 -1
  205. package/dist-esm/ui/format-time.mjs.map +2 -2
  206. package/dist-esm/ui/icons.mjs +95 -0
  207. package/dist-esm/ui/icons.mjs.map +7 -0
  208. package/dist-esm/ui/reaction-picker.mjs +59 -0
  209. package/dist-esm/ui/reaction-picker.mjs.map +7 -0
  210. package/dist-esm/ui/reaction.mjs +59 -7
  211. package/dist-esm/ui/reaction.mjs.map +2 -2
  212. package/dist-esm/ui/reactions.mjs +21 -8
  213. package/dist-esm/ui/reactions.mjs.map +2 -2
  214. package/dist-esm/ui/reply-count.mjs +9 -0
  215. package/dist-esm/ui/reply-count.mjs.map +7 -0
  216. package/dist-esm/ui/send-button.mjs +13 -1
  217. package/dist-esm/ui/send-button.mjs.map +2 -2
  218. package/dist-esm/ui/visual-viewport.mjs +12 -0
  219. package/dist-esm/ui/visual-viewport.mjs.map +7 -0
  220. package/package.json +6 -6
  221. package/src/canvas/anchor-lifecycle.test.ts +290 -0
  222. package/src/canvas/anchor-lifecycle.ts +191 -0
  223. package/src/canvas/canvas-events.ts +18 -0
  224. package/src/canvas/canvas.css +464 -55
  225. package/src/canvas/cluster-badge.tsx +133 -0
  226. package/src/canvas/cluster-fade.ts +102 -0
  227. package/src/canvas/cluster-input.test.ts +178 -36
  228. package/src/canvas/cluster-input.ts +95 -9
  229. package/src/canvas/cluster-model.ts +378 -0
  230. package/src/canvas/comment-body.tsx +1 -1
  231. package/src/canvas/comment-drafts.test.ts +55 -0
  232. package/src/canvas/comment-drafts.ts +46 -0
  233. package/src/canvas/comment-mutations.test.ts +452 -0
  234. package/src/canvas/comment-mutations.ts +299 -0
  235. package/src/canvas/comment-reactions.test.ts +154 -0
  236. package/src/canvas/comment-reactions.tsx +246 -0
  237. package/src/canvas/comment-render.test.ts +1 -1
  238. package/src/canvas/comment-render.ts +17 -13
  239. package/src/canvas/comment-store.ts +68 -33
  240. package/src/canvas/comment-tool.test.ts +162 -0
  241. package/src/canvas/comment-tool.tsx +103 -25
  242. package/src/canvas/comments-filter-menu.tsx +20 -36
  243. package/src/canvas/comments-overflow-menu.tsx +17 -19
  244. package/src/canvas/comments-overlay.tsx +252 -1369
  245. package/src/canvas/comments-sidebar.test.ts +45 -0
  246. package/src/canvas/comments-sidebar.tsx +112 -73
  247. package/src/canvas/comments-visibility-toggle.tsx +25 -0
  248. package/src/canvas/context.ts +48 -0
  249. package/src/canvas/hooks.test.ts +94 -0
  250. package/src/canvas/hooks.ts +66 -11
  251. package/src/canvas/license.ts +1 -1
  252. package/src/canvas/mobile-placement.ts +115 -0
  253. package/src/canvas/options.test.ts +176 -4
  254. package/src/canvas/options.ts +276 -18
  255. package/src/canvas/pending-composer.tsx +157 -0
  256. package/src/canvas/pin-stacking.test.ts +224 -0
  257. package/src/canvas/pin-stacking.ts +103 -0
  258. package/src/canvas/region-box.tsx +124 -0
  259. package/src/canvas/sidebar-filters.ts +4 -3
  260. package/src/canvas/state.ts +88 -39
  261. package/src/canvas/thread-pin.tsx +418 -0
  262. package/src/canvas/thread-preview.test.ts +91 -0
  263. package/src/canvas/thread-preview.tsx +294 -0
  264. package/src/canvas/thread-stack.tsx +242 -0
  265. package/src/canvas/thread-state.test.ts +260 -0
  266. package/src/canvas/thread-state.ts +171 -37
  267. package/src/canvas/thread-view.test.ts +72 -0
  268. package/src/canvas/thread-view.tsx +614 -0
  269. package/src/clustering/computeClusterTable.test.ts +24 -23
  270. package/src/clustering/computeClusterTable.ts +17 -8
  271. package/src/clustering/replay.test.ts +0 -7
  272. package/src/clustering/replay.ts +131 -32
  273. package/src/clustering/runtime.test.ts +267 -13
  274. package/src/clustering/runtime.ts +176 -19
  275. package/src/clustering/schedule.test.ts +0 -6
  276. package/src/clustering/screen-offsets.test.ts +171 -0
  277. package/src/clustering/types.ts +19 -9
  278. package/src/index.ts +91 -42
  279. package/src/ui/byline.tsx +21 -9
  280. package/src/ui/comment-card.tsx +20 -10
  281. package/src/ui/comment-composer.tsx +178 -56
  282. package/src/ui/comment-pin.tsx +13 -2
  283. package/src/ui/comment-thread.tsx +13 -6
  284. package/src/ui/comments-list.test.ts +31 -0
  285. package/src/ui/comments-list.tsx +82 -47
  286. package/src/ui/comments.css +577 -294
  287. package/src/ui/count-badge.tsx +9 -2
  288. package/src/ui/emoji-picker.test.ts +25 -0
  289. package/src/ui/emoji-picker.tsx +76 -0
  290. package/src/ui/empty-state.tsx +3 -3
  291. package/src/ui/format-time.test.ts +69 -0
  292. package/src/ui/format-time.ts +27 -2
  293. package/src/ui/icons.tsx +116 -0
  294. package/src/ui/reaction-picker.tsx +102 -0
  295. package/src/ui/reaction.tsx +125 -6
  296. package/src/ui/reactions.tsx +69 -10
  297. package/src/ui/reply-count.ts +16 -0
  298. package/src/ui/send-button.tsx +13 -3
  299. package/src/ui/visual-viewport.test.ts +36 -0
  300. package/src/ui/visual-viewport.ts +27 -0
  301. package/dist-cjs/canvas/region-options.js +0 -49
  302. package/dist-cjs/canvas/region-options.js.map +0 -7
  303. package/dist-cjs/ui/avatar.js.map +0 -7
  304. package/dist-cjs/ui/comment-mention.js +0 -42
  305. package/dist-cjs/ui/comment-mention.js.map +0 -7
  306. package/dist-cjs/ui/comment-text.js.map +0 -7
  307. package/dist-cjs/ui/mention-list.js +0 -70
  308. package/dist-cjs/ui/mention-list.js.map +0 -7
  309. package/dist-cjs/ui/mention-suggestion.js +0 -206
  310. package/dist-cjs/ui/mention-suggestion.js.map +0 -7
  311. package/dist-cjs/ui/mention.js.map +0 -7
  312. package/dist-cjs/ui/render-markdown.js +0 -63
  313. package/dist-cjs/ui/render-markdown.js.map +0 -7
  314. package/dist-esm/canvas/region-options.mjs +0 -29
  315. package/dist-esm/canvas/region-options.mjs.map +0 -7
  316. package/dist-esm/ui/avatar.mjs +0 -23
  317. package/dist-esm/ui/avatar.mjs.map +0 -7
  318. package/dist-esm/ui/comment-mention.mjs +0 -22
  319. package/dist-esm/ui/comment-mention.mjs.map +0 -7
  320. package/dist-esm/ui/comment-text.mjs +0 -9
  321. package/dist-esm/ui/comment-text.mjs.map +0 -7
  322. package/dist-esm/ui/mention-list.mjs +0 -50
  323. package/dist-esm/ui/mention-list.mjs.map +0 -7
  324. package/dist-esm/ui/mention-suggestion.mjs +0 -186
  325. package/dist-esm/ui/mention-suggestion.mjs.map +0 -7
  326. package/dist-esm/ui/mention.mjs +0 -11
  327. package/dist-esm/ui/mention.mjs.map +0 -7
  328. package/dist-esm/ui/render-markdown.mjs +0 -45
  329. package/dist-esm/ui/render-markdown.mjs.map +0 -7
  330. package/src/canvas/region-options.ts +0 -57
  331. package/src/ui/avatar.tsx +0 -31
  332. package/src/ui/comment-mention.ts +0 -47
  333. package/src/ui/comment-text.tsx +0 -12
  334. package/src/ui/mention-list.tsx +0 -106
  335. package/src/ui/mention-suggestion.test.ts +0 -18
  336. package/src/ui/mention-suggestion.tsx +0 -285
  337. package/src/ui/mention.tsx +0 -9
  338. package/src/ui/render-markdown.tsx +0 -72
@@ -1,84 +1,114 @@
1
1
  /* Real comment UI components. Co-located so styles travel to any view (studio,
2
2
  canvas), and themed via tldraw's --tl-color tokens so they follow light/dark. */
3
- .cmt-card {
3
+ .tlui-cmt-card {
4
4
  position: relative;
5
5
  display: flex;
6
- gap: 10px;
7
- padding: 12px;
6
+ flex-direction: column;
7
+ gap: 8px;
8
+ padding: 8px;
8
9
  width: 260px;
9
10
  background: var(--tl-color-panel);
10
11
  border: 1px solid var(--tl-color-divider);
11
- border-radius: 12px;
12
+ border-radius: var(--tl-radius-3);
13
+ }
14
+
15
+ /* The avatar lives in the byline row (see Byline), so the body text below indents to line up with
16
+ the name — the avatar's width plus the head's gap. */
17
+ .tlui-cmt-body {
18
+ padding-left: calc(28px + 6px);
12
19
  }
13
20
 
14
- /* hover-revealed controls (edit…) at the card's top-right */
15
- .cmt-card__actions {
21
+ /* hover-revealed controls (edit, react…) stacked at the card's top-right */
22
+ .tlui-cmt-card__actions {
16
23
  position: absolute;
17
24
  top: 6px;
18
25
  right: 6px;
19
26
  display: flex;
20
- gap: 2px;
27
+ gap: 0;
21
28
  opacity: 0;
22
29
  }
23
- .cmt-card:hover .cmt-card__actions,
24
- .cmt-card:focus-within .cmt-card__actions {
30
+ .tlui-cmt-card:hover .tlui-cmt-card__actions,
31
+ .tlui-cmt-card:focus-within .tlui-cmt-card__actions,
32
+ /* an open menu is portaled out of the card, so neither :hover nor :focus-within survives moving
33
+ the pointer into it — keep the controls up while their menu is open */
34
+ .tlui-cmt-card__actions:has([data-state='open']) {
25
35
  opacity: 1;
26
36
  }
27
37
 
28
- .cmt-body {
38
+ .tlui-cmt-body {
29
39
  flex: 1;
30
40
  min-width: 0;
31
41
  }
32
42
 
33
- .cmt-head {
43
+ .tlui-cmt-head {
34
44
  display: flex;
35
- align-items: baseline;
45
+ align-items: center;
36
46
  gap: 6px;
37
47
  }
38
48
 
39
- .cmt-author {
40
- font-weight: 600;
41
- font-size: 13px;
49
+ .tlui-cmt-author {
50
+ font-weight: 500;
51
+ font-size: 12px;
42
52
  color: var(--tl-color-text-1);
53
+ /* a long name ellipsizes rather than pushing the time out or running under the actions */
54
+ min-width: 0;
55
+ overflow: hidden;
56
+ text-overflow: ellipsis;
57
+ white-space: nowrap;
43
58
  }
44
59
 
45
- .cmt-time {
46
- font-size: 11px;
60
+ .tlui-cmt-time {
61
+ font-size: 12px;
47
62
  color: var(--tl-color-text-3);
63
+ flex-shrink: 0;
64
+ white-space: nowrap;
48
65
  }
49
66
 
50
- .cmt-text {
51
- margin: 3px 0 0;
52
- font-size: 13px;
67
+ /* In the hover preview a long comment truncates with an ellipsis rather than growing the card —
68
+ ~7 lines (≈120px at this line height). Preview only. */
69
+ .tlui-cmt-canvas-preview--thread .tlui-cmt-text {
70
+ display: -webkit-box;
71
+ -webkit-box-orient: vertical;
72
+ -webkit-line-clamp: 7;
73
+ line-clamp: 7;
74
+ overflow: hidden;
75
+ }
76
+
77
+ .tlui-cmt-text {
78
+ margin: 0 0 6px;
79
+ font-size: 12px;
53
80
  line-height: 1.4;
54
81
  color: var(--tl-color-text-1);
82
+ /* Break long unbroken strings (URLs, keyboard-mashing) so they wrap inside the card instead of
83
+ overflowing it. `anywhere` also lets the flex body shrink to the card width. */
84
+ overflow-wrap: anywhere;
55
85
  }
56
86
 
57
- .cmt-edited {
87
+ .tlui-cmt-edited {
58
88
  font-style: italic;
59
89
  }
60
90
 
61
91
  /* rendered rich text inside a comment body — bare tags emitted by the comment renderer
62
92
  (paragraphs, lists, code, highlight, links), matching the limited comment extension set. */
63
- .cmt-text p {
93
+ .tlui-cmt-text p {
64
94
  margin: 0;
65
95
  }
66
96
 
67
- .cmt-text p + p,
68
- .cmt-text p + ul,
69
- .cmt-text p + ol,
70
- .cmt-text ul + p,
71
- .cmt-text ol + p {
97
+ .tlui-cmt-text p + p,
98
+ .tlui-cmt-text p + ul,
99
+ .tlui-cmt-text p + ol,
100
+ .tlui-cmt-text ul + p,
101
+ .tlui-cmt-text ol + p {
72
102
  margin-top: 6px;
73
103
  }
74
104
 
75
- .cmt-text ul,
76
- .cmt-text ol {
105
+ .tlui-cmt-text ul,
106
+ .tlui-cmt-text ol {
77
107
  margin: 0;
78
108
  padding-left: 18px;
79
109
  }
80
110
 
81
- .cmt-text code {
111
+ .tlui-cmt-text code {
82
112
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
83
113
  font-size: 0.92em;
84
114
  background: var(--tl-color-muted-2);
@@ -86,212 +116,272 @@
86
116
  padding: 0 3px;
87
117
  }
88
118
 
89
- .cmt-text mark {
119
+ .tlui-cmt-text mark {
90
120
  background: color-mix(in srgb, #ffeb3b 60%, transparent);
91
121
  color: inherit;
92
122
  border-radius: 2px;
93
123
  }
94
124
 
95
- .cmt-text a {
125
+ .tlui-cmt-text a {
96
126
  color: var(--tl-color-selected);
97
127
  text-decoration: underline;
98
128
  }
99
129
 
100
- .cmt-avatar {
101
- width: 28px;
102
- height: 28px;
103
- border-radius: 50%;
104
- background: var(--tl-color-selected);
105
- color: #fff;
106
- display: flex;
107
- align-items: center;
108
- justify-content: center;
109
- font-size: 11px;
110
- font-weight: 600;
111
- flex-shrink: 0;
112
- }
113
-
114
- .cmt-avatar--image {
115
- object-fit: cover;
116
- background: none;
117
- }
130
+ /* Avatar and mention styles live in @tldraw/mentions (src/mention.css) and are bundled into
131
+ commenting.css by copy-css-files.mjs. */
118
132
 
119
133
  /* composer — an avatar beside a rounded-rect field holding the rich-text input and the send button.
120
134
  Formatting is applied via markdown and keyboard shortcuts (no toolbar). The avatar aligns to the
121
135
  top so it stays put as the field grows to multiple lines. */
122
- .cmt-composer {
136
+ .tlui-cmt-composer {
123
137
  display: flex;
124
138
  align-items: flex-start;
125
139
  gap: 10px;
126
140
  padding: 4px 0 8px 4px;
127
141
  }
128
142
 
129
- .cmt-composer__field {
143
+ .tlui-cmt-composer__field {
130
144
  flex: 1;
131
145
  min-width: 0;
132
146
  display: flex;
133
147
  align-items: center;
134
148
  gap: 6px;
135
- padding: 3px 3px 3px 12px;
136
- background: var(--tl-color-muted-2);
149
+ padding: 3px 3px 3px 8px;
150
+ background: var(--tl-color-muted-0);
137
151
  border: 1px solid var(--tl-color-divider);
138
- border-radius: var(--tl-radius-3);
152
+ border-radius: var(--tl-radius-2);
153
+ /* The whole field reads as the text input — clicking its empty area focuses the editor
154
+ (see CommentComposer). The send button restores its own pointer cursor. */
155
+ cursor: text;
139
156
  }
140
157
 
141
- .cmt-composer__field:focus-within {
158
+ .tlui-cmt-composer__field:focus-within {
142
159
  border-color: var(--tl-color-selected);
160
+ background: var(--tl-color-panel);
161
+ }
162
+
163
+ /* Expanded: the content no longer fits on one line beside the send button, so the input takes
164
+ the full width and the send button drops to its own row, right-aligned. */
165
+ .tlui-cmt-composer__field--expanded {
166
+ flex-wrap: wrap;
167
+ /* No vertical gap between the input and the send-button row it wraps onto. */
168
+ row-gap: 0;
169
+ }
170
+ .tlui-cmt-composer__field--expanded .tlui-cmt-composer__input-wrap {
171
+ flex-basis: 100%;
172
+ /* The field pads 8px left but only 3px right (the send button's inset). With the input
173
+ spanning the full width, give the text the same 8px on the right. */
174
+ padding-right: 5px;
175
+ }
176
+ .tlui-cmt-composer__field--expanded .tlui-cmt-send {
177
+ margin-left: auto;
143
178
  }
144
179
 
145
180
  /* the editable area, with the placeholder overlaid while it's empty */
146
- .cmt-composer__input-wrap {
181
+ .tlui-cmt-composer__input-wrap {
147
182
  position: relative;
148
183
  flex: 1;
149
184
  min-width: 0;
150
- padding: 3px 0;
185
+ /* Frames the input's line height symmetrically so the text sits centred in the field. Paired
186
+ with the input's min-height, which equals its line height (no gap for the text to top-align
187
+ into). Keeps the field's overall height. */
188
+ padding: 4.5px 0;
151
189
  }
152
190
 
153
- .cmt-input {
191
+ /* The hidden single-line measuring clone of the editor's content (see CommentComposer). */
192
+ .tlui-cmt-composer__mirror {
193
+ position: absolute;
194
+ top: 0;
195
+ left: 0;
196
+ visibility: hidden;
197
+ pointer-events: none;
198
+ white-space: nowrap;
199
+ width: max-content;
200
+ }
201
+
202
+ .tlui-cmt-input {
154
203
  font: inherit;
155
- font-size: 13px;
204
+ font-size: 12px;
156
205
  line-height: 1.4;
157
206
  color: var(--tl-color-text-1);
158
207
  outline: none;
159
- min-height: 20px;
160
- max-height: 40vh;
161
- overflow-y: auto;
208
+ min-height: 17px;
162
209
  white-space: pre-wrap;
163
210
  word-break: break-word;
164
211
  }
165
212
 
166
- .cmt-input p {
213
+ .tlui-cmt-input p {
167
214
  margin: 0;
168
215
  }
169
216
 
170
- .cmt-input p + p,
171
- .cmt-input p + ul,
172
- .cmt-input p + ol {
217
+ .tlui-cmt-input p + p,
218
+ .tlui-cmt-input p + ul,
219
+ .tlui-cmt-input p + ol {
173
220
  margin-top: 4px;
174
221
  }
175
222
 
176
- .cmt-input ul,
177
- .cmt-input ol {
223
+ .tlui-cmt-input ul,
224
+ .tlui-cmt-input ol {
178
225
  margin: 0;
179
226
  padding-left: 18px;
180
227
  }
181
228
 
182
- .cmt-input__placeholder {
229
+ .tlui-cmt-input__placeholder {
183
230
  position: absolute;
184
- top: 3px;
231
+ top: 4.5px;
185
232
  left: 0;
186
- font-size: 13px;
233
+ font-size: 12px;
187
234
  line-height: 1.4;
188
235
  color: var(--tl-color-text-3);
189
236
  pointer-events: none;
190
237
  }
191
238
 
192
- .cmt-send {
239
+ /* iOS Safari zooms the whole page in when a text input with a sub-16px font takes focus, and doesn't
240
+ zoom back out. Raising the font to 16px on touch devices suppresses that without disabling
241
+ pinch-zoom of the canvas (which a `maximum-scale` viewport lock would). Must come after both base
242
+ rules above: a media query adds no specificity, so it only wins the placeholder on source order. */
243
+ @media (pointer: coarse) {
244
+ .tlui-cmt-input,
245
+ .tlui-cmt-input__placeholder {
246
+ font-size: 16px;
247
+ }
248
+ }
249
+
250
+ /* A bare up-arrow icon button (matching the placement composer): no fill by default, a grey square
251
+ on hover, grey while there's nothing to send and dark once there is. */
252
+ .tlui-cmt-send {
253
+ flex-shrink: 0;
254
+ display: inline-flex;
255
+ align-items: center;
256
+ justify-content: center;
257
+ width: 28px;
258
+ height: 28px;
193
259
  border: 0;
194
260
  border-radius: var(--tl-radius-2);
195
- background: var(--tl-color-selected);
196
- color: #fff;
197
- font: inherit;
198
- font-size: 12px;
199
- font-weight: 600;
200
- padding: 6px 12px;
261
+ background: transparent;
262
+ color: var(--tl-color-text-3);
201
263
  cursor: pointer;
202
- align-self: flex-end;
264
+ align-self: center;
203
265
  }
204
266
 
205
- .cmt-send:hover,
206
- .pseudo-hover .cmt-send {
207
- background: color-mix(in srgb, var(--tl-color-selected) 88%, black);
267
+ .tlui-cmt-send:not(:disabled) {
268
+ color: var(--tl-color-text-1);
269
+ }
270
+
271
+ .tlui-cmt-send:hover:not(:disabled) {
272
+ background: var(--tl-color-muted-2);
208
273
  }
209
274
 
210
- .cmt-send:active,
211
- .pseudo-active .cmt-send {
212
- background: color-mix(in srgb, var(--tl-color-selected) 78%, black);
275
+ .tlui-cmt-send:active:not(:disabled),
276
+ .pseudo-active .tlui-cmt-send:not(:disabled) {
277
+ background: var(--tl-color-muted-1);
213
278
  }
214
279
 
215
- .cmt-send:focus-visible,
216
- .pseudo-focus-visible .cmt-send {
280
+ .tlui-cmt-send:focus-visible,
281
+ .pseudo-focus-visible .tlui-cmt-send {
217
282
  outline: 2px solid var(--tl-color-selected);
218
283
  outline-offset: 2px;
219
284
  }
220
285
 
221
- .cmt-send:disabled {
222
- opacity: 0.45;
286
+ .tlui-cmt-send:disabled {
287
+ background: transparent;
288
+ color: var(--tl-color-text-3);
223
289
  cursor: not-allowed;
224
290
  }
225
291
 
226
- /* pin */
227
- .cmt-pin {
228
- width: 34px;
229
- height: 34px;
230
- border-radius: 50% 50% 50% 3px;
231
- background: var(--tl-color-selected);
292
+ /* The shared marker treatment. To the pointer a comment pin and a count badge are the same
293
+ object — a token sitting on the canvas — so they rest and lift identically; everything shared
294
+ lives here so the two can't drift apart. */
295
+ .tlui-cmt-marker {
296
+ box-shadow: var(--tlui-cmt-marker-shadow);
297
+ cursor: pointer;
298
+ transition:
299
+ transform var(--tlui-cmt-marker-transition),
300
+ box-shadow var(--tlui-cmt-marker-transition);
301
+ }
302
+
303
+ .tlui-cmt-marker:hover {
304
+ transform: scale(var(--tlui-cmt-marker-hover-scale));
305
+ }
306
+
307
+ /* The hover shadow is for closed markers only — an open one keeps its selection ring, which this
308
+ box-shadow would otherwise override (the hover selector outranks the --open rule). */
309
+ .tlui-cmt-marker:not(.tlui-cmt-marker--open):hover {
310
+ box-shadow: var(--tlui-cmt-marker-shadow-hover);
311
+ }
312
+
313
+ /* Count badges don't react to hover — no scale, no shadow lift. Only pins do. */
314
+ .tlui-cmt-count-badge:hover {
315
+ transform: none;
316
+ box-shadow: var(--tlui-cmt-marker-shadow);
317
+ }
318
+
319
+ /* Pins don't scale on hover — only the shadow lifts. */
320
+ .tlui-cmt-pin:hover {
321
+ transform: none;
322
+ }
323
+
324
+ /* open: the thread (or a stack's list) is showing — the active marker just keeps its lift shadow,
325
+ no selection ring. */
326
+ .tlui-cmt-marker--open {
327
+ box-shadow: var(--tlui-cmt-marker-shadow);
328
+ }
329
+
330
+ /* pin — a canvas marker: a white teardrop holding the author's avatar circle, so a thread is
331
+ identifiable at a glance. */
332
+ .tlui-cmt-pin {
333
+ --tlui-cmt-marker-size: var(--tlui-cmt-pin-size);
334
+ width: var(--tlui-cmt-marker-size);
335
+ height: var(--tlui-cmt-marker-size);
336
+ border-radius: 50% 50% 50% 0;
337
+ background: var(--tl-color-panel);
232
338
  color: #fff;
233
339
  display: flex;
234
340
  align-items: center;
235
341
  justify-content: center;
236
342
  font-size: 14px;
237
343
  font-weight: 600;
238
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
239
- cursor: pointer;
240
- transition:
241
- transform 0.08s ease,
242
- box-shadow 0.08s ease;
243
344
  }
244
-
245
- .cmt-pin:hover,
246
- .pseudo-hover .cmt-pin {
247
- transform: scale(1.08);
248
- box-shadow: 0 3px 10px rgba(0, 0, 0, 0.32);
249
- }
250
-
251
- /* open: the thread is showing — a selection ring marks the active pin */
252
- .cmt-pin--open {
253
- box-shadow:
254
- 0 0 0 3px var(--tl-color-panel),
255
- 0 0 0 5px var(--tl-color-selected),
256
- 0 2px 6px rgba(0, 0, 0, 0.25);
345
+ /* The pin holds the author's 22px avatar circle, centred in its 28px face. */
346
+ .tlui-cmt-pin .tlui-cmt-avatar {
347
+ width: 22px;
348
+ height: 22px;
257
349
  }
258
350
 
259
351
  /* resolved: a solid, muted grey (the default --tl-color-muted-1 is 10% black, so it goes
260
352
  translucent over the canvas). Dark mode gets its own grey — the token's dark value is near-black. */
261
- .cmt-pin--resolved {
353
+ .tlui-cmt-pin--resolved {
262
354
  background: #dfe0e1;
263
355
  color: hsl(214, 8%, 42%);
264
356
  }
265
- .tl-theme__dark .cmt-pin--resolved {
357
+ .tl-theme__dark .tlui-cmt-pin--resolved {
266
358
  background: hsl(240, 5%, 30%);
267
359
  color: hsl(0, 0%, 72%);
268
360
  }
269
361
 
270
- /* count badge */
271
- .cmt-count-badge {
272
- width: 34px;
273
- height: 34px;
362
+ /* count badge — the same marker as a pin. */
363
+ .tlui-cmt-count-badge {
364
+ width: var(--tlui-cmt-marker-size);
365
+ height: var(--tlui-cmt-marker-size);
274
366
  border-radius: 50%;
275
367
  display: flex;
276
368
  align-items: center;
277
369
  justify-content: center;
278
370
  background: var(--tl-color-text-1);
279
371
  color: var(--tl-color-panel);
280
- font-size: 13px;
372
+ font-size: 12px;
281
373
  font-weight: 700;
282
- box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
283
374
  user-select: none;
284
375
  }
285
376
 
286
377
  /* thread */
287
- .cmt-thread {
378
+ .tlui-cmt-thread {
288
379
  display: flex;
289
380
  flex-direction: column;
290
- gap: 8px;
291
381
  width: 300px;
292
382
  }
293
383
 
294
- .cmt-thread__head {
384
+ .tlui-cmt-thread__head {
295
385
  display: flex;
296
386
  align-items: center;
297
387
  gap: 8px;
@@ -302,7 +392,7 @@
302
392
  letter-spacing: 0.04em;
303
393
  }
304
394
 
305
- .cmt-badge {
395
+ .tlui-cmt-badge {
306
396
  font-size: 10px;
307
397
  font-weight: 600;
308
398
  text-transform: none;
@@ -314,134 +404,111 @@
314
404
  }
315
405
 
316
406
  /* reactions */
317
- .cmt-reactions {
407
+ .tlui-cmt-reactions {
318
408
  display: flex;
319
- gap: 6px;
409
+ flex-wrap: wrap;
410
+ gap: 4px;
411
+ margin-top: 6px;
320
412
  }
321
413
 
322
- .cmt-reaction {
414
+ .tlui-cmt-reaction {
323
415
  display: inline-flex;
324
416
  align-items: center;
325
- gap: 5px;
326
- padding: 3px 9px;
327
- border-radius: 999px;
328
- border: 1px solid var(--tl-color-divider);
329
- background: var(--tl-color-panel);
417
+ gap: 4px;
418
+ padding: 2px 6px;
419
+ border: none;
420
+ border-radius: var(--tl-radius-1);
421
+ background: var(--tl-color-muted-2);
330
422
  font: inherit;
331
- font-size: 12px;
423
+ font-size: 10px;
424
+ font-weight: 400;
332
425
  color: var(--tl-color-text-1);
426
+ }
427
+
428
+ /* An inert pill renders as a span (e.g. in a notification row); only the button variant is
429
+ clickable, so only it gets the pointer cursor and hover shade. */
430
+ button.tlui-cmt-reaction {
333
431
  cursor: pointer;
334
432
  }
335
433
 
336
- .cmt-reaction:hover,
337
- .pseudo-hover .cmt-reaction {
338
- border-color: var(--tl-color-selected);
434
+ /* Hover deepens the grey — no border to tint now. Mixing toward the text colour is theme-aware:
435
+ it darkens the fill in light mode and lightens it in dark, tracking the pill's own contrast. */
436
+ button.tlui-cmt-reaction:hover {
437
+ background: var(--tl-color-muted-1);
339
438
  }
340
439
 
341
- .cmt-reaction--active {
342
- border-color: var(--tl-color-selected);
343
- background: color-mix(in srgb, var(--tl-color-selected) 12%, var(--tl-color-panel));
440
+ /* a reaction you're part of fills with the selection colour, so "I reacted with this" stands out
441
+ from the grey pills of reactions you haven't joined. */
442
+ .tlui-cmt-reaction--active {
443
+ background: color-mix(in srgb, var(--tl-color-selected) 28%, var(--tl-color-panel));
344
444
  }
345
445
 
346
- .cmt-reaction__count {
347
- color: var(--tl-color-text-3);
446
+ button.tlui-cmt-reaction--active:hover {
447
+ background: color-mix(in srgb, var(--tl-color-selected) 38%, var(--tl-color-panel));
448
+ }
449
+
450
+ /* The emoji renders larger than the 10px count, but its pinned line-height keeps the pill the
451
+ count's height — the glyph overflows the line box rather than growing it. */
452
+ .tlui-cmt-reaction__emoji {
453
+ font-size: 13px;
454
+ line-height: 10px;
348
455
  }
349
456
 
350
- .cmt-reaction--add {
457
+ .tlui-cmt-reaction__count {
351
458
  color: var(--tl-color-text-3);
352
- font-weight: 600;
459
+ font-variant-numeric: tabular-nums;
353
460
  }
354
461
 
355
- /* mention */
356
- .cmt-mention {
357
- color: var(--tl-color-selected);
358
- font-weight: 600;
359
- background: color-mix(in srgb, var(--tl-color-selected) 12%, transparent);
360
- padding: 0 4px;
361
- border-radius: 4px;
462
+ .tlui-cmt-reaction--active .tlui-cmt-reaction__count {
463
+ color: var(--tl-color-text-1);
362
464
  }
363
465
 
364
- /* mention picker */
365
- .cmt-mention-list {
366
- display: flex;
367
- flex-direction: column;
368
- gap: 1px;
466
+ /* emoji picker */
467
+ .tlui-cmt-emoji-picker {
468
+ display: grid;
469
+ grid-template-columns: repeat(5, 40px);
470
+ gap: 0;
369
471
  padding: 4px;
370
- width: 100%;
371
- box-sizing: border-box;
372
- max-height: 260px;
373
- overflow-y: auto;
374
- color: var(--tl-color-text-1, #1d1d1d);
375
- background: var(--tl-color-panel, #fff);
376
- border: 1px solid var(--tl-color-divider, rgba(0, 0, 0, 0.08));
377
- border-radius: 10px;
378
- box-shadow: var(--tl-shadow-2, 0 2px 12px rgba(0, 0, 0, 0.14));
379
472
  }
380
473
 
381
- .cmt-mention-list__item {
474
+ .tlui-cmt-emoji-picker__item {
475
+ position: relative;
382
476
  display: flex;
383
477
  align-items: center;
384
- gap: 8px;
385
- padding: 6px 8px;
478
+ justify-content: center;
479
+ width: 40px;
480
+ height: 40px;
481
+ padding: 0;
386
482
  border: none;
387
- background: transparent;
388
- border-radius: 6px;
389
- cursor: pointer;
390
- text-align: left;
391
- color: var(--tl-color-text-1);
483
+ background: none;
392
484
  font: inherit;
485
+ font-size: 21px;
486
+ line-height: 1;
487
+ cursor: pointer;
393
488
  }
394
489
 
395
- .cmt-mention-list__item--active,
396
- .cmt-mention-list__item:hover {
397
- background: var(--tl-color-muted-2, rgba(0, 0, 0, 0.06));
398
- }
399
-
400
- .cmt-mention-list__text {
401
- display: flex;
402
- flex-direction: column;
403
- min-width: 0;
404
- line-height: 1.3;
405
- }
406
-
407
- .cmt-mention-list__name {
408
- font-size: 13px;
409
- font-weight: 500;
410
- white-space: nowrap;
411
- overflow: hidden;
412
- text-overflow: ellipsis;
490
+ /* Inset wash behind the glyph — the 40px hit cells tile edge-to-edge, the squares sit 4px apart,
491
+ like the thread action buttons. Sits under the emoji so an opaque selected fill can't hide it. */
492
+ .tlui-cmt-emoji-picker__item::after {
493
+ content: '';
494
+ position: absolute;
495
+ inset: 2px;
496
+ z-index: -1;
497
+ border-radius: var(--tl-radius-2);
413
498
  }
414
-
415
- .cmt-mention-list__you {
416
- margin-left: 4px;
417
- font-weight: 400;
418
- color: var(--tl-color-text-3);
499
+ .tlui-cmt-emoji-picker__item:hover {
500
+ z-index: 1;
419
501
  }
420
-
421
- .cmt-mention-list__secondary {
422
- font-size: 12px;
423
- color: var(--tl-color-text-3);
424
- white-space: nowrap;
425
- overflow: hidden;
426
- text-overflow: ellipsis;
427
- }
428
-
429
- .cmt-mention-list--empty {
430
- padding: 8px 10px;
431
- width: 100%;
432
- box-sizing: border-box;
433
- color: var(--tl-color-text-3);
434
- font-size: 13px;
502
+ .tlui-cmt-emoji-picker__item:hover::after {
503
+ background: var(--tl-color-muted-2);
435
504
  }
436
505
 
437
- /* the @-picker popup — caret-anchored above the page, positioned by the suggestion plugin */
438
- .cmt-mention-popup {
439
- position: fixed;
440
- z-index: var(--tl-layer-menus);
506
+ .tlui-cmt-emoji-picker__item--active::after {
507
+ background: color-mix(in srgb, var(--tl-color-selected) 28%, var(--tl-color-panel));
441
508
  }
442
509
 
443
510
  /* empty state */
444
- .cmt-empty {
511
+ .tlui-cmt-empty {
445
512
  display: flex;
446
513
  flex-direction: column;
447
514
  align-items: center;
@@ -451,92 +518,260 @@
451
518
  width: 240px;
452
519
  }
453
520
 
454
- .cmt-empty__icon {
521
+ .tlui-cmt-empty__icon {
455
522
  font-size: 28px;
456
523
  }
457
524
 
458
- .cmt-empty__message {
525
+ .tlui-cmt-empty__message {
459
526
  margin: 0;
460
527
  color: var(--tl-color-text-3);
461
- font-size: 13px;
528
+ font-size: 12px;
462
529
  line-height: 1.4;
463
530
  }
464
531
 
465
- /* a comment thread: an elevated panel the same surface treatment as the toolbar — holding a
466
- header, an optional resolved banner, the comments, and a reply composer */
467
- .cmt-thread {
532
+ /* a comment thread: an elevated panel holding a header, an optional resolved banner, the
533
+ comments, and a reply composer */
534
+ /* The thread panel's layout metrics live on the container because two separate portals need them:
535
+ the panel itself, and the canvas hover preview, which has to land its first comment on exactly
536
+ the pixel the panel would. Deriving the preview's offset from these means the two can't drift —
537
+ retune the padding or the header here and the preview follows. */
538
+ .tl-container {
539
+ /* Everything that has to line up against a pin — its preview's bridge, the draft composer's
540
+ offsets, `PIN_SIZE` in thread-view.tsx — derives from this, so the pin's size stays one
541
+ number. */
542
+ --tlui-cmt-pin-size: 28px;
543
+ /* A cluster badge and a stack badge are this square — the same size as a pin, so the marker
544
+ kinds read as one family. The hover preview measures its bridge against it, so the bridge
545
+ stops at the marker's edge instead of covering it. Mirrored by `MARKER_SIZE` in
546
+ thread-view.tsx. */
547
+ --tlui-cmt-marker-size: var(--tlui-cmt-pin-size);
548
+ /* How a marker sits, lifts, and rings. Shared so a pin and a badge respond identically.
549
+ shadow-3's depth without its `inset 1px panel-contrast` edge — that inset reads as a white
550
+ border on a coloured pin (it's invisible on the panel-white menus shadow-3 is meant for). */
551
+ --tlui-cmt-marker-shadow: 0px 1px 2px hsl(0, 0%, 0%, 28%), 0px 2px 6px hsl(0, 0%, 0%, 14%);
552
+ --tlui-cmt-marker-shadow-hover: var(--tlui-cmt-marker-shadow);
553
+ --tlui-cmt-marker-hover-scale: 1.08;
554
+ --tlui-cmt-marker-transition: 0.08s ease;
555
+ --tlui-cmt-thread-padding: 12px;
556
+ --tlui-cmt-thread-gap: 0px;
557
+ /* Hit-area width of one .tlui-cmt-thread__action button (drawn as a 32px square inset 4px). */
558
+ --tlui-cmt-thread-action-size: 40px;
559
+ /* A floating pill's edge — its hairline ring is the only thing separating it from the panel it
560
+ overlaps, so the ring is a theme token rather than a literal black: a near-black hairline
561
+ vanishes on a dark panel, where the divider token lightens instead. The drop below it stays
562
+ literal; a soft dark blur reads on both themes. */
563
+ --tlui-cmt-pill-shadow: 0 0 0 1px var(--tl-color-divider), 0 1px 3px hsl(0, 0%, 0%, 0.05);
564
+ }
565
+
566
+ .tlui-cmt-thread {
567
+ position: relative;
468
568
  display: flex;
469
569
  flex-direction: column;
470
- gap: 6px;
471
570
  width: 300px;
472
- padding: 8px;
473
571
  background: var(--tl-color-panel);
474
572
  border-radius: var(--tl-radius-4);
475
- box-shadow: var(--tl-shadow-2);
573
+ box-shadow: var(--tl-shadow-3);
476
574
  }
477
- .cmt-thread__header {
575
+ /* A pill of its own, floating above the panel's top-right corner and overlapping its top edge. */
576
+ .tlui-cmt-thread__header {
577
+ position: absolute;
578
+ right: 10px;
579
+ bottom: calc(100% - 15px);
478
580
  display: flex;
581
+ gap: 2px;
582
+ padding: 2px;
583
+ background: var(--tl-color-panel);
584
+ border-radius: var(--tl-radius-3);
585
+ box-shadow: var(--tlui-cmt-pill-shadow);
586
+ transition: opacity 0.1s ease;
587
+ }
588
+ /* The first comment's hover actions surface right where the header pill sits, so hide the pill
589
+ while that comment is hovered — one pill in the corner, never two stacked. */
590
+ .tlui-cmt-thread:has(.tlui-cmt-thread__list > :first-child:hover)
591
+ .tlui-cmt-thread__header:not(:has(.tlui-cmt-thread__title)) {
592
+ opacity: 0;
593
+ pointer-events: none;
594
+ }
595
+ /* A title puts the header back in the panel, in flow. The pill above is tuned for the actions-only
596
+ case tldraw itself uses: right-anchored and only as wide as its buttons, so a title inside it
597
+ would grow leftwards off the panel's edge and float over whatever sits above. `header` is public
598
+ API (see `CommentThreadProps`), so it has to keep laying out sensibly for anyone passing one. */
599
+ .tlui-cmt-thread__header:has(.tlui-cmt-thread__title) {
600
+ position: static;
479
601
  align-items: center;
480
- justify-content: space-between;
481
- padding: 2px 2px 2px 4px;
602
+ padding: 0;
603
+ background: none;
604
+ border-radius: 0;
605
+ box-shadow: none;
482
606
  }
483
- .cmt-thread__title {
607
+ .tlui-cmt-thread__title {
608
+ padding: 10px 12px;
484
609
  font-size: 12px;
485
- font-weight: 600;
610
+ line-height: 20px;
611
+ font-weight: 500;
486
612
  color: var(--tl-color-text-1);
487
613
  }
488
- .cmt-thread__actions {
489
- display: flex;
490
- gap: 2px;
491
- }
492
- .cmt-thread__action {
614
+ .tlui-cmt-thread__actions {
493
615
  display: flex;
494
- align-items: center;
495
- justify-content: center;
496
- width: 22px;
497
- height: 22px;
616
+ gap: 0;
617
+ /* Right-align the actions whether or not the header has a title (it currently has none, so
618
+ space-between alone would leave them at the left). */
619
+ margin-left: auto;
620
+ }
621
+ /* These are TldrawUiButtons (type="icon"), so the 40px box, the 32px ::after square carrying the
622
+ hover wash, and the hover z-index flip all come from .tlui-button — the hit area (not the
623
+ ::after) is what's clickable, and it never reaches past its row. Only the bits that differ from
624
+ a toolbar button are set here, at .tlui-button's specificity + 1 so stylesheet order can't
625
+ decide the winner. */
626
+ .tlui-button.tlui-cmt-thread__action {
627
+ width: 40px;
498
628
  padding: 0;
499
- border: none;
500
629
  border-radius: 6px;
501
- background: transparent;
502
630
  color: var(--tl-color-text-3);
503
631
  font-size: 14px;
504
632
  line-height: 1;
505
- cursor: pointer;
506
633
  }
507
- .cmt-thread__action:hover {
508
- background: var(--tl-color-muted-2);
634
+ /* Overlap each button 4px into the previous so the 32px visual squares sit 4px apart, not 8px.
635
+ Left-only, so the last button's hit area still stops at its row's right edge. */
636
+ .tlui-cmt-thread__action + .tlui-cmt-thread__action {
637
+ margin-left: -4px;
638
+ }
639
+ .tlui-button.tlui-cmt-thread__action:hover {
509
640
  color: var(--tl-color-text-1);
510
641
  }
511
- .cmt-thread__resolved {
642
+ .tlui-button.tlui-cmt-thread__action--danger:hover {
643
+ color: var(--tl-color-danger);
644
+ }
645
+ .tlui-cmt-thread__resolved {
646
+ margin: 4px 12px;
512
647
  padding: 6px 10px;
513
648
  border-radius: 8px;
514
649
  background: var(--tl-color-muted-2);
515
650
  font-size: 12px;
516
651
  color: var(--tl-color-text-3);
517
652
  }
518
- .cmt-thread__list {
653
+ .tlui-cmt-thread__list {
519
654
  display: flex;
520
655
  flex-direction: column;
521
- gap: 6px;
656
+ gap: var(--tlui-cmt-thread-gap);
657
+ }
658
+ /* When nothing follows the list (a resolved thread has no composer or footer) the last comment
659
+ would sit against the panel's rounded bottom — restore the trailing inset the composer supplies. */
660
+ .tlui-cmt-thread__list:last-child {
661
+ padding-bottom: 12px;
662
+ }
663
+ /* The footer slot sits where the composer would — its content (e.g. a sign-in prompt) sits at
664
+ the thread's trailing edge, like the composer's send button. */
665
+ .tlui-cmt-thread__footer {
666
+ display: flex;
667
+ justify-content: flex-end;
668
+ padding: 4px 2px 2px;
669
+ }
670
+ /* Inside a thread, author identity is a small colour dot, no initial — the letter doesn't fit
671
+ at this size. */
672
+ .tlui-cmt-thread .tlui-cmt-avatar,
673
+ .tlui-cmt-canvas-preview--thread .tlui-cmt-avatar,
674
+ .tlui-cmt-canvas-preview--list .tlui-cmt-avatar,
675
+ .tlui-cmt-stack-list .tlui-cmt-avatar {
676
+ width: 12px;
677
+ height: 12px;
678
+ font-size: 0;
679
+ }
680
+
681
+ .tlui-cmt-thread .tlui-cmt-composer {
682
+ padding: 12px;
683
+ }
684
+ .tlui-cmt-thread .tlui-cmt-composer .tlui-cmt-avatar {
685
+ display: none;
686
+ }
687
+
688
+ /* The sidebar's rows use the same small colour dot as the thread view. */
689
+ .tlui-cmt-list .tlui-cmt-avatar {
690
+ width: 14px;
691
+ height: 14px;
692
+ font-size: 0;
693
+ margin-top: 2px;
694
+ }
695
+ /* The sidebar row already leads with its own avatar (the flex row's first column); the byline's
696
+ avatar — added for the canvas thread views — would double it, so hide the byline's inside a row. */
697
+ .tlui-cmt-list .tlui-cmt-head .tlui-cmt-avatar {
698
+ display: none;
699
+ }
700
+
701
+ /* The dot treatment is for colour-only identity — an image avatar stays full size. */
702
+ .tlui-cmt-thread .tlui-cmt-avatar--image,
703
+ .tlui-cmt-canvas-preview--thread .tlui-cmt-avatar--image,
704
+ .tlui-cmt-canvas-preview--list .tlui-cmt-avatar--image,
705
+ .tlui-cmt-stack-list .tlui-cmt-avatar--image {
706
+ /* Match the 12px colour dot's width so the body's calc(12px + 6px) indent still lines up under
707
+ the byline name when the author has an image rather than a dot. */
708
+ width: 12px;
709
+ height: 12px;
710
+ margin-top: 0;
522
711
  }
712
+ .tlui-cmt-list .tlui-cmt-avatar--image {
713
+ width: 24px;
714
+ height: 24px;
715
+ margin-top: 0;
716
+ }
717
+
523
718
  /* inside the panel, comments are plain content — no surrounding box; the composer's field carries
524
- its own surface. */
525
- .cmt-thread .cmt-card {
719
+ its own surface. The hover preview is the same panel without a header, so its comment is laid
720
+ out by the same rule rather than a copy of it. */
721
+ .tlui-cmt-thread .tlui-cmt-card,
722
+ .tlui-cmt-canvas-preview--thread .tlui-cmt-card {
526
723
  width: 100%;
527
- padding: 6px 0 6px 4px;
724
+ gap: 0;
725
+ padding: 0 var(--tlui-cmt-thread-padding);
528
726
  background: transparent;
529
727
  border: none;
530
728
  }
729
+ /* The avatar is a 12px dot, so the body lines up 12px + the head's 6px gap in from the row. */
730
+ .tlui-cmt-thread .tlui-cmt-body,
731
+ .tlui-cmt-canvas-preview--thread .tlui-cmt-body,
732
+ .tlui-cmt-canvas-preview--list .tlui-cmt-body,
733
+ .tlui-cmt-stack-list .tlui-cmt-body {
734
+ padding-left: calc(12px + 6px);
735
+ }
736
+ /* Inside a panel the actions float as their own pill — the same pill the thread header is, in the
737
+ same corner (which is why the header hides while the first comment is hovered). It sits just
738
+ above the card's top edge rather than on the byline. */
739
+ /* Line the card actions up with the header actions: flush to the full-width card's right edge (the
740
+ panel edge, matching the header ✕) and flush on the 40px byline row, so the 40px buttons fill it. */
741
+ .tlui-cmt-thread .tlui-cmt-card .tlui-cmt-card__actions {
742
+ top: 0;
743
+ right: 0;
744
+ }
745
+ /* The byline row is 40px: on the opened thread it fits the action pills (react/edit/delete) that
746
+ float in its corner without the text running underneath; previews and collapsed cards carry the
747
+ same height so every comment row reads identically, solo or in a stack. */
748
+ .tlui-cmt-thread .tlui-cmt-card .tlui-cmt-head,
749
+ .tlui-cmt-canvas-preview--thread .tlui-cmt-card .tlui-cmt-head,
750
+ .tlui-cmt-canvas-preview--list .tlui-cmt-card .tlui-cmt-head,
751
+ .tlui-cmt-stack-list .tlui-cmt-card .tlui-cmt-head {
752
+ min-height: 40px;
753
+ }
754
+ /* Reserve head room only for pills that actually rendered (one child / two children) — pill count
755
+ is a permissions question (canModifyComment), not ownership, and empty slots (read-only viewers)
756
+ keep the full row. Sized from the 40px hit areas (4px overlap), minus the card padding the
757
+ right:0 pills sit over; text stops 4px shy of the visible square. */
758
+ .tlui-cmt-thread .tlui-cmt-card:has(.tlui-cmt-card__actions > *) .tlui-cmt-head {
759
+ padding-right: calc(var(--tlui-cmt-thread-action-size) - var(--tlui-cmt-thread-padding));
760
+ }
761
+ .tlui-cmt-thread .tlui-cmt-card:has(.tlui-cmt-card__actions > * + *) .tlui-cmt-head {
762
+ padding-right: calc(
763
+ 2 * var(--tlui-cmt-thread-action-size) - 4px - var(--tlui-cmt-thread-padding)
764
+ );
765
+ }
531
766
 
532
767
  /* comments list — thread summaries, one per row (used by the canvas sidebar) */
533
- .cmt-list {
768
+ .tlui-cmt-list {
534
769
  display: flex;
535
770
  flex-direction: column;
536
771
  width: 100%;
537
772
  min-height: 0;
538
773
  }
539
- .cmt-list__header {
774
+ .tlui-cmt-list__header {
540
775
  flex-shrink: 0;
541
776
  display: flex;
542
777
  align-items: center;
@@ -545,73 +780,102 @@
545
780
  padding: 6px 6px 6px 14px;
546
781
  border-bottom: 1px solid var(--tl-color-divider);
547
782
  }
548
- .cmt-list__header-title {
549
- font-size: 11px;
550
- font-weight: 600;
551
- letter-spacing: 0.06em;
552
- text-transform: uppercase;
553
- color: var(--tl-color-text-3);
783
+ .tlui-cmt-list__header-title {
784
+ font-size: 12px;
785
+ font-weight: 500;
786
+ color: var(--tl-color-text-1);
554
787
  }
555
788
 
556
- /* a small square icon button in the sidebar header (filter funnel, overflow …) */
557
- .cmt-header-btn {
558
- display: flex;
559
- align-items: center;
560
- justify-content: center;
789
+ /* A small square icon button in the sidebar header (filter funnel, overflow …). Also a
790
+ TldrawUiButton, but a bespoke 26px size — so it has to override .tlui-button's 40px box, and
791
+ `min-width` in particular would otherwise beat `width`. Selectors carry .tlui-button so
792
+ stylesheet order can't decide the winner. */
793
+ .tlui-button.tlui-cmt-header-btn {
561
794
  width: 26px;
795
+ min-width: 26px;
562
796
  height: 26px;
563
797
  padding: 0;
564
- border: none;
565
798
  border-radius: 6px;
566
- background: transparent;
567
799
  color: var(--tl-color-text-2);
568
- cursor: pointer;
569
800
  }
570
- .cmt-header-btn:hover,
571
- .cmt-header-btn[data-state='open'] {
801
+ /* Same hit-target expansion as the thread actions, tiled the same way — this row's gap is 2px too
802
+ (see `.tlui-cmt-list__header-actions`). Unlike the thread actions, the hover fill sits on the
803
+ button itself, so .tlui-button's ::after wash is cleared and the pseudo-element is left doing
804
+ nothing but widening the hit area. */
805
+ .tlui-button.tlui-cmt-header-btn::after {
806
+ inset: -6px -1px;
807
+ background: none;
808
+ }
809
+ .tlui-button.tlui-cmt-header-btn:first-child::after {
810
+ left: -6px;
811
+ }
812
+ .tlui-button.tlui-cmt-header-btn:last-child::after {
813
+ right: -6px;
814
+ }
815
+ .tlui-button.tlui-cmt-header-btn:hover,
816
+ .tlui-button.tlui-cmt-header-btn[data-state='open'] {
572
817
  background: var(--tl-color-muted-2);
573
818
  color: var(--tl-color-text-1);
574
819
  }
575
- .cmt-list__header-actions {
820
+ .tlui-cmt-list__header-actions {
576
821
  display: flex;
577
822
  align-items: center;
578
823
  gap: 2px;
579
824
  }
580
825
 
826
+ /* The commenting dropdowns' surface — a little air between the items and the menu edge. */
827
+ .tlui-cmt-menu {
828
+ min-width: 100px;
829
+ padding: 4px;
830
+ }
831
+
581
832
  /* a menu row with a label and a right-aligned shortcut hint (overflow menu) */
582
- .cmt-menu-item {
833
+ .tlui-cmt-menu-item {
834
+ position: relative;
583
835
  display: flex;
584
836
  align-items: center;
585
837
  justify-content: space-between;
586
838
  gap: 24px;
587
839
  width: 100%;
588
- padding: 6px 8px;
840
+ min-height: 40px;
841
+ padding: 0 10px;
589
842
  border: none;
590
- border-radius: 6px;
591
843
  background: transparent;
592
844
  font: inherit;
593
- font-size: 13px;
845
+ font-size: 12px;
594
846
  color: var(--tl-color-text-1);
595
847
  cursor: pointer;
596
848
  }
597
- .cmt-menu-item:hover {
849
+ /* 36px visual inset within the 40px row — the hover wash the action and emoji buttons use. */
850
+ .tlui-cmt-menu-item::after {
851
+ content: '';
852
+ position: absolute;
853
+ inset: 2px;
854
+ border-radius: var(--tl-radius-2);
855
+ }
856
+ .tlui-cmt-menu-item:hover::after {
598
857
  background: var(--tl-color-muted-2);
599
858
  }
600
- .cmt-menu-item__shortcut {
859
+ /* Destructive menu entries (delete) — the same danger colour as tldraw's danger buttons. */
860
+ .tlui-cmt-menu-item--danger {
861
+ color: var(--tl-color-danger);
862
+ }
863
+
864
+ .tlui-cmt-menu-item__shortcut {
601
865
  color: var(--tl-color-text-3);
602
866
  font-size: 12px;
603
867
  }
604
- .cmt-list__items {
868
+ .tlui-cmt-list__items {
605
869
  flex: 1;
606
870
  min-height: 0;
607
871
  overflow-y: auto;
608
872
  }
609
- .cmt-list__empty {
873
+ .tlui-cmt-list__empty {
610
874
  padding: 20px 14px;
611
875
  color: var(--tl-color-text-3);
612
- font-size: 13px;
876
+ font-size: 12px;
613
877
  }
614
- .cmt-list__item {
878
+ .tlui-cmt-list__item {
615
879
  display: flex;
616
880
  gap: 10px;
617
881
  width: 100%;
@@ -622,34 +886,48 @@
622
886
  font: inherit;
623
887
  text-align: left;
624
888
  cursor: pointer;
889
+ /* rows can render as anchors (for open-in-new-tab); keep them looking like list rows */
890
+ color: inherit;
891
+ text-decoration: none;
625
892
  }
626
- .cmt-list__item:hover {
893
+ .tlui-cmt-list__item:hover {
627
894
  background: var(--tl-color-muted-2);
628
895
  }
629
- .cmt-list__item--selected {
630
- background: var(--tl-color-muted-1);
896
+ /* Selected sits a step above hover so the open thread's row stays distinguishable while
897
+ pointing at other rows — but only a step: the muted-1 token (10%) reads too heavy here.
898
+ These rows sit on the opaque sidebar panel, so a translucent tint composes safely. */
899
+ .tlui-cmt-list__item--selected,
900
+ .tlui-cmt-list__item--selected:hover {
901
+ background: hsl(0, 0%, 0%, 5%);
902
+ }
903
+ .tl-theme__dark .tlui-cmt-list__item--selected,
904
+ .tl-theme__dark .tlui-cmt-list__item--selected:hover {
905
+ background: hsl(0, 0%, 100%, 5%);
631
906
  }
632
907
  /* resolved rows mute their content but keep the "Resolved" marker legible */
633
- .cmt-list__item[data-resolved] .cmt-head,
634
- .cmt-list__item[data-resolved] .cmt-list__item-preview {
908
+ .tlui-cmt-list__item[data-resolved] .tlui-cmt-head,
909
+ .tlui-cmt-list__item[data-resolved] .tlui-cmt-list__item-preview {
635
910
  opacity: 0.55;
636
911
  }
637
- .cmt-list__item-body {
912
+ .tlui-cmt-list__item-body {
638
913
  flex: 1;
639
914
  min-width: 0;
640
915
  }
641
- .cmt-list__item-preview {
916
+ .tlui-cmt-list__item-preview {
642
917
  margin-top: 2px;
643
- font-size: 13px;
918
+ font-size: 12px;
644
919
  color: var(--tl-color-text-1);
645
920
  overflow: hidden;
646
921
  text-overflow: ellipsis;
647
922
  display: -webkit-box;
648
923
  -webkit-line-clamp: 2;
649
924
  -webkit-box-orient: vertical;
925
+ /* Long unbroken strings (URLs, mashed keys) wrap onto the clamped lines instead of clipping
926
+ mid-string — same treatment as the card body. */
927
+ overflow-wrap: anywhere;
650
928
  }
651
929
  /* meta line under the preview: page label and/or a resolved marker */
652
- .cmt-list__item-meta {
930
+ .tlui-cmt-list__item-meta {
653
931
  display: flex;
654
932
  align-items: center;
655
933
  gap: 8px;
@@ -657,22 +935,27 @@
657
935
  font-size: 11px;
658
936
  color: var(--tl-color-text-3);
659
937
  }
660
- .cmt-list__item-resolved {
938
+ .tlui-cmt-list__item-resolved {
661
939
  display: inline-flex;
662
940
  align-items: center;
663
941
  gap: 3px;
664
942
  font-weight: 600;
665
943
  }
666
- .cmt-list__item-page {
944
+ .tlui-cmt-list__item-page {
667
945
  display: inline-flex;
668
946
  align-items: center;
669
947
  padding: 1px 6px;
670
948
  border-radius: 4px;
671
949
  background: var(--tl-color-muted-2);
672
950
  }
673
- .cmt-list__item-count {
674
- flex-shrink: 0;
675
- align-self: center;
951
+ .tlui-cmt-list__item-replies {
952
+ display: inline-flex;
953
+ align-items: center;
954
+ }
955
+ /* reply count under a preview card's opening comment — the thread continues past what's shown */
956
+ .tlui-cmt-card__replies {
957
+ display: block;
958
+ margin-top: 6px;
676
959
  font-size: 12px;
677
960
  color: var(--tl-color-text-3);
678
961
  }