@agent-native/core 0.80.8 → 0.80.10

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 (359) hide show
  1. package/corpus/README.md +2 -2
  2. package/corpus/core/CHANGELOG.md +19 -0
  3. package/corpus/core/docs/content/locales/ar-SA/template-design.mdx +6 -0
  4. package/corpus/core/docs/content/locales/de-DE/template-design.mdx +8 -0
  5. package/corpus/core/docs/content/locales/es-ES/template-design.mdx +10 -2
  6. package/corpus/core/docs/content/locales/fr-FR/template-design.mdx +10 -2
  7. package/corpus/core/docs/content/locales/hi-IN/template-design.mdx +7 -0
  8. package/corpus/core/docs/content/locales/ja-JP/template-design.mdx +7 -0
  9. package/corpus/core/docs/content/locales/ko-KR/template-design.mdx +7 -0
  10. package/corpus/core/docs/content/locales/pt-BR/template-design.mdx +9 -2
  11. package/corpus/core/docs/content/locales/zh-CN/template-design.mdx +6 -0
  12. package/corpus/core/docs/content/locales/zh-TW/template-design.mdx +6 -0
  13. package/corpus/core/docs/content/template-design.mdx +9 -2
  14. package/corpus/core/package.json +1 -1
  15. package/corpus/core/src/cli/design-connect.ts +28 -2
  16. package/corpus/core/src/cli/mcp.ts +10 -0
  17. package/corpus/core/src/cli/skills.ts +103 -36
  18. package/corpus/core/src/client/error-format.ts +25 -0
  19. package/corpus/core/src/client/extensions/ExtensionViewer.tsx +13 -11
  20. package/corpus/core/src/client/guided-questions.tsx +32 -4
  21. package/corpus/core/src/client/onboarding/OnboardingPanel.tsx +33 -1
  22. package/corpus/core/src/client/resources/BuiltinCapabilityDetail.tsx +8 -0
  23. package/corpus/core/src/client/resources/use-builtin-capabilities.ts +4 -2
  24. package/corpus/core/src/client/session-replay.ts +34 -0
  25. package/corpus/core/src/client/sharing/ShareButton.tsx +106 -21
  26. package/corpus/core/src/coding-tools/index.ts +1 -1
  27. package/corpus/core/src/mcp/index.ts +2 -0
  28. package/corpus/core/src/mcp/screen-memory-stdio.ts +290 -0
  29. package/corpus/core/src/mcp-client/builtin-capabilities.ts +13 -1
  30. package/corpus/core/src/mcp-client/index.ts +9 -0
  31. package/corpus/core/src/mcp-client/screen-memory-local.ts +461 -0
  32. package/corpus/core/src/onboarding/types.ts +7 -0
  33. package/corpus/core/src/server/agent-chat-plugin.ts +25 -0
  34. package/corpus/core/src/server/agents-bundle.ts +35 -7
  35. package/corpus/core/src/styles/agent-native.css +5 -0
  36. package/corpus/core/src/templates/default/app/global.css +35 -35
  37. package/corpus/templates/analytics/AGENTS.md +6 -0
  38. package/corpus/templates/analytics/actions/github-repo-files.ts +9 -0
  39. package/corpus/templates/analytics/app/components/layout/Layout.tsx +4 -4
  40. package/corpus/templates/analytics/app/global.css +144 -40
  41. package/corpus/templates/analytics/app/pages/adhoc/explorer/index.tsx +1 -1
  42. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/ChartCard.tsx +1 -1
  43. package/corpus/templates/analytics/app/pages/adhoc/explorer-dashboard/index.tsx +1 -1
  44. package/corpus/templates/analytics/app/pages/sessions/SessionDetailPage.tsx +4 -4
  45. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +9 -9
  46. package/corpus/templates/analytics/changelog/2026-06-29-agents-can-search-and-read-connected-github-repositories-whe.md +6 -0
  47. package/corpus/templates/analytics/changelog/2026-06-29-sessions-and-explorer-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  48. package/corpus/templates/assets/app/components/layout/Layout.tsx +3 -1
  49. package/corpus/templates/assets/app/components/library/LibraryPresetGrid.tsx +1 -1
  50. package/corpus/templates/assets/app/global.css +99 -35
  51. package/corpus/templates/assets/app/routes/asset.$id.tsx +2 -2
  52. package/corpus/templates/assets/app/routes/brand-kits.$id.tsx +4 -4
  53. package/corpus/templates/assets/app/routes/library.tsx +4 -4
  54. package/corpus/templates/assets/changelog/2026-06-29-asset-library-and-detail-layouts-adapt-when-the-agent-sidebar.md +6 -0
  55. package/corpus/templates/brain/app/components/layout/Layout.tsx +1 -1
  56. package/corpus/templates/brain/app/global.css +63 -35
  57. package/corpus/templates/brain/app/routes/search.tsx +1 -1
  58. package/corpus/templates/brain/app/routes/settings.tsx +1 -1
  59. package/corpus/templates/brain/app/routes/sources.tsx +2 -2
  60. package/corpus/templates/brain/changelog/2026-06-29-search-settings-and-source-layouts-adapt-when-the-agent-sidebar.md +6 -0
  61. package/corpus/templates/calendar/app/components/calendar/EventDetailPanel.tsx +4 -4
  62. package/corpus/templates/calendar/app/components/calendar/FindTimePanel.tsx +3 -2
  63. package/corpus/templates/calendar/app/components/layout/AppLayout.tsx +4 -2
  64. package/corpus/templates/calendar/app/global.css +69 -35
  65. package/corpus/templates/calendar/changelog/2026-06-29-event-and-find-time-layouts-adapt-when-the-agent-sidebar-is.md +6 -0
  66. package/corpus/templates/chat/app/components/layout/Layout.tsx +1 -1
  67. package/corpus/templates/chat/app/global.css +35 -35
  68. package/corpus/templates/chat/changelog/2026-06-29-chat-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  69. package/corpus/templates/clips/AGENTS.md +13 -0
  70. package/corpus/templates/clips/actions/get-screen-memory-status.ts +12 -0
  71. package/corpus/templates/clips/actions/query-screen-memory-context.ts +29 -0
  72. package/corpus/templates/clips/actions/view-screen.ts +2 -2
  73. package/corpus/templates/clips/app/components/library/library-layout.tsx +1 -1
  74. package/corpus/templates/clips/app/global.css +47 -35
  75. package/corpus/templates/clips/app/routes/_app.meetings.$meetingId.tsx +3 -3
  76. package/corpus/templates/clips/app/routes/r.$recordingId.tsx +45 -18
  77. package/corpus/templates/clips/changelog/2026-06-29-meeting-detail-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  78. package/corpus/templates/clips/changelog/2026-06-29-screen-memory-keeps-a-local-rolling-screen-buffer-for-agent-context.md +5 -0
  79. package/corpus/templates/clips/changelog/2026-06-29-video-chat-is-easier-to-find-on-recording-pages-and-s3-setup.md +6 -0
  80. package/corpus/templates/clips/chrome-extension/src/styles.css +39 -39
  81. package/corpus/templates/clips/desktop/src/app.tsx +290 -1
  82. package/corpus/templates/clips/desktop/src/shared/config.ts +83 -0
  83. package/corpus/templates/clips/desktop/src/styles.css +67 -52
  84. package/corpus/templates/clips/desktop/src-tauri/src/config.rs +50 -0
  85. package/corpus/templates/clips/desktop/src-tauri/src/lib.rs +17 -0
  86. package/corpus/templates/clips/desktop/src-tauri/src/native_screen.rs +13 -13
  87. package/corpus/templates/clips/desktop/src-tauri/src/screen_memory.rs +990 -0
  88. package/corpus/templates/clips/server/plugins/onboarding.ts +2 -0
  89. package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +3 -3
  90. package/corpus/templates/content/app/components/layout/Layout.tsx +1 -1
  91. package/corpus/templates/content/app/global.css +29 -15
  92. package/corpus/templates/content/changelog/2026-06-29-database-gallery-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  93. package/corpus/templates/design/.agents/skills/design-generation/SKILL.md +25 -20
  94. package/corpus/templates/design/.agents/skills/design-systems/SKILL.md +8 -0
  95. package/corpus/templates/design/.agents/skills/export-handoff/SKILL.md +8 -0
  96. package/corpus/templates/design/.agents/skills/visual-edit/SKILL.md +13 -0
  97. package/corpus/templates/design/AGENTS.md +20 -12
  98. package/corpus/templates/design/CODE_NATIVE_DESIGN_STUDIO_IMPLEMENTATION_PLAN.md +1054 -0
  99. package/corpus/templates/design/DESIGN-STUDIO-PLAN.md +717 -0
  100. package/corpus/templates/design/actions/add-breakpoint.ts +143 -0
  101. package/corpus/templates/design/actions/add-localhost-screens.ts +5 -0
  102. package/corpus/templates/design/actions/apply-a11y-fix.ts +317 -0
  103. package/corpus/templates/design/actions/apply-component-prop-edit.ts +433 -0
  104. package/corpus/templates/design/actions/apply-design-state.ts +200 -0
  105. package/corpus/templates/design/actions/apply-design-token-edit.ts +202 -0
  106. package/corpus/templates/design/actions/apply-motion-edit.ts +450 -0
  107. package/corpus/templates/design/actions/apply-shader-fill.ts +404 -0
  108. package/corpus/templates/design/actions/apply-visual-edit.ts +214 -8
  109. package/corpus/templates/design/actions/capture-design-state.ts +224 -0
  110. package/corpus/templates/design/actions/connect-builder-app.ts +162 -0
  111. package/corpus/templates/design/actions/create-component.ts +447 -0
  112. package/corpus/templates/design/actions/create-design-branch.ts +263 -0
  113. package/corpus/templates/design/actions/create-design-state.ts +162 -0
  114. package/corpus/templates/design/actions/delete-design-state.ts +55 -0
  115. package/corpus/templates/design/actions/deploy-design-preview.ts +275 -0
  116. package/corpus/templates/design/actions/export-coding-handoff.ts +12 -4
  117. package/corpus/templates/design/actions/generate-design.ts +6 -21
  118. package/corpus/templates/design/actions/generate-screens.ts +43 -2
  119. package/corpus/templates/design/actions/get-component-details.ts +242 -0
  120. package/corpus/templates/design/actions/get-design-branch-diff.ts +362 -0
  121. package/corpus/templates/design/actions/get-design-review.ts +314 -0
  122. package/corpus/templates/design/actions/get-design-surface-index.ts +582 -0
  123. package/corpus/templates/design/actions/get-design.ts +1 -0
  124. package/corpus/templates/design/actions/get-motion-timeline.ts +99 -0
  125. package/corpus/templates/design/actions/index-components.ts +258 -0
  126. package/corpus/templates/design/actions/index-design-tokens.ts +273 -0
  127. package/corpus/templates/design/actions/list-design-extensions.ts +309 -0
  128. package/corpus/templates/design/actions/list-design-source-capabilities.ts +153 -0
  129. package/corpus/templates/design/actions/list-design-states.ts +72 -0
  130. package/corpus/templates/design/actions/migrate-inline-design-to-app.ts +298 -0
  131. package/corpus/templates/design/actions/open-component-source.ts +237 -0
  132. package/corpus/templates/design/actions/present-design-variants.ts +355 -30
  133. package/corpus/templates/design/actions/preview-component-prop-edit.ts +254 -0
  134. package/corpus/templates/design/actions/preview-design-token-edit.ts +113 -0
  135. package/corpus/templates/design/actions/preview-shader-fill.ts +189 -0
  136. package/corpus/templates/design/actions/remove-breakpoint.ts +103 -0
  137. package/corpus/templates/design/actions/remove-motion-timeline.ts +196 -0
  138. package/corpus/templates/design/actions/run-design-audit.ts +421 -0
  139. package/corpus/templates/design/actions/run-design-extension-action.ts +284 -0
  140. package/corpus/templates/design/actions/set-active-breakpoint.ts +39 -0
  141. package/corpus/templates/design/actions/view-screen.ts +75 -31
  142. package/corpus/templates/design/app/components/design/DesignCanvas.tsx +1738 -135
  143. package/corpus/templates/design/app/components/design/DesignEditorSkeleton.tsx +1 -1
  144. package/corpus/templates/design/app/components/design/DesignExtensionsPanel.tsx +632 -43
  145. package/corpus/templates/design/app/components/design/DrawOverlay.tsx +1 -1
  146. package/corpus/templates/design/app/components/design/EditPanel.tsx +1873 -132
  147. package/corpus/templates/design/app/components/design/LayersPanel.tsx +384 -219
  148. package/corpus/templates/design/app/components/design/LocalSourceEditBanner.tsx +157 -0
  149. package/corpus/templates/design/app/components/design/MotionDock.tsx +1062 -0
  150. package/corpus/templates/design/app/components/design/MultiScreenCanvas.tsx +2103 -295
  151. package/corpus/templates/design/app/components/design/QuestionFlow.tsx +83 -206
  152. package/corpus/templates/design/app/components/design/ReviewPanel.tsx +759 -0
  153. package/corpus/templates/design/app/components/design/StatesPanel.tsx +579 -0
  154. package/corpus/templates/design/app/components/design/TokensPanel.tsx +573 -0
  155. package/corpus/templates/design/app/components/design/TweaksPanel.tsx +1 -1
  156. package/corpus/templates/design/app/components/design/canvas-primitive-style.ts +241 -0
  157. package/corpus/templates/design/app/components/design/index.ts +16 -1
  158. package/corpus/templates/design/app/components/design/inspector/AutoLayoutMatrix.tsx +238 -137
  159. package/corpus/templates/design/app/components/design/inspector/DesignColorPicker.tsx +188 -14
  160. package/corpus/templates/design/app/components/design/inspector/ExportSettingsPanel.tsx +24 -5
  161. package/corpus/templates/design/app/components/design/inspector/ImageFillControls.tsx +57 -1
  162. package/corpus/templates/design/app/components/design/inspector/InspectorAiActions.tsx +145 -0
  163. package/corpus/templates/design/app/components/design/inspector/SHADER_INTEGRATION.md +42 -12
  164. package/corpus/templates/design/app/components/design/inspector/ScrubInput.tsx +37 -12
  165. package/corpus/templates/design/app/components/design/inspector/index.ts +1 -0
  166. package/corpus/templates/design/app/components/design/inspector/scrub-input-utils.ts +12 -5
  167. package/corpus/templates/design/app/components/design/types.ts +9 -0
  168. package/corpus/templates/design/app/components/layout/Layout.tsx +23 -5
  169. package/corpus/templates/design/app/components/visual-editor/DrawOverlay.tsx +1 -1
  170. package/corpus/templates/design/app/global.css +77 -49
  171. package/corpus/templates/design/app/hooks/use-question-flow.ts +2 -2
  172. package/corpus/templates/design/app/hooks/useAgentEditRequest.ts +131 -0
  173. package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +11 -2
  174. package/corpus/templates/design/app/i18n/zh-TW.ts +34 -0
  175. package/corpus/templates/design/app/i18n-data.ts +314 -3
  176. package/corpus/templates/design/app/pages/DesignEditor.tsx +4929 -892
  177. package/corpus/templates/design/app/root.tsx +1 -1
  178. package/corpus/templates/design/changelog/2026-06-29-added-a-review-panel-in-the-design-editor-s-inspector-with-a.md +6 -0
  179. package/corpus/templates/design/changelog/2026-06-29-containers-no-longer-block-selecting-nested-elements-and-nor.md +6 -0
  180. package/corpus/templates/design/changelog/2026-06-29-copying-and-pasting-layers-no-longer-shows-success-notificat.md +6 -0
  181. package/corpus/templates/design/changelog/2026-06-29-design-agents-now-generate-and-refine-variants-from-stronger.md +6 -0
  182. package/corpus/templates/design/changelog/2026-06-29-design-inspector-controls-now-match-figmas-softer-dark-chrome.md +6 -0
  183. package/corpus/templates/design/changelog/2026-06-29-design-questions-now-appear-as-a-cleaner-canvas-intake-with-.md +6 -0
  184. package/corpus/templates/design/changelog/2026-06-29-design-variant-directions-now-appear-as-board-screens-with-chat-buttons.md +5 -0
  185. package/corpus/templates/design/changelog/2026-06-29-device-presets-in-all-screens-view-resize-the-selected-previ.md +6 -0
  186. package/corpus/templates/design/changelog/2026-06-29-element-selection-no-longer-snaps-back-to-the-previous-layer.md +6 -0
  187. package/corpus/templates/design/changelog/2026-06-29-frame-resize-measurements-now-stay-beside-the-cursor-while-d.md +6 -0
  188. package/corpus/templates/design/changelog/2026-06-29-inspector-number-fields-have-cleaner-tooltips-and-draggable-.md +6 -0
  189. package/corpus/templates/design/changelog/2026-06-29-layer-and-canvas-drags-keep-the-layer-list-stable-while-chan.md +6 -0
  190. package/corpus/templates/design/changelog/2026-06-29-layer-locking-layer-nesting-generated-question-intake-and-im.md +6 -0
  191. package/corpus/templates/design/changelog/2026-06-29-layer-moves-can-be-undone-and-redone-without-flashing-the-ca.md +6 -0
  192. package/corpus/templates/design/changelog/2026-06-29-layer-names-in-the-sidebar-can-scroll-horizontally-instead-o.md +6 -0
  193. package/corpus/templates/design/changelog/2026-06-29-layer-nesting-in-the-sidebar-now-uses-tighter-spacing-so-nam.md +6 -0
  194. package/corpus/templates/design/changelog/2026-06-29-layers-no-longer-repeat-document-wrapper-rows-when-a-screen-.md +6 -0
  195. package/corpus/templates/design/changelog/2026-06-29-overview-previews-now-keep-element-hover-and-selection-tied-.md +6 -0
  196. package/corpus/templates/design/changelog/2026-06-29-pressing-escape-now-cancels-a-stuck-screen-drag-in-the-overv.md +6 -0
  197. package/corpus/templates/design/changelog/2026-06-29-screen-overview-is-easier-to-find-and-named-screens-open-dir.md +6 -0
  198. package/corpus/templates/design/changelog/2026-06-29-screen-overview-only-highlights-screens-when-the-frame-or-ti.md +6 -0
  199. package/corpus/templates/design/changelog/2026-06-29-screen-overview-previews-now-resize-to-match-the-selected-de.md +6 -0
  200. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-now-uses-a-pointer-cursor-instead-.md +6 -0
  201. package/corpus/templates/design/changelog/2026-06-29-screen-overview-selection-outlines-now-stay-locked-to-the-se.md +6 -0
  202. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zoom-now-reports-real-screen-scale-separatel.md +6 -0
  203. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-feels-smoother-and-selection-outline.md +6 -0
  204. package/corpus/templates/design/changelog/2026-06-29-screen-overview-zooming-now-stays-on-the-overview-canvas-ins.md +6 -0
  205. package/corpus/templates/design/changelog/2026-06-29-screen-previews-use-a-single-blue-hover-border-in-all-screen.md +6 -0
  206. package/corpus/templates/design/changelog/2026-06-29-selected-containers-show-draggable-padding-and-gap-guides-on.md +6 -0
  207. package/corpus/templates/design/changelog/2026-06-29-selecting-a-nested-layer-from-all-screens-now-keeps-you-in-a.md +6 -0
  208. package/corpus/templates/design/changelog/2026-06-29-share-now-groups-link-sharing-exports-and-agent-handoff.md +6 -0
  209. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-adds-a-studio-layer-with-tokens-respon.md +6 -0
  210. package/corpus/templates/design/changelog/2026-06-29-the-design-editor-loading-skeleton-now-uses-a-softer-charcoa.md +6 -0
  211. package/corpus/templates/design/changelog/2026-06-29-the-device-preview-menu-now-sits-next-to-the-preview-button-.md +6 -0
  212. package/corpus/templates/design/changelog/2026-06-29-the-inspector-stays-read-only-while-an-empty-design-is-still.md +6 -0
  213. package/corpus/templates/design/changelog/2026-06-29-the-missing-design-view-now-matches-the-rest-of-the-editor-c.md +6 -0
  214. package/corpus/templates/design/changelog/2026-06-29-the-pen-tool-icon-and-tool-option-menus-better-match-the-edi.md +6 -0
  215. package/corpus/templates/design/changelog/2026-06-29-typography-controls-now-keep-the-font-name-visible-and-move-.md +6 -0
  216. package/corpus/templates/design/changelog/2026-06-30-accessibility-findings-now-offer-a-one-click-fix.md +6 -0
  217. package/corpus/templates/design/changelog/2026-06-30-component-instances-now-have-editable-props-in-the-inspe.md +6 -0
  218. package/corpus/templates/design/changelog/2026-06-30-inspect-code-now-shows-the-elements-opening-tag-at-a-gla.md +6 -0
  219. package/corpus/templates/design/changelog/2026-06-30-shader-fill-presets-can-now-be-applied-to-an-element.md +6 -0
  220. package/corpus/templates/design/changelog/2026-06-30-the-motion-timeline-can-now-add-a-track-to-any-element-a.md +6 -0
  221. package/corpus/templates/design/changelog/2026-06-30-visual-editor-selection-layer-paint-and-drawing-controls-are-more-reliable.md +6 -0
  222. package/corpus/templates/design/e2e/README.md +3 -3
  223. package/corpus/templates/design/e2e/global-setup.ts +11 -22
  224. package/corpus/templates/design/e2e/helpers.ts +128 -11
  225. package/corpus/templates/design/playwright.config.ts +9 -3
  226. package/corpus/templates/design/server/db/schema.ts +123 -0
  227. package/corpus/templates/design/server/lib/coding-handoff.ts +126 -2
  228. package/corpus/templates/design/server/plugins/core-routes.ts +1 -2
  229. package/corpus/templates/design/server/plugins/db.ts +90 -0
  230. package/corpus/templates/design/server/routes/api/design-handoff/[id].zip.get.ts +86 -0
  231. package/corpus/templates/design/shared/builder-app.ts +297 -0
  232. package/corpus/templates/design/shared/capability-resolver.ts +123 -0
  233. package/corpus/templates/design/shared/capture-sanitize.ts +70 -0
  234. package/corpus/templates/design/shared/code-layer.ts +1141 -93
  235. package/corpus/templates/design/shared/component-model.ts +239 -0
  236. package/corpus/templates/design/shared/design-review.ts +275 -0
  237. package/corpus/templates/design/shared/design-source-capabilities.ts +286 -0
  238. package/corpus/templates/design/shared/design-state.ts +112 -0
  239. package/corpus/templates/design/shared/design-surface-index.ts +258 -0
  240. package/corpus/templates/design/shared/generation-session.ts +41 -0
  241. package/corpus/templates/design/shared/motion-compiler.ts +278 -0
  242. package/corpus/templates/design/shared/motion-timeline.ts +193 -0
  243. package/corpus/templates/design/shared/responsive-classes.ts +452 -0
  244. package/corpus/templates/design/shared/shader-fill.ts +323 -0
  245. package/corpus/templates/design/shared/source-mode.ts +245 -0
  246. package/corpus/templates/dispatch/app/global.css +79 -35
  247. package/corpus/templates/dispatch/app/routes/integrations.tsx +8 -7
  248. package/corpus/templates/dispatch/changelog/2026-06-29-integration-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  249. package/corpus/templates/forms/app/components/layout/Layout.tsx +6 -2
  250. package/corpus/templates/forms/app/global.css +64 -35
  251. package/corpus/templates/forms/app/pages/FormsListPage.tsx +2 -2
  252. package/corpus/templates/forms/app/pages/ResponseInsightsPage.tsx +3 -3
  253. package/corpus/templates/forms/changelog/2026-06-29-form-list-and-insight-layouts-adapt-when-the-agent-sidebar.md +6 -0
  254. package/corpus/templates/macros/app/components/layout/AppLayout.tsx +3 -1
  255. package/corpus/templates/macros/app/global.css +25 -9
  256. package/corpus/templates/macros/changelog/2026-06-29-macro-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  257. package/corpus/templates/mail/app/components/layout/AppLayout.tsx +6 -2
  258. package/corpus/templates/mail/app/global.css +42 -36
  259. package/corpus/templates/mail/app/pages/InboxPage.tsx +1 -1
  260. package/corpus/templates/mail/changelog/2026-06-29-the-contact-panel-now-adapts-to-the-available-mail-pane-width.md +6 -0
  261. package/corpus/templates/plan/app/components/layout/Layout.tsx +3 -1
  262. package/corpus/templates/plan/app/components/plan/CanvasArea.tsx +6 -2
  263. package/corpus/templates/plan/app/components/plan/DocumentArea.tsx +6 -7
  264. package/corpus/templates/plan/app/global.css +74 -42
  265. package/corpus/templates/plan/changelog/2026-06-29-plan-canvases-open-without-an-initial-pan-and-zoom-flicker.md +6 -0
  266. package/corpus/templates/plan/changelog/2026-06-29-plan-document-blocks-adapt-to-the-available-document-width.md +6 -0
  267. package/corpus/templates/plan/changelog/2026-06-29-plan-titles-and-summaries-can-be-edited-inline-without-focus.md +6 -0
  268. package/corpus/templates/slides/app/components/layout/Layout.tsx +3 -1
  269. package/corpus/templates/slides/app/global.css +49 -33
  270. package/corpus/templates/slides/changelog/2026-06-29-slide-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  271. package/corpus/templates/videos/app/components/layout/Layout.tsx +3 -1
  272. package/corpus/templates/videos/app/global.css +35 -35
  273. package/corpus/templates/videos/changelog/2026-06-29-video-layouts-adapt-when-the-agent-sidebar-is-open.md +6 -0
  274. package/dist/cli/design-connect.d.ts.map +1 -1
  275. package/dist/cli/design-connect.js +28 -2
  276. package/dist/cli/design-connect.js.map +1 -1
  277. package/dist/cli/mcp.d.ts.map +1 -1
  278. package/dist/cli/mcp.js +10 -0
  279. package/dist/cli/mcp.js.map +1 -1
  280. package/dist/cli/skills.d.ts.map +1 -1
  281. package/dist/cli/skills.js +95 -33
  282. package/dist/cli/skills.js.map +1 -1
  283. package/dist/client/error-format.d.ts.map +1 -1
  284. package/dist/client/error-format.js +17 -0
  285. package/dist/client/error-format.js.map +1 -1
  286. package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
  287. package/dist/client/extensions/ExtensionViewer.js +3 -4
  288. package/dist/client/extensions/ExtensionViewer.js.map +1 -1
  289. package/dist/client/guided-questions.d.ts +4 -0
  290. package/dist/client/guided-questions.d.ts.map +1 -1
  291. package/dist/client/guided-questions.js +16 -7
  292. package/dist/client/guided-questions.js.map +1 -1
  293. package/dist/client/onboarding/OnboardingPanel.js +26 -1
  294. package/dist/client/onboarding/OnboardingPanel.js.map +1 -1
  295. package/dist/client/resources/BuiltinCapabilityDetail.d.ts.map +1 -1
  296. package/dist/client/resources/BuiltinCapabilityDetail.js +1 -1
  297. package/dist/client/resources/BuiltinCapabilityDetail.js.map +1 -1
  298. package/dist/client/resources/use-builtin-capabilities.d.ts +1 -1
  299. package/dist/client/resources/use-builtin-capabilities.d.ts.map +1 -1
  300. package/dist/client/resources/use-builtin-capabilities.js +2 -1
  301. package/dist/client/resources/use-builtin-capabilities.js.map +1 -1
  302. package/dist/client/session-replay.d.ts.map +1 -1
  303. package/dist/client/session-replay.js +31 -0
  304. package/dist/client/session-replay.js.map +1 -1
  305. package/dist/client/sharing/ShareButton.d.ts +14 -0
  306. package/dist/client/sharing/ShareButton.d.ts.map +1 -1
  307. package/dist/client/sharing/ShareButton.js +36 -7
  308. package/dist/client/sharing/ShareButton.js.map +1 -1
  309. package/dist/coding-tools/index.js +1 -1
  310. package/dist/coding-tools/index.js.map +1 -1
  311. package/dist/mcp/index.d.ts +2 -0
  312. package/dist/mcp/index.d.ts.map +1 -1
  313. package/dist/mcp/index.js +1 -0
  314. package/dist/mcp/index.js.map +1 -1
  315. package/dist/mcp/screen-memory-stdio.d.ts +6 -0
  316. package/dist/mcp/screen-memory-stdio.d.ts.map +1 -0
  317. package/dist/mcp/screen-memory-stdio.js +213 -0
  318. package/dist/mcp/screen-memory-stdio.js.map +1 -0
  319. package/dist/mcp-client/builtin-capabilities.d.ts +1 -1
  320. package/dist/mcp-client/builtin-capabilities.d.ts.map +1 -1
  321. package/dist/mcp-client/builtin-capabilities.js +10 -0
  322. package/dist/mcp-client/builtin-capabilities.js.map +1 -1
  323. package/dist/mcp-client/index.d.ts +1 -0
  324. package/dist/mcp-client/index.d.ts.map +1 -1
  325. package/dist/mcp-client/index.js +1 -0
  326. package/dist/mcp-client/index.js.map +1 -1
  327. package/dist/mcp-client/screen-memory-local.d.ts +61 -0
  328. package/dist/mcp-client/screen-memory-local.d.ts.map +1 -0
  329. package/dist/mcp-client/screen-memory-local.js +336 -0
  330. package/dist/mcp-client/screen-memory-local.js.map +1 -0
  331. package/dist/observability/routes.d.ts +3 -3
  332. package/dist/onboarding/types.d.ts +7 -0
  333. package/dist/onboarding/types.d.ts.map +1 -1
  334. package/dist/onboarding/types.js.map +1 -1
  335. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  336. package/dist/server/agent-chat-plugin.js +26 -0
  337. package/dist/server/agent-chat-plugin.js.map +1 -1
  338. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  339. package/dist/server/agents-bundle.d.ts.map +1 -1
  340. package/dist/server/agents-bundle.js +22 -7
  341. package/dist/server/agents-bundle.js.map +1 -1
  342. package/dist/styles/agent-native.css +5 -0
  343. package/dist/templates/default/app/global.css +35 -35
  344. package/docs/content/locales/ar-SA/template-design.mdx +6 -0
  345. package/docs/content/locales/de-DE/template-design.mdx +8 -0
  346. package/docs/content/locales/es-ES/template-design.mdx +10 -2
  347. package/docs/content/locales/fr-FR/template-design.mdx +10 -2
  348. package/docs/content/locales/hi-IN/template-design.mdx +7 -0
  349. package/docs/content/locales/ja-JP/template-design.mdx +7 -0
  350. package/docs/content/locales/ko-KR/template-design.mdx +7 -0
  351. package/docs/content/locales/pt-BR/template-design.mdx +9 -2
  352. package/docs/content/locales/zh-CN/template-design.mdx +6 -0
  353. package/docs/content/locales/zh-TW/template-design.mdx +6 -0
  354. package/docs/content/template-design.mdx +9 -2
  355. package/package.json +1 -1
  356. package/src/templates/default/app/global.css +35 -35
  357. package/corpus/templates/design/app/components/design/VariantGrid.tsx +0 -189
  358. package/corpus/templates/design/app/components/design/VariantHandoffCard.tsx +0 -115
  359. package/corpus/templates/design/app/hooks/use-variant-flow.ts +0 -342
