@tldraw/commenting 0.0.0-bootstrap → 5.3.0-internal.5f14a24c179e

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 (174) hide show
  1. package/commenting.css +280 -151
  2. package/dist-cjs/canvas/comment-body.js +1 -1
  3. package/dist-cjs/canvas/comment-body.js.map +2 -2
  4. package/dist-cjs/canvas/comment-drafts.js +54 -0
  5. package/dist-cjs/canvas/comment-drafts.js.map +7 -0
  6. package/dist-cjs/canvas/comment-render.js +2 -0
  7. package/dist-cjs/canvas/comment-render.js.map +2 -2
  8. package/dist-cjs/canvas/comment-tool.js +55 -11
  9. package/dist-cjs/canvas/comment-tool.js.map +2 -2
  10. package/dist-cjs/canvas/comments-filter-menu.js +55 -56
  11. package/dist-cjs/canvas/comments-filter-menu.js.map +2 -2
  12. package/dist-cjs/canvas/comments-overflow-menu.js +21 -19
  13. package/dist-cjs/canvas/comments-overflow-menu.js.map +2 -2
  14. package/dist-cjs/canvas/comments-overlay.js +271 -109
  15. package/dist-cjs/canvas/comments-overlay.js.map +2 -2
  16. package/dist-cjs/canvas/comments-sidebar.js +12 -18
  17. package/dist-cjs/canvas/comments-sidebar.js.map +2 -2
  18. package/dist-cjs/canvas/comments-visibility-toggle.js +67 -0
  19. package/dist-cjs/canvas/comments-visibility-toggle.js.map +7 -0
  20. package/dist-cjs/canvas/sidebar-filters.js +2 -2
  21. package/dist-cjs/canvas/sidebar-filters.js.map +2 -2
  22. package/dist-cjs/canvas/state.js +11 -0
  23. package/dist-cjs/canvas/state.js.map +2 -2
  24. package/dist-cjs/canvas/thread-state.js +8 -1
  25. package/dist-cjs/canvas/thread-state.js.map +2 -2
  26. package/dist-cjs/clustering/runtime.js +119 -7
  27. package/dist-cjs/clustering/runtime.js.map +2 -2
  28. package/dist-cjs/index.d.ts +100 -39
  29. package/dist-cjs/index.js +7 -1
  30. package/dist-cjs/index.js.map +2 -2
  31. package/dist-cjs/ui/avatar.js +14 -6
  32. package/dist-cjs/ui/avatar.js.map +2 -2
  33. package/dist-cjs/ui/byline.js +4 -4
  34. package/dist-cjs/ui/byline.js.map +2 -2
  35. package/dist-cjs/ui/comment-author.js +17 -0
  36. package/dist-cjs/ui/comment-author.js.map +7 -0
  37. package/dist-cjs/ui/comment-card.js +4 -4
  38. package/dist-cjs/ui/comment-card.js.map +2 -2
  39. package/dist-cjs/ui/comment-composer.js +92 -29
  40. package/dist-cjs/ui/comment-composer.js.map +2 -2
  41. package/dist-cjs/ui/comment-mention.js +1 -1
  42. package/dist-cjs/ui/comment-mention.js.map +2 -2
  43. package/dist-cjs/ui/comment-pin.js +23 -3
  44. package/dist-cjs/ui/comment-pin.js.map +2 -2
  45. package/dist-cjs/ui/comment-text.js +1 -1
  46. package/dist-cjs/ui/comment-text.js.map +2 -2
  47. package/dist-cjs/ui/comment-thread.js +6 -6
  48. package/dist-cjs/ui/comment-thread.js.map +2 -2
  49. package/dist-cjs/ui/comments-list.js +12 -12
  50. package/dist-cjs/ui/comments-list.js.map +2 -2
  51. package/dist-cjs/ui/count-badge.js +1 -1
  52. package/dist-cjs/ui/count-badge.js.map +2 -2
  53. package/dist-cjs/ui/empty-state.js +3 -3
  54. package/dist-cjs/ui/empty-state.js.map +2 -2
  55. package/dist-cjs/ui/format-time.js +3 -0
  56. package/dist-cjs/ui/format-time.js.map +2 -2
  57. package/dist-cjs/ui/mention-list.js +8 -8
  58. package/dist-cjs/ui/mention-list.js.map +2 -2
  59. package/dist-cjs/ui/mention-suggestion.js +3 -3
  60. package/dist-cjs/ui/mention-suggestion.js.map +2 -2
  61. package/dist-cjs/ui/mention.js +1 -1
  62. package/dist-cjs/ui/mention.js.map +2 -2
  63. package/dist-cjs/ui/reaction.js +11 -4
  64. package/dist-cjs/ui/reaction.js.map +2 -2
  65. package/dist-cjs/ui/reactions.js +10 -2
  66. package/dist-cjs/ui/reactions.js.map +2 -2
  67. package/dist-cjs/ui/send-button.js +1 -1
  68. package/dist-cjs/ui/send-button.js.map +2 -2
  69. package/dist-esm/canvas/comment-body.mjs +1 -1
  70. package/dist-esm/canvas/comment-body.mjs.map +2 -2
  71. package/dist-esm/canvas/comment-drafts.mjs +34 -0
  72. package/dist-esm/canvas/comment-drafts.mjs.map +7 -0
  73. package/dist-esm/canvas/comment-render.mjs +2 -0
  74. package/dist-esm/canvas/comment-render.mjs.map +2 -2
  75. package/dist-esm/canvas/comment-tool.mjs +56 -12
  76. package/dist-esm/canvas/comment-tool.mjs.map +2 -2
  77. package/dist-esm/canvas/comments-filter-menu.mjs +55 -56
  78. package/dist-esm/canvas/comments-filter-menu.mjs.map +2 -2
  79. package/dist-esm/canvas/comments-overflow-menu.mjs +22 -19
  80. package/dist-esm/canvas/comments-overflow-menu.mjs.map +2 -2
  81. package/dist-esm/canvas/comments-overlay.mjs +289 -111
  82. package/dist-esm/canvas/comments-overlay.mjs.map +2 -2
  83. package/dist-esm/canvas/comments-sidebar.mjs +15 -21
  84. package/dist-esm/canvas/comments-sidebar.mjs.map +2 -2
  85. package/dist-esm/canvas/comments-visibility-toggle.mjs +47 -0
  86. package/dist-esm/canvas/comments-visibility-toggle.mjs.map +7 -0
  87. package/dist-esm/canvas/sidebar-filters.mjs +2 -2
  88. package/dist-esm/canvas/sidebar-filters.mjs.map +2 -2
  89. package/dist-esm/canvas/state.mjs +11 -0
  90. package/dist-esm/canvas/state.mjs.map +2 -2
  91. package/dist-esm/canvas/thread-state.mjs +8 -1
  92. package/dist-esm/canvas/thread-state.mjs.map +2 -2
  93. package/dist-esm/clustering/runtime.mjs +119 -7
  94. package/dist-esm/clustering/runtime.mjs.map +2 -2
  95. package/dist-esm/index.d.mts +100 -39
  96. package/dist-esm/index.mjs +11 -1
  97. package/dist-esm/index.mjs.map +2 -2
  98. package/dist-esm/ui/avatar.mjs +14 -6
  99. package/dist-esm/ui/avatar.mjs.map +2 -2
  100. package/dist-esm/ui/byline.mjs +4 -4
  101. package/dist-esm/ui/byline.mjs.map +2 -2
  102. package/dist-esm/ui/comment-author.mjs +1 -0
  103. package/dist-esm/ui/comment-author.mjs.map +7 -0
  104. package/dist-esm/ui/comment-card.mjs +4 -4
  105. package/dist-esm/ui/comment-card.mjs.map +2 -2
  106. package/dist-esm/ui/comment-composer.mjs +93 -30
  107. package/dist-esm/ui/comment-composer.mjs.map +2 -2
  108. package/dist-esm/ui/comment-mention.mjs +1 -1
  109. package/dist-esm/ui/comment-mention.mjs.map +2 -2
  110. package/dist-esm/ui/comment-pin.mjs +23 -3
  111. package/dist-esm/ui/comment-pin.mjs.map +2 -2
  112. package/dist-esm/ui/comment-text.mjs +1 -1
  113. package/dist-esm/ui/comment-text.mjs.map +2 -2
  114. package/dist-esm/ui/comment-thread.mjs +6 -6
  115. package/dist-esm/ui/comment-thread.mjs.map +2 -2
  116. package/dist-esm/ui/comments-list.mjs +12 -12
  117. package/dist-esm/ui/comments-list.mjs.map +2 -2
  118. package/dist-esm/ui/count-badge.mjs +1 -1
  119. package/dist-esm/ui/count-badge.mjs.map +2 -2
  120. package/dist-esm/ui/empty-state.mjs +3 -3
  121. package/dist-esm/ui/empty-state.mjs.map +2 -2
  122. package/dist-esm/ui/format-time.mjs +3 -0
  123. package/dist-esm/ui/format-time.mjs.map +2 -2
  124. package/dist-esm/ui/mention-list.mjs +8 -8
  125. package/dist-esm/ui/mention-list.mjs.map +2 -2
  126. package/dist-esm/ui/mention-suggestion.mjs +3 -3
  127. package/dist-esm/ui/mention-suggestion.mjs.map +2 -2
  128. package/dist-esm/ui/mention.mjs +1 -1
  129. package/dist-esm/ui/mention.mjs.map +2 -2
  130. package/dist-esm/ui/reaction.mjs +11 -4
  131. package/dist-esm/ui/reaction.mjs.map +2 -2
  132. package/dist-esm/ui/reactions.mjs +10 -2
  133. package/dist-esm/ui/reactions.mjs.map +2 -2
  134. package/dist-esm/ui/send-button.mjs +1 -1
  135. package/dist-esm/ui/send-button.mjs.map +2 -2
  136. package/package.json +3 -3
  137. package/src/canvas/canvas.css +79 -36
  138. package/src/canvas/comment-body.tsx +1 -1
  139. package/src/canvas/comment-drafts.test.ts +55 -0
  140. package/src/canvas/comment-drafts.ts +46 -0
  141. package/src/canvas/comment-render.test.ts +1 -1
  142. package/src/canvas/comment-render.ts +7 -2
  143. package/src/canvas/comment-tool.tsx +87 -15
  144. package/src/canvas/comments-filter-menu.tsx +14 -16
  145. package/src/canvas/comments-overflow-menu.tsx +11 -15
  146. package/src/canvas/comments-overlay.tsx +399 -141
  147. package/src/canvas/comments-sidebar.tsx +27 -28
  148. package/src/canvas/comments-visibility-toggle.tsx +51 -0
  149. package/src/canvas/sidebar-filters.ts +4 -3
  150. package/src/canvas/state.ts +22 -0
  151. package/src/canvas/thread-state.ts +13 -1
  152. package/src/clustering/runtime.test.ts +183 -7
  153. package/src/clustering/runtime.ts +164 -15
  154. package/src/index.ts +6 -0
  155. package/src/ui/avatar.tsx +15 -11
  156. package/src/ui/byline.tsx +6 -5
  157. package/src/ui/comment-author.ts +15 -0
  158. package/src/ui/comment-card.tsx +6 -5
  159. package/src/ui/comment-composer.tsx +122 -33
  160. package/src/ui/comment-mention.ts +2 -2
  161. package/src/ui/comment-pin.tsx +35 -4
  162. package/src/ui/comment-text.tsx +1 -1
  163. package/src/ui/comment-thread.tsx +8 -6
  164. package/src/ui/comments-list.tsx +19 -14
  165. package/src/ui/comments.css +201 -115
  166. package/src/ui/count-badge.tsx +1 -1
  167. package/src/ui/empty-state.tsx +3 -3
  168. package/src/ui/format-time.ts +5 -0
  169. package/src/ui/mention-list.tsx +13 -16
  170. package/src/ui/mention-suggestion.tsx +3 -3
  171. package/src/ui/mention.tsx +1 -1
  172. package/src/ui/reaction.tsx +6 -3
  173. package/src/ui/reactions.tsx +6 -2
  174. package/src/ui/send-button.tsx +1 -1
