proto-plugin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/AGENTS.md +350 -0
  2. package/README.md +279 -0
  3. package/components.json +18 -0
  4. package/package.json +73 -0
  5. package/scripts/download-mobbin-reference-images.mjs +112 -0
  6. package/scripts/lib/host-config.example.sh +48 -0
  7. package/scripts/lib/host-config.sh +25 -0
  8. package/scripts/lib/resolve-host-root.mjs +18 -0
  9. package/scripts/lib/source-path.sh +49 -0
  10. package/scripts/link-source-db.sh +128 -0
  11. package/scripts/link-source.sh +40 -0
  12. package/scripts/publish-package.sh +147 -0
  13. package/scripts/share-prototype.sh +279 -0
  14. package/scripts/sync-from-source.sh +74 -0
  15. package/scripts/verify-prototype-component-ids.mjs +151 -0
  16. package/scripts/verify-prototype-preview-states.mjs +135 -0
  17. package/src/app.ts +4 -0
  18. package/src/components/platform-ui/code-block.tsx +21 -0
  19. package/src/components/platform-ui/controls-panel-options.tsx +71 -0
  20. package/src/components/platform-ui/controls-panel-select.tsx +438 -0
  21. package/src/components/platform-ui/empty-state.tsx +15 -0
  22. package/src/components/platform-ui/icon-button.tsx +18 -0
  23. package/src/components/platform-ui/panel-select.tsx +123 -0
  24. package/src/components/platform-ui/panel.tsx +97 -0
  25. package/src/components/platform-ui/review-dropdown-menu.tsx +35 -0
  26. package/src/components/platform-ui/sidebar.tsx +293 -0
  27. package/src/components/platform-ui/toolbar-icon-button.tsx +34 -0
  28. package/src/components/platform-ui/toolbar.tsx +37 -0
  29. package/src/components/prototype-gallery-client.tsx +57 -0
  30. package/src/components/prototype-provider.tsx +20 -0
  31. package/src/components/prototypes/mini-pill-label.tsx +37 -0
  32. package/src/components/prototypes/prototype-change-log-panel.tsx +207 -0
  33. package/src/components/prototypes/prototype-comment-provider.tsx +61 -0
  34. package/src/components/prototypes/prototype-comment-toolbar.tsx +65 -0
  35. package/src/components/prototypes/prototype-control.tsx +31 -0
  36. package/src/components/prototypes/prototype-controls.tsx +553 -0
  37. package/src/components/prototypes/prototype-create-exploration-modal.tsx +117 -0
  38. package/src/components/prototypes/prototype-create-state-modal.tsx +117 -0
  39. package/src/components/prototypes/prototype-default-state-map-page.tsx +66 -0
  40. package/src/components/prototypes/prototype-design-brief-modal.tsx +128 -0
  41. package/src/components/prototypes/prototype-design-brief-panel.tsx +525 -0
  42. package/src/components/prototypes/prototype-design-context-panel.tsx +65 -0
  43. package/src/components/prototypes/prototype-floating-pill.module.scss +1341 -0
  44. package/src/components/prototypes/prototype-mobbin-gallery.tsx +330 -0
  45. package/src/components/prototypes/prototype-reference-docs.tsx +222 -0
  46. package/src/components/prototypes/prototype-review-chrome.module.scss +630 -0
  47. package/src/components/prototypes/prototype-review-chrome.tsx +1241 -0
  48. package/src/components/prototypes/prototype-review-dropdown-menu-item.tsx +1 -0
  49. package/src/components/prototypes/prototype-review-dropdown-menu-separator.tsx +1 -0
  50. package/src/components/prototypes/prototype-review-panel-menu-item.tsx +1 -0
  51. package/src/components/prototypes/prototype-review-panel-menu-separator.tsx +1 -0
  52. package/src/components/prototypes/prototype-review-panel-select.tsx +4 -0
  53. package/src/components/prototypes/prototype-review-sidebar.tsx +167 -0
  54. package/src/components/prototypes/prototype-share-link-restore.tsx +75 -0
  55. package/src/components/prototypes/prototype-share-mode.tsx +206 -0
  56. package/src/components/prototypes/prototype-spec-panel-content.tsx +538 -0
  57. package/src/components/prototypes/prototype-state-canvas-overlay.module.scss +336 -0
  58. package/src/components/prototypes/prototype-state-canvas-overlay.tsx +1023 -0
  59. package/src/components/prototypes/prototype-state-canvas.tsx +38 -0
  60. package/src/components/prototypes/prototype-state-screenshot-preview.tsx +47 -0
  61. package/src/components/prototypes/prototype-target.tsx +120 -0
  62. package/src/components/prototypes/prototype-tweak-highlight.tsx +132 -0
  63. package/src/components/prototypes/prototype-tweaks.tsx +48 -0
  64. package/src/components/prototypes/prototype-variant-explorer.tsx +347 -0
  65. package/src/components/prototypes/prototype-variant-rationale-panel.tsx +49 -0
  66. package/src/components/prototypes/prototype-variant-tabs.tsx +207 -0
  67. package/src/components/prototypes/prototype-vercel-preview-modal.tsx +120 -0
  68. package/src/components/prototypes/state-map-annotation-tooltip.module.scss +89 -0
  69. package/src/components/prototypes/state-map-annotation-tooltip.tsx +137 -0
  70. package/src/components/prototypes/state-map-wireframe-highlight.module.scss +25 -0
  71. package/src/components/prototypes/state-map-wireframe-highlight.tsx +82 -0
  72. package/src/components/shell/prototype-gallery-shell.tsx +79 -0
  73. package/src/components/shell/prototype-screenshot-capture.tsx +45 -0
  74. package/src/components/shell/prototype-shell.module.scss +194 -0
  75. package/src/components/shell/prototype-shell.tsx +160 -0
  76. package/src/components/shell/prototype-state-screenshot-capture.tsx +68 -0
  77. package/src/components/ui/button.tsx +58 -0
  78. package/src/components/ui/dialog.module.scss +81 -0
  79. package/src/components/ui/dialog.tsx +127 -0
  80. package/src/components/ui/dropdown-menu.tsx +200 -0
  81. package/src/components/ui/input.tsx +22 -0
  82. package/src/components/ui/label.tsx +26 -0
  83. package/src/components/ui/option-select.tsx +81 -0
  84. package/src/components/ui/scroll-area.tsx +48 -0
  85. package/src/components/ui/separator.tsx +31 -0
  86. package/src/components/ui/slider.tsx +28 -0
  87. package/src/components/ui/switch.tsx +29 -0
  88. package/src/components/ui/tabs.tsx +55 -0
  89. package/src/components/ui/toggle-group.tsx +80 -0
  90. package/src/components/ui/tooltip.tsx +32 -0
  91. package/src/config/create-prototype-gallery-page.tsx +65 -0
  92. package/src/config/create-prototype-host-app.tsx +121 -0
  93. package/src/config/create-prototype-page.tsx +41 -0
  94. package/src/config/create-prototype-site-layout.tsx +28 -0
  95. package/src/config/define-prototype-config.ts +7 -0
  96. package/src/config/prototype-icon.tsx +25 -0
  97. package/src/config/prototype-site-layout-client.tsx +35 -0
  98. package/src/config/with-prototype.ts +20 -0
  99. package/src/index.ts +303 -0
  100. package/src/lib/pr-split/build-pr-agent-prompt.ts +68 -0
  101. package/src/lib/pr-split/build-pr-split-prototype-url.ts +12 -0
  102. package/src/lib/pr-split/pr-split-highlight.ts +6 -0
  103. package/src/lib/pr-split/pr-split-types.ts +58 -0
  104. package/src/lib/pr-split/resolve-source-preview-url.ts +45 -0
  105. package/src/lib/pr-split/use-pr-vercel-previews.ts +69 -0
  106. package/src/lib/prototype-comments/core/annotation-channel.ts +41 -0
  107. package/src/lib/prototype-comments/core/annotation-status.ts +60 -0
  108. package/src/lib/prototype-comments/core/annotation-target.ts +567 -0
  109. package/src/lib/prototype-comments/core/capture-theme.ts +41 -0
  110. package/src/lib/prototype-comments/core/capture.ts +11 -0
  111. package/src/lib/prototype-comments/core/comment-capture-blocked.ts +47 -0
  112. package/src/lib/prototype-comments/core/comment-threads.ts +52 -0
  113. package/src/lib/prototype-comments/core/element-identification.ts +615 -0
  114. package/src/lib/prototype-comments/core/export.ts +35 -0
  115. package/src/lib/prototype-comments/core/freeze-animations.ts +266 -0
  116. package/src/lib/prototype-comments/core/identify-element.ts +76 -0
  117. package/src/lib/prototype-comments/core/normalize-viewport.ts +35 -0
  118. package/src/lib/prototype-comments/core/react-detection.ts +704 -0
  119. package/src/lib/prototype-comments/core/restore.ts +7 -0
  120. package/src/lib/prototype-comments/core/screenshot.ts +428 -0
  121. package/src/lib/prototype-comments/core/source-location.ts +906 -0
  122. package/src/lib/prototype-comments/core/storage.ts +80 -0
  123. package/src/lib/prototype-comments/core/types.ts +79 -0
  124. package/src/lib/prototype-comments/core/validation.ts +17 -0
  125. package/src/lib/prototype-comments/hooks/useLayoutShift.ts +61 -0
  126. package/src/lib/prototype-comments/index.ts +58 -0
  127. package/src/lib/prototype-comments/react/CommentCaptureToolbar.tsx +1398 -0
  128. package/src/lib/prototype-comments/react/CommentProvider.tsx +298 -0
  129. package/src/lib/prototype-comments/scss.d.ts +10 -0
  130. package/src/lib/prototype-comments/ui/CommentAnnotationOverlay.tsx +253 -0
  131. package/src/lib/prototype-comments/ui/CommentDetailPage.tsx +56 -0
  132. package/src/lib/prototype-comments/ui/CommentHeaderCount.tsx +28 -0
  133. package/src/lib/prototype-comments/ui/CommentThread.tsx +331 -0
  134. package/src/lib/prototype-comments/ui/CommentsGrid.tsx +780 -0
  135. package/src/lib/prototype-comments/ui/CommentsListPage.tsx +25 -0
  136. package/src/lib/prototype-comments/ui/CommentsSidebar.tsx +77 -0
  137. package/src/lib/prototype-comments/ui/annotation-marker/index.tsx +200 -0
  138. package/src/lib/prototype-comments/ui/annotation-marker/styles.module.scss +194 -0
  139. package/src/lib/prototype-comments/ui/annotation-popup/index.tsx +335 -0
  140. package/src/lib/prototype-comments/ui/annotation-popup/styles.module.scss +469 -0
  141. package/src/lib/prototype-comments/ui/capture-styles.module.scss +2225 -0
  142. package/src/lib/prototype-comments/ui/comment-highlight.ts +48 -0
  143. package/src/lib/prototype-comments/ui/comment-thread.module.scss +203 -0
  144. package/src/lib/prototype-comments/ui/comments-grid-card.module.scss +253 -0
  145. package/src/lib/prototype-comments/ui/comments-sidebar.module.scss +123 -0
  146. package/src/lib/prototype-comments/ui/icon-transitions.module.scss +51 -0
  147. package/src/lib/prototype-comments/ui/icons.tsx +1086 -0
  148. package/src/lib/prototype-comments/ui/is-comment-detail-path.ts +7 -0
  149. package/src/lib/prototypes/capture-prototype-viewport.ts +32 -0
  150. package/src/lib/prototypes/changelog-meta-context.tsx +162 -0
  151. package/src/lib/prototypes/changelog-meta-storage.ts +62 -0
  152. package/src/lib/prototypes/changelog-meta.ts +95 -0
  153. package/src/lib/prototypes/create-prototype-registry.ts +74 -0
  154. package/src/lib/prototypes/create-state-screenshot-thumbnail.ts +46 -0
  155. package/src/lib/prototypes/design-exploration-default-storage.ts +68 -0
  156. package/src/lib/prototypes/design-exploration-default.ts +51 -0
  157. package/src/lib/prototypes/design-exploration-types.ts +203 -0
  158. package/src/lib/prototypes/prototype-comment-registry.tsx +145 -0
  159. package/src/lib/prototypes/prototype-comment-review-bridge.tsx +40 -0
  160. package/src/lib/prototypes/prototype-comment-review-state.ts +57 -0
  161. package/src/lib/prototypes/prototype-component-registry.ts +40 -0
  162. package/src/lib/prototypes/prototype-config-types.ts +34 -0
  163. package/src/lib/prototypes/prototype-preview-state-registry.ts +443 -0
  164. package/src/lib/prototypes/prototype-preview-state-types.ts +89 -0
  165. package/src/lib/prototypes/prototype-review-context.tsx +905 -0
  166. package/src/lib/prototypes/prototype-review-url.ts +134 -0
  167. package/src/lib/prototypes/prototype-share-link.ts +175 -0
  168. package/src/lib/prototypes/prototype-state-canvas-constants.ts +118 -0
  169. package/src/lib/prototypes/prototype-state-canvas-types.ts +159 -0
  170. package/src/lib/prototypes/prototype-state-screenshot.ts +39 -0
  171. package/src/lib/prototypes/prototype-tweak-registry.ts +96 -0
  172. package/src/lib/prototypes/prototype-tweak-types.ts +31 -0
  173. package/src/lib/prototypes/reference-docs.ts +137 -0
  174. package/src/lib/prototypes/screenshot-manifest.ts +33 -0
  175. package/src/lib/prototypes/screenshot-src.ts +7 -0
  176. package/src/lib/prototypes/share-command.ts +8 -0
  177. package/src/lib/prototypes/state-map-annotation.ts +70 -0
  178. package/src/lib/prototypes/use-design-exploration-default.ts +114 -0
  179. package/src/lib/prototypes/use-persisted-local-state.ts +140 -0
  180. package/src/lib/prototypes/use-prototype-comments.ts +63 -0
  181. package/src/lib/prototypes/use-prototype-mobile-viewport-frame.ts +46 -0
  182. package/src/lib/prototypes/use-prototype-state-screenshot-src.ts +71 -0
  183. package/src/lib/prototypes/use-prototype-tool-theme.tsx +115 -0
  184. package/src/lib/prototypes/use-prototype-viewport-frame.ts +34 -0
  185. package/src/lib/prototypes/use-register-prototype-reference-docs.ts +16 -0
  186. package/src/lib/prototypes/use-snap-corner-position.ts +417 -0
  187. package/src/lib/prototypes/use-toolbar-hover-panel.ts +98 -0
  188. package/src/lib/prototypes/variant-set-lucide-icon.tsx +55 -0
  189. package/src/lib/tool-portal.ts +33 -0
  190. package/src/lib/use-copy-to-clipboard.ts +81 -0
  191. package/src/lib/utils.ts +6 -0
  192. package/src/lib/vercel-preview/parse-vercel-github-comment.ts +81 -0
  193. package/src/server/create-host-api-route.ts +100 -0
  194. package/src/server/create-prototype-api-routes.ts +428 -0
  195. package/src/server/gallery/create-gallery-api.ts +56 -0
  196. package/src/server/gallery/folders-route.ts +156 -0
  197. package/src/server/gallery/gallery-env.ts +39 -0
  198. package/src/server/gallery/gallery-route.ts +150 -0
  199. package/src/server/gallery/gallery-types.ts +15 -0
  200. package/src/server/gallery/image-route.ts +59 -0
  201. package/src/server/gallery/item-route.ts +92 -0
  202. package/src/server/pr-vercel-preview-route.ts +162 -0
  203. package/src/server/redis/client.ts +55 -0
  204. package/src/server/redis/prototype-changelog-meta.ts +31 -0
  205. package/src/server/redis/prototype-comments.ts +92 -0
  206. package/src/server/redis/prototype-design-exploration-default.ts +32 -0
  207. package/src/server.ts +51 -0
  208. package/src/styles/globals.css +624 -0
  209. package/tsconfig.json +19 -0
