@opengeni/react 1.0.1 → 2.2.0-canary.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 (174) hide show
  1. package/README.md +33 -10
  2. package/dist/artifacts-spreadsheet.js +1 -1
  3. package/dist/artifacts.js +1 -1
  4. package/dist/browser-viewer-GXUICIAG.js +14 -0
  5. package/dist/{chunk-R3AZOAB5.js → chunk-4MDLEHXL.js} +9 -115
  6. package/dist/chunk-4MDLEHXL.js.map +1 -0
  7. package/dist/{chunk-Y7OEDUJ5.js → chunk-5RZN3DD5.js} +1014 -420
  8. package/dist/chunk-5RZN3DD5.js.map +1 -0
  9. package/dist/chunk-5YK2ZDIG.js +116 -0
  10. package/dist/chunk-5YK2ZDIG.js.map +1 -0
  11. package/dist/chunk-H5YGYNXS.js +329 -0
  12. package/dist/chunk-H5YGYNXS.js.map +1 -0
  13. package/dist/{chunk-7WCLAEFV.js → chunk-ICA6R6TW.js} +2 -2
  14. package/dist/{chunk-7WCLAEFV.js.map → chunk-ICA6R6TW.js.map} +1 -1
  15. package/dist/{chunk-IGC6A2ZI.js → chunk-JOAVA2TW.js} +589 -217
  16. package/dist/chunk-JOAVA2TW.js.map +1 -0
  17. package/dist/{chunk-5UQPNLIO.js → chunk-LTCHJ4MS.js} +9 -9
  18. package/dist/chunk-LTCHJ4MS.js.map +1 -0
  19. package/dist/{chunk-C5ZPSSS5.js → chunk-NEXLLTP4.js} +2 -1
  20. package/dist/{chunk-C5ZPSSS5.js.map → chunk-NEXLLTP4.js.map} +1 -1
  21. package/dist/chunk-QGBJ6GHG.js +2300 -0
  22. package/dist/chunk-QGBJ6GHG.js.map +1 -0
  23. package/dist/{chunk-B6WPZSTT.js → chunk-UOLJWT5Y.js} +78 -16
  24. package/dist/chunk-UOLJWT5Y.js.map +1 -0
  25. package/dist/{chunk-MKPIAGVL.js → chunk-W6NFJXSA.js} +8 -19
  26. package/dist/chunk-W6NFJXSA.js.map +1 -0
  27. package/dist/{chunk-XBZWOM2K.js → chunk-X4A66EWZ.js} +8 -3
  28. package/dist/chunk-X4A66EWZ.js.map +1 -0
  29. package/dist/chunk-X4JAFD5R.js +3907 -0
  30. package/dist/chunk-X4JAFD5R.js.map +1 -0
  31. package/dist/{chunk-6KLX2RH5.js → chunk-XSA2QAKP.js} +334 -19
  32. package/dist/chunk-XSA2QAKP.js.map +1 -0
  33. package/dist/{chunk-HA46CYQK.js → chunk-XXWH2JLC.js} +792 -206
  34. package/dist/chunk-XXWH2JLC.js.map +1 -0
  35. package/dist/client.d.ts +2 -2
  36. package/dist/components/browser-viewer.d.ts +7 -1
  37. package/dist/components/computer-viewer.d.ts +4 -1
  38. package/dist/components/enrollment-consent.d.ts +6 -3
  39. package/dist/components/file-browser.d.ts +7 -1
  40. package/dist/components/human-input-form.d.ts +1 -1
  41. package/dist/components/human-input-surface.d.ts +1 -1
  42. package/dist/components/machine-card.d.ts +4 -1
  43. package/dist/components/machines/machine-detail.d.ts +4 -1
  44. package/dist/components/machines/machine-operation-policy.d.ts +11 -0
  45. package/dist/components/machines-dashboard.d.ts +3 -1
  46. package/dist/components/markdown.d.ts +20 -1
  47. package/dist/components/message-timeline.d.ts +1 -1
  48. package/dist/components/model-policy-picker.d.ts +2 -0
  49. package/dist/components/pierre-file.d.ts +1 -1
  50. package/dist/components/sandbox-files.d.ts +8 -2
  51. package/dist/components/sandbox-workspace.d.ts +33 -3
  52. package/dist/components/session-chrome.d.ts +15 -3
  53. package/dist/components/workspace-dock.d.ts +6 -2
  54. package/dist/composer.js +5 -5
  55. package/dist/computer-viewer-ZOP4Q7A7.js +16 -0
  56. package/dist/computer-viewer-ZOP4Q7A7.js.map +1 -0
  57. package/dist/hooks/channel-cache.d.ts +23 -0
  58. package/dist/hooks/shared-machines-list.d.ts +14 -0
  59. package/dist/hooks/use-attached-browsers.d.ts +2 -1
  60. package/dist/hooks/use-channels.d.ts +1 -0
  61. package/dist/hooks/use-composer.d.ts +37 -9
  62. package/dist/hooks/use-machine-chip.d.ts +3 -3
  63. package/dist/hooks/use-machines.d.ts +19 -1
  64. package/dist/hooks/use-sandbox-files.d.ts +1 -0
  65. package/dist/hooks/use-session-background-commands.d.ts +14 -0
  66. package/dist/hooks/use-turn-queue.d.ts +12 -0
  67. package/dist/hooks/use-workspace-sessions.d.ts +1 -0
  68. package/dist/index.d.ts +7 -5
  69. package/dist/index.js +1096 -623
  70. package/dist/index.js.map +1 -1
  71. package/dist/interaction.js +29 -181
  72. package/dist/interaction.js.map +1 -1
  73. package/dist/lib/interaction-errors.d.ts +3 -0
  74. package/dist/machines.d.ts +4 -2
  75. package/dist/machines.js +10 -2
  76. package/dist/model-policy.d.ts +1 -1
  77. package/dist/model-policy.js +1 -1
  78. package/dist/platform-activity-row-BJHUHXAT.js +169 -0
  79. package/dist/platform-activity-row-BJHUHXAT.js.map +1 -0
  80. package/dist/{queue-surface-implementation-2KVJTYXH.js → queue-surface-implementation-BSKUWHRI.js} +76 -16
  81. package/dist/queue-surface-implementation-BSKUWHRI.js.map +1 -0
  82. package/dist/realtime/realtime-control.d.ts +6 -3
  83. package/dist/realtime.js +36 -14
  84. package/dist/realtime.js.map +1 -1
  85. package/dist/session-ui.d.ts +1 -1
  86. package/dist/session-ui.js +6 -2
  87. package/dist/session.d.ts +2 -2
  88. package/dist/session.js +4 -4
  89. package/dist/timeline/index.d.ts +1 -1
  90. package/dist/timeline/platform-activity-row.d.ts +15 -0
  91. package/dist/timeline/screenshot-lightbox.d.ts +1 -1
  92. package/dist/timeline/shared.d.ts +4 -2
  93. package/dist/timeline/types.d.ts +48 -5
  94. package/dist/types/machines.d.ts +2 -2
  95. package/package.json +3 -3
  96. package/src/client.ts +12 -1
  97. package/src/components/artifacts/editable-spreadsheet.tsx +1 -1
  98. package/src/components/browser-viewer.tsx +361 -58
  99. package/src/components/chat-composer.tsx +1 -1
  100. package/src/components/composer.tsx +6 -6
  101. package/src/components/computer-viewer.tsx +368 -115
  102. package/src/components/enrollment-consent.tsx +64 -6
  103. package/src/components/file-browser.tsx +117 -2
  104. package/src/components/human-input-form.tsx +91 -55
  105. package/src/components/human-input-surface.tsx +1 -1
  106. package/src/components/machine-card.tsx +111 -0
  107. package/src/components/machine-input-display.ts +15 -0
  108. package/src/components/machines/machine-detail.tsx +47 -0
  109. package/src/components/machines/machine-operation-policy.tsx +179 -0
  110. package/src/components/machines-dashboard.tsx +6 -0
  111. package/src/components/markdown.tsx +174 -20
  112. package/src/components/message-timeline.tsx +162 -17
  113. package/src/components/model-policy-picker.tsx +9 -17
  114. package/src/components/pierre-file.tsx +1 -1
  115. package/src/components/queue-surface-implementation.tsx +82 -16
  116. package/src/components/sandbox-files.tsx +135 -19
  117. package/src/components/sandbox-workspace.tsx +204 -92
  118. package/src/components/session-chrome.tsx +415 -208
  119. package/src/components/session-status.tsx +1 -1
  120. package/src/components/user-message-body.tsx +168 -48
  121. package/src/components/workspace-dock.tsx +141 -175
  122. package/src/hooks/channel-cache.ts +104 -0
  123. package/src/hooks/shared-machines-list.ts +239 -0
  124. package/src/hooks/use-attached-browsers.ts +5 -1
  125. package/src/hooks/use-browser-frame-stream.ts +6 -1
  126. package/src/hooks/use-browser-session.ts +6 -4
  127. package/src/hooks/use-browser-sessions.ts +7 -1
  128. package/src/hooks/use-channels.ts +32 -10
  129. package/src/hooks/use-composer.ts +760 -291
  130. package/src/hooks/use-computer-frame-stream.ts +14 -9
  131. package/src/hooks/use-computer-session.ts +16 -14
  132. package/src/hooks/use-computer-sessions.ts +8 -1
  133. package/src/hooks/use-last-started-turn-policy.ts +1 -1
  134. package/src/hooks/use-machine-chip.ts +23 -6
  135. package/src/hooks/use-machines.ts +104 -6
  136. package/src/hooks/use-sandbox-files.ts +195 -140
  137. package/src/hooks/use-sandbox-git.ts +58 -29
  138. package/src/hooks/use-session-background-commands.ts +56 -0
  139. package/src/hooks/use-session-capabilities.ts +18 -0
  140. package/src/hooks/use-turn-queue.ts +111 -12
  141. package/src/hooks/use-workspace-sessions.ts +5 -1
  142. package/src/index.ts +26 -4
  143. package/src/lib/interaction-errors.ts +18 -0
  144. package/src/machines.ts +9 -1
  145. package/src/model-policy.ts +10 -2
  146. package/src/realtime/realtime-control.tsx +53 -17
  147. package/src/session-context.ts +1 -0
  148. package/src/session-ui.ts +6 -1
  149. package/src/session.ts +9 -1
  150. package/src/timeline/activity-rail.tsx +20 -75
  151. package/src/timeline/index.ts +4 -0
  152. package/src/timeline/platform-activity-row.tsx +201 -0
  153. package/src/timeline/projection.ts +476 -23
  154. package/src/timeline/screenshot-lightbox.tsx +48 -14
  155. package/src/timeline/shared.tsx +8 -2
  156. package/src/timeline/tool-renderers.tsx +104 -6
  157. package/src/timeline/turn-summary.tsx +6 -1
  158. package/src/timeline/types.ts +75 -2
  159. package/src/types/machines.ts +10 -0
  160. package/styles/compiled.css +115 -104
  161. package/dist/chunk-5UQPNLIO.js.map +0 -1
  162. package/dist/chunk-6KLX2RH5.js.map +0 -1
  163. package/dist/chunk-B6WPZSTT.js.map +0 -1
  164. package/dist/chunk-HA46CYQK.js.map +0 -1
  165. package/dist/chunk-IGC6A2ZI.js.map +0 -1
  166. package/dist/chunk-LLOLUHVG.js +0 -5937
  167. package/dist/chunk-LLOLUHVG.js.map +0 -1
  168. package/dist/chunk-MKPIAGVL.js.map +0 -1
  169. package/dist/chunk-R3AZOAB5.js.map +0 -1
  170. package/dist/chunk-XBZWOM2K.js.map +0 -1
  171. package/dist/chunk-Y7OEDUJ5.js.map +0 -1
  172. package/dist/interactive-workbench-viewers-TOHBXJEE.js +0 -15
  173. package/dist/queue-surface-implementation-2KVJTYXH.js.map +0 -1
  174. /package/dist/{interactive-workbench-viewers-TOHBXJEE.js.map → browser-viewer-GXUICIAG.js.map} +0 -0