@@ -0,0 +1,759 @@
1
+ // i18n-raw-literal-disable-file — new Design Studio panel; UI strings are localized when this feature is finalized in the follow-up PR.
2
+ /**
3
+ * ReviewPanel — Design Studio accessibility + visual-diff review panel.
4
+ *
5
+ * Displays severity-dot a11y findings from `run-design-audit` /
6
+ * `get-design-review`, and a structural visual-diff section comparing two
7
+ * `design_versions`.
8
+ *
9
+ * The "Fix" button is wired to the `apply-a11y-fix` action for findings that
10
+ * are auto-fixable inline (contrast/color, tap-target, focus-visibility) — the
11
+ * fix reduces to a deterministic style/class edit against the SQL-backed HTML,
12
+ * and the canvas re-renders from the written content. Findings that need a new
13
+ * attribute (alt / aria-label) or a semantic rewrite stay informational with no
14
+ * Fix affordance. When no design source (`designId`/`fileId`) is provided the
15
+ * panel falls back to read-only.
16
+ *
17
+ * Layout matches the Review artboard in the canonical plan visual:
18
+ * <https://plan.agent-native.com/plans/plan-88dc4a09fb0c46bc>
19
+ *
20
+ * shadcn/ui primitives + Tabler icons throughout. No emojis.
21
+ */
22
+
23
+ import { useActionMutation } from "@agent-native/core/client";
24
+ import {
25
+ IconAlertCircle,
26
+ IconAlertTriangle,
27
+ IconArrowsLeftRight,
28
+ IconCheck,
29
+ IconChevronDown,
30
+ IconChevronRight,
31
+ IconInfoCircle,
32
+ IconRefresh,
33
+ IconShieldCheck,
34
+ IconWand,
35
+ } from "@tabler/icons-react";
36
+ import { useState } from "react";
37
+
38
+ import { Badge } from "@/components/ui/badge";
39
+ import { Button } from "@/components/ui/button";
40
+ import { ScrollArea } from "@/components/ui/scroll-area";
41
+ import { Separator } from "@/components/ui/separator";
42
+ import { cn } from "@/lib/utils";
43
+
44
+ import {
45
+ isA11yFindingAutoFixable,
46
+ type A11yFinding,
47
+ type A11ySeverity,
48
+ type VisualDiffChangeKind,
49
+ type VisualDiffEntry,
50
+ } from "../../../shared/design-review.js";
51
+
52
+ // ---------------------------------------------------------------------------
53
+ // Inline a11y fix wiring
54
+ // ---------------------------------------------------------------------------
55
+
56
+ /**
57
+ * Identifies the inline design source a fix should be applied to. Required for
58
+ * the "Fix" affordance to be enabled — without it the panel is read-only.
59
+ */
60
+ export interface ReviewFixSource {
61
+ designId?: string;
62
+ fileId?: string;
63
+ filename?: string;
64
+ }
65
+
66
+ /** Per-finding state for the optimistic Fix flow. */
67
+ type FixStatus = "idle" | "pending" | "fixed" | "error";
68
+
69
+ // ---------------------------------------------------------------------------
70
+ // Shared sub-types
71
+ // ---------------------------------------------------------------------------
72
+
73
+ export interface ReviewVersionOption {
74
+ id: string;
75
+ label: string;
76
+ createdAt?: string;
77
+ }
78
+
79
+ export interface ReviewPanelProps {
80
+ /** The a11y findings to show. Pass `[]` if audit has not been run yet. */
81
+ findings: A11yFinding[];
82
+ /** `true` while the audit is running. */
83
+ auditLoading?: boolean;
84
+ /** ISO-8601 timestamp of the last audit run. */
85
+ auditedAt?: string | null;
86
+ /** Error message if the last audit run failed. */
87
+ auditError?: string | null;
88
+ /** Called when the user clicks "Run audit". */
89
+ onRunAudit?: () => void;
90
+ /** Visual diff entries between base and compare versions. */
91
+ visualDiff?: VisualDiffEntry[];
92
+ /** All available design_versions for the base/compare selectors. */
93
+ versionOptions?: ReviewVersionOption[];
94
+ /** Currently selected base version id. */
95
+ baseVersionId?: string | null;
96
+ /** Currently selected compare version id. */
97
+ compareVersionId?: string | null;
98
+ /** Called when the user changes either version selector. */
99
+ onVersionChange?: (
100
+ kind: "base" | "compare",
101
+ versionId: string | null,
102
+ ) => void;
103
+ /** `true` while the diff is loading. */
104
+ diffLoading?: boolean;
105
+ /** Error message if the diff failed. */
106
+ diffError?: string | null;
107
+ /** Called when a finding row is clicked — navigates the canvas to the node. */
108
+ onFindingClick?: (finding: A11yFinding) => void;
109
+ /**
110
+ * Inline design source for the "Fix" affordance. When provided (and a
111
+ * finding is auto-fixable), a "Fix" button applies `apply-a11y-fix` against
112
+ * this source. Omit to keep the panel read-only.
113
+ */
114
+ fixSource?: ReviewFixSource;
115
+ /**
116
+ * Called after a fix is successfully applied — e.g. to refetch the audit so
117
+ * the resolved finding drops out of the list. The applied finding is passed.
118
+ */
119
+ onFixApplied?: (finding: A11yFinding) => void;
120
+ className?: string;
121
+ }
122
+
123
+ // ---------------------------------------------------------------------------
124
+ // Severity helpers
125
+ // ---------------------------------------------------------------------------
126
+
127
+ interface SeverityConfig {
128
+ dot: string;
129
+ icon: React.ElementType;
130
+ label: string;
131
+ }
132
+
133
+ const SEVERITY_CONFIG: Record<A11ySeverity, SeverityConfig> = {
134
+ error: {
135
+ dot: "bg-destructive",
136
+ icon: IconAlertCircle,
137
+ label: "Error",
138
+ },
139
+ warning: {
140
+ dot: "bg-amber-400",
141
+ icon: IconAlertTriangle,
142
+ label: "Warning",
143
+ },
144
+ info: {
145
+ dot: "bg-blue-400",
146
+ icon: IconInfoCircle,
147
+ label: "Info",
148
+ },
149
+ };
150
+
151
+ const DIFF_KIND_CONFIG: Record<
152
+ VisualDiffChangeKind,
153
+ { badge: string; label: string }
154
+ > = {
155
+ added: {
156
+ badge:
157
+ "border-emerald-500/40 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400",
158
+ label: "Added",
159
+ },
160
+ removed: {
161
+ badge:
162
+ "border-destructive/40 bg-destructive/10 text-destructive dark:text-red-400",
163
+ label: "Removed",
164
+ },
165
+ modified: {
166
+ badge:
167
+ "border-amber-500/40 bg-amber-500/10 text-amber-600 dark:text-amber-400",
168
+ label: "Modified",
169
+ },
170
+ moved: {
171
+ badge: "border-blue-500/40 bg-blue-500/10 text-blue-600 dark:text-blue-400",
172
+ label: "Moved",
173
+ },
174
+ };
175
+
176
+ // ---------------------------------------------------------------------------
177
+ // Finding row
178
+ // ---------------------------------------------------------------------------
179
+
180
+ function FindingRow({
181
+ finding,
182
+ onClick,
183
+ fixSource,
184
+ onFixApplied,
185
+ }: {
186
+ finding: A11yFinding;
187
+ onClick?: (finding: A11yFinding) => void;
188
+ fixSource?: ReviewFixSource;
189
+ onFixApplied?: (finding: A11yFinding) => void;
190
+ }) {
191
+ const cfg = SEVERITY_CONFIG[finding.severity];
192
+ const Icon = cfg.icon;
193
+ const [expanded, setExpanded] = useState(false);
194
+ const hasDetail = !!(finding.detail ?? finding.wcag);
195
+
196
+ const applyFix = useActionMutation("apply-a11y-fix");
197
+ const [fixStatus, setFixStatus] = useState<FixStatus>("idle");
198
+
199
+ // A Fix affordance is shown only when (a) the finding maps to a deterministic
200
+ // inline edit and (b) a design source is available to write to. Everything
201
+ // else stays informational.
202
+ const hasSource = !!(fixSource?.designId ?? fixSource?.fileId);
203
+ const canFix = hasSource && isA11yFindingAutoFixable(finding);
204
+
205
+ const handleFix = async (e: React.MouseEvent) => {
206
+ e.stopPropagation();
207
+ if (!canFix || fixStatus === "pending" || fixStatus === "fixed") return;
208
+ // Optimistic: flip to "fixed" immediately; the canvas re-renders from the
209
+ // written content and the parent can refetch to drop the resolved finding.
210
+ setFixStatus("pending");
211
+ try {
212
+ const res = (await applyFix.mutateAsync({
213
+ designId: fixSource?.designId,
214
+ fileId: fixSource?.fileId,
215
+ filename: fixSource?.filename,
216
+ finding: {
217
+ id: finding.id,
218
+ severity: finding.severity,
219
+ category: finding.category,
220
+ message: finding.message,
221
+ detail: finding.detail,
222
+ nodeId: finding.nodeId,
223
+ selector: finding.selector,
224
+ wcag: finding.wcag,
225
+ fixAvailable: finding.fixAvailable,
226
+ },
227
+ })) as { applied?: boolean } | undefined;
228
+ if (res?.applied) {
229
+ setFixStatus("fixed");
230
+ onFixApplied?.(finding);
231
+ } else {
232
+ // The engine could not apply it (e.g. selector no longer resolves).
233
+ setFixStatus("error");
234
+ }
235
+ } catch {
236
+ setFixStatus("error");
237
+ }
238
+ };
239
+
240
+ return (
241
+ <div
242
+ className={cn(
243
+ "group rounded px-2 py-1.5 transition-colors",
244
+ onClick ? "cursor-pointer hover:bg-accent/60" : "cursor-default",
245
+ )}
246
+ role={onClick ? "button" : undefined}
247
+ tabIndex={onClick ? 0 : undefined}
248
+ onClick={() => onClick?.(finding)}
249
+ onKeyDown={(e) => {
250
+ if (e.key === "Enter" || e.key === " ") onClick?.(finding);
251
+ }}
252
+ aria-label={finding.message}
253
+ >
254
+ <div className="flex items-start gap-2">
255
+ {/* Severity dot */}
256
+ <span
257
+ className={cn("mt-[5px] size-1.5 shrink-0 rounded-full", cfg.dot)}
258
+ aria-hidden="true"
259
+ />
260
+
261
+ {/* Message + expand toggle */}
262
+ <div className="min-w-0 flex-1">
263
+ <div className="flex items-center gap-1">
264
+ <Icon
265
+ className={cn(
266
+ "size-3.5 shrink-0",
267
+ finding.severity === "error"
268
+ ? "text-destructive"
269
+ : finding.severity === "warning"
270
+ ? "text-amber-500"
271
+ : "text-blue-500",
272
+ )}
273
+ aria-hidden="true"
274
+ />
275
+ <span className="truncate text-[11px] text-foreground leading-snug">
276
+ {finding.message}
277
+ </span>
278
+ {hasDetail && (
279
+ <button
280
+ type="button"
281
+ className="ml-auto shrink-0 text-muted-foreground/50 hover:text-foreground"
282
+ onClick={(e) => {
283
+ e.stopPropagation();
284
+ setExpanded((v) => !v);
285
+ }}
286
+ aria-label={expanded ? "Collapse detail" : "Expand detail"}
287
+ aria-expanded={expanded}
288
+ >
289
+ {expanded ? (
290
+ <IconChevronDown className="size-3" />
291
+ ) : (
292
+ <IconChevronRight className="size-3" />
293
+ )}
294
+ </button>
295
+ )}
296
+ </div>
297
+
298
+ {/* WCAG badge */}
299
+ {finding.wcag && (
300
+ <span className="text-[10px] text-muted-foreground/60">
301
+ WCAG {finding.wcag}
302
+ </span>
303
+ )}
304
+
305
+ {/* Expanded detail */}
306
+ {expanded && finding.detail && (
307
+ <p className="mt-1 text-[11px] leading-snug text-muted-foreground">
308
+ {finding.detail}
309
+ </p>
310
+ )}
311
+ </div>
312
+
313
+ {/* Fix button — enabled only for inline auto-fixable findings with a
314
+ design source. Non-fixable findings render nothing (informational). */}
315
+ {canFix &&
316
+ (fixStatus === "fixed" ? (
317
+ <span
318
+ className="flex h-5 shrink-0 items-center gap-1 px-1.5 text-[10px] text-emerald-500"
319
+ title="Fix applied"
320
+ >
321
+ <IconCheck className="size-3" />
322
+ Fixed
323
+ </span>
324
+ ) : (
325
+ <Button
326
+ type="button"
327
+ variant="ghost"
328
+ size="sm"
329
+ disabled={fixStatus === "pending"}
330
+ className={cn(
331
+ "h-5 shrink-0 gap-1 px-1.5 text-[10px]",
332
+ fixStatus === "error"
333
+ ? "text-destructive hover:text-destructive"
334
+ : "text-muted-foreground hover:text-foreground",
335
+ )}
336
+ title={
337
+ fixStatus === "error"
338
+ ? "Fix could not be applied — retry"
339
+ : "Apply this fix inline"
340
+ }
341
+ onClick={handleFix}
342
+ >
343
+ {fixStatus === "pending" ? (
344
+ <IconRefresh className="size-3 animate-spin" />
345
+ ) : (
346
+ <IconWand className="size-3" />
347
+ )}
348
+ {fixStatus === "error" ? "Retry" : "Fix"}
349
+ </Button>
350
+ ))}
351
+ </div>
352
+ </div>
353
+ );
354
+ }
355
+
356
+ // ---------------------------------------------------------------------------
357
+ // A11y findings section
358
+ // ---------------------------------------------------------------------------
359
+
360
+ function A11ySection({
361
+ findings,
362
+ loading,
363
+ auditedAt,
364
+ auditError,
365
+ onRunAudit,
366
+ onFindingClick,
367
+ fixSource,
368
+ onFixApplied,
369
+ }: {
370
+ findings: A11yFinding[];
371
+ loading?: boolean;
372
+ auditedAt?: string | null;
373
+ auditError?: string | null;
374
+ onRunAudit?: () => void;
375
+ onFindingClick?: (finding: A11yFinding) => void;
376
+ fixSource?: ReviewFixSource;
377
+ onFixApplied?: (finding: A11yFinding) => void;
378
+ }) {
379
+ const errors = findings.filter((f) => f.severity === "error");
380
+ const warnings = findings.filter((f) => f.severity === "warning");
381
+ const infos = findings.filter((f) => f.severity === "info");
382
+
383
+ const hasFindings = findings.length > 0;
384
+ const notRun = !auditedAt && !loading && !auditError && !hasFindings;
385
+
386
+ return (
387
+ <section aria-labelledby="review-a11y-heading">
388
+ {/* Section header */}
389
+ <div className="flex h-8 items-center justify-between px-3">
390
+ <div className="flex items-center gap-1.5">
391
+ <IconShieldCheck className="size-3.5 text-muted-foreground" />
392
+ <span
393
+ id="review-a11y-heading"
394
+ className="text-[11px] font-semibold text-foreground"
395
+ >
396
+ Accessibility
397
+ </span>
398
+ {hasFindings && (
399
+ <div className="flex items-center gap-1">
400
+ {errors.length > 0 && (
401
+ <Badge
402
+ variant="outline"
403
+ className="h-4 border-destructive/40 bg-destructive/10 px-1 text-[9px] text-destructive"
404
+ >
405
+ {errors.length}
406
+ </Badge>
407
+ )}
408
+ {warnings.length > 0 && (
409
+ <Badge
410
+ variant="outline"
411
+ className="h-4 border-amber-500/40 bg-amber-500/10 px-1 text-[9px] text-amber-600 dark:text-amber-400"
412
+ >
413
+ {warnings.length}
414
+ </Badge>
415
+ )}
416
+ {infos.length > 0 && (
417
+ <Badge
418
+ variant="outline"
419
+ className="h-4 border-blue-500/40 bg-blue-500/10 px-1 text-[9px] text-blue-600 dark:text-blue-400"
420
+ >
421
+ {infos.length}
422
+ </Badge>
423
+ )}
424
+ </div>
425
+ )}
426
+ </div>
427
+
428
+ {/* Run audit button */}
429
+ {onRunAudit && (
430
+ <Button
431
+ type="button"
432
+ variant="ghost"
433
+ size="sm"
434
+ disabled={loading}
435
+ onClick={onRunAudit}
436
+ className="h-6 px-2 text-[10px] text-muted-foreground hover:text-foreground"
437
+ >
438
+ {loading ? (
439
+ <IconRefresh className="size-3 animate-spin" />
440
+ ) : (
441
+ <IconRefresh className="size-3" />
442
+ )}
443
+ {loading ? "Running…" : "Run"}
444
+ </Button>
445
+ )}
446
+ </div>
447
+
448
+ <Separator className="mx-3" />
449
+
450
+ <div className="px-1 py-1">
451
+ {/* Error state */}
452
+ {auditError && (
453
+ <div className="flex items-center gap-2 rounded px-2 py-1.5">
454
+ <IconAlertCircle className="size-3.5 shrink-0 text-destructive" />
455
+ <span className="text-[11px] text-muted-foreground">
456
+ {auditError}
457
+ </span>
458
+ </div>
459
+ )}
460
+
461
+ {/* Not yet run */}
462
+ {notRun && (
463
+ <div className="flex flex-col items-center gap-2 py-5 text-center">
464
+ <IconShieldCheck className="size-5 text-muted-foreground/30" />
465
+ <p className="text-[11px] leading-snug text-muted-foreground/60">
466
+ No audit has been run yet.
467
+ {onRunAudit && (
468
+ <>
469
+ {" "}
470
+ Click <strong>Run</strong> to scan this design.
471
+ </>
472
+ )}
473
+ </p>
474
+ </div>
475
+ )}
476
+
477
+ {/* Loading */}
478
+ {loading && !hasFindings && (
479
+ <div className="flex items-center gap-2 px-2 py-3">
480
+ <IconRefresh className="size-3.5 animate-spin text-muted-foreground/50" />
481
+ <span className="text-[11px] text-muted-foreground/60">
482
+ Scanning…
483
+ </span>
484
+ </div>
485
+ )}
486
+
487
+ {/* All clear */}
488
+ {!loading && !auditError && !notRun && !hasFindings && (
489
+ <div className="flex items-center gap-2 px-2 py-3">
490
+ <IconCheck className="size-3.5 text-emerald-500" />
491
+ <span className="text-[11px] text-muted-foreground">
492
+ No issues found.
493
+ </span>
494
+ </div>
495
+ )}
496
+
497
+ {/* Findings list */}
498
+ {hasFindings && (
499
+ <div className="space-y-0.5">
500
+ {[...errors, ...warnings, ...infos].map((finding) => (
501
+ <FindingRow
502
+ key={finding.id}
503
+ finding={finding}
504
+ onClick={onFindingClick}
505
+ fixSource={fixSource}
506
+ onFixApplied={onFixApplied}
507
+ />
508
+ ))}
509
+ </div>
510
+ )}
511
+
512
+ {/* Audit timestamp */}
513
+ {auditedAt && (
514
+ <p className="mt-1.5 px-2 text-[10px] text-muted-foreground/40">
515
+ Last audited{" "}
516
+ {new Date(auditedAt).toLocaleString(undefined, {
517
+ dateStyle: "short",
518
+ timeStyle: "short",
519
+ })}
520
+ </p>
521
+ )}
522
+ </div>
523
+ </section>
524
+ );
525
+ }
526
+
527
+ // ---------------------------------------------------------------------------
528
+ // Visual diff section
529
+ // ---------------------------------------------------------------------------
530
+
531
+ function VersionLabel({
532
+ options,
533
+ value,
534
+ placeholder,
535
+ onChange,
536
+ }: {
537
+ options: ReviewVersionOption[];
538
+ value: string | null | undefined;
539
+ placeholder: string;
540
+ onChange: (id: string | null) => void;
541
+ }) {
542
+ // Native <select> keeps bundle small; matches design-editor's compact inputs.
543
+ return (
544
+ <select
545
+ value={value ?? ""}
546
+ onChange={(e) => onChange(e.target.value || null)}
547
+ className="h-6 max-w-[120px] flex-1 truncate rounded border border-border bg-transparent px-1.5 text-[10px] text-foreground focus:outline-none focus:ring-1 focus:ring-ring"
548
+ aria-label={placeholder}
549
+ >
550
+ <option value="">{placeholder}</option>
551
+ {options.map((opt) => (
552
+ <option key={opt.id} value={opt.id}>
553
+ {opt.label}
554
+ </option>
555
+ ))}
556
+ </select>
557
+ );
558
+ }
559
+
560
+ function DiffRow({ entry }: { entry: VisualDiffEntry }) {
561
+ const cfg = DIFF_KIND_CONFIG[entry.kind];
562
+ return (
563
+ <div className="flex items-center gap-2 rounded px-2 py-1 hover:bg-accent/40">
564
+ <Badge
565
+ variant="outline"
566
+ className={cn("h-4 shrink-0 px-1 text-[9px] font-medium", cfg.badge)}
567
+ >
568
+ {cfg.label}
569
+ </Badge>
570
+ <span className="truncate text-[11px] text-foreground leading-snug">
571
+ {entry.description ?? entry.id}
572
+ </span>
573
+ </div>
574
+ );
575
+ }
576
+
577
+ function VisualDiffSection({
578
+ diff,
579
+ versionOptions,
580
+ baseVersionId,
581
+ compareVersionId,
582
+ onVersionChange,
583
+ loading,
584
+ diffError,
585
+ }: {
586
+ diff: VisualDiffEntry[];
587
+ versionOptions: ReviewVersionOption[];
588
+ baseVersionId?: string | null;
589
+ compareVersionId?: string | null;
590
+ onVersionChange?: (kind: "base" | "compare", id: string | null) => void;
591
+ loading?: boolean;
592
+ diffError?: string | null;
593
+ }) {
594
+ const hasDiff = diff.length > 0;
595
+ const hasVersions = versionOptions.length > 0;
596
+ const noVersionsSelected = !baseVersionId && !compareVersionId;
597
+
598
+ return (
599
+ <section aria-labelledby="review-diff-heading">
600
+ <div className="flex h-8 items-center gap-1.5 px-3">
601
+ <IconArrowsLeftRight className="size-3.5 text-muted-foreground" />
602
+ <span
603
+ id="review-diff-heading"
604
+ className="text-[11px] font-semibold text-foreground"
605
+ >
606
+ Visual diff
607
+ </span>
608
+ {hasDiff && (
609
+ <Badge
610
+ variant="outline"
611
+ className="h-4 border-border px-1 text-[9px] text-muted-foreground"
612
+ >
613
+ {diff.length}
614
+ </Badge>
615
+ )}
616
+ </div>
617
+
618
+ <Separator className="mx-3" />
619
+
620
+ <div className="px-3 py-2 space-y-2">
621
+ {/* Version selectors */}
622
+ {hasVersions && (
623
+ <div className="flex items-center gap-1.5">
624
+ <span className="shrink-0 text-[10px] text-muted-foreground/70">
625
+ Base
626
+ </span>
627
+ <VersionLabel
628
+ options={versionOptions}
629
+ value={baseVersionId}
630
+ placeholder="Select…"
631
+ onChange={(id) => onVersionChange?.("base", id)}
632
+ />
633
+ <IconArrowsLeftRight className="size-3 shrink-0 text-muted-foreground/40" />
634
+ <VersionLabel
635
+ options={versionOptions}
636
+ value={compareVersionId}
637
+ placeholder="Select…"
638
+ onChange={(id) => onVersionChange?.("compare", id)}
639
+ />
640
+ </div>
641
+ )}
642
+
643
+ {/* States */}
644
+ {diffError && (
645
+ <div className="flex items-center gap-2">
646
+ <IconAlertCircle className="size-3.5 shrink-0 text-destructive" />
647
+ <span className="text-[11px] text-muted-foreground">
648
+ {diffError}
649
+ </span>
650
+ </div>
651
+ )}
652
+
653
+ {loading && (
654
+ <div className="flex items-center gap-2">
655
+ <IconRefresh className="size-3.5 animate-spin text-muted-foreground/50" />
656
+ <span className="text-[11px] text-muted-foreground/60">
657
+ Comparing…
658
+ </span>
659
+ </div>
660
+ )}
661
+
662
+ {!loading && !diffError && noVersionsSelected && !hasDiff && (
663
+ <p className="text-[11px] text-muted-foreground/50">
664
+ {hasVersions
665
+ ? "Select two versions above to see what changed."
666
+ : "No versions saved yet. Save a version to compare."}
667
+ </p>
668
+ )}
669
+
670
+ {!loading && !diffError && !noVersionsSelected && !hasDiff && (
671
+ <div className="flex items-center gap-2">
672
+ <IconCheck className="size-3.5 text-emerald-500" />
673
+ <span className="text-[11px] text-muted-foreground">
674
+ No structural changes detected.
675
+ </span>
676
+ </div>
677
+ )}
678
+
679
+ {/* Diff rows */}
680
+ {hasDiff && (
681
+ <div className="space-y-0.5">
682
+ {diff.map((entry) => (
683
+ <DiffRow key={entry.id} entry={entry} />
684
+ ))}
685
+ </div>
686
+ )}
687
+ </div>
688
+ </section>
689
+ );
690
+ }
691
+
692
+ // ---------------------------------------------------------------------------
693
+ // Top-level ReviewPanel
694
+ // ---------------------------------------------------------------------------
695
+
696
+ /**
697
+ * ReviewPanel renders the accessibility audit results and visual-diff section
698
+ * for the Design Studio's Review inspector tab / bottom dock.
699
+ *
700
+ * When a `fixSource` is supplied, auto-fixable findings (contrast/color,
701
+ * tap-target, focus-visibility) show an inline "Fix" button wired to the
702
+ * `apply-a11y-fix` action; the canvas re-renders from the written content.
703
+ * Findings that need a new attribute or a semantic rewrite remain
704
+ * informational. Without a `fixSource` the panel is read-only.
705
+ */
706
+ export function ReviewPanel({
707
+ findings,
708
+ auditLoading,
709
+ auditedAt,
710
+ auditError,
711
+ onRunAudit,
712
+ visualDiff = [],
713
+ versionOptions = [],
714
+ baseVersionId,
715
+ compareVersionId,
716
+ onVersionChange,
717
+ diffLoading,
718
+ diffError,
719
+ onFindingClick,
720
+ fixSource,
721
+ onFixApplied,
722
+ className,
723
+ }: ReviewPanelProps) {
724
+ return (
725
+ <div
726
+ className={cn("flex flex-col overflow-hidden text-[11px]", className)}
727
+ data-testid="review-panel"
728
+ >
729
+ <ScrollArea className="flex-1">
730
+ <div className="py-1">
731
+ <A11ySection
732
+ findings={findings}
733
+ loading={auditLoading}
734
+ auditedAt={auditedAt}
735
+ auditError={auditError}
736
+ onRunAudit={onRunAudit}
737
+ onFindingClick={onFindingClick}
738
+ fixSource={fixSource}
739
+ onFixApplied={onFixApplied}
740
+ />
741
+
742
+ <div className="my-2 mx-3">
743
+ <Separator />
744
+ </div>
745
+
746
+ <VisualDiffSection
747
+ diff={visualDiff}
748
+ versionOptions={versionOptions}
749
+ baseVersionId={baseVersionId}
750
+ compareVersionId={compareVersionId}
751
+ onVersionChange={onVersionChange}
752
+ loading={diffLoading}
753
+ diffError={diffError}
754
+ />
755
+ </div>
756
+ </ScrollArea>
757
+ </div>
758
+ );
759
+ }