@cat-factory/app 0.308.0 → 0.310.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 (265) hide show
  1. package/README.md +32 -2
  2. package/app/assets/css/main.css +22 -0
  3. package/app/assets/css/prose.css +4 -4
  4. package/app/assets/css/type.css +24 -0
  5. package/app/components/assistant/AssistantModal.vue +8 -6
  6. package/app/components/auth/BackendMisconfiguredScreen.vue +4 -3
  7. package/app/components/auth/LoginScreen.vue +40 -26
  8. package/app/components/auth/ResetPasswordScreen.vue +9 -4
  9. package/app/components/auth/UserMenu.vue +5 -4
  10. package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +48 -37
  11. package/app/components/binaryOutput/BinaryOutputReport.vue +10 -14
  12. package/app/components/binaryOutput/StoredAssetView.vue +13 -11
  13. package/app/components/board/AddTaskModal.vue +30 -27
  14. package/app/components/board/AgentFailureCard.vue +21 -18
  15. package/app/components/board/AgentFailureHistory.vue +18 -9
  16. package/app/components/board/CreateInitiativeModal.vue +7 -6
  17. package/app/components/board/FailureDetail.vue +22 -12
  18. package/app/components/board/FailureHistoryList.vue +5 -5
  19. package/app/components/board/RecurringPipelineModal.vue +12 -11
  20. package/app/components/board/ReviewFrictionDialog.vue +8 -6
  21. package/app/components/board/StepExecutionHistory.vue +8 -8
  22. package/app/components/board/nodes/AgentChip.vue +1 -1
  23. package/app/components/board/nodes/BlockNode.vue +25 -24
  24. package/app/components/board/nodes/DecisionBadge.vue +4 -3
  25. package/app/components/board/nodes/EpicNode.vue +4 -4
  26. package/app/components/board/nodes/FrameSwimlanes.vue +8 -10
  27. package/app/components/board/nodes/InitiativeCard.vue +4 -4
  28. package/app/components/board/nodes/LaneGroup.vue +3 -5
  29. package/app/components/board/nodes/TaskCard.vue +20 -15
  30. package/app/components/board/nodes/TaskLane.vue +3 -3
  31. package/app/components/board/nodes/TaskPipelineMini.vue +21 -18
  32. package/app/components/bootstrap/AdoptionReviewModal.vue +36 -26
  33. package/app/components/bootstrap/BootstrapModal.vue +14 -13
  34. package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
  35. package/app/components/brainstorm/BrainstormWindow.vue +13 -10
  36. package/app/components/bugFishing/BugFishingWindow.vue +81 -58
  37. package/app/components/clarity/ClarityReviewWindow.vue +13 -10
  38. package/app/components/common/AsyncViewError.vue +1 -1
  39. package/app/components/common/ClarificationItem.vue +6 -6
  40. package/app/components/common/CopyButton.vue +12 -11
  41. package/app/components/common/DescriptorFields.vue +1 -1
  42. package/app/components/common/EmptyState.vue +1 -1
  43. package/app/components/common/IconButton.vue +34 -9
  44. package/app/components/common/InterviewGateNotice.vue +4 -4
  45. package/app/components/common/MarkdownProse.vue +8 -2
  46. package/app/components/common/SectionLabel.vue +38 -0
  47. package/app/components/consensus/ConsensusSessionWindow.vue +10 -9
  48. package/app/components/context/ContextAttachmentFields.vue +32 -20
  49. package/app/components/docs/DocInterviewWindow.vue +10 -9
  50. package/app/components/documents/ContextDocumentPicker.vue +22 -21
  51. package/app/components/documents/DocumentImportModal.vue +7 -5
  52. package/app/components/documents/DocumentOriginLink.vue +12 -9
  53. package/app/components/documents/DocumentSourceConnectModal.vue +2 -2
  54. package/app/components/documents/DocumentSyncState.vue +4 -4
  55. package/app/components/documents/DocumentTemplatesModal.vue +5 -4
  56. package/app/components/documents/RepoContextDocPicker.vue +7 -9
  57. package/app/components/documents/StartFromDesignModal.vue +4 -4
  58. package/app/components/documents/TaskContextDocs.vue +1 -1
  59. package/app/components/environments/EnvSetupStepper.vue +3 -3
  60. package/app/components/environments/EnvironmentStatusPanel.vue +15 -13
  61. package/app/components/environments/steps/EnvPreflightStep.vue +8 -8
  62. package/app/components/environments/steps/EnvReviewStep.vue +23 -22
  63. package/app/components/environments/steps/EnvSaveStep.vue +5 -5
  64. package/app/components/focus/BlockFocusView.vue +11 -10
  65. package/app/components/followUp/FollowUpWindow.vue +18 -15
  66. package/app/components/forkDecision/ForkDecisionWindow.vue +85 -97
  67. package/app/components/foundational/FoundationalContractSummary.vue +2 -2
  68. package/app/components/foundational/FoundationalServiceCatalogList.vue +6 -5
  69. package/app/components/foundational/FoundationalServiceRegistry.vue +10 -9
  70. package/app/components/foundational/FoundationalServiceSources.vue +7 -6
  71. package/app/components/foundational/FoundationalSuppressions.vue +2 -2
  72. package/app/components/fragments/FragmentLibraryManager.vue +8 -7
  73. package/app/components/fragments/FragmentSelector.vue +22 -20
  74. package/app/components/gates/GateFailingCheckList.vue +7 -6
  75. package/app/components/gates/GateResultView.vue +55 -49
  76. package/app/components/github/AddServiceFromRepoModal.vue +16 -11
  77. package/app/components/github/BranchProtectionPreflight.vue +5 -5
  78. package/app/components/github/GitHubConnect.vue +5 -3
  79. package/app/components/github/GitHubOnboarding.vue +7 -2
  80. package/app/components/github/GitHubPanel.vue +23 -19
  81. package/app/components/github/RepoTreeBrowser.vue +16 -13
  82. package/app/components/humanTest/HumanTestWindow.vue +29 -24
  83. package/app/components/initiative/InitiativePlanNotice.vue +3 -3
  84. package/app/components/initiative/InitiativePlanReview.vue +46 -38
  85. package/app/components/initiative/InitiativePlanningWindow.vue +5 -5
  86. package/app/components/initiative/InitiativeTrackerWindow.vue +213 -165
  87. package/app/components/judge/JudgeResultView.vue +28 -27
  88. package/app/components/kaizen/KaizenPanel.vue +70 -56
  89. package/app/components/kaizen/KaizenStepStatus.vue +7 -6
  90. package/app/components/layout/AccountAuditLog.vue +1 -1
  91. package/app/components/layout/AccountDeploymentSettings.vue +10 -10
  92. package/app/components/layout/AccountFailureKindRules.vue +13 -13
  93. package/app/components/layout/AccountFoundationalSettings.vue +1 -1
  94. package/app/components/layout/AccountFragmentSettings.vue +1 -1
  95. package/app/components/layout/AccountModelPolicySettings.vue +7 -7
  96. package/app/components/layout/AccountPlatformAlertSettings.vue +8 -8
  97. package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
  98. package/app/components/layout/AccountRunCredentialSettings.vue +3 -3
  99. package/app/components/layout/AccountSkillSettings.vue +1 -1
  100. package/app/components/layout/AccountTeamSettings.vue +13 -9
  101. package/app/components/layout/AiProvidersBanner.vue +1 -1
  102. package/app/components/layout/AppearanceSwitcher.vue +5 -4
  103. package/app/components/layout/BoardSwitcher.vue +13 -10
  104. package/app/components/layout/BoardToolbar.vue +10 -5
  105. package/app/components/layout/CommandBar.vue +8 -5
  106. package/app/components/layout/DefaultTestEnvBanner.vue +6 -5
  107. package/app/components/layout/IntegrationsHub.vue +12 -9
  108. package/app/components/layout/LanguageSwitcher.vue +5 -4
  109. package/app/components/layout/ModelProvidersHub.vue +10 -7
  110. package/app/components/layout/NotificationsInbox.vue +47 -36
  111. package/app/components/layout/PersonalSetupModal.vue +9 -6
  112. package/app/components/layout/RolePrompt.vue +5 -4
  113. package/app/components/layout/SideBar.vue +7 -8
  114. package/app/components/layout/SpendWarningBanner.vue +3 -3
  115. package/app/components/layout/TranslationWarningBanner.vue +5 -4
  116. package/app/components/layout/UiModeSwitcher.vue +15 -12
  117. package/app/components/layout/UiRoleSwitcher.vue +10 -8
  118. package/app/components/layout/WorkspaceMembersSettings.vue +2 -2
  119. package/app/components/media/ArtifactLightbox.vue +74 -44
  120. package/app/components/media/ImageCompare.vue +80 -85
  121. package/app/components/merge/MergeEffortChips.vue +4 -6
  122. package/app/components/notifications/NotificationSettingsPanel.vue +6 -5
  123. package/app/components/observability/OutcomeFilterChips.vue +6 -5
  124. package/app/components/observability/RunFailureSummary.vue +22 -23
  125. package/app/components/observability/StepMetricsBar.vue +9 -8
  126. package/app/components/observability/StepModelActivity.vue +8 -5
  127. package/app/components/observability/ToolCallList.vue +19 -20
  128. package/app/components/outcome/OutcomeSummaryWindow.vue +48 -46
  129. package/app/components/palettes/AgentPalette.vue +21 -15
  130. package/app/components/palettes/AgentTierSelect.vue +1 -1
  131. package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
  132. package/app/components/panels/AgentStepDetail.vue +57 -49
  133. package/app/components/panels/AttemptEntryHeader.vue +2 -2
  134. package/app/components/panels/DecisionModal.vue +1 -1
  135. package/app/components/panels/GenericStructuredResultView.vue +6 -5
  136. package/app/components/panels/InspectorPanel.vue +15 -13
  137. package/app/components/panels/MergerResultView.vue +10 -9
  138. package/app/components/panels/ObservabilityPanel.vue +211 -186
  139. package/app/components/panels/OperatorDashboardPanel.vue +124 -115
  140. package/app/components/panels/ReportsPanel.vue +87 -83
  141. package/app/components/panels/ReportsSpendBreakdown.vue +2 -2
  142. package/app/components/panels/ResultWindowShell.vue +152 -137
  143. package/app/components/panels/RunDetailLoadState.vue +1 -1
  144. package/app/components/panels/StepContainerStatus.vue +17 -16
  145. package/app/components/panels/StepDelegatedStatus.vue +24 -21
  146. package/app/components/panels/StepEffortReport.vue +12 -17
  147. package/app/components/panels/StepFragmentAdherence.vue +9 -10
  148. package/app/components/panels/StepMetadataCard.vue +41 -43
  149. package/app/components/panels/StepReproductionReport.vue +18 -20
  150. package/app/components/panels/StepRestartControl.vue +3 -2
  151. package/app/components/panels/StepRunMeta.vue +27 -26
  152. package/app/components/panels/StepTestReport.vue +16 -15
  153. package/app/components/panels/StepToolServers.vue +7 -8
  154. package/app/components/panels/StepValidationReport.vue +5 -5
  155. package/app/components/panels/inspector/ContainerSummary.vue +4 -4
  156. package/app/components/panels/inspector/DocReferenceRepos.vue +5 -4
  157. package/app/components/panels/inspector/EnvProbeReport.vue +16 -13
  158. package/app/components/panels/inspector/EpicChildren.vue +12 -10
  159. package/app/components/panels/inspector/FrontendBindingsResolved.vue +5 -4
  160. package/app/components/panels/inspector/FrontendConfig.vue +29 -36
  161. package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
  162. package/app/components/panels/inspector/InspectorSection.vue +25 -17
  163. package/app/components/panels/inspector/RecurringScheduleSettings.vue +9 -8
  164. package/app/components/panels/inspector/ServiceConnections.vue +5 -4
  165. package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
  166. package/app/components/panels/inspector/ServiceSelfTests.vue +9 -13
  167. package/app/components/panels/inspector/ServiceTestConfig.vue +46 -49
  168. package/app/components/panels/inspector/ServiceTestSecrets.vue +3 -3
  169. package/app/components/panels/inspector/ServiceTestingContext.vue +2 -2
  170. package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
  171. package/app/components/panels/inspector/TaskAgentConfig.vue +2 -2
  172. package/app/components/panels/inspector/TaskAprioriBranches.vue +6 -5
  173. package/app/components/panels/inspector/TaskDependencies.vue +1 -1
  174. package/app/components/panels/inspector/TaskEstimateBadge.vue +3 -7
  175. package/app/components/panels/inspector/TaskExecution.vue +18 -16
  176. package/app/components/panels/inspector/TaskRunSettings.vue +45 -44
  177. package/app/components/panels/inspector/TaskStructure.vue +5 -4
  178. package/app/components/pipeline/AgentPromptEditor.vue +15 -14
  179. package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -52
  180. package/app/components/pipeline/EstimateThresholdFields.vue +14 -11
  181. package/app/components/pipeline/GateConfigFields.vue +19 -23
  182. package/app/components/pipeline/IterationCapPrompt.vue +1 -1
  183. package/app/components/pipeline/PipelineBuilder.vue +113 -99
  184. package/app/components/pipeline/PipelineHealthModal.vue +7 -7
  185. package/app/components/pipeline/PipelinePicker.vue +11 -9
  186. package/app/components/pipeline/PipelinePreview.vue +6 -7
  187. package/app/components/pipeline/PipelineProgress.vue +49 -45
  188. package/app/components/prReview/PrReviewWindow.vue +87 -65
  189. package/app/components/providers/AiPresetMismatchDialog.vue +4 -3
  190. package/app/components/providers/AiProviderOnboardingModal.vue +2 -2
  191. package/app/components/providers/ApiKeysSection.vue +11 -9
  192. package/app/components/providers/PersonalSubscriptionSection.vue +4 -3
  193. package/app/components/providers/VendorCredentialsModal.vue +5 -4
  194. package/app/components/provisioning/ProvisioningLogsDrawer.vue +10 -9
  195. package/app/components/ralph/RalphLoopResultView.vue +29 -29
  196. package/app/components/requirements/RequirementsReviewWindow.vue +22 -17
  197. package/app/components/riskPolicy/RiskPolicyPicker.vue +13 -11
  198. package/app/components/riskPolicy/RiskPolicyPreview.vue +16 -15
  199. package/app/components/sandbox/SandboxPanel.vue +93 -73
  200. package/app/components/settings/ApiTokensPanel.vue +1 -1
  201. package/app/components/settings/BudgetSettings.vue +18 -17
  202. package/app/components/settings/CapabilityCredentialsPanel.vue +5 -5
  203. package/app/components/settings/CloudflareHandlerSection.vue +44 -41
  204. package/app/components/settings/ComposeEnvironmentSetupSection.vue +14 -12
  205. package/app/components/settings/ConnectionTestVerdict.vue +1 -1
  206. package/app/components/settings/ConsensusGroupsSection.vue +58 -47
  207. package/app/components/settings/CustomManifestTypeEditor.vue +8 -7
  208. package/app/components/settings/DefaultProvisionTypeSection.vue +5 -5
  209. package/app/components/settings/InfraHandlersConfigurator.vue +26 -24
  210. package/app/components/settings/InfrastructureBackendPicker.vue +18 -18
  211. package/app/components/settings/IssueTrackerPanel.vue +30 -21
  212. package/app/components/settings/KubernetesEngineForm.vue +9 -8
  213. package/app/components/settings/KubernetesEnvironmentForm.vue +4 -3
  214. package/app/components/settings/LocalContainerPoolSettings.vue +2 -2
  215. package/app/components/settings/LocalModelEndpointsPanel.vue +13 -11
  216. package/app/components/settings/MergeClassRulesEditor.vue +6 -5
  217. package/app/components/settings/MergeRolePolicyEditor.vue +13 -12
  218. package/app/components/settings/ModelConfigurationPanel.vue +17 -19
  219. package/app/components/settings/ModelPresetHealthModal.vue +3 -3
  220. package/app/components/settings/ObservabilityConnectionPanel.vue +1 -1
  221. package/app/components/settings/OpenRouterCatalogPanel.vue +10 -8
  222. package/app/components/settings/PackageRegistriesPanel.vue +4 -4
  223. package/app/components/settings/ProviderConnectionTab.vue +5 -4
  224. package/app/components/settings/ProviderManifestEditor.vue +9 -8
  225. package/app/components/settings/ProviderPreferenceEditor.vue +13 -13
  226. package/app/components/settings/RiskPolicyCreateForm.vue +40 -26
  227. package/app/components/settings/RiskPolicyEditorRow.vue +21 -19
  228. package/app/components/settings/RiskPolicyHealthModal.vue +3 -3
  229. package/app/components/settings/RiskPolicyPanel.vue +11 -13
  230. package/app/components/settings/ServiceFragmentDefaultsPanel.vue +15 -12
  231. package/app/components/settings/SharedStacksPanel.vue +5 -5
  232. package/app/components/settings/TaskSourceCard.vue +2 -2
  233. package/app/components/settings/TaskTypeSuppressionsPanel.vue +4 -4
  234. package/app/components/settings/ToolServerChecklist.vue +22 -22
  235. package/app/components/settings/UsageSettings.vue +13 -13
  236. package/app/components/settings/UserSecretsSection.vue +4 -3
  237. package/app/components/settings/WorkspaceMetadataSettings.vue +6 -5
  238. package/app/components/settings/WorkspaceSettingsPanel.vue +72 -58
  239. package/app/components/skills/ReviewSkillQueue.vue +12 -10
  240. package/app/components/skills/SkillLibraryManager.vue +9 -8
  241. package/app/components/slack/SlackPanel.vue +17 -12
  242. package/app/components/spec/ServiceSpecWindow.vue +19 -19
  243. package/app/components/tasks/BugHuntModal.vue +1 -1
  244. package/app/components/tasks/ContextIssuePicker.vue +16 -15
  245. package/app/components/tasks/TaskContextIssues.vue +5 -4
  246. package/app/components/tasks/TaskImportModal.vue +3 -2
  247. package/app/components/tasks/TaskSourceConnectModal.vue +5 -5
  248. package/app/components/testing/TestReportWindow.vue +67 -60
  249. package/app/components/theme/ThemeImportModal.vue +2 -2
  250. package/app/components/tutorial/TutorialNudge.vue +3 -2
  251. package/app/components/tutorial/TutorialOverlay.vue +3 -2
  252. package/app/components/vcs/GitLabConnect.vue +1 -1
  253. package/app/components/visualConfirm/VisualConfirmationWindow.vue +79 -54
  254. package/app/utils/theme/builtins.ts +7 -1
  255. package/i18n/locales/de.json +7 -3
  256. package/i18n/locales/en.json +7 -3
  257. package/i18n/locales/es.json +7 -3
  258. package/i18n/locales/fr.json +7 -3
  259. package/i18n/locales/he.json +7 -3
  260. package/i18n/locales/it.json +7 -3
  261. package/i18n/locales/ja.json +7 -3
  262. package/i18n/locales/pl.json +7 -3
  263. package/i18n/locales/tr.json +7 -3
  264. package/i18n/locales/uk.json +7 -3
  265. package/package.json +1 -1