@@ -12,7 +12,7 @@ export type SessionStatusMeta = {
12
12
 
13
13
  export const SESSION_STATUS_META: Record<SessionStatusValue, SessionStatusMeta> = {
14
14
  queued: {
15
- label: "Queued",
15
+ label: "Starting",
16
16
  dotClassName: "bg-og-status-queued",
17
17
  badgeClassName: "text-og-fg-muted border-og-border bg-og-status-queued/10",
18
18
  pulse: true,
@@ -109,6 +109,87 @@ function isFullyInsideVisiblePreview(rect: DOMRect, clipRect: DOMRect): boolean
109
109
 
110
110
  type RestoreDisclosureAnchor = (() => void) | null;
111
111
 
112
+ type SharedResizeObserverState = {
113
+ callbacks: Map<Element, () => void>;
114
+ observer: ResizeObserver;
115
+ handleWindowResize: () => void;
116
+ };
117
+
118
+ type DisclosureMeasurementJob = {
119
+ read: () => boolean;
120
+ write: (collapsible: boolean) => void;
121
+ };
122
+
123
+ const sharedResizeObservers = new WeakMap<Window, SharedResizeObserverState>();
124
+ const disclosureMeasurementJobs = new Map<object, DisclosureMeasurementJob>();
125
+ let disclosureMeasurementQueued = false;
126
+
127
+ /**
128
+ * Coalesce a commit's disclosure reads before applying any presentation writes.
129
+ * Reading and writing one message at a time forced a fresh layout for every
130
+ * newly mounted row in large history prepends.
131
+ */
132
+ function scheduleDisclosureMeasurement(
133
+ view: Window,
134
+ key: object,
135
+ job: DisclosureMeasurementJob,
136
+ ): () => void {
137
+ disclosureMeasurementJobs.set(key, job);
138
+ if (!disclosureMeasurementQueued) {
139
+ disclosureMeasurementQueued = true;
140
+ view.queueMicrotask(() => {
141
+ disclosureMeasurementQueued = false;
142
+ const pending = [...disclosureMeasurementJobs.values()];
143
+ disclosureMeasurementJobs.clear();
144
+ const decisions = pending.map(({ read }) => read());
145
+ for (let index = 0; index < pending.length; index += 1) {
146
+ pending[index]!.write(decisions[index]!);
147
+ }
148
+ });
149
+ }
150
+ return () => disclosureMeasurementJobs.delete(key);
151
+ }
152
+
153
+ function observeSharedResize(element: Element, callback: () => void): (() => void) | null {
154
+ const view = element.ownerDocument.defaultView;
155
+ if (!view || typeof ResizeObserver === "undefined") {
156
+ return null;
157
+ }
158
+ let state = sharedResizeObservers.get(view);
159
+ if (!state) {
160
+ const callbacks = new Map<Element, () => void>();
161
+ const handleWindowResize = () => {
162
+ for (const registered of new Set(callbacks.values())) registered();
163
+ };
164
+ const observer = new ResizeObserver((entries) => {
165
+ if (entries.length === 0) {
166
+ handleWindowResize();
167
+ } else {
168
+ for (const entry of entries) {
169
+ callbacks.get(entry.target)?.();
170
+ }
171
+ }
172
+ });
173
+ view.addEventListener("resize", handleWindowResize);
174
+ state = { callbacks, observer, handleWindowResize };
175
+ sharedResizeObservers.set(view, state);
176
+ }
177
+ state.callbacks.set(element, callback);
178
+ state.observer.observe(element);
179
+ return () => {
180
+ if (state.callbacks.get(element) !== callback) {
181
+ return;
182
+ }
183
+ state.callbacks.delete(element);
184
+ state.observer.unobserve(element);
185
+ if (state.callbacks.size === 0) {
186
+ state.observer.disconnect();
187
+ view.removeEventListener("resize", state.handleWindowResize);
188
+ sharedResizeObservers.delete(view);
189
+ }
190
+ };
191
+ }
192
+
112
193
  export type UserMessageDisclosureContextValue = {
113
194
  expandedByMessageId: Map<string, boolean>;
114
195
  beginChange: (
@@ -171,16 +252,33 @@ export function UserMessageBody({ messageId, text, children, className }: UserMe
171
252
  const [expanded, setExpanded] = useState(
172
253
  () => disclosure?.expandedByMessageId.get(messageId) ?? false,
173
254
  );
174
- const [collapsible, setCollapsible] = useState(() => userMessageLikelyNeedsDisclosure(text));
255
+ const collapsibleRef = useRef(userMessageLikelyNeedsDisclosure(text));
256
+ const expandedRef = useRef(expanded);
257
+ expandedRef.current = expanded;
175
258
  const rootRef = useRef<HTMLDivElement | null>(null);
176
259
  const clipRef = useRef<HTMLDivElement | null>(null);
177
260
  const contentRef = useRef<HTMLDivElement | null>(null);
178
261
  const thresholdRef = useRef<HTMLSpanElement | null>(null);
262
+ const fadeRef = useRef<HTMLSpanElement | null>(null);
263
+ const disclosureControlRef = useRef<HTMLButtonElement | null>(null);
179
264
  const pendingRestoreRef = useRef<RestoreDisclosureAnchor>(null);
180
265
  const managedInertDescendantsRef = useRef(new Set<HTMLElement>());
266
+ const measurementKeyRef = useRef({});
181
267
  const contentId = `og-user-message-${useId().replace(/:/g, "")}`;
268
+ const collapsible = collapsibleRef.current;
182
269
  const collapsed = collapsible && !expanded;
183
270
 
271
+ const syncDisclosurePresentation = useCallback((nextCollapsible: boolean) => {
272
+ collapsibleRef.current = nextCollapsible;
273
+ const nextCollapsed = nextCollapsible && !expandedRef.current;
274
+ const clip = clipRef.current;
275
+ clip?.classList.toggle("max-h-56", nextCollapsed);
276
+ clip?.classList.toggle("overflow-hidden", nextCollapsed);
277
+ clip?.classList.toggle("sm:max-h-72", nextCollapsed);
278
+ if (fadeRef.current) fadeRef.current.hidden = !nextCollapsed;
279
+ if (disclosureControlRef.current) disclosureControlRef.current.hidden = !nextCollapsible;
280
+ }, []);
281
+
184
282
  const restoreManagedInertDescendants = useCallback(() => {
185
283
  for (const descendant of managedInertDescendantsRef.current) {
186
284
  if (descendant.hasAttribute("data-og-user-message-managed-inert")) {
@@ -193,7 +291,7 @@ export function UserMessageBody({ messageId, text, children, className }: UserMe
193
291
 
194
292
  const syncCollapsedInteractivity = useCallback(() => {
195
293
  restoreManagedInertDescendants();
196
- if (!collapsed) {
294
+ if (!collapsibleRef.current || expandedRef.current) {
197
295
  return;
198
296
  }
199
297
 
@@ -220,58 +318,80 @@ export function UserMessageBody({ messageId, text, children, className }: UserMe
220
318
  descendant.setAttribute("data-og-user-message-managed-inert", "");
221
319
  managedInertDescendantsRef.current.add(descendant);
222
320
  }
223
- }, [collapsed, restoreManagedInertDescendants]);
321
+ }, [restoreManagedInertDescendants]);
224
322
 
225
- const measure = useCallback(() => {
323
+ const readCollapsible = useCallback(() => {
226
324
  const content = contentRef.current;
227
325
  const threshold = thresholdRef.current;
228
326
  if (!content || !threshold) {
229
- return;
327
+ return userMessageLikelyNeedsDisclosure(text);
230
328
  }
231
329
  const renderedHeight = Math.max(content.scrollHeight, content.getBoundingClientRect().height);
232
330
  const collapseHeight = Math.max(
233
331
  threshold.offsetHeight,
234
332
  threshold.getBoundingClientRect().height,
235
333
  );
236
- setCollapsible(
237
- renderedHeight > 0 && collapseHeight > 0
238
- ? renderedHeight > collapseHeight + 1
239
- : userMessageLikelyNeedsDisclosure(text),
240
- );
334
+ return renderedHeight > 0 && collapseHeight > 0
335
+ ? renderedHeight > collapseHeight + 1
336
+ : userMessageLikelyNeedsDisclosure(text);
241
337
  }, [text]);
242
338
 
339
+ const measure = useCallback(() => {
340
+ const view = rootRef.current?.ownerDocument.defaultView;
341
+ if (!view) {
342
+ syncDisclosurePresentation(readCollapsible());
343
+ syncCollapsedInteractivity();
344
+ return () => undefined;
345
+ }
346
+ return scheduleDisclosureMeasurement(view, measurementKeyRef.current, {
347
+ read: readCollapsible,
348
+ write: (nextCollapsible) => {
349
+ syncDisclosurePresentation(nextCollapsible);
350
+ syncCollapsedInteractivity();
351
+ },
352
+ });
353
+ }, [readCollapsible, syncCollapsedInteractivity, syncDisclosurePresentation]);
354
+
243
355
  useLayoutEffect(() => {
244
- measure();
356
+ const cancelPendingMeasurement = measure();
245
357
  const content = contentRef.current;
246
358
  const threshold = thresholdRef.current;
247
- const observer =
248
- typeof ResizeObserver === "undefined"
249
- ? null
250
- : new ResizeObserver(() => {
251
- measure();
252
- syncCollapsedInteractivity();
253
- });
254
- if (content) {
255
- observer?.observe(content);
256
- }
257
- if (threshold) {
258
- observer?.observe(threshold);
259
- }
359
+ const onResize = () => {
360
+ measure();
361
+ };
362
+ const stopObservingContent = content ? observeSharedResize(content, onResize) : null;
363
+ const stopObservingThreshold = threshold ? observeSharedResize(threshold, onResize) : null;
364
+ const observerAvailable = stopObservingContent !== null || stopObservingThreshold !== null;
260
365
  const handleResize = () => {
261
366
  measure();
262
- syncCollapsedInteractivity();
263
367
  };
264
- window.addEventListener("resize", handleResize);
368
+ // ResizeObserver already reports viewport-driven wrapping/height changes
369
+ // for both measured elements. The window listener is only the fallback for
370
+ // runtimes without ResizeObserver; installing both created one redundant
371
+ // global listener per durable user message in large timelines.
372
+ if (!observerAvailable) {
373
+ window.addEventListener("resize", handleResize);
374
+ }
265
375
  return () => {
266
- observer?.disconnect();
267
- window.removeEventListener("resize", handleResize);
376
+ cancelPendingMeasurement();
377
+ stopObservingContent?.();
378
+ stopObservingThreshold?.();
379
+ if (!observerAvailable) {
380
+ window.removeEventListener("resize", handleResize);
381
+ }
268
382
  };
269
383
  }, [measure, syncCollapsedInteractivity]);
270
384
 
271
385
  useLayoutEffect(() => {
386
+ syncDisclosurePresentation(collapsibleRef.current);
272
387
  syncCollapsedInteractivity();
273
388
  return restoreManagedInertDescendants;
274
- });
389
+ }, [
390
+ expanded,
391
+ restoreManagedInertDescendants,
392
+ syncCollapsedInteractivity,
393
+ syncDisclosurePresentation,
394
+ ]);
275
395
 
276
396
  useLayoutEffect(() => {
277
397
  const restore = pendingRestoreRef.current;
@@ -316,26 +436,26 @@ export function UserMessageBody({ messageId, text, children, className }: UserMe
316
436
  >
317
437
  {children}
318
438
  </div>
319
- {collapsed ? (
320
- <span
321
- aria-hidden="true"
322
- data-og-user-message-fade=""
323
- className="pointer-events-none absolute inset-x-0 bottom-0 h-16 bg-gradient-to-t from-og-surface-2 via-og-surface-2/90 to-transparent"
324
- />
325
- ) : null}
439
+ <span
440
+ ref={fadeRef}
441
+ aria-hidden="true"
442
+ hidden={!collapsed}
443
+ data-og-user-message-fade=""
444
+ className="pointer-events-none absolute inset-x-0 bottom-0 h-16 bg-gradient-to-t from-og-surface-2 via-og-surface-2/90 to-transparent"
445
+ />
326
446
  </div>
327
- {collapsible ? (
328
- <button
329
- type="button"
330
- aria-controls={contentId}
331
- aria-expanded={expanded}
332
- data-og-user-message-disclosure=""
333
- className="mt-1.5 inline-flex min-h-7 items-center rounded-og-sm px-1.5 text-og-xs font-medium text-og-fg-muted outline-hidden transition-colors hover:bg-og-surface-3/60 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/45 pointer-coarse:min-h-11"
334
- onClick={(event) => toggle(event.currentTarget)}
335
- >
336
- {expanded ? "Show less" : "Show more"}
337
- </button>
338
- ) : null}
447
+ <button
448
+ ref={disclosureControlRef}
449
+ type="button"
450
+ hidden={!collapsible}
451
+ aria-controls={contentId}
452
+ aria-expanded={expanded}
453
+ data-og-user-message-disclosure=""
454
+ className="mt-1.5 inline-flex min-h-7 items-center rounded-og-sm px-1.5 text-og-xs font-medium text-og-fg-muted outline-hidden transition-colors hover:bg-og-surface-3/60 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent/45 pointer-coarse:min-h-11"
455
+ onClick={(event) => toggle(event.currentTarget)}
456
+ >
457
+ {expanded ? "Show less" : "Show more"}
458
+ </button>
339
459
  </div>
340
460
  );
341
461
  }