@@ -1,6 +1,6 @@
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
6
  gap: 10px;
@@ -12,7 +12,7 @@
12
12
  }
13
13
 
14
14
  /* hover-revealed controls (edit…) at the card's top-right */
15
- .cmt-card__actions {
15
+ .tlui-cmt-card__actions {
16
16
  position: absolute;
17
17
  top: 6px;
18
18
  right: 6px;
@@ -20,65 +20,68 @@
20
20
  gap: 2px;
21
21
  opacity: 0;
22
22
  }
23
- .cmt-card:hover .cmt-card__actions,
24
- .cmt-card:focus-within .cmt-card__actions {
23
+ .tlui-cmt-card:hover .tlui-cmt-card__actions,
24
+ .tlui-cmt-card:focus-within .tlui-cmt-card__actions {
25
25
  opacity: 1;
26
26
  }
27
27
 
28
- .cmt-body {
28
+ .tlui-cmt-body {
29
29
  flex: 1;
30
30
  min-width: 0;
31
31
  }
32
32
 
33
- .cmt-head {
33
+ .tlui-cmt-head {
34
34
  display: flex;
35
35
  align-items: baseline;
36
36
  gap: 6px;
37
37
  }
38
38
 
39
- .cmt-author {
39
+ .tlui-cmt-author {
40
40
  font-weight: 600;
41
41
  font-size: 13px;
42
42
  color: var(--tl-color-text-1);
43
43
  }
44
44
 
45
- .cmt-time {
45
+ .tlui-cmt-time {
46
46
  font-size: 11px;
47
47
  color: var(--tl-color-text-3);
48
48
  }
49
49
 
50
- .cmt-text {
50
+ .tlui-cmt-text {
51
51
  margin: 3px 0 0;
52
52
  font-size: 13px;
53
53
  line-height: 1.4;
54
54
  color: var(--tl-color-text-1);
55
+ /* Break long unbroken strings (URLs, keyboard-mashing) so they wrap inside the card instead of
56
+ overflowing it. `anywhere` also lets the flex body shrink to the card width. */
57
+ overflow-wrap: anywhere;
55
58
  }
56
59
 
57
- .cmt-edited {
60
+ .tlui-cmt-edited {
58
61
  font-style: italic;
59
62
  }
60
63
 
61
64
  /* rendered rich text inside a comment body — bare tags emitted by the comment renderer
62
65
  (paragraphs, lists, code, highlight, links), matching the limited comment extension set. */
63
- .cmt-text p {
66
+ .tlui-cmt-text p {
64
67
  margin: 0;
65
68
  }
66
69
 
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 {
70
+ .tlui-cmt-text p + p,
71
+ .tlui-cmt-text p + ul,
72
+ .tlui-cmt-text p + ol,
73
+ .tlui-cmt-text ul + p,
74
+ .tlui-cmt-text ol + p {
72
75
  margin-top: 6px;
73
76
  }
74
77
 
75
- .cmt-text ul,
76
- .cmt-text ol {
78
+ .tlui-cmt-text ul,
79
+ .tlui-cmt-text ol {
77
80
  margin: 0;
78
81
  padding-left: 18px;
79
82
  }
80
83
 
81
- .cmt-text code {
84
+ .tlui-cmt-text code {
82
85
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
83
86
  font-size: 0.92em;
84
87
  background: var(--tl-color-muted-2);
@@ -86,18 +89,18 @@
86
89
  padding: 0 3px;
87
90
  }
88
91
 
89
- .cmt-text mark {
92
+ .tlui-cmt-text mark {
90
93
  background: color-mix(in srgb, #ffeb3b 60%, transparent);
91
94
  color: inherit;
92
95
  border-radius: 2px;
93
96
  }
94
97
 
95
- .cmt-text a {
98
+ .tlui-cmt-text a {
96
99
  color: var(--tl-color-selected);
97
100
  text-decoration: underline;
98
101
  }
99
102
 
100
- .cmt-avatar {
103
+ .tlui-cmt-avatar {
101
104
  width: 28px;
102
105
  height: 28px;
103
106
  border-radius: 50%;
@@ -111,7 +114,7 @@
111
114
  flex-shrink: 0;
112
115
  }
113
116
 
114
- .cmt-avatar--image {
117
+ .tlui-cmt-avatar--image {
115
118
  object-fit: cover;
116
119
  background: none;
117
120
  }
@@ -119,14 +122,14 @@
119
122
  /* composer — an avatar beside a rounded-rect field holding the rich-text input and the send button.
120
123
  Formatting is applied via markdown and keyboard shortcuts (no toolbar). The avatar aligns to the
121
124
  top so it stays put as the field grows to multiple lines. */
122
- .cmt-composer {
125
+ .tlui-cmt-composer {
123
126
  display: flex;
124
127
  align-items: flex-start;
125
128
  gap: 10px;
126
129
  padding: 4px 0 8px 4px;
127
130
  }
128
131
 
129
- .cmt-composer__field {
132
+ .tlui-cmt-composer__field {
130
133
  flex: 1;
131
134
  min-width: 0;
132
135
  display: flex;
@@ -138,19 +141,47 @@
138
141
  border-radius: var(--tl-radius-3);
139
142
  }
140
143
 
141
- .cmt-composer__field:focus-within {
144
+ .tlui-cmt-composer__field:focus-within {
142
145
  border-color: var(--tl-color-selected);
143
146
  }
144
147
 
148
+ /* Expanded: the content no longer fits on one line beside the send button, so the input takes
149
+ the full width and the send button drops to its own row, right-aligned. */
150
+ .tlui-cmt-composer__field--expanded {
151
+ flex-wrap: wrap;
152
+ }
153
+ .tlui-cmt-composer__field--expanded .tlui-cmt-composer__input-wrap {
154
+ flex-basis: 100%;
155
+ /* The field pads 12px left but only 3px right (the send button's inset). With the input
156
+ spanning the full width, give the text the same 12px on the right. */
157
+ padding-right: 9px;
158
+ }
159
+ .tlui-cmt-composer__field--expanded .tlui-cmt-send {
160
+ margin-left: auto;
161
+ }
162
+
145
163
  /* the editable area, with the placeholder overlaid while it's empty */
146
- .cmt-composer__input-wrap {
164
+ .tlui-cmt-composer__input-wrap {
147
165
  position: relative;
148
166
  flex: 1;
149
167
  min-width: 0;
150
168
  padding: 3px 0;
151
169
  }
152
170
 
153
- .cmt-input {
171
+ /* The hidden single-line measuring clone of the editor's content (see CommentComposer). */
172
+ .tlui-cmt-composer__mirror {
173
+ position: absolute;
174
+ top: 0;
175
+ left: 0;
176
+ visibility: hidden;
177
+ pointer-events: none;
178
+ white-space: nowrap;
179
+ width: max-content;
180
+ max-height: none;
181
+ overflow: visible;
182
+ }
183
+
184
+ .tlui-cmt-input {
154
185
  font: inherit;
155
186
  font-size: 13px;
156
187
  line-height: 1.4;
@@ -163,23 +194,23 @@
163
194
  word-break: break-word;
164
195
  }
165
196
 
166
- .cmt-input p {
197
+ .tlui-cmt-input p {
167
198
  margin: 0;
168
199
  }
169
200
 
170
- .cmt-input p + p,
171
- .cmt-input p + ul,
172
- .cmt-input p + ol {
201
+ .tlui-cmt-input p + p,
202
+ .tlui-cmt-input p + ul,
203
+ .tlui-cmt-input p + ol {
173
204
  margin-top: 4px;
174
205
  }
175
206
 
176
- .cmt-input ul,
177
- .cmt-input ol {
207
+ .tlui-cmt-input ul,
208
+ .tlui-cmt-input ol {
178
209
  margin: 0;
179
210
  padding-left: 18px;
180
211
  }
181
212
 
182
- .cmt-input__placeholder {
213
+ .tlui-cmt-input__placeholder {
183
214
  position: absolute;
184
215
  top: 3px;
185
216
  left: 0;
@@ -189,7 +220,7 @@
189
220
  pointer-events: none;
190
221
  }
191
222
 
192
- .cmt-send {
223
+ .tlui-cmt-send {
193
224
  border: 0;
194
225
  border-radius: var(--tl-radius-2);
195
226
  background: var(--tl-color-selected);
@@ -202,33 +233,33 @@
202
233
  align-self: flex-end;
203
234
  }
204
235
 
205
- .cmt-send:hover,
206
- .pseudo-hover .cmt-send {
236
+ .tlui-cmt-send:hover,
237
+ .pseudo-hover .tlui-cmt-send {
207
238
  background: color-mix(in srgb, var(--tl-color-selected) 88%, black);
208
239
  }
209
240
 
210
- .cmt-send:active,
211
- .pseudo-active .cmt-send {
241
+ .tlui-cmt-send:active,
242
+ .pseudo-active .tlui-cmt-send {
212
243
  background: color-mix(in srgb, var(--tl-color-selected) 78%, black);
213
244
  }
214
245
 
215
- .cmt-send:focus-visible,
216
- .pseudo-focus-visible .cmt-send {
246
+ .tlui-cmt-send:focus-visible,
247
+ .pseudo-focus-visible .tlui-cmt-send {
217
248
  outline: 2px solid var(--tl-color-selected);
218
249
  outline-offset: 2px;
219
250
  }
220
251
 
221
- .cmt-send:disabled {
252
+ .tlui-cmt-send:disabled {
222
253
  opacity: 0.45;
223
254
  cursor: not-allowed;
224
255
  }
225
256
 
226
257
  /* pin */
227
- .cmt-pin {
258
+ .tlui-cmt-pin {
228
259
  width: 34px;
229
260
  height: 34px;
230
261
  border-radius: 50% 50% 50% 3px;
231
- background: var(--tl-color-selected);
262
+ background: var(--tlui-cmt-pin-color, var(--tl-color-selected));
232
263
  color: #fff;
233
264
  display: flex;
234
265
  align-items: center;
@@ -242,33 +273,39 @@
242
273
  box-shadow 0.08s ease;
243
274
  }
244
275
 
245
- .cmt-pin:hover,
246
- .pseudo-hover .cmt-pin {
276
+ .tlui-cmt-pin:hover,
277
+ .pseudo-hover .tlui-cmt-pin {
247
278
  transform: scale(1.08);
279
+ }
280
+
281
+ /* The hover shadow is for closed pins only — an open pin keeps its selection ring, which this
282
+ box-shadow would otherwise override (the hover selector outranks the --open rule). */
283
+ .tlui-cmt-pin:not(.tlui-cmt-pin--open):hover,
284
+ .pseudo-hover .tlui-cmt-pin:not(.tlui-cmt-pin--open) {
248
285
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.32);
249
286
  }
250
287
 
251
- /* open: the thread is showing — a selection ring marks the active pin */
252
- .cmt-pin--open {
288
+ /* open: the thread is showing — a selection ring marks the active pin (in the pin's own tint) */
289
+ .tlui-cmt-pin--open {
253
290
  box-shadow:
254
291
  0 0 0 3px var(--tl-color-panel),
255
- 0 0 0 5px var(--tl-color-selected),
292
+ 0 0 0 5px var(--tlui-cmt-pin-color, var(--tl-color-selected)),
256
293
  0 2px 6px rgba(0, 0, 0, 0.25);
257
294
  }
258
295
 
259
296
  /* resolved: a solid, muted grey (the default --tl-color-muted-1 is 10% black, so it goes
260
297
  translucent over the canvas). Dark mode gets its own grey — the token's dark value is near-black. */
261
- .cmt-pin--resolved {
298
+ .tlui-cmt-pin--resolved {
262
299
  background: #dfe0e1;
263
300
  color: hsl(214, 8%, 42%);
264
301
  }
265
- .tl-theme__dark .cmt-pin--resolved {
302
+ .tl-theme__dark .tlui-cmt-pin--resolved {
266
303
  background: hsl(240, 5%, 30%);
267
304
  color: hsl(0, 0%, 72%);
268
305
  }
269
306
 
270
307
  /* count badge */
271
- .cmt-count-badge {
308
+ .tlui-cmt-count-badge {
272
309
  width: 34px;
273
310
  height: 34px;
274
311
  border-radius: 50%;
@@ -284,14 +321,14 @@
284
321
  }
285
322
 
286
323
  /* thread */
287
- .cmt-thread {
324
+ .tlui-cmt-thread {
288
325
  display: flex;
289
326
  flex-direction: column;
290
327
  gap: 8px;
291
328
  width: 300px;
292
329
  }
293
330
 
294
- .cmt-thread__head {
331
+ .tlui-cmt-thread__head {
295
332
  display: flex;
296
333
  align-items: center;
297
334
  gap: 8px;
@@ -302,7 +339,7 @@
302
339
  letter-spacing: 0.04em;
303
340
  }
304
341
 
305
- .cmt-badge {
342
+ .tlui-cmt-badge {
306
343
  font-size: 10px;
307
344
  font-weight: 600;
308
345
  text-transform: none;
@@ -314,12 +351,12 @@
314
351
  }
315
352
 
316
353
  /* reactions */
317
- .cmt-reactions {
354
+ .tlui-cmt-reactions {
318
355
  display: flex;
319
356
  gap: 6px;
320
357
  }
321
358
 
322
- .cmt-reaction {
359
+ .tlui-cmt-reaction {
323
360
  display: inline-flex;
324
361
  align-items: center;
325
362
  gap: 5px;
@@ -333,27 +370,27 @@
333
370
  cursor: pointer;
334
371
  }
335
372
 
336
- .cmt-reaction:hover,
337
- .pseudo-hover .cmt-reaction {
373
+ .tlui-cmt-reaction:hover,
374
+ .pseudo-hover .tlui-cmt-reaction {
338
375
  border-color: var(--tl-color-selected);
339
376
  }
340
377
 
341
- .cmt-reaction--active {
378
+ .tlui-cmt-reaction--active {
342
379
  border-color: var(--tl-color-selected);
343
380
  background: color-mix(in srgb, var(--tl-color-selected) 12%, var(--tl-color-panel));
344
381
  }
345
382
 
346
- .cmt-reaction__count {
383
+ .tlui-cmt-reaction__count {
347
384
  color: var(--tl-color-text-3);
348
385
  }
349
386
 
350
- .cmt-reaction--add {
387
+ .tlui-cmt-reaction--add {
351
388
  color: var(--tl-color-text-3);
352
389
  font-weight: 600;
353
390
  }
354
391
 
355
392
  /* mention */
356
- .cmt-mention {
393
+ .tlui-cmt-mention {
357
394
  color: var(--tl-color-selected);
358
395
  font-weight: 600;
359
396
  background: color-mix(in srgb, var(--tl-color-selected) 12%, transparent);
@@ -362,7 +399,7 @@
362
399
  }
363
400
 
364
401
  /* mention picker */
365
- .cmt-mention-list {
402
+ .tlui-cmt-mention-list {
366
403
  display: flex;
367
404
  flex-direction: column;
368
405
  gap: 1px;
@@ -378,7 +415,7 @@
378
415
  box-shadow: var(--tl-shadow-2, 0 2px 12px rgba(0, 0, 0, 0.14));
379
416
  }
380
417
 
381
- .cmt-mention-list__item {
418
+ .tlui-cmt-mention-list__item {
382
419
  display: flex;
383
420
  align-items: center;
384
421
  gap: 8px;
@@ -392,19 +429,19 @@
392
429
  font: inherit;
393
430
  }
394
431
 
395
- .cmt-mention-list__item--active,
396
- .cmt-mention-list__item:hover {
432
+ .tlui-cmt-mention-list__item--active,
433
+ .tlui-cmt-mention-list__item:hover {
397
434
  background: var(--tl-color-muted-2, rgba(0, 0, 0, 0.06));
398
435
  }
399
436
 
400
- .cmt-mention-list__text {
437
+ .tlui-cmt-mention-list__text {
401
438
  display: flex;
402
439
  flex-direction: column;
403
440
  min-width: 0;
404
441
  line-height: 1.3;
405
442
  }
406
443
 
407
- .cmt-mention-list__name {
444
+ .tlui-cmt-mention-list__name {
408
445
  font-size: 13px;
409
446
  font-weight: 500;
410
447
  white-space: nowrap;
@@ -412,13 +449,13 @@
412
449
  text-overflow: ellipsis;
413
450
  }
414
451
 
415
- .cmt-mention-list__you {
452
+ .tlui-cmt-mention-list__you {
416
453
  margin-left: 4px;
417
454
  font-weight: 400;
418
455
  color: var(--tl-color-text-3);
419
456
  }
420
457
 
421
- .cmt-mention-list__secondary {
458
+ .tlui-cmt-mention-list__secondary {
422
459
  font-size: 12px;
423
460
  color: var(--tl-color-text-3);
424
461
  white-space: nowrap;
@@ -426,7 +463,7 @@
426
463
  text-overflow: ellipsis;
427
464
  }
428
465
 
429
- .cmt-mention-list--empty {
466
+ .tlui-cmt-mention-list--empty {
430
467
  padding: 8px 10px;
431
468
  width: 100%;
432
469
  box-sizing: border-box;
@@ -435,13 +472,13 @@
435
472
  }
436
473
 
437
474
  /* the @-picker popup — caret-anchored above the page, positioned by the suggestion plugin */
438
- .cmt-mention-popup {
475
+ .tlui-cmt-mention-popup {
439
476
  position: fixed;
440
477
  z-index: var(--tl-layer-menus);
441
478
  }
442
479
 
443
480
  /* empty state */
444
- .cmt-empty {
481
+ .tlui-cmt-empty {
445
482
  display: flex;
446
483
  flex-direction: column;
447
484
  align-items: center;
@@ -451,11 +488,11 @@
451
488
  width: 240px;
452
489
  }
453
490
 
454
- .cmt-empty__icon {
491
+ .tlui-cmt-empty__icon {
455
492
  font-size: 28px;
456
493
  }
457
494
 
458
- .cmt-empty__message {
495
+ .tlui-cmt-empty__message {
459
496
  margin: 0;
460
497
  color: var(--tl-color-text-3);
461
498
  font-size: 13px;
@@ -464,7 +501,7 @@
464
501
 
465
502
  /* a comment thread: an elevated panel — the same surface treatment as the toolbar — holding a
466
503
  header, an optional resolved banner, the comments, and a reply composer */
467
- .cmt-thread {
504
+ .tlui-cmt-thread {
468
505
  display: flex;
469
506
  flex-direction: column;
470
507
  gap: 6px;
@@ -474,22 +511,22 @@
474
511
  border-radius: var(--tl-radius-4);
475
512
  box-shadow: var(--tl-shadow-2);
476
513
  }
477
- .cmt-thread__header {
514
+ .tlui-cmt-thread__header {
478
515
  display: flex;
479
516
  align-items: center;
480
517
  justify-content: space-between;
481
518
  padding: 2px 2px 2px 4px;
482
519
  }
483
- .cmt-thread__title {
520
+ .tlui-cmt-thread__title {
484
521
  font-size: 12px;
485
522
  font-weight: 600;
486
523
  color: var(--tl-color-text-1);
487
524
  }
488
- .cmt-thread__actions {
525
+ .tlui-cmt-thread__actions {
489
526
  display: flex;
490
527
  gap: 2px;
491
528
  }
492
- .cmt-thread__action {
529
+ .tlui-cmt-thread__action {
493
530
  display: flex;
494
531
  align-items: center;
495
532
  justify-content: center;
@@ -504,25 +541,55 @@
504
541
  line-height: 1;
505
542
  cursor: pointer;
506
543
  }
507
- .cmt-thread__action:hover {
544
+ .tlui-cmt-thread__action:hover {
508
545
  background: var(--tl-color-muted-2);
509
546
  color: var(--tl-color-text-1);
510
547
  }
511
- .cmt-thread__resolved {
548
+ .tlui-cmt-thread__resolved {
512
549
  padding: 6px 10px;
513
550
  border-radius: 8px;
514
551
  background: var(--tl-color-muted-2);
515
552
  font-size: 12px;
516
553
  color: var(--tl-color-text-3);
517
554
  }
518
- .cmt-thread__list {
555
+ .tlui-cmt-thread__list {
519
556
  display: flex;
520
557
  flex-direction: column;
521
558
  gap: 6px;
522
559
  }
560
+ /* Inside a thread, author identity is a small colour dot, no initial — the letter doesn't fit
561
+ at this size. */
562
+ .tlui-cmt-thread .tlui-cmt-avatar {
563
+ width: 14px;
564
+ height: 14px;
565
+ font-size: 0;
566
+ margin-top: 2px;
567
+ }
568
+
569
+ /* The reply composer carries no avatar at all — the field spans the thread's full width. */
570
+ .tlui-cmt-thread .tlui-cmt-composer .tlui-cmt-avatar {
571
+ display: none;
572
+ }
573
+
574
+ /* The sidebar's rows use the same small colour dot as the thread view. */
575
+ .tlui-cmt-list .tlui-cmt-avatar {
576
+ width: 14px;
577
+ height: 14px;
578
+ font-size: 0;
579
+ margin-top: 2px;
580
+ }
581
+
582
+ /* The dot treatment is for colour-only identity — an image avatar stays full size. */
583
+ .tlui-cmt-thread .tlui-cmt-avatar--image,
584
+ .tlui-cmt-list .tlui-cmt-avatar--image {
585
+ width: 24px;
586
+ height: 24px;
587
+ margin-top: 0;
588
+ }
589
+
523
590
  /* inside the panel, comments are plain content — no surrounding box; the composer's field carries
524
591
  its own surface. */
525
- .cmt-thread .cmt-card {
592
+ .tlui-cmt-thread .tlui-cmt-card {
526
593
  width: 100%;
527
594
  padding: 6px 0 6px 4px;
528
595
  background: transparent;
@@ -530,13 +597,13 @@
530
597
  }
531
598
 
532
599
  /* comments list — thread summaries, one per row (used by the canvas sidebar) */
533
- .cmt-list {
600
+ .tlui-cmt-list {
534
601
  display: flex;
535
602
  flex-direction: column;
536
603
  width: 100%;
537
604
  min-height: 0;
538
605
  }
539
- .cmt-list__header {
606
+ .tlui-cmt-list__header {
540
607
  flex-shrink: 0;
541
608
  display: flex;
542
609
  align-items: center;
@@ -545,16 +612,14 @@
545
612
  padding: 6px 6px 6px 14px;
546
613
  border-bottom: 1px solid var(--tl-color-divider);
547
614
  }
548
- .cmt-list__header-title {
549
- font-size: 11px;
615
+ .tlui-cmt-list__header-title {
616
+ font-size: 13px;
550
617
  font-weight: 600;
551
- letter-spacing: 0.06em;
552
- text-transform: uppercase;
553
- color: var(--tl-color-text-3);
618
+ color: var(--tl-color-text-1);
554
619
  }
555
620
 
556
621
  /* a small square icon button in the sidebar header (filter funnel, overflow …) */
557
- .cmt-header-btn {
622
+ .tlui-cmt-header-btn {
558
623
  display: flex;
559
624
  align-items: center;
560
625
  justify-content: center;
@@ -567,19 +632,24 @@
567
632
  color: var(--tl-color-text-2);
568
633
  cursor: pointer;
569
634
  }
570
- .cmt-header-btn:hover,
571
- .cmt-header-btn[data-state='open'] {
635
+ .tlui-cmt-header-btn:hover,
636
+ .tlui-cmt-header-btn[data-state='open'] {
572
637
  background: var(--tl-color-muted-2);
573
638
  color: var(--tl-color-text-1);
574
639
  }
575
- .cmt-list__header-actions {
640
+ .tlui-cmt-list__header-actions {
576
641
  display: flex;
577
642
  align-items: center;
578
643
  gap: 2px;
579
644
  }
580
645
 
646
+ /* The commenting dropdowns' surface — a little air between the items and the menu edge. */
647
+ .tlui-cmt-menu {
648
+ padding: 4px;
649
+ }
650
+
581
651
  /* a menu row with a label and a right-aligned shortcut hint (overflow menu) */
582
- .cmt-menu-item {
652
+ .tlui-cmt-menu-item {
583
653
  display: flex;
584
654
  align-items: center;
585
655
  justify-content: space-between;
@@ -590,28 +660,33 @@
590
660
  border-radius: 6px;
591
661
  background: transparent;
592
662
  font: inherit;
593
- font-size: 13px;
663
+ font-size: 12px;
594
664
  color: var(--tl-color-text-1);
595
665
  cursor: pointer;
596
666
  }
597
- .cmt-menu-item:hover {
667
+ .tlui-cmt-menu-item:hover {
598
668
  background: var(--tl-color-muted-2);
599
669
  }
600
- .cmt-menu-item__shortcut {
670
+ /* Destructive menu entries (delete) — the same danger colour as tldraw's danger buttons. */
671
+ .tlui-cmt-menu-item--danger {
672
+ color: var(--tl-color-danger);
673
+ }
674
+
675
+ .tlui-cmt-menu-item__shortcut {
601
676
  color: var(--tl-color-text-3);
602
677
  font-size: 12px;
603
678
  }
604
- .cmt-list__items {
679
+ .tlui-cmt-list__items {
605
680
  flex: 1;
606
681
  min-height: 0;
607
682
  overflow-y: auto;
608
683
  }
609
- .cmt-list__empty {
684
+ .tlui-cmt-list__empty {
610
685
  padding: 20px 14px;
611
686
  color: var(--tl-color-text-3);
612
687
  font-size: 13px;
613
688
  }
614
- .cmt-list__item {
689
+ .tlui-cmt-list__item {
615
690
  display: flex;
616
691
  gap: 10px;
617
692
  width: 100%;
@@ -623,22 +698,30 @@
623
698
  text-align: left;
624
699
  cursor: pointer;
625
700
  }
626
- .cmt-list__item:hover {
701
+ .tlui-cmt-list__item:hover {
627
702
  background: var(--tl-color-muted-2);
628
703
  }
629
- .cmt-list__item--selected {
630
- background: var(--tl-color-muted-1);
704
+ /* Selected sits a step above hover so the open thread's row stays distinguishable while
705
+ pointing at other rows — but only a step: the muted-1 token (10%) reads too heavy here.
706
+ These rows sit on the opaque sidebar panel, so a translucent tint composes safely. */
707
+ .tlui-cmt-list__item--selected,
708
+ .tlui-cmt-list__item--selected:hover {
709
+ background: hsl(0, 0%, 0%, 5%);
710
+ }
711
+ .tl-theme__dark .tlui-cmt-list__item--selected,
712
+ .tl-theme__dark .tlui-cmt-list__item--selected:hover {
713
+ background: hsl(0, 0%, 100%, 5%);
631
714
  }
632
715
  /* 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 {
716
+ .tlui-cmt-list__item[data-resolved] .tlui-cmt-head,
717
+ .tlui-cmt-list__item[data-resolved] .tlui-cmt-list__item-preview {
635
718
  opacity: 0.55;
636
719
  }
637
- .cmt-list__item-body {
720
+ .tlui-cmt-list__item-body {
638
721
  flex: 1;
639
722
  min-width: 0;
640
723
  }
641
- .cmt-list__item-preview {
724
+ .tlui-cmt-list__item-preview {
642
725
  margin-top: 2px;
643
726
  font-size: 13px;
644
727
  color: var(--tl-color-text-1);
@@ -647,9 +730,12 @@
647
730
  display: -webkit-box;
648
731
  -webkit-line-clamp: 2;
649
732
  -webkit-box-orient: vertical;
733
+ /* Long unbroken strings (URLs, mashed keys) wrap onto the clamped lines instead of clipping
734
+ mid-string — same treatment as the card body. */
735
+ overflow-wrap: anywhere;
650
736
  }
651
737
  /* meta line under the preview: page label and/or a resolved marker */
652
- .cmt-list__item-meta {
738
+ .tlui-cmt-list__item-meta {
653
739
  display: flex;
654
740
  align-items: center;
655
741
  gap: 8px;
@@ -657,20 +743,20 @@
657
743
  font-size: 11px;
658
744
  color: var(--tl-color-text-3);
659
745
  }
660
- .cmt-list__item-resolved {
746
+ .tlui-cmt-list__item-resolved {
661
747
  display: inline-flex;
662
748
  align-items: center;
663
749
  gap: 3px;
664
750
  font-weight: 600;
665
751
  }
666
- .cmt-list__item-page {
752
+ .tlui-cmt-list__item-page {
667
753
  display: inline-flex;
668
754
  align-items: center;
669
755
  padding: 1px 6px;
670
756
  border-radius: 4px;
671
757
  background: var(--tl-color-muted-2);
672
758
  }
673
- .cmt-list__item-count {
759
+ .tlui-cmt-list__item-count {
674
760
  flex-shrink: 0;
675
761
  align-self: center;
676
762
  font-size: 12px;