hale-commenting-system 3.5.1 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,8 +16,23 @@ npm uninstall hale-commenting-system
16
16
 
17
17
  ## Features
18
18
 
19
- - **Pin-based commenting** - Click anywhere on a page to add a comment pin
20
- - **Thread discussions** - Organize comments into threads with replies
19
+ - **React Component-Based Commenting** - Detects and attaches comments to React components, not just DOM elements
20
+ - Automatically identifies React component names, types, and props
21
+ - Shows component tree path (e.g., "App > Dashboard > Button")
22
+ - Displays component metadata including props in the comment panel
23
+ - **Hover Preview** - See what will be selected before clicking with a visual preview
24
+ - Dashed blue border highlights the element you're about to select
25
+ - Component name label appears above the element
26
+ - Works on all elements including buttons, links, and interactive components
27
+ - **Smart Pin Positioning** - Pins anchor precisely to elements using CSS selectors
28
+ - Pins appear at the top-left corner of selected components
29
+ - Automatically follows elements on scroll and resize
30
+ - Falls back to stored coordinates if element is deleted
31
+ - **Component Highlighting** - Selected components are highlighted with a blue border (similar to Chrome DevTools)
32
+ - **Show Pins Toggle** - View comment pins even when commenting is disabled
33
+ - **Resizable Widget** - Adjust the commenting panel size to fit your workflow
34
+ - **Missing Element Detection** - Pins fade and show [deleted] when target component is removed
35
+ - **Thread Discussions** - Organize comments into threads with replies
21
36
  - **GitHub Integration** - Sync comments with GitHub Issues automatically
22
37
  - **Jira Integration** - Link Jira tickets to specific pages or sections
23
38
  - **PatternFly Design** - Built with PatternFly React components
@@ -140,17 +155,94 @@ After running the integration script, the commenting system will be available in
140
155
 
141
156
  ### Adding Comments
142
157
 
143
- - **Click anywhere** on a page to add a comment pin
144
- - **View all comments** in the "Comments" menu item in the sidebar
145
- - **Reply to comments** to create discussion threads
146
- - **Navigate to pins** using the "Go to pin" button in the comments view
158
+ 1. **Hover to preview** - Move your mouse over any component to see a preview of what will be selected
159
+ - A dashed blue border highlights the element
160
+ - A label shows the component or element name
161
+ - This helps you target the exact component you want to comment on
162
+
163
+ 2. **Click on any component** to attach a comment pin
164
+ - The system detects React components automatically
165
+ - Falls back to DOM element detection for non-React elements
166
+ - Pins anchor to specific elements using CSS selectors
167
+ - Pins appear at the top-left corner of the selected component
168
+
169
+ 3. **View component information** in the comment panel
170
+ - **React Components:** Shows component name, type (function/class/memo), component tree path, and props
171
+ - **DOM Elements:** Shows element description (e.g., "button.pf-c-button")
172
+ - Components marked as [deleted] if the element is removed from the page
173
+ - Expandable props section shows all component props in formatted JSON
174
+
175
+ 4. **Pin behavior:**
176
+ - **Element exists:** Pin positions at top-left corner and follows it on scroll/resize
177
+ - **Element deleted:** Pin fades to 40% opacity, uses fallback position, and shows [deleted] label
178
+ - **Selected pin:** Highlighted with blue border around the target component
179
+
180
+ 5. **Control visibility:**
181
+ - **Enable Comments:** Toggle to enable/disable creating new comments
182
+ - **Show pins:** Toggle to show/hide pins even when commenting is disabled
183
+ - Use both toggles to view existing comments without creating new ones
184
+
185
+ 6. **Resize the widget:**
186
+ - Drag the resize handle in the bottom-right corner of the commenting panel
187
+ - Adjust width (300-800px) and height (200px to viewport height)
188
+ - Size is maintained during your session
189
+
190
+ 7. **Navigate and manage comments:**
191
+ - **View all comments** in the "Comments" menu item in the sidebar
192
+ - **Reply to comments** to create discussion threads
193
+ - **Select pins** by clicking on them to view/edit comments
194
+ - **Close/reopen threads** just like GitHub Issues
195
+ - **Remove pins** to delete comment threads
196
+
197
+ ### How It Works
198
+
199
+ The commenting system uses a **hybrid approach** combining React component detection and CSS selectors:
200
+
201
+ #### React Component Detection (Primary)
202
+
203
+ 1. **Component identification:**
204
+ - Detects React components using React fiber nodes
205
+ - Extracts component name, type (function/class/memo/forwardRef), and props
206
+ - Builds component tree path showing hierarchy (e.g., "App > Dashboard > Button")
207
+ - Works with all React component types including HOCs and wrapped components
208
+
209
+ 2. **Component metadata:**
210
+ - Component name (e.g., "Button", "Card", "CustomComponent")
211
+ - Component type (function, class, memo, forwardRef, etc.)
212
+ - Component props (sanitized for display, functions shown as [Function])
213
+ - Component tree path showing parent hierarchy
214
+
215
+ #### CSS Selector Fallback
216
+
217
+ For non-React elements or when component detection isn't available:
218
+
219
+ 1. **Priority selection strategy:**
220
+ - `data-testid` or `data-id` attributes (most stable)
221
+ - `id` attribute
222
+ - Combination of tag + class + aria attributes
223
+ - Fallback to nth-child path
224
+
225
+ 2. **Stored metadata for each pin:**
226
+ - CSS selector for the target element
227
+ - React component metadata (if available)
228
+ - Simplified element/component name for display
229
+ - Fallback coordinates (if element is deleted)
230
+
231
+ 3. **Example:** Clicking a React Button component might show:
232
+ - **Component Name:** `Button`
233
+ - **Component Type:** `function`
234
+ - **Component Path:** `App > Dashboard > Button`
235
+ - **Props:** `{ variant: "primary", children: "Submit" }`
236
+ - **CSS Selector:** `button.pf-c-button[aria-label="Submit"]` (fallback)
147
237
 