@@ -267,7 +267,7 @@ const hasOverrides = computed(
267
267
  <h4 class="text-sm font-semibold text-default">
268
268
  {{ t('settings.platformAlerts.title') }}
269
269
  </h4>
270
- <p class="text-[11px] text-muted">{{ t('settings.platformAlerts.description') }}</p>
270
+ <p class="text-2xs text-muted">{{ t('settings.platformAlerts.description') }}</p>
271
271
  </div>
272
272
 
273
273
  <!--
@@ -282,11 +282,11 @@ const hasOverrides = computed(
282
282
  :label="t('settings.platformAlerts.muteLabel')"
283
283
  data-testid="platform-alerts-mute"
284
284
  />
285
- <p class="ps-6 text-[11px] text-muted">{{ t('settings.platformAlerts.muteHint') }}</p>
285
+ <p class="ps-6 text-2xs text-muted">{{ t('settings.platformAlerts.muteHint') }}</p>
286
286
  </div>
287
287
 
288
288
  <div class="space-y-1">
289
- <label class="text-[11px] font-medium text-toned">
289
+ <label class="text-2xs font-medium text-toned">
290
290
  {{ t('settings.platformAlerts.windowLabel') }}
291
291
  </label>
292
292
  <div class="grid grid-cols-1 gap-2 sm:grid-cols-2">
@@ -298,17 +298,17 @@ const hasOverrides = computed(
298
298
  data-testid="platform-alerts-window"
299
299
  />
300
300
  </div>
301
- <p class="text-[11px] text-muted">{{ t('settings.platformAlerts.windowHint') }}</p>
301
+ <p class="text-2xs text-muted">{{ t('settings.platformAlerts.windowHint') }}</p>
302
302
  </div>
303
303
 
304
304
  <div class="space-y-2">
305
- <label class="text-[11px] font-medium text-toned">
305
+ <label class="text-2xs font-medium text-toned">
306
306
  {{ t('settings.platformAlerts.thresholdsLabel') }}
307
307
  </label>
308
- <p class="text-[11px] text-muted">{{ t('settings.platformAlerts.inheritHint') }}</p>
308
+ <p class="text-2xs text-muted">{{ t('settings.platformAlerts.inheritHint') }}</p>
309
309
  <div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
310
310
  <div v-for="th in THRESHOLDS" :key="th.field" class="space-y-1">
311
- <label class="block text-[11px] text-toned" :for="`platform-alert-${th.field}`">
311
+ <label class="block text-2xs text-toned" :for="`platform-alert-${th.field}`">
312
312
  {{ thresholdLabels[th.field] }}
313
313
  </label>
314
314
  <UInput
@@ -320,7 +320,7 @@ const hasOverrides = computed(
320
320
  :placeholder="t('settings.platformAlerts.inheritPlaceholder')"
321
321
  :data-testid="`platform-alert-${th.field}`"
322
322
  />
323
- <p class="text-[11px] leading-snug text-dimmed">{{ thresholdHints[th.field] }}</p>
323
+ <p class="text-2xs leading-snug text-dimmed">{{ thresholdHints[th.field] }}</p>
324
324
  </div>
325
325
  </div>
326
326
  </div>
@@ -99,9 +99,9 @@ async function create(input: CreateRiskPolicyInput) {
99
99
 
100
100
  <template>
101
101
  <div class="space-y-4 text-sm" data-testid="account-risk-policy-panel">
102
- <p class="text-[11px] text-muted">{{ t('layout.accountRiskPolicies.intro') }}</p>
102
+ <p class="text-2xs text-muted">{{ t('layout.accountRiskPolicies.intro') }}</p>
103
103
 
104
- <p v-if="!store.loading && policies.length === 0" class="text-[11px] text-dimmed">
104
+ <p v-if="!store.loading && policies.length === 0" class="text-2xs text-dimmed">
105
105
  {{ t('layout.accountRiskPolicies.empty') }}
106
106
  </p>
107
107
 
@@ -62,7 +62,7 @@ async function save() {
62
62
  <h3 class="text-sm font-semibold text-default">
63
63
  {{ t('settings.runCredentialPolicy.heading') }}
64
64
  </h3>
65
- <p class="text-[11px] text-muted">{{ t('settings.runCredentialPolicy.body') }}</p>
65
+ <p class="text-2xs text-muted">{{ t('settings.runCredentialPolicy.body') }}</p>
66
66
 
67
67
  <label class="flex items-center gap-2">
68
68
  <USwitch v-model="forbid" size="sm" data-testid="account-forbid-initiator-pat" />
@@ -71,10 +71,10 @@ async function save() {
71
71
 
72
72
  <!-- What the choice actually costs, stated at the point of choosing rather than discovered
73
73
  later: attribution is a real feature, and turning this on is what trades it away. -->
74
- <p v-if="forbid" class="text-[11px] text-app-warning-300">
74
+ <p v-if="forbid" class="text-2xs text-app-warning-300">
75
75
  {{ t('settings.runCredentialPolicy.onHint') }}
76
76
  </p>
77
- <p v-else class="text-[11px] text-dimmed">
77
+ <p v-else class="text-2xs text-dimmed">
78
78
  {{ t('settings.runCredentialPolicy.offHint') }}
79
79
  </p>
80
80
 
@@ -12,7 +12,7 @@ const { t } = useI18n()
12
12
  <template>
13
13
  <div class="space-y-6 text-sm">
14
14
  <section>
15
- <p class="mb-3 text-[11px] text-muted">
15
+ <p class="mb-3 text-2xs text-muted">
16
16
  {{ t('layout.accountSkills.intro') }}
17
17
  </p>
18
18
  <SkillLibraryManager :account-id="props.accountId" />
@@ -8,6 +8,7 @@ import AccountModelPolicySettings from '~/components/layout/AccountModelPolicySe
8
8
  import AccountPlatformAlertSettings from '~/components/layout/AccountPlatformAlertSettings.vue'
9
9
  import AccountRunCredentialSettings from '~/components/layout/AccountRunCredentialSettings.vue'
10
10
  import SecretInput from '~/components/common/SecretInput.vue'
11
+ import IconButton from '~/components/common/IconButton.vue'
11
12
 
12
13
  // Team settings for an org account: the member roster (with combinable admin /
13
14
  // developer / product roles), pending email invitations, and the per-account
@@ -207,7 +208,7 @@ async function disconnectEmail() {
207
208
  <p class="mb-3 text-muted">
208
209
  {{ t('layout.accountTeam.org.ctaBody') }}
209
210
  </p>
210
- <form class="flex gap-2" @submit.prevent="createOrganization">
211
+ <UForm class="flex gap-2" @submit="createOrganization">
211
212
  <UInput
212
213
  v-model="newOrgName"
213
214
  :placeholder="t('layout.accountTeam.org.namePlaceholder')"
@@ -216,7 +217,7 @@ async function disconnectEmail() {
216
217
  <UButton type="submit" color="primary" :loading="busy" icon="i-lucide-plus">
217
218
  {{ t('layout.accountTeam.org.create') }}
218
219
  </UButton>
219
- </form>
220
+ </UForm>
220
221
  </section>
221
222
 
222
223
  <!-- members -->
@@ -240,20 +241,22 @@ async function disconnectEmail() {
240
241
  class="w-44"
241
242
  @update:model-value="(r: AccountRole[]) => updateMemberRoles(m.userId, r)"
242
243
  />
244
+ <!-- The roles a member HOLDS, read-only where the select would be: the row's data, not
245
+ a heading over it, so it keeps its own classes rather than adopting the eyebrow
246
+ recipe (`common/SectionLabel.vue`). -->
243
247
  <span v-else class="text-xs uppercase tracking-wide text-muted">
244
248
  {{ m.roles.join(', ') }}
245
249
  </span>
246
250
  <!-- Offboarding: end every session this member holds, leaving their membership and
247
251
  roles alone. Confirmed, because it is not undoable from here (the person simply
248
252
  signs in again) and because it is the sort of thing a mis-click should not do. -->
249
- <UButton
253
+ <IconButton
250
254
  v-if="isAdmin"
251
255
  size="xs"
252
256
  color="neutral"
253
257
  variant="ghost"
254
258
  icon="i-lucide-log-out"
255
- :title="t('layout.accountTeam.members.revokeSessions')"
256
- :aria-label="t('layout.accountTeam.members.revokeSessions')"
259
+ :label="t('layout.accountTeam.members.revokeSessions')"
257
260
  data-testid="revoke-member-sessions"
258
261
  @click="revokeSessions(m.userId, m.name || m.email || m.userId)"
259
262
  />
@@ -269,7 +272,7 @@ async function disconnectEmail() {
269
272
  <h3 class="mb-2 font-semibold text-highlighted">
270
273
  {{ t('layout.accountTeam.invite.title') }}
271
274
  </h3>
272
- <form class="flex gap-2" @submit.prevent="sendInvite">
275
+ <UForm class="flex gap-2" @submit="sendInvite">
273
276
  <UInput
274
277
  v-model="inviteEmail"
275
278
  type="email"
@@ -280,7 +283,7 @@ async function disconnectEmail() {
280
283
  <UButton type="submit" color="primary" :loading="busy" icon="i-lucide-send">
281
284
  {{ t('layout.accountTeam.invite.submit') }}
282
285
  </UButton>
283
- </form>
286
+ </UForm>
284
287
 
285
288
  <ul v-if="accounts.invitations.length" class="mt-3 space-y-1">
286
289
  <li
@@ -290,6 +293,7 @@ async function disconnectEmail() {
290
293
  >
291
294
  <span class="truncate">{{ inv.email }}</span>
292
295
  <span class="flex items-center gap-2 text-xs">
296
+ <!-- The invitation's STATE, which is what this row is about. Not an eyebrow. -->
293
297
  <span class="uppercase tracking-wide text-muted">
294
298
  {{ invitationStatusLabel(inv.status) }}
295
299
  </span>
@@ -328,7 +332,7 @@ async function disconnectEmail() {
328
332
  {{ t('layout.accountTeam.email.disconnect') }}
329
333
  </UButton>
330
334
  </div>
331
- <form v-else class="space-y-2" @submit.prevent="connectEmail">
335
+ <UForm v-else class="space-y-2" @submit="connectEmail">
332
336
  <USelect v-model="emailProvider" :items="EMAIL_PROVIDER_ITEMS" class="w-full" />
333
337
  <UInput
334
338
  v-model="emailFrom"
@@ -344,7 +348,7 @@ async function disconnectEmail() {
344
348
  <UButton type="submit" color="primary" :loading="busy">
345
349
  {{ t('layout.accountTeam.email.connect') }}
346
350
  </UButton>
347
- </form>
351
+ </UForm>
348
352
  </template>
349
353
  </section>
350
354
 
@@ -85,7 +85,7 @@ const show = computed(() => showSetup.value || showPreset.value)
85
85
  @click="ui.dismissAiPresetMismatch()"
86
86
  />
87
87
  </div>
88
- <p class="mt-1 text-[13px] text-app-warning-200/90">
88
+ <p class="mt-1 text-sm text-app-warning-200/90">
89
89
  {{ t('layout.aiProvidersBanner.preset.body') }}
90
90
  </p>
91
91
  <div class="mt-3">
@@ -86,8 +86,9 @@ const items = computed<DropdownMenuItem[][]>(() => [
86
86
 
87
87
  <template>
88
88
  <UDropdownMenu :items="items" :content="{ side: 'top', align: 'start' }">
89
- <button
90
- type="button"
89
+ <UButton
90
+ color="neutral"
91
+ variant="ghost"
91
92
  data-testid="appearance-switcher"
92
93
  :aria-label="t('appearance.switcher')"
93
94
  :title="collapsed ? `${t('appearance.switcher')}: ${summary}` : undefined"
@@ -96,13 +97,13 @@ const items = computed<DropdownMenuItem[][]>(() => [
96
97
  >
97
98
  <UIcon :name="MODE_ICONS[preference]" class="h-4 w-4 shrink-0 text-muted" />
98
99
  <div v-if="!collapsed" class="min-w-0 flex-1">
99
- <div class="truncate text-[10px] uppercase tracking-wide text-dimmed">
100
+ <div class="truncate text-2xs uppercase tracking-wide text-muted">
100
101
  {{ t('appearance.switcher') }}
101
102
  </div>
102
103
  <div class="truncate text-xs font-medium text-highlighted">{{ summary }}</div>
103
104
  </div>
104
105
  <UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-dimmed" />
105
- </button>
106
+ </UButton>
106
107
  </UDropdownMenu>
107
108
  <ThemeImportModal v-model:open="importOpen" />
108
109
  </template>
@@ -1,6 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import type { DropdownMenuItem } from '@nuxt/ui'
3
3
  import type { CloudProvider } from '~/types/domain'
4
+ import SectionLabel from '~/components/common/SectionLabel.vue'
4
5
 
5
6
  // Account + board switching. Picks the active account (personal / org) and the
6
7
  // active board within it, and manages boards (new / rename / delete). The account
@@ -256,8 +257,9 @@ async function submitPrompt() {
256
257
  :content="{ align: 'start' }"
257
258
  class="w-full"
258
259
  >
259
- <button
260
- type="button"
260
+ <UButton
261
+ color="neutral"
262
+ variant="ghost"
261
263
  class="flex w-full items-center gap-2 rounded-md px-1.5 py-1 text-start transition hover:bg-elevated/60"
262
264
  :disabled="busy"
263
265
  >
@@ -265,17 +267,18 @@ async function submitPrompt() {
265
267
  :name="accounts.activeAccount?.type === 'org' ? 'i-lucide-users' : 'i-lucide-user'"
266
268
  class="h-3.5 w-3.5 shrink-0 text-muted"
267
269
  />
268
- <span class="truncate text-[11px] font-medium uppercase tracking-wide text-muted">
270
+ <SectionLabel as="span" class="truncate">
269
271
  {{ accounts.activeAccount?.name ?? t('layout.boardSwitcher.accountFallback') }}
270
- </span>
272
+ </SectionLabel>
271
273
  <UIcon name="i-lucide-chevrons-up-down" class="ms-auto h-3.5 w-3.5 shrink-0 text-app-600" />
272
- </button>
274
+ </UButton>
273
275
  </UDropdownMenu>
274
276
 
275
277
  <!-- board selector -->
276
278
  <UDropdownMenu :items="boardItems" :content="{ align: 'start' }" class="w-full">
277
- <button
278
- type="button"
279
+ <UButton
280
+ color="neutral"
281
+ variant="ghost"
279
282
  :title="
280
283
  collapsed
281
284
  ? (workspace.activeWorkspace?.name ?? t('layout.boardSwitcher.boardFallback'))
@@ -296,13 +299,13 @@ async function submitPrompt() {
296
299
  name="i-lucide-chevron-down"
297
300
  class="ms-auto h-4 w-4 shrink-0 text-dimmed"
298
301
  />
299
- </button>
302
+ </UButton>
300
303
  </UDropdownMenu>
301
304
 
302
305
  <!-- create / rename prompt -->
303
306
  <UModal v-model:open="promptOpen" :title="prompt ? promptMeta[prompt].title : ''">
304
307
  <template #body>
305
- <form class="space-y-3" @submit.prevent="submitPrompt">
308
+ <UForm class="space-y-3" @submit="submitPrompt">
306
309
  <UFormField :label="t('layout.boardSwitcher.prompt.nameLabel')">
307
310
  <UInput
308
311
  v-model="promptValue"
@@ -340,7 +343,7 @@ async function submitPrompt() {
340
343
  {{ prompt ? promptMeta[prompt].cta : '' }}
341
344
  </UButton>
342
345
  </div>
343
- </form>
346
+ </UForm>
344
347
  </template>
345
348
  </UModal>
346
349
  </div>
@@ -151,19 +151,24 @@ const decisionItems = computed(() =>
151
151
  />
152
152
  <!-- Click the readout to snap back to 100%. Always visible (only the LOD sub-label
153
153
  drops on narrow viewports) so the zoom level is never a mystery. -->
154
- <button
155
- type="button"
156
- class="w-16 rounded text-center text-xs tabular-nums text-toned hover:bg-elevated focus-visible:ring-2 focus-visible:ring-app-400/60 sm:w-20"
154
+ <UButton
155
+ color="neutral"
156
+ variant="ghost"
157
+ class="flex w-16 flex-col items-center gap-0 rounded-sm p-0 text-center text-xs tabular-nums text-toned hover:bg-elevated sm:w-20"
157
158
  :title="t('board.toolbar.resetZoom')"
158
159
  :aria-label="t('board.toolbar.resetZoom')"
159
160
  data-testid="board-zoom-reset"
160
161
  @click="resetZoom()"
161
162
  >
162
163
  {{ zoomPct }}%
163
- <span class="hidden text-[9px] uppercase tracking-wide text-dimmed sm:block">{{
164
+ <!-- The zoom band this readout is currently in, under the percentage: a second VALUE
165
+ annotating the first, not a heading over what follows, so it is not a
166
+ `common/SectionLabel.vue`. It stays a step smaller and unweighted so it does not compete
167
+ with the percentage inside a `w-20` button. -->
168
+ <span class="hidden text-3xs uppercase tracking-wide text-dimmed sm:block">{{
164
169
  lodLabel
165
170
  }}</span>
166
- </button>
171
+ </UButton>
167
172
  <IconButton
168
173
  :label="t('board.toolbar.zoomIn')"
169
174
  icon="i-lucide-zoom-in"
@@ -6,6 +6,8 @@
6
6
  // from the add-task flow.) Commands are assembled from the live stores so only
7
7
  // available actions (connected integrations, etc.) show.
8
8
 
9
+ import SectionLabel from '~/components/common/SectionLabel.vue'
10
+
9
11
  interface Command {
10
12
  id: string
11
13
  label: string
@@ -276,13 +278,14 @@ function indexOf(cmd: Command) {
276
278
  </p>
277
279
 
278
280
  <div v-for="group in groups" :key="group.name" class="mb-1">
279
- <p class="px-2 pb-1 pt-2 text-[11px] font-semibold uppercase tracking-wide text-dimmed">
281
+ <SectionLabel as="p" class="px-2 pb-1 pt-2">
280
282
  {{ group.name }}
281
- </p>
282
- <button
283
+ </SectionLabel>
284
+ <UButton
285
+ color="neutral"
286
+ variant="ghost"
283
287
  v-for="cmd in group.items"
284
288
  :key="cmd.id"
285
- type="button"
286
289
  :data-testid="`command-${cmd.id}`"
287
290
  class="flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-start text-sm transition"
288
291
  :class="
@@ -295,7 +298,7 @@ function indexOf(cmd: Command) {
295
298
  >
296
299
  <UIcon :name="cmd.icon" class="h-4 w-4 shrink-0 text-muted" />
297
300
  <span class="truncate">{{ cmd.label }}</span>
298
- </button>
301
+ </UButton>
299
302
  </div>
300
303
  </div>
301
304
  </div>
@@ -74,7 +74,7 @@ function openConfig(event: MouseEvent) {
74
74
  @click="ui.dismissDefaultProvision()"
75
75
  />
76
76
  </div>
77
- <p class="mt-1 text-[13px] text-app-info-200/90">
77
+ <p class="mt-1 text-sm text-app-info-200/90">
78
78
  {{ t('layout.defaultTestEnvBanner.body') }}
79
79
  </p>
80
80
  <div class="mt-3 flex flex-wrap items-center gap-x-3 gap-y-2">
@@ -90,14 +90,15 @@ function openConfig(event: MouseEvent) {
90
90
  {{ t('layout.defaultTestEnvBanner.action') }}
91
91
  </UButton>
92
92
  <!-- The URL itself, shown so it can be read and copied, not just clicked. -->
93
- <a
94
- :href="configUrl"
95
- class="min-w-0 truncate font-mono text-[11px] text-app-info-300/80 underline decoration-dotted underline-offset-2 hover:text-app-info-200"
93
+ <ULink
94
+ raw
95
+ :to="configUrl"
96
+ class="min-w-0 truncate font-mono text-2xs text-app-info-300/80 underline decoration-dotted underline-offset-2 hover:text-app-info-200"
96
97
  data-testid="default-test-env-url"
97
98
  @click="openConfig"
98
99
  >
99
100
  {{ configUrl }}
100
- </a>
101
+ </ULink>
101
102
  </div>
102
103
  </div>
103
104
  </div>
@@ -1,5 +1,6 @@
1
1
  <script setup lang="ts">
2
2
  import { showOverrideField } from '~/utils/uiMode'
3
+ import SectionLabel from '~/components/common/SectionLabel.vue'
3
4
 
4
5
  // The Integrations hub: a single modal that lists the OPTIONAL external systems the WORKSPACE
5
6
  // can enable or link in — the ones that feed a run its context (source control, documents,
@@ -422,14 +423,15 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
422
423
  </p>
423
424
 
424
425
  <section v-for="group in filteredGroups" :key="group.title">
425
- <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
426
+ <SectionLabel as="h3" class="mb-2 px-1">
426
427
  {{ group.title }}
427
- </h3>
428
+ </SectionLabel>
428
429
  <div class="space-y-1.5">
429
- <button
430
+ <UButton
431
+ color="neutral"
432
+ variant="ghost"
430
433
  v-for="item in group.items"
431
434
  :key="item.key"
432
- type="button"
433
435
  class="flex w-full items-center gap-3 rounded-lg border border-default bg-default/50 px-3 py-2.5 text-start transition hover:border-muted hover:bg-default"
434
436
  @click="item.onClick()"
435
437
  >
@@ -443,7 +445,7 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
443
445
  <UBadge v-else-if="item.attention" color="warning" variant="subtle" size="sm">
444
446
  {{ item.attentionLabel || t('layout.integrationsHub.status.needsAttention') }}
445
447
  </UBadge>
446
- <span v-else class="text-[11px] text-dimmed">{{
448
+ <span v-else class="text-2xs text-dimmed">{{
447
449
  t('layout.integrationsHub.status.notConnected')
448
450
  }}</span>
449
451
  <UBadge
@@ -461,13 +463,14 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
461
463
  name="i-lucide-chevron-right"
462
464
  class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
463
465
  />
464
- </button>
466
+ </UButton>
465
467
  </div>
466
468
 
467
469
  <!-- De-emphasised workspace-config link (e.g. issue tracker settings). -->
468
- <button
470
+ <UButton
471
+ color="neutral"
472
+ variant="ghost"
469
473
  v-if="group.footerLink"
470
- type="button"
471
474
  class="mt-1.5 flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-start text-xs text-muted transition hover:bg-default/60 hover:text-default"
472
475
  @click="group.footerLink.onClick()"
473
476
  >
@@ -480,7 +483,7 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
480
483
  name="i-lucide-chevron-right"
481
484
  class="h-3.5 w-3.5 shrink-0 text-app-600 rtl:-scale-x-100"
482
485
  />
483
- </button>
486
+ </UButton>
484
487
  </section>
485
488
  </div>
486
489
  </template>
@@ -40,8 +40,9 @@ const items = computed<DropdownMenuItem[][]>(() => [
40
40
 
41
41
  <template>
42
42
  <UDropdownMenu :items="items" :content="{ side: 'top', align: 'start' }">
43
- <button
44
- type="button"
43
+ <UButton
44
+ color="neutral"
45
+ variant="ghost"
45
46
  data-testid="language-switcher"
46
47
  :aria-label="t('language.switcher')"
47
48
  :title="collapsed ? `${t('language.switcher')}: ${current}` : undefined"
@@ -50,12 +51,12 @@ const items = computed<DropdownMenuItem[][]>(() => [
50
51
  >
51
52
  <UIcon name="i-lucide-languages" class="h-4 w-4 shrink-0 text-muted" />
52
53
  <div v-if="!collapsed" class="min-w-0 flex-1">
53
- <div class="truncate text-[10px] uppercase tracking-wide text-dimmed">
54
+ <div class="truncate text-2xs uppercase tracking-wide text-muted">
54
55
  {{ t('language.switcher') }}
55
56
  </div>
56
57
  <div class="truncate text-xs font-medium text-highlighted">{{ current }}</div>
57
58
  </div>
58
59
  <UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-dimmed" />
59
- </button>
60
+ </UButton>
60
61
  </UDropdownMenu>
61
62
  </template>
@@ -12,6 +12,8 @@
12
12
  // `ui.openFromModelProviders(...)`, so opening one closes this hub and gives that panel a
13
13
  // "Back to Model providers" control (IntegrationBackTitle). Layout mirrors the Integrations
14
14
  // hub row-for-row so the two read as siblings.
15
+ import SectionLabel from '~/components/common/SectionLabel.vue'
16
+
15
17
  const { t } = useI18n()
16
18
  const ui = useUiStore()
17
19
  const apiKeys = useApiKeysStore()
@@ -200,14 +202,15 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
200
202
  </p>
201
203
 
202
204
  <section v-for="group in filteredGroups" :key="group.title">
203
- <h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
205
+ <SectionLabel as="h3" class="mb-2 px-1">
204
206
  {{ group.title }}
205
- </h3>
207
+ </SectionLabel>
206
208
  <div class="space-y-1.5">
207
- <button
209
+ <UButton
210
+ color="neutral"
211
+ variant="ghost"
208
212
  v-for="item in group.items"
209
213
  :key="item.key"
210
- type="button"
211
214
  class="flex w-full items-center gap-3 rounded-lg border border-default bg-default/50 px-3 py-2.5 text-start transition hover:border-muted hover:bg-default"
212
215
  :data-testid="`model-provider-${item.key}`"
213
216
  @click="item.onClick()"
@@ -219,7 +222,7 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
219
222
  <UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
220
223
  {{ item.status || t('layout.modelProvidersHub.status.connected') }}
221
224
  </UBadge>
222
- <span v-else class="text-[11px] text-dimmed">{{
225
+ <span v-else class="text-2xs text-dimmed">{{
223
226
  t('layout.modelProvidersHub.status.notConnected')
224
227
  }}</span>
225
228
  <UBadge
@@ -237,9 +240,9 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
237
240
  name="i-lucide-chevron-right"
238
241
  class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
239
242
  />
240
- </button>
243
+ </UButton>
241
244
  </div>
242
- <p v-if="group.note" class="mt-1.5 px-1 text-[11px] text-dimmed">{{ group.note }}</p>
245
+ <p v-if="group.note" class="mt-1.5 px-1 text-2xs text-dimmed">{{ group.note }}</p>
243
246
  </section>
244
247
  </div>
245
248
  </template>