@@ -0,0 +1,48 @@
1
+ import type { AnnotationBoundingBox, CommentAnnotationFields } from "../core/types";
2
+
3
+ type HighlightInput = Pick<
4
+ CommentAnnotationFields,
5
+ "viewportBoundingBox" | "boundingBox" | "isFixed" | "captureViewport"
6
+ >;
7
+
8
+ export function getViewportBoundingBox(annotation: HighlightInput): AnnotationBoundingBox | null {
9
+ if (annotation.viewportBoundingBox) {
10
+ return annotation.viewportBoundingBox;
11
+ }
12
+
13
+ if (!annotation.boundingBox) return null;
14
+
15
+ if (annotation.isFixed) {
16
+ return annotation.boundingBox;
17
+ }
18
+
19
+ if (annotation.captureViewport) {
20
+ return {
21
+ x: annotation.boundingBox.x,
22
+ y: annotation.boundingBox.y - annotation.captureViewport.scrollY,
23
+ width: annotation.boundingBox.width,
24
+ height: annotation.boundingBox.height,
25
+ };
26
+ }
27
+
28
+ return null;
29
+ }
30
+
31
+ export function getCaptureAspectRatio(
32
+ annotation: Pick<CommentAnnotationFields, "captureViewport">,
33
+ ): string | undefined {
34
+ const viewport = annotation.captureViewport;
35
+ if (!viewport?.width || !viewport?.height) return undefined;
36
+ return `${viewport.width} / ${viewport.height}`;
37
+ }
38
+
39
+ /** Centers the screenshot crop on the annotated element (sidebar card previews). */
40
+ export function getScreenshotObjectPosition(
41
+ annotation: HighlightInput & Pick<CommentAnnotationFields, "captureViewport">,
42
+ ): string {
43
+ const box = getViewportBoundingBox(annotation);
44
+ const viewport = annotation.captureViewport;
45
+ if (!box || !viewport?.height) return "top";
46
+ const centerY = ((box.y + box.height / 2) / viewport.height) * 100;
47
+ return `50% ${centerY}%`;
48
+ }
@@ -0,0 +1,203 @@
1
+ .threadPanel {
2
+ padding: 0.625rem 0.875rem 0.75rem;
3
+ border-radius: 0 0 16px 16px;
4
+ margin-top: -6px;
5
+ background: #fff;
6
+ box-shadow:
7
+ 0 4px 24px rgba(0, 0, 0, 0.12),
8
+ 0 0 0 1px rgba(0, 0, 0, 0.06);
9
+ }
10
+
11
+ .threadPanelDark {
12
+ padding: 0.625rem 0.875rem 0.75rem;
13
+ border-radius: 0 0 16px 16px;
14
+ margin-top: -6px;
15
+ background: #1e1e1e;
16
+ box-shadow:
17
+ 0 4px 20px rgba(0, 0, 0, 0.35),
18
+ 0 8px 32px rgba(0, 0, 0, 0.18),
19
+ 0 0 0 1px #333333;
20
+ }
21
+
22
+ .replies {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: 0.5rem;
26
+ padding-left: 0.625rem;
27
+ border-left: 2px solid var(--border-solid, rgba(0, 0, 0, 0.08));
28
+ }
29
+
30
+ .repliesDark {
31
+ border-left-color: rgba(255, 255, 255, 0.12);
32
+ }
33
+
34
+ .replyRow {
35
+ position: relative;
36
+ padding-right: 3.25rem;
37
+ }
38
+
39
+ .replyMeta {
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: space-between;
43
+ gap: 0.5rem;
44
+ font-size: 0.6875rem;
45
+ color: var(--text-tertiary, rgba(0, 0, 0, 0.45));
46
+ margin-bottom: 0.125rem;
47
+ }
48
+
49
+ .replyMetaDark {
50
+ color: rgba(255, 255, 255, 0.45);
51
+ }
52
+
53
+ .replyText {
54
+ font-size: 0.8125rem;
55
+ line-height: 1.45;
56
+ color: var(--text-secondary, rgba(0, 0, 0, 0.7));
57
+ margin: 0;
58
+ }
59
+
60
+ .replyTextDark {
61
+ color: rgba(255, 255, 255, 0.75);
62
+ }
63
+
64
+ .rowActions {
65
+ position: absolute;
66
+ top: 0;
67
+ right: 0;
68
+ display: flex;
69
+ gap: 0.25rem;
70
+ opacity: 0;
71
+ pointer-events: none;
72
+ transition: opacity 0.15s ease;
73
+ }
74
+
75
+ .replyRow:hover .rowActions,
76
+ .replyRow:focus-within .rowActions,
77
+ .rowActionsVisible {
78
+ opacity: 1;
79
+ pointer-events: auto;
80
+ }
81
+
82
+ .iconBtn {
83
+ width: 1.5rem;
84
+ height: 1.5rem;
85
+ border-radius: 0.375rem;
86
+ border: 1px solid var(--border-solid, rgba(0, 0, 0, 0.1));
87
+ background: var(--bg-main, #fff);
88
+ color: var(--text-secondary, rgba(0, 0, 0, 0.55));
89
+ cursor: pointer;
90
+ display: flex;
91
+ align-items: center;
92
+ justify-content: center;
93
+ padding: 0;
94
+ box-shadow: var(--shadow-xs, 0 1px 2px rgba(0, 0, 0, 0.06));
95
+
96
+ &:hover {
97
+ border-color: var(--border-medium, rgba(0, 0, 0, 0.16));
98
+ color: var(--text-primary, rgba(0, 0, 0, 0.85));
99
+ }
100
+ }
101
+
102
+ .iconBtnDark {
103
+ background: rgba(255, 255, 255, 0.06);
104
+ border-color: rgba(255, 255, 255, 0.12);
105
+ color: rgba(255, 255, 255, 0.55);
106
+ box-shadow: none;
107
+
108
+ &:hover {
109
+ background: rgba(255, 255, 255, 0.1);
110
+ color: rgba(255, 255, 255, 0.9);
111
+ }
112
+ }
113
+
114
+ .iconBtnDanger:hover {
115
+ color: var(--error, #dc2626);
116
+ border-color: color-mix(in srgb, var(--error, #dc2626) 35%, transparent);
117
+ }
118
+
119
+ .textarea {
120
+ font-size: 0.8125rem;
121
+ line-height: 1.45;
122
+ color: var(--text-primary, #e0e0e0);
123
+ border: 1px solid var(--border-medium, rgba(0, 0, 0, 0.12));
124
+ border-radius: 0.375rem;
125
+ padding: 0.375rem 0.5rem;
126
+ outline: none;
127
+ resize: none;
128
+ width: 100%;
129
+ font-family: inherit;
130
+ box-sizing: border-box;
131
+ background: var(--bg-main, #fff);
132
+ min-height: 3.25rem;
133
+ }
134
+
135
+ .textareaDark {
136
+ background: rgba(255, 255, 255, 0.05);
137
+ color: #fff;
138
+ border-color: rgba(255, 255, 255, 0.15);
139
+ }
140
+
141
+ .rowComposerActions,
142
+ .composerActions {
143
+ display: flex;
144
+ justify-content: flex-end;
145
+ gap: 0.375rem;
146
+ margin-top: 0.375rem;
147
+ }
148
+
149
+ .secondaryBtn,
150
+ .primaryBtn {
151
+ font-size: 0.75rem;
152
+ padding: 0.25rem 0.5rem;
153
+ border-radius: 0.375rem;
154
+ cursor: pointer;
155
+ }
156
+
157
+ .secondaryBtn {
158
+ border: 1px solid var(--border-solid, rgba(0, 0, 0, 0.1));
159
+ background: var(--bg-main, #fff);
160
+ color: var(--text-secondary, rgba(0, 0, 0, 0.55));
161
+ }
162
+
163
+ .primaryBtn {
164
+ border: none;
165
+ background: var(--color-active, #3c82f7);
166
+ color: var(--text-on-active, #fff);
167
+
168
+ &:disabled {
169
+ opacity: 0.5;
170
+ cursor: default;
171
+ }
172
+ }
173
+
174
+ .replyLink {
175
+ align-self: flex-start;
176
+ font-size: 0.75rem;
177
+ font-weight: 500;
178
+ color: var(--text-secondary, rgba(0, 0, 0, 0.55));
179
+ background: none;
180
+ border: none;
181
+ padding: 0;
182
+ cursor: pointer;
183
+ text-decoration: underline;
184
+ text-underline-offset: 2px;
185
+
186
+ &:hover {
187
+ color: var(--text-primary, rgba(0, 0, 0, 0.85));
188
+ }
189
+ }
190
+
191
+ .replyLinkDark {
192
+ color: rgba(255, 255, 255, 0.55);
193
+
194
+ &:hover {
195
+ color: rgba(255, 255, 255, 0.9);
196
+ }
197
+ }
198
+
199
+ .root {
200
+ display: flex;
201
+ flex-direction: column;
202
+ gap: 0.5rem;
203
+ }
@@ -0,0 +1,253 @@
1
+ .card {
2
+ display: flex;
3
+ flex-direction: column;
4
+ position: relative;
5
+ border-radius: 6px;
6
+ overflow: hidden;
7
+ cursor: pointer;
8
+ transition:
9
+ border-color 0.2s cubic-bezier(0.215, 0.61, 0.355, 1),
10
+ background 0.2s cubic-bezier(0.215, 0.61, 0.355, 1),
11
+ opacity 0.25s cubic-bezier(0.215, 0.61, 0.355, 1);
12
+ }
13
+
14
+ .cardSidebar {
15
+ border-radius: 0.375rem;
16
+ }
17
+
18
+ .cardResolved {
19
+ opacity: 0.72;
20
+ }
21
+
22
+ .screenshotCollapse {
23
+ display: grid;
24
+ grid-template-rows: 1fr;
25
+ transition: grid-template-rows 0.28s cubic-bezier(0.215, 0.61, 0.355, 1);
26
+ }
27
+
28
+ .cardCondensed .screenshotCollapse {
29
+ grid-template-rows: 0fr;
30
+ }
31
+
32
+ .screenshotInner {
33
+ min-height: 0;
34
+ overflow: hidden;
35
+ }
36
+
37
+ .screenshot {
38
+ position: relative;
39
+ overflow: hidden;
40
+ background: var(--bg-subtle);
41
+ border-bottom: 1px solid var(--border-solid);
42
+ transition: border-color 0.2s cubic-bezier(0.215, 0.61, 0.355, 1);
43
+ }
44
+
45
+ .screenshotImgSidebar {
46
+ display: block;
47
+ width: 100%;
48
+ height: auto;
49
+ max-height: 220px;
50
+ }
51
+
52
+ .cardCondensed .screenshot {
53
+ border-bottom-color: transparent;
54
+ }
55
+
56
+ .body {
57
+ display: flex;
58
+ flex-direction: row;
59
+ align-items: flex-start;
60
+ gap: 0;
61
+ padding: 6px 12px 10px;
62
+ flex: 1;
63
+ min-width: 0;
64
+ transition:
65
+ flex-direction 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
66
+ align-items 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
67
+ gap 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
68
+ padding 0.28s cubic-bezier(0.215, 0.61, 0.355, 1);
69
+ }
70
+
71
+ .cardCondensed .body {
72
+ flex-direction: row;
73
+ align-items: center;
74
+ gap: 8px;
75
+ padding: 6px 56px 6px 10px;
76
+ min-height: 40px;
77
+ }
78
+
79
+ .statusIcon {
80
+ display: none;
81
+ flex-shrink: 0;
82
+ align-items: center;
83
+ justify-content: center;
84
+ width: 14px;
85
+ color: var(--success);
86
+ }
87
+
88
+ .cardCondensed .statusIcon {
89
+ display: flex;
90
+ margin-right: 8px;
91
+ }
92
+
93
+ .bodyMain {
94
+ display: flex;
95
+ flex-direction: column;
96
+ gap: 4px;
97
+ flex: 1;
98
+ min-width: 0;
99
+ transition: gap 0.28s cubic-bezier(0.215, 0.61, 0.355, 1);
100
+ }
101
+
102
+ .cardCondensed .bodyMain {
103
+ flex-direction: row;
104
+ align-items: center;
105
+ gap: 8px;
106
+ }
107
+
108
+ .comment {
109
+ margin: 0;
110
+ font-size: 14px;
111
+ line-height: 1.5;
112
+ color: var(--text-primary);
113
+ display: -webkit-box;
114
+ -webkit-box-orient: vertical;
115
+ -webkit-line-clamp: 3;
116
+ overflow: hidden;
117
+ transition:
118
+ font-size 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
119
+ line-height 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
120
+ color 0.2s ease,
121
+ -webkit-line-clamp 0.28s cubic-bezier(0.215, 0.61, 0.355, 1);
122
+ }
123
+
124
+ .commentExpanded {
125
+ display: block;
126
+ -webkit-line-clamp: unset;
127
+ overflow: visible;
128
+ overflow-wrap: anywhere;
129
+ }
130
+
131
+ .cardCondensed .comment {
132
+ font-size: 13px;
133
+ line-height: 1.35;
134
+ color: var(--text-secondary);
135
+ -webkit-line-clamp: 1;
136
+ display: block;
137
+ white-space: nowrap;
138
+ text-overflow: ellipsis;
139
+ text-decoration: line-through;
140
+ }
141
+
142
+ .cardCondensed .commentExpanded {
143
+ white-space: normal;
144
+ text-overflow: unset;
145
+ -webkit-line-clamp: unset;
146
+ }
147
+
148
+ .resolvedBadgeCollapse {
149
+ display: grid;
150
+ grid-template-rows: 0fr;
151
+ transition: grid-template-rows 0.28s cubic-bezier(0.215, 0.61, 0.355, 1);
152
+ }
153
+
154
+ .resolvedBadgeCollapseExpanded {
155
+ grid-template-rows: 1fr;
156
+ }
157
+
158
+ .cardCondensed .resolvedBadgeCollapse {
159
+ grid-template-rows: 0fr;
160
+ }
161
+
162
+ .resolvedBadgeInner {
163
+ min-height: 0;
164
+ overflow: hidden;
165
+ }
166
+
167
+ .threadCollapse {
168
+ display: grid;
169
+ grid-template-rows: 1fr;
170
+ transition: grid-template-rows 0.28s cubic-bezier(0.215, 0.61, 0.355, 1);
171
+ }
172
+
173
+ .cardCondensed .threadCollapse {
174
+ grid-template-rows: 0fr;
175
+ }
176
+
177
+ .threadInner {
178
+ min-height: 0;
179
+ overflow: hidden;
180
+ }
181
+
182
+ .replyCount {
183
+ flex-shrink: 0;
184
+ font-size: 11px;
185
+ color: var(--text-tertiary);
186
+ max-width: 0;
187
+ opacity: 0;
188
+ overflow: hidden;
189
+ white-space: nowrap;
190
+ transition:
191
+ max-width 0.28s cubic-bezier(0.215, 0.61, 0.355, 1),
192
+ opacity 0.2s cubic-bezier(0.215, 0.61, 0.355, 1);
193
+ }
194
+
195
+ .cardCondensed .replyCountVisible {
196
+ max-width: 80px;
197
+ opacity: 1;
198
+ }
199
+
200
+ .actions {
201
+ position: absolute;
202
+ top: 8px;
203
+ right: 8px;
204
+ display: flex;
205
+ gap: 4px;
206
+ z-index: 2;
207
+ transition:
208
+ gap 0.25s cubic-bezier(0.215, 0.61, 0.355, 1),
209
+ opacity 0.15s ease;
210
+ }
211
+
212
+ .cardCondensed .actions {
213
+ gap: 3px;
214
+ }
215
+
216
+ .secondaryAction {
217
+ display: flex;
218
+ overflow: hidden;
219
+ max-width: 28px;
220
+ opacity: 1;
221
+ transition:
222
+ max-width 0.25s cubic-bezier(0.215, 0.61, 0.355, 1),
223
+ opacity 0.2s cubic-bezier(0.215, 0.61, 0.355, 1),
224
+ margin 0.25s cubic-bezier(0.215, 0.61, 0.355, 1);
225
+ }
226
+
227
+ .cardCondensed .secondaryAction {
228
+ max-width: 0;
229
+ opacity: 0;
230
+ margin: 0;
231
+ pointer-events: none;
232
+ }
233
+
234
+ .actionBtnCompact {
235
+ width: 24px !important;
236
+ height: 24px !important;
237
+ border-radius: 5px !important;
238
+ }
239
+
240
+ @media (prefers-reduced-motion: reduce) {
241
+ .card,
242
+ .screenshotCollapse,
243
+ .body,
244
+ .statusIcon,
245
+ .comment,
246
+ .resolvedBadgeCollapse,
247
+ .threadCollapse,
248
+ .replyCount,
249
+ .actions,
250
+ .secondaryAction {
251
+ transition: none;
252
+ }
253
+ }
@@ -0,0 +1,123 @@
1
+ .sidebar {
2
+ position: relative;
3
+ display: flex;
4
+ flex-direction: column;
5
+ flex-shrink: 0;
6
+ width: 0;
7
+ max-width: min(var(--sidebar-width, var(--comments-sidebar-width, 400px)), 100vw);
8
+ height: 100%;
9
+ overflow: hidden;
10
+ background: var(--bg-main);
11
+ border-left: 1px solid transparent;
12
+ color: var(--text-primary);
13
+ transition:
14
+ width 0.25s cubic-bezier(0.32, 0.72, 0, 1),
15
+ border-color 0.25s cubic-bezier(0.32, 0.72, 0, 1);
16
+
17
+ &.open {
18
+ width: min(var(--sidebar-width, var(--comments-sidebar-width, 400px)), 100vw);
19
+ border-left-color: var(--border-solid);
20
+ }
21
+
22
+ &.resizing {
23
+ transition: none;
24
+ user-select: none;
25
+ }
26
+ }
27
+
28
+ .resizeHandle {
29
+ position: absolute;
30
+ top: 0;
31
+ left: -4px;
32
+ z-index: 1;
33
+ width: 8px;
34
+ height: 100%;
35
+ cursor: col-resize;
36
+ touch-action: none;
37
+
38
+ &::before {
39
+ content: "";
40
+ position: absolute;
41
+ top: 0;
42
+ left: 3px;
43
+ width: 2px;
44
+ height: 100%;
45
+ background: transparent;
46
+ transition: background 0.15s;
47
+ }
48
+
49
+ @media (hover: hover) and (pointer: fine) {
50
+ &:hover::before {
51
+ background: var(--border-medium);
52
+ }
53
+ }
54
+
55
+ .sidebar.resizing &::before {
56
+ background: var(--border-medium);
57
+ }
58
+ }
59
+
60
+ .header {
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: space-between;
64
+ gap: 12px;
65
+ min-width: min(var(--sidebar-width, var(--comments-sidebar-width, 400px)), 100vw);
66
+ padding: 16px 16px 12px;
67
+ border-bottom: 1px solid var(--border-solid);
68
+ flex-shrink: 0;
69
+ }
70
+
71
+ .title {
72
+ margin: 0;
73
+ font-size: 15px;
74
+ font-weight: 600;
75
+ letter-spacing: -0.01em;
76
+ }
77
+
78
+ .count {
79
+ margin-left: 6px;
80
+ font-size: 13px;
81
+ font-weight: 500;
82
+ color: var(--text-tertiary);
83
+ }
84
+
85
+ .headerActions {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 4px;
89
+ flex-shrink: 0;
90
+ }
91
+
92
+ .headerButton {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ width: 32px;
97
+ height: 32px;
98
+ border: none;
99
+ border-radius: 8px;
100
+ background: transparent;
101
+ color: var(--text-secondary);
102
+ cursor: pointer;
103
+ transition: background 0.15s, color 0.15s;
104
+
105
+ @media (hover: hover) and (pointer: fine) {
106
+ &:hover {
107
+ background: var(--bg-layered);
108
+ color: var(--text-primary);
109
+ }
110
+ }
111
+ }
112
+
113
+ .headerButtonActive {
114
+ background: color-mix(in srgb, var(--color-active) 12%, transparent);
115
+ color: var(--color-active);
116
+ }
117
+
118
+ .content {
119
+ flex: 1;
120
+ min-width: min(var(--sidebar-width, var(--comments-sidebar-width, 400px)), 100vw);
121
+ overflow-y: auto;
122
+ padding: 12px 12px 24px;
123
+ }
@@ -0,0 +1,51 @@
1
+ // Scoped icon transition classes.
2
+ // Replaces inline <style> tags that injected global class names (e.g. .copy-icon)
3
+ // which could conflict with host page styles. CSS module class names are hashed,
4
+ // so they're immune to host CSS collisions.
5
+ // Using !important ensures host rules like `svg * { opacity: 1 !important }` can't
6
+ // force both icon states visible simultaneously (class specificity 0,1,0 beats
7
+ // element selectors like `svg *` at 0,0,1 even when both use !important).
8
+ // See: https://github.com/prototype-comments/issues/58
9
+
10
+ // Opacity + transform transitions (copy, send icons)
11
+ .iconState {
12
+ transition: opacity 0.2s ease, transform 0.2s ease;
13
+ transform-origin: center;
14
+ }
15
+
16
+ .iconStateFast {
17
+ transition: opacity 0.15s ease, transform 0.15s ease;
18
+ transform-origin: center;
19
+ }
20
+
21
+ // Opacity-only transitions (eye, pause/play icons)
22
+ .iconFade {
23
+ transition: opacity 0.2s ease;
24
+ }
25
+
26
+ .iconFadeFast {
27
+ transition: opacity 0.15s ease;
28
+ }
29
+
30
+ .visible {
31
+ opacity: 1 !important;
32
+ }
33
+
34
+ .visibleScaled {
35
+ opacity: 1 !important;
36
+ transform: scale(1);
37
+ }
38
+
39
+ .hidden {
40
+ opacity: 0 !important;
41
+ }
42
+
43
+ .hiddenScaled {
44
+ opacity: 0 !important;
45
+ transform: scale(0.8);
46
+ }
47
+
48
+ .sending {
49
+ opacity: 0.5 !important;
50
+ transform: scale(0.8);
51
+ }