148
238
  ### GitHub Integration (Optional)
149
239
 
150
240
  When configured, comments automatically sync with GitHub Issues:
151
- - Each comment thread becomes a GitHub Issue
152
- - Replies sync as Issue comments
241
+ - Each comment thread becomes a GitHub Issue with component metadata
242
+ - Issue body includes: React component name (if available), CSS selector, and fallback position
243
+ - Replies sync as Issue comments with proper threading
153
244
  - Status changes (open/closed) sync between the app and GitHub
245
+ - Component metadata is preserved in issue descriptions
154
246
 
155
247
  ### Jira Integration (Optional)
156
248
 
@@ -196,6 +288,93 @@ The integration script automatically modifies your project:
196
288
  5. **`src/app/Comments/Comments.tsx`** - Creates the Comments view component
197
289
  6. **`.env` and `.env.server`** - Creates configuration files
198
290
 
291
+ ## Testing Before Publishing
292
+
293
+ To test this package locally before publishing to npm:
294
+
295
+ ### Method 1: Using npm link (Recommended)
296
+
297
+ 1. **In the package directory** (hale-npm-package):
298
+ ```bash
299
+ npm run build
300
+ npm link
301
+ ```
302
+
303
+ 2. **In your test application** (e.g., PatternFly React Seed):
304
+ ```bash
305
+ npm link hale-commenting-system
306
+ npx hale-commenting-system init
307
+ npm run start:dev
308
+ ```
309
+
310
+ 3. **Test the features:**
311
+ - Hover over components to see preview highlighting
312
+ - Click on various components (buttons, cards, inputs)
313
+ - Verify pins attach to components and appear at top-left corner
314
+ - Check that React component metadata is displayed correctly
315
+ - Scroll/resize and verify pins follow elements
316
+ - Add comments and replies
317
+ - Test "Show pins" toggle to view pins without enabling comments
318
+ - Resize the commenting widget
319
+ - Remove a component from the DOM and verify pin fades and shows [deleted]
320
+ - Reload page and verify pins reattach correctly
321
+
322
+ 4. **When done testing:**
323
+ ```bash
324
+ # In your test app
325
+ npx hale-commenting-system remove
326
+ npm unlink hale-commenting-system
327
+ npm install
328
+
329
+ # In the package directory
330
+ npm unlink
331
+ ```
332
+
333
+ ### Method 2: Using npm pack
334
+
335
+ 1. **In the package directory:**
336
+ ```bash
337
+ npm run build
338
+ npm pack
339
+ ```
340
+ This creates a `.tgz` file (e.g., `hale-commenting-system-3.6.0.tgz`)
341
+
342
+ 2. **In your test application:**
343
+ ```bash
344
+ npm install /path/to/hale-commenting-system-3.5.2.tgz
345
+ npx hale-commenting-system init
346
+ npm run start:dev
347
+ ```
348
+
349
+ 3. **Test and clean up as above**
350
+
351
+ ### Method 3: Using Local Path
352
+
353
+ 1. **In your test application:**
354
+ ```bash
355
+ npm install /path/to/hale-npm-package
356
+ npx hale-commenting-system init
357
+ npm run start:dev
358
+ ```
359
+
360
+ ### What to Test
361
+
362
+ - ✅ **Hover preview** - Verify preview shows correct element and component name
363
+ - ✅ **Pin creation** - Click on different component types (React and DOM elements)
364
+ - ✅ **Pin positioning** - Verify pins appear at top-left corner of elements
365
+ - ✅ **Component detection** - Verify React components show name, type, path, and props
366
+ - ✅ **Component highlighting** - Verify selected components are highlighted with blue border
367
+ - ✅ **Show pins toggle** - Verify pins are visible when toggle is on, even with comments disabled
368
+ - ✅ **Widget resizing** - Verify widget can be resized and maintains size
369
+ - ✅ **Dynamic tracking** - Scroll, resize, and verify pins follow elements
370
+ - ✅ **Element deletion** - Remove components and verify fade + [deleted] label
371
+ - ✅ **Page reload** - Verify pins reattach to correct elements
372
+ - ✅ **Component display** - Check panel shows React component info or DOM element names
373
+ - ✅ **GitHub sync** (if configured) - Verify issues include component metadata
374
+ - ✅ **Comments & replies** - Test threaded discussions
375
+ - ✅ **Close/reopen** - Test thread status changes
376
+ - ✅ **Remove pin** - Verify removing a pin doesn't create a new one
377
+
199
378
  ## Development
200
379
 
201
380
  ### Running Locally
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hale-commenting-system",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "description": "A commenting system for PatternFly React applications that allows designers and developers to add comments directly on design pages, sync with GitHub Issues, and link Jira tickets.",
5
5
  "homepage": "https://www.npmjs.com/package/hale-commenting-system",
6
6
  "license": "MIT",
@@ -91,6 +91,8 @@
91
91
  "@babel/parser": "^7.23.0",
92
92
  "@babel/traverse": "^7.23.0",
93
93
  "@babel/types": "^7.23.0",
94
+ "dotenv": "^16.4.5",
95
+ "express": "^4.21.1",
94
96
  "inquirer": "^8.2.6",
95
97
  "node-fetch": "^2.7.0"
96
98
  },
@@ -3,44 +3,310 @@ import { useLocation } from 'react-router-dom';
3
3
  import { useComments } from '../contexts/CommentContext';
4
4
  import { CommentPin } from './CommentPin';
5
5
  import { getVersionFromPathOrQuery } from '../utils/version';
6
+ import { generateSelectorForElement, getElementDescription, getElementComponentMetadata, findElementBySelector } from '../utils/selectorUtils';
7
+ import { getFiberFromElement, getComponentName } from '../utils/componentUtils';
6
8
 
7
9
  export const CommentOverlay: React.FunctionComponent = () => {
8
10
  const location = useLocation();
9
- const { commentsEnabled, addThread, selectedThreadId, setSelectedThreadId, syncFromGitHub, getThreadsForRoute } = useComments();
11
+ const { commentsEnabled, showPinsEnabled, addThread, selectedThreadId, setSelectedThreadId, syncFromGitHub, getThreadsForRoute } = useComments();
10
12
  const detectedVersion = getVersionFromPathOrQuery(location.pathname, location.search);
11
13
  const overlayRef = React.useRef<HTMLDivElement>(null);
12
14
 
13
15
  // Show both open and closed threads as pins (GitHub-style: closed issues still exist)
14
16
  const currentThreads = getThreadsForRoute(location.pathname, detectedVersion);
17
+ const selectedThread = currentThreads.find((t) => t.id === selectedThreadId);
18
+ const highlightRef = React.useRef<HTMLDivElement | null>(null);
19
+ const previewRef = React.useRef<HTMLDivElement | null>(null);
20
+ const previewLabelRef = React.useRef<HTMLDivElement | null>(null);
21
+ const hoveredElementRef = React.useRef<Element | null>(null);
22
+
23
+ // Component highlighting effect (similar to Chrome DevTools)
24
+ React.useEffect(() => {
25
+ // Hide highlight when comments are disabled
26
+ if (!commentsEnabled || !selectedThread || !selectedThread.cssSelector) {
27
+ // Remove highlight
28
+ if (highlightRef.current) {
29
+ highlightRef.current.remove();
30
+ highlightRef.current = null;
31
+ }
32
+ return;
33
+ }
34
+
35
+ const element = findElementBySelector(selectedThread.cssSelector);
36
+ if (!element) {
37
+ // Element not found, remove highlight
38
+ if (highlightRef.current) {
39
+ highlightRef.current.remove();
40
+ highlightRef.current = null;
41
+ }
42
+ return;
43
+ }
44
+
45
+ // Create or update highlight overlay
46
+ let highlight = highlightRef.current;
47
+ if (!highlight) {
48
+ highlight = document.createElement('div');
49
+ highlight.style.cssText = `
50
+ position: fixed;
51
+ pointer-events: none;
52
+ z-index: 998;
53
+ border: 2px solid #0066CC;
54
+ background-color: rgba(0, 102, 204, 0.1);
55
+ box-shadow: 0 0 0 1px rgba(0, 102, 204, 0.3);
56
+ transition: all 0.15s ease;
57
+ `;
58
+ document.body.appendChild(highlight);
59
+ highlightRef.current = highlight;
60
+ }
61
+
62
+ // Update highlight position and size
63
+ const updateHighlight = () => {
64
+ if (!highlight || !element) return;
65
+ const rect = element.getBoundingClientRect();
66
+ highlight.style.left = `${rect.left + window.scrollX}px`;
67
+ highlight.style.top = `${rect.top + window.scrollY}px`;
68
+ highlight.style.width = `${rect.width}px`;
69
+ highlight.style.height = `${rect.height}px`;
70
+ };
71
+
72
+ updateHighlight();
73
+
74
+ // Update on scroll/resize
75
+ const handleUpdate = () => updateHighlight();
76
+ window.addEventListener('scroll', handleUpdate, true);
77
+ window.addEventListener('resize', handleUpdate);
78
+
79
+ return () => {
80
+ window.removeEventListener('scroll', handleUpdate, true);
81
+ window.removeEventListener('resize', handleUpdate);
82
+ };
83
+ }, [commentsEnabled, selectedThreadId, selectedThread]);
84
+
85
+ // Cleanup highlight on unmount
86
+ React.useEffect(() => {
87
+ return () => {
88
+ if (highlightRef.current) {
89
+ highlightRef.current.remove();
90
+ highlightRef.current = null;
91
+ }
92
+ if (previewRef.current) {
93
+ previewRef.current.remove();
94
+ previewRef.current = null;
95
+ }
96
+ if (previewLabelRef.current) {
97
+ previewLabelRef.current.remove();
98
+ previewLabelRef.current = null;
99
+ }
100
+ };
101
+ }, []);
102
+
103
+ // Hover preview effect - shows what will be selected before clicking
104
+ const handleMouseMove = React.useCallback((e: MouseEvent) => {
105
+ if (!commentsEnabled) {
106
+ // Remove preview if comments are disabled
107
+ if (previewRef.current) {
108
+ previewRef.current.remove();
109
+ previewRef.current = null;
110
+ }
111
+ if (previewLabelRef.current) {
112
+ previewLabelRef.current.remove();
113
+ previewLabelRef.current = null;
114
+ }
115
+ hoveredElementRef.current = null;
116
+ return;
117
+ }
118
+
119
+ const target = e.target as HTMLElement;
120
+
121
+ // Don't show preview on comment system UI elements (but allow buttons/links to be selected)
122
+ if (
123
+ target.closest('[data-comment-controls]') ||
124
+ target.closest('[data-comment-pin]') ||
125
+ target.closest('[data-floating-widget]') ||
126
+ target.closest('[data-comment-preview]')
127
+ ) {
128
+ if (previewRef.current) {
129
+ previewRef.current.style.display = 'none';
130
+ }
131
+ if (previewLabelRef.current) {
132
+ previewLabelRef.current.style.display = 'none';
133
+ }
134
+ hoveredElementRef.current = null;
135
+ return;
136
+ }
137
+
138
+ // Use the actual element being hovered (don't traverse up for preview)
139
+ const element = target as Element;
140
+
141
+ // Only update if hovering over a different element
142
+ if (hoveredElementRef.current === element) {
143
+ return;
144
+ }
145
+
146
+ hoveredElementRef.current = element;
147
+
148
+ // Get element info for preview - use the actual element, not parent component
149
+ const elementDescription = getElementDescription(element);
150
+
151
+ // Only get component metadata if this element itself is a React component
152
+ // Don't traverse up to parent components for preview
153
+ const fiber = getFiberFromElement(element);
154
+ let previewName = elementDescription;
155
+
156
+ if (fiber) {
157
+ const type = fiber.type;
158
+ // Only use component name if this element IS a React component (not native)
159
+ if (type && typeof type !== 'string') {
160
+ const componentName = getComponentName(fiber);
161
+ const displayName = (typeof type === 'function' && (type.displayName || type.name)) ||
162
+ (type?.$$typeof === Symbol.for('react.forward_ref') && (type.render?.displayName || type.render?.name)) ||
163
+ undefined;
164
+ previewName = componentName || displayName || elementDescription;
165
+ }
166
+ }
167
+
168
+ // Create or update preview highlight
169
+ let preview = previewRef.current;
170
+ if (!preview) {
171
+ preview = document.createElement('div');
172
+ preview.setAttribute('data-comment-preview', 'true');
173
+ preview.style.cssText = `
174
+ position: fixed;
175
+ pointer-events: none;
176
+ z-index: 997;
177
+ border: 2px dashed #0066CC;
178
+ background-color: rgba(0, 102, 204, 0.05);
179
+ box-shadow: 0 0 0 1px rgba(0, 102, 204, 0.2);
180
+ transition: all 0.1s ease;
181
+ `;
182
+ document.body.appendChild(preview);
183
+ previewRef.current = preview;
184
+ }
185
+
186
+ // Create or update preview label
187
+ let previewLabel = previewLabelRef.current;
188
+ if (!previewLabel) {
189
+ previewLabel = document.createElement('div');
190
+ previewLabel.setAttribute('data-comment-preview', 'true');
191
+ previewLabel.style.cssText = `
192
+ position: fixed;
193
+ pointer-events: none;
194
+ z-index: 998;
195
+ background-color: #0066CC;
196
+ color: white;
197
+ padding: 4px 8px;
198
+ border-radius: 4px;
199
+ font-size: 12px;
200
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
201
+ white-space: nowrap;
202
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
203
+ transition: all 0.1s ease;
204
+ `;
205
+ document.body.appendChild(previewLabel);
206
+ previewLabelRef.current = previewLabel;
207
+ }
208
+
209
+ // Update preview position and size
210
+ const rect = element.getBoundingClientRect();
211
+ preview.style.display = 'block';
212
+ preview.style.left = `${rect.left + window.scrollX}px`;
213
+ preview.style.top = `${rect.top + window.scrollY}px`;
214
+ preview.style.width = `${rect.width}px`;
215
+ preview.style.height = `${rect.height}px`;
216
+
217
+ // Update label position (above the element, top-left, but ensure it stays on screen)
218
+ previewLabel.style.display = 'block';
219
+ previewLabel.textContent = previewName;
220
+
221
+ const labelLeft = rect.left + window.scrollX;
222
+ const labelTop = rect.top + window.scrollY - 28;
223
+
224
+ // Ensure label doesn't go off the left edge
225
+ const adjustedLeft = Math.max(8, labelLeft);
226
+
227
+ // If element is near top of viewport, show label below instead
228
+ const adjustedTop = labelTop < window.scrollY + 40
229
+ ? rect.bottom + window.scrollY + 4
230
+ : labelTop;
231
+
232
+ previewLabel.style.left = `${adjustedLeft}px`;
233
+ previewLabel.style.top = `${adjustedTop}px`;
234
+ }, [commentsEnabled]);
235
+
236
+ // Mouse leave handler to hide preview
237
+ const handleMouseLeave = React.useCallback(() => {
238
+ if (previewRef.current) {
239
+ previewRef.current.style.display = 'none';
240
+ }
241
+ if (previewLabelRef.current) {
242
+ previewLabelRef.current.style.display = 'none';
243
+ }
244
+ hoveredElementRef.current = null;
245
+ }, []);
246
+
247
+ // Set up hover preview listeners
248
+ React.useEffect(() => {
249
+ if (commentsEnabled) {
250
+ document.addEventListener('mousemove', handleMouseMove);
251
+ document.addEventListener('mouseleave', handleMouseLeave, true);
252
+
253
+ return () => {
254
+ document.removeEventListener('mousemove', handleMouseMove);
255
+ document.removeEventListener('mouseleave', handleMouseLeave, true);
256
+ };
257
+ } else {
258
+ // Clean up preview when disabled
259
+ if (previewRef.current) {
260
+ previewRef.current.remove();
261
+ previewRef.current = null;
262
+ }
263
+ if (previewLabelRef.current) {
264
+ previewLabelRef.current.remove();
265
+ previewLabelRef.current = null;
266
+ }
267
+ return undefined;
268
+ }
269
+ }, [commentsEnabled, handleMouseMove, handleMouseLeave]);
15
270
 
16
271
  const handlePageClick = (e: MouseEvent) => {
17
272
  if (!commentsEnabled) return;
18
273
 
19
- // Check if clicking on a pin or any interactive element (including FloatingWidget)
274
+ // Check if clicking on comment system UI elements (but allow buttons/links to be selected)
20
275
  const target = e.target as HTMLElement;
21
276
  if (
22
- target.closest('button') ||
23
- target.closest('a') ||
24
- target.closest('input') ||
25
- target.closest('select') ||
26
- target.closest('textarea') ||
27
- target.closest('[role="button"]') ||
28
277
  target.closest('[data-comment-controls]') ||
29
278
  target.closest('[data-comment-pin]') ||
30
- target.closest('[data-floating-widget]')
279
+ target.closest('[data-floating-widget]') ||
280
+ target.closest('[data-comment-preview]') ||
281
+ target.closest('button[aria-label*="Remove"]') ||
282
+ target.closest('button[aria-label*="Delete"]')
31
283
  ) {
32
- return; // Don't create pin if clicking interactive elements or floating widget
284
+ return; // Don't create pin if clicking comment system UI or remove/delete buttons
285
+ }
286
+
287
+ // Also check if the click originated from within the floating widget
288
+ // This prevents clicks on "Remove pin" button from creating new pins
289
+ if (e.target && (e.target as Element).closest('[data-floating-widget]')) {
290
+ return;
33
291
  }
34
292
 
35
293
  // Get the overlay container dimensions (accounts for drawer being open)
36
294
  if (!overlayRef.current) return;
37
295
  const rect = overlayRef.current.getBoundingClientRect();
38
296
 
39
- // Calculate percentage based on the content area, not the full window
297
+ // Calculate percentage based on the content area, not the full window (used as fallback)
40
298
  const xPercent = ((e.clientX - rect.left) / rect.width) * 100;
41
299
  const yPercent = ((e.clientY - rect.top) / rect.height) * 100;
42
300
 
43
- const threadId = addThread(xPercent, yPercent, location.pathname, detectedVersion);
301
+ // Generate CSS selector for the clicked element
302
+ const clickedElement = target as Element;
303
+ const cssSelector = generateSelectorForElement(clickedElement);
304
+ const elementDescription = getElementDescription(clickedElement);
305
+
306
+ // Extract React component metadata (component-based commenting)
307
+ const componentMetadata = getElementComponentMetadata(clickedElement);
308
+
309
+ const threadId = addThread(cssSelector, elementDescription, componentMetadata, xPercent, yPercent, location.pathname, detectedVersion);
44
310
  setSelectedThreadId(threadId);
45
311
  };
46
312
 
@@ -60,14 +326,15 @@ export const CommentOverlay: React.FunctionComponent = () => {
60
326
  // eslint-disable-next-line react-hooks/exhaustive-deps
61
327
  }, [commentsEnabled, location.pathname, detectedVersion]);
62
328
 
63
- // Only show pins when commenting is enabled
64
- if (!commentsEnabled) {
329
+ // Show pins when comments are enabled OR when showPinsEnabled is true
330
+ if (!commentsEnabled && !showPinsEnabled) {
65
331
  return null;
66
332
  }
67
333
 
68
334
  return (
69
335
  <div
70
336
  ref={overlayRef}
337
+ data-comment-overlay
71
338
  style={{
72
339
  position: 'absolute',
73
340
  top: 0,
@@ -84,6 +351,7 @@ export const CommentOverlay: React.FunctionComponent = () => {
84
351
  {currentThreads.map((thread) => (
85
352
  <CommentPin
86
353
  key={thread.id}
354
+ cssSelector={thread.cssSelector}
87
355
  xPercent={thread.xPercent}
88
356
  yPercent={thread.yPercent}
89
357
  commentCount={thread.comments.length}