@cat-factory/app 0.302.2 → 0.303.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -14
- package/app/app.config.ts +19 -10
- package/app/assets/css/main.css +13 -13
- package/app/assets/css/prose.css +22 -22
- package/app/assets/css/tokens.css +298 -0
- package/app/components/assistant/AssistantModal.vue +22 -22
- package/app/components/auth/AuthGate.vue +1 -1
- package/app/components/auth/BackendMisconfiguredScreen.vue +10 -10
- package/app/components/auth/LoginScreen.vue +34 -36
- package/app/components/auth/ResetPasswordScreen.vue +12 -12
- package/app/components/auth/UserMenu.vue +4 -4
- package/app/components/binaryCandidates/BinaryCandidatesWindow.vue +27 -25
- package/app/components/binaryOutput/BinaryOutputReport.vue +15 -15
- package/app/components/binaryOutput/StoredAssetView.vue +5 -5
- package/app/components/board/AddTaskModal.vue +17 -20
- package/app/components/board/AgentFailureCard.vue +11 -11
- package/app/components/board/AgentFailureHistory.vue +2 -2
- package/app/components/board/BoardCanvas.vue +6 -5
- package/app/components/board/CreateInitiativeModal.vue +8 -10
- package/app/components/board/DependencyConnectOverlay.vue +1 -1
- package/app/components/board/FailureHistoryList.vue +7 -7
- package/app/components/board/RecurringPipelineModal.vue +17 -17
- package/app/components/board/ReviewFrictionDialog.vue +6 -6
- package/app/components/board/StepExecutionHistory.vue +13 -13
- package/app/components/board/TaskDependencyEdges.vue +8 -8
- package/app/components/board/nodes/AgentChip.vue +10 -10
- package/app/components/board/nodes/BlockNode.vue +29 -29
- package/app/components/board/nodes/DecisionBadge.vue +2 -2
- package/app/components/board/nodes/EpicNode.vue +14 -10
- package/app/components/board/nodes/FrameSwimlanes.vue +7 -9
- package/app/components/board/nodes/InitiativeCard.vue +8 -8
- package/app/components/board/nodes/LaneGroup.vue +1 -1
- package/app/components/board/nodes/LaneTask.vue +2 -2
- package/app/components/board/nodes/ResizeGrips.vue +4 -4
- package/app/components/board/nodes/TaskCard.vue +18 -18
- package/app/components/board/nodes/TaskLane.vue +5 -5
- package/app/components/board/nodes/TaskPipelineMini.vue +18 -18
- package/app/components/bootstrap/AdoptionReviewModal.vue +29 -26
- package/app/components/bootstrap/BootstrapModal.vue +21 -23
- package/app/components/bootstrap/BootstrapRunSteps.vue +1 -1
- package/app/components/brainstorm/BrainstormWindow.vue +30 -33
- package/app/components/bugFishing/BugFishingWindow.vue +49 -49
- package/app/components/clarity/ClarityReviewWindow.vue +30 -30
- package/app/components/common/AsyncViewError.vue +5 -5
- package/app/components/common/ClarificationItem.vue +8 -13
- package/app/components/common/ConfirmDialog.vue +4 -2
- package/app/components/common/DescriptorFields.vue +1 -1
- package/app/components/common/EmptyState.vue +3 -3
- package/app/components/common/InterviewGateNotice.vue +7 -7
- package/app/components/common/KeyboardShortcutsHelp.vue +1 -1
- package/app/components/common/MarkdownProse.vue +14 -13
- package/app/components/consensus/ConsensusSessionWindow.vue +26 -26
- package/app/components/context/ContextAttachmentFields.vue +17 -17
- package/app/components/docs/DocInterviewWindow.vue +14 -14
- package/app/components/documents/ContextDocumentPicker.vue +17 -17
- package/app/components/documents/DocumentImportModal.vue +7 -7
- package/app/components/documents/DocumentSourceConnectModal.vue +3 -3
- package/app/components/documents/DocumentSyncState.vue +5 -5
- package/app/components/documents/DocumentTemplatesModal.vue +15 -15
- package/app/components/documents/RepoContextDocPicker.vue +5 -5
- package/app/components/documents/SpawnPreviewModal.vue +12 -12
- package/app/components/documents/StartFromDesignModal.vue +11 -11
- package/app/components/documents/TaskContextDocs.vue +5 -5
- package/app/components/environments/EnvSetupStepper.vue +6 -6
- package/app/components/environments/EnvironmentStatusPanel.vue +17 -17
- package/app/components/environments/steps/EnvPickStep.vue +3 -3
- package/app/components/environments/steps/EnvPreflightStep.vue +9 -9
- package/app/components/environments/steps/EnvReviewStep.vue +25 -22
- package/app/components/environments/steps/EnvSaveStep.vue +7 -5
- package/app/components/environments/steps/JourneyStepNav.vue +1 -1
- package/app/components/focus/BlockFocusView.vue +17 -19
- package/app/components/followUp/FollowUpWindow.vue +23 -23
- package/app/components/forkDecision/ForkDecisionWindow.vue +37 -39
- package/app/components/foundational/FoundationalContractSummary.vue +7 -7
- package/app/components/foundational/FoundationalServiceCatalogList.vue +11 -11
- package/app/components/foundational/FoundationalServiceManager.vue +1 -1
- package/app/components/foundational/FoundationalServiceRegistry.vue +13 -13
- package/app/components/foundational/FoundationalServiceSources.vue +13 -13
- package/app/components/foundational/FoundationalSuppressions.vue +7 -7
- package/app/components/foundational/ServiceCatalogConnection.vue +10 -10
- package/app/components/fragments/FragmentLibraryManager.vue +41 -44
- package/app/components/fragments/FragmentSelector.vue +13 -13
- package/app/components/fragments/GitHubDocUrlImport.vue +1 -1
- package/app/components/gates/GateFailingCheckList.vue +5 -5
- package/app/components/gates/GateResultView.vue +50 -47
- package/app/components/github/AddServiceFromRepoModal.vue +14 -14
- package/app/components/github/BranchProtectionPreflight.vue +13 -13
- package/app/components/github/GitHubConnect.vue +7 -7
- package/app/components/github/GitHubOnboarding.vue +7 -7
- package/app/components/github/GitHubPanel.vue +37 -40
- package/app/components/github/RepoTreeBrowser.vue +18 -18
- package/app/components/humanTest/HumanTestWindow.vue +30 -33
- package/app/components/initiative/InitiativePlanNotice.vue +5 -5
- package/app/components/initiative/InitiativePlanReview.vue +27 -29
- package/app/components/initiative/InitiativePlanningWindow.vue +10 -10
- package/app/components/initiative/InitiativeTrackerWindow.vue +71 -65
- package/app/components/inputGate/InputGateNotice.vue +2 -4
- package/app/components/judge/JudgeResultView.vue +30 -32
- package/app/components/kaizen/KaizenPanel.vue +40 -36
- package/app/components/kaizen/KaizenStepStatus.vue +21 -21
- package/app/components/layout/AccountAuditLog.vue +10 -10
- package/app/components/layout/AccountDeploymentSettings.vue +20 -20
- package/app/components/layout/AccountFailureKindRules.vue +13 -13
- package/app/components/layout/AccountFoundationalSettings.vue +1 -1
- package/app/components/layout/AccountFragmentSettings.vue +1 -1
- package/app/components/layout/AccountModelPolicySettings.vue +9 -9
- package/app/components/layout/AccountPlatformAlertSettings.vue +11 -11
- package/app/components/layout/AccountRiskPolicySettings.vue +2 -2
- package/app/components/layout/AccountRunCredentialSettings.vue +5 -5
- package/app/components/layout/AccountSkillSettings.vue +1 -1
- package/app/components/layout/AccountTeamSettings.vue +23 -15
- package/app/components/layout/AiProvidersBanner.vue +11 -8
- package/app/components/layout/AppearanceSwitcher.vue +108 -0
- package/app/components/layout/BoardSwitcher.vue +8 -11
- package/app/components/layout/BoardToolbar.vue +3 -3
- package/app/components/layout/CommandBar.vue +7 -9
- package/app/components/layout/ConnectionStatusBanner.vue +2 -2
- package/app/components/layout/DefaultTestEnvBanner.vue +5 -5
- package/app/components/layout/GitHubPatBanner.vue +5 -5
- package/app/components/layout/GitHubPatPermissionsBanner.vue +16 -10
- package/app/components/layout/InfraSetupBanner.vue +6 -6
- package/app/components/layout/IntegrationsHub.vue +15 -15
- package/app/components/layout/LanguageSwitcher.vue +5 -5
- package/app/components/layout/ModelProvidersHub.vue +13 -16
- package/app/components/layout/NotificationsInbox.vue +10 -10
- package/app/components/layout/PersonalSetupModal.vue +8 -8
- package/app/components/layout/ProviderConfigBanner.vue +4 -4
- package/app/components/layout/RolePrompt.vue +7 -7
- package/app/components/layout/SideBar.vue +6 -4
- package/app/components/layout/SpendWarningBanner.vue +17 -14
- package/app/components/layout/TranslationWarningBanner.vue +4 -4
- package/app/components/layout/UiModeSwitcher.vue +13 -13
- package/app/components/layout/UiRoleSwitcher.vue +8 -8
- package/app/components/layout/WorkspaceMembersSettings.vue +15 -11
- package/app/components/media/ArtifactLightbox.vue +13 -13
- package/app/components/media/ImageCompare.vue +31 -24
- package/app/components/merge/MergeEffortChips.vue +2 -2
- package/app/components/notifications/NotificationSettingsPanel.vue +14 -12
- package/app/components/observability/OutcomeFilterChips.vue +6 -6
- package/app/components/observability/RunFailureSummary.vue +28 -25
- package/app/components/observability/StepMetricsBar.vue +26 -28
- package/app/components/observability/StepModelActivity.vue +2 -2
- package/app/components/observability/ToolCallList.vue +24 -24
- package/app/components/outcome/OutcomeSummaryWindow.vue +47 -47
- package/app/components/palettes/AgentPalette.vue +8 -8
- package/app/components/palettes/AgentTierSelect.vue +1 -1
- package/app/components/palettes/PipelinePurposeSelect.vue +1 -1
- package/app/components/panels/AgentStepDetail.vue +52 -51
- package/app/components/panels/AttemptEntryHeader.vue +4 -6
- package/app/components/panels/DecisionModal.vue +7 -7
- package/app/components/panels/GenericStructuredResultView.vue +7 -7
- package/app/components/panels/InspectorPanel.vue +17 -17
- package/app/components/panels/MergerResultView.vue +19 -19
- package/app/components/panels/ObservabilityPanel.vue +115 -123
- package/app/components/panels/OperatorDashboardPanel.vue +89 -97
- package/app/components/panels/ReportsPanel.vue +69 -66
- package/app/components/panels/ReportsSpendBreakdown.vue +9 -9
- package/app/components/panels/ResultWindowShell.vue +38 -38
- package/app/components/panels/RunDetailLoadState.vue +2 -2
- package/app/components/panels/StepContainerStatus.vue +9 -9
- package/app/components/panels/StepDelegatedStatus.logic.spec.ts +135 -0
- package/app/components/panels/StepDelegatedStatus.logic.ts +160 -0
- package/app/components/panels/StepDelegatedStatus.vue +181 -0
- package/app/components/panels/StepEffortReport.vue +16 -15
- package/app/components/panels/StepFragmentAdherence.vue +14 -10
- package/app/components/panels/StepMetadataCard.vue +74 -45
- package/app/components/panels/StepReproductionReport.vue +25 -21
- package/app/components/panels/StepRunMeta.vue +20 -20
- package/app/components/panels/StepTestReport.logic.spec.ts +8 -3
- package/app/components/panels/StepTestReport.logic.ts +4 -4
- package/app/components/panels/StepTestReport.vue +28 -28
- package/app/components/panels/StepToolServers.vue +14 -11
- package/app/components/panels/StepValidationReport.vue +7 -7
- package/app/components/panels/inspector/ContainerSummary.vue +9 -9
- package/app/components/panels/inspector/DocReferenceRepos.vue +3 -3
- package/app/components/panels/inspector/EnvProbeReport.vue +24 -27
- package/app/components/panels/inspector/EpicChildren.vue +8 -12
- package/app/components/panels/inspector/FrontendBindingsResolved.vue +11 -11
- package/app/components/panels/inspector/FrontendConfig.vue +37 -41
- package/app/components/panels/inspector/InitiativeInspector.vue +3 -3
- package/app/components/panels/inspector/InspectorSection.vue +6 -6
- package/app/components/panels/inspector/RecurringScheduleSettings.vue +16 -19
- package/app/components/panels/inspector/ServiceConnections.vue +2 -2
- package/app/components/panels/inspector/ServiceReleaseHealthConfig.vue +2 -2
- package/app/components/panels/inspector/ServiceSelfTests.vue +21 -17
- package/app/components/panels/inspector/ServiceTestConfig.vue +51 -59
- package/app/components/panels/inspector/ServiceTestSecrets.vue +5 -5
- package/app/components/panels/inspector/ServiceTestingContext.vue +3 -3
- package/app/components/panels/inspector/ServiceValidationConfig.vue +2 -2
- package/app/components/panels/inspector/TaskAgentConfig.vue +3 -3
- package/app/components/panels/inspector/TaskAprioriBranches.vue +8 -5
- package/app/components/panels/inspector/TaskDependencies.vue +1 -1
- package/app/components/panels/inspector/TaskEstimateBadge.vue +11 -11
- package/app/components/panels/inspector/TaskExecution.vue +17 -17
- package/app/components/panels/inspector/TaskReviewTarget.vue +2 -2
- package/app/components/panels/inspector/TaskRunSettings.vue +35 -37
- package/app/components/panels/inspector/TaskStructure.vue +3 -3
- package/app/components/pipeline/AgentKindIcon.vue +1 -1
- package/app/components/pipeline/AgentPromptEditor.vue +17 -17
- package/app/components/pipeline/BinaryOutputStepPicker.vue +42 -56
- package/app/components/pipeline/EstimateThresholdFields.vue +4 -4
- package/app/components/pipeline/GateConfigFields.vue +13 -10
- package/app/components/pipeline/IterationCapPrompt.vue +4 -2
- package/app/components/pipeline/PipelineBuilder.vue +47 -55
- package/app/components/pipeline/PipelineHealthModal.vue +27 -29
- package/app/components/pipeline/PipelinePicker.vue +10 -10
- package/app/components/pipeline/PipelinePreview.vue +10 -10
- package/app/components/pipeline/PipelineProgress.vue +64 -67
- package/app/components/prReview/PrReviewPhaseBadge.vue +7 -7
- package/app/components/prReview/PrReviewWindow.vue +75 -77
- package/app/components/providers/AiPresetMismatchDialog.vue +5 -5
- package/app/components/providers/AiProviderOnboardingModal.vue +9 -9
- package/app/components/providers/ApiKeysSection.vue +13 -13
- package/app/components/providers/PersonalCredentialModal.vue +2 -2
- package/app/components/providers/PersonalSubscriptionSection.vue +10 -10
- package/app/components/providers/SignInRequiredNotice.vue +1 -1
- package/app/components/providers/VendorCredentialsModal.vue +10 -10
- package/app/components/provisioning/ProvisioningLogsDrawer.vue +13 -13
- package/app/components/ralph/RalphLoopResultView.vue +28 -30
- package/app/components/recurring/RecurrenceEditor.vue +2 -2
- package/app/components/requirements/RequirementsReviewWindow.vue +51 -58
- package/app/components/riskPolicy/RiskPolicyPicker.vue +12 -15
- package/app/components/riskPolicy/RiskPolicyPreview.vue +14 -14
- package/app/components/sandbox/SandboxPanel.vue +58 -59
- package/app/components/settings/AccountSettingsPanel.vue +1 -1
- package/app/components/settings/ApiTokensPanel.vue +10 -10
- package/app/components/settings/BudgetSettings.vue +18 -22
- package/app/components/settings/CapabilityCredentialsPanel.vue +15 -15
- package/app/components/settings/CloudflareHandlerSection.vue +20 -20
- package/app/components/settings/ComposeEnvironmentSetupSection.vue +13 -13
- package/app/components/settings/ConnectionTestVerdict.vue +3 -3
- package/app/components/settings/ConnectionWarnings.vue +1 -1
- package/app/components/settings/ConsensusGroupsSection.vue +27 -35
- package/app/components/settings/CustomManifestTypeEditor.vue +10 -10
- package/app/components/settings/DefaultProvisionTypeSection.vue +6 -6
- package/app/components/settings/InfraHandlersConfigurator.vue +24 -22
- package/app/components/settings/InfrastructureBackendPicker.vue +6 -6
- package/app/components/settings/InfrastructureWindow.vue +5 -5
- package/app/components/settings/IssueTrackerPanel.vue +29 -23
- package/app/components/settings/KubernetesEngineForm.vue +11 -11
- package/app/components/settings/KubernetesEnvironmentForm.vue +4 -4
- package/app/components/settings/LocalContainerPoolSettings.vue +6 -11
- package/app/components/settings/LocalModelEndpointsPanel.vue +20 -18
- package/app/components/settings/McpAuthorizeScreen.vue +13 -15
- package/app/components/settings/McpOAuthCallbackScreen.vue +16 -10
- package/app/components/settings/MergeClassRulesEditor.vue +6 -9
- package/app/components/settings/MergeRolePolicyEditor.vue +16 -16
- package/app/components/settings/ModelConfigurationPanel.vue +23 -30
- package/app/components/settings/ModelPresetHealthModal.vue +15 -13
- package/app/components/settings/ObservabilityConnectionPanel.vue +4 -4
- package/app/components/settings/OpenRouterCatalogPanel.vue +26 -19
- package/app/components/settings/PackageRegistriesPanel.vue +8 -8
- package/app/components/settings/ProviderConnectionTab.vue +8 -11
- package/app/components/settings/ProviderManifestEditor.vue +9 -9
- package/app/components/settings/ProviderPreferenceEditor.vue +8 -8
- package/app/components/settings/RiskPolicyCreateForm.vue +10 -10
- package/app/components/settings/RiskPolicyEditorRow.vue +14 -14
- package/app/components/settings/RiskPolicyHealthModal.vue +15 -13
- package/app/components/settings/RiskPolicyInheritedRow.vue +1 -1
- package/app/components/settings/RiskPolicyPanel.vue +10 -15
- package/app/components/settings/ServiceFragmentDefaultsPanel.vue +7 -7
- package/app/components/settings/SharedStacksPanel.vue +9 -12
- package/app/components/settings/TaskSourceCard.vue +4 -4
- package/app/components/settings/TaskTypeSuppressionsPanel.vue +6 -6
- package/app/components/settings/ToolServerChecklist.vue +36 -29
- package/app/components/settings/UsageSettings.vue +15 -15
- package/app/components/settings/UserSecretsSection.vue +9 -12
- package/app/components/settings/WorkspaceMetadataSettings.vue +5 -5
- package/app/components/settings/WorkspaceSettingsPanel.vue +47 -47
- package/app/components/skills/ReviewSkillQueue.vue +10 -10
- package/app/components/skills/SkillLibraryManager.vue +23 -20
- package/app/components/slack/SlackPanel.vue +13 -17
- package/app/components/spec/ServiceSpecWindow.vue +45 -42
- package/app/components/tasks/BugHuntModal.vue +24 -27
- package/app/components/tasks/ContextIssuePicker.vue +11 -11
- package/app/components/tasks/TaskContextIssues.vue +3 -3
- package/app/components/tasks/TaskImportModal.vue +7 -7
- package/app/components/tasks/TaskSourceConnectModal.vue +10 -8
- package/app/components/testing/TestReportWindow.vue +99 -82
- package/app/components/theme/ThemeImportModal.vue +115 -0
- package/app/components/tutorial/TutorialCatalogue.vue +9 -9
- package/app/components/tutorial/TutorialNudge.vue +5 -5
- package/app/components/tutorial/TutorialOverlay.vue +12 -12
- package/app/components/tutorial/TutorialPrompt.vue +6 -9
- package/app/components/vcs/GitLabConnect.vue +4 -4
- package/app/components/vcs/VcsConnectSurfaces.vue +2 -2
- package/app/components/visualConfirm/VisualConfirmationWindow.vue +36 -36
- package/app/composables/api/client.ts +6 -1
- package/app/composables/usePipelineErrorToast.ts +17 -0
- package/app/modular/agent-kinds.ts +24 -0
- package/app/pages/index.vue +5 -5
- package/app/plugins/theme.client.ts +125 -0
- package/app/spa-loading-template.html +52 -14
- package/app/stores/agents.ts +1 -1
- package/app/stores/theme.spec.ts +56 -0
- package/app/stores/theme.ts +87 -0
- package/app/types/domain.ts +19 -0
- package/app/types/execution.ts +4 -0
- package/app/utils/agentOutput.ts +1 -1
- package/app/utils/binaryOutput.ts +6 -6
- package/app/utils/bootstrapSteps.ts +14 -14
- package/app/utils/catalog.ts +87 -83
- package/app/utils/colorTint.ts +10 -0
- package/app/utils/failureKinds.ts +1 -0
- package/app/utils/observability.ts +3 -3
- package/app/utils/pipelineRender.ts +13 -17
- package/app/utils/swimlanes.ts +4 -4
- package/app/utils/theme/bootPalette.spec.ts +54 -0
- package/app/utils/theme/bootPalette.ts +108 -0
- package/app/utils/theme/builtins.spec.ts +38 -0
- package/app/utils/theme/builtins.ts +55 -0
- package/app/utils/theme/css.ts +162 -0
- package/app/utils/theme/doc.ts +353 -0
- package/app/utils/theme/link.ts +93 -0
- package/app/utils/theme/presets.ts +509 -0
- package/app/utils/theme/theme.spec.ts +224 -0
- package/i18n/locales/de.json +61 -4
- package/i18n/locales/en.json +70 -4
- package/i18n/locales/es.json +61 -4
- package/i18n/locales/fr.json +61 -4
- package/i18n/locales/he.json +61 -4
- package/i18n/locales/it.json +61 -4
- package/i18n/locales/ja.json +61 -4
- package/i18n/locales/pl.json +61 -4
- package/i18n/locales/tr.json +61 -4
- package/i18n/locales/uk.json +61 -4
- package/nuxt.config.ts +37 -11
- package/package.json +10 -9
|
@@ -102,15 +102,15 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
102
102
|
<Transition name="fade">
|
|
103
103
|
<div v-if="show" class="pointer-events-auto w-full max-w-3xl">
|
|
104
104
|
<div
|
|
105
|
-
class="w-full max-w-3xl rounded-2xl border-2 border-
|
|
105
|
+
class="w-full max-w-3xl rounded-2xl border-2 border-app-error-500/70 bg-app-error-950/95 p-5 shadow-2xl backdrop-blur"
|
|
106
106
|
role="alert"
|
|
107
107
|
data-testid="github-pat-permissions-banner"
|
|
108
108
|
>
|
|
109
109
|
<div class="flex items-start gap-4">
|
|
110
|
-
<UIcon name="i-lucide-shield-alert" class="mt-0.5 h-9 w-9 shrink-0 text-
|
|
110
|
+
<UIcon name="i-lucide-shield-alert" class="mt-0.5 h-9 w-9 shrink-0 text-app-error-400" />
|
|
111
111
|
<div class="min-w-0 flex-1">
|
|
112
112
|
<div class="flex items-start justify-between gap-3">
|
|
113
|
-
<h2 class="text-lg font-semibold text-
|
|
113
|
+
<h2 class="text-lg font-semibold text-app-error-100">
|
|
114
114
|
{{
|
|
115
115
|
claim === 'rejected'
|
|
116
116
|
? t('layout.githubPatPermissionsBanner.rejectedTitle')
|
|
@@ -131,7 +131,7 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
131
131
|
/>
|
|
132
132
|
</div>
|
|
133
133
|
|
|
134
|
-
<p class="mt-1 text-sm text-
|
|
134
|
+
<p class="mt-1 text-sm text-app-error-200/90">
|
|
135
135
|
{{
|
|
136
136
|
claim === 'rejected'
|
|
137
137
|
? t('layout.githubPatPermissionsBanner.rejectedBody')
|
|
@@ -141,11 +141,11 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
141
141
|
|
|
142
142
|
<!-- The established gaps, named one by one. A bare "permissions are missing" leaves
|
|
143
143
|
the reader to guess which box to tick on a form with dozens. -->
|
|
144
|
-
<p v-if="missing.length" class="mt-3 text-sm text-
|
|
144
|
+
<p v-if="missing.length" class="mt-3 text-sm text-app-error-100">
|
|
145
145
|
<span class="font-medium">{{ t('layout.githubPatPermissionsBanner.missing') }}</span>
|
|
146
146
|
{{ missing.map(capabilityLabel).join(', ') }}
|
|
147
147
|
</p>
|
|
148
|
-
<p v-if="advisory.length" class="mt-1 text-xs text-
|
|
148
|
+
<p v-if="advisory.length" class="mt-1 text-xs text-app-error-200/80">
|
|
149
149
|
{{
|
|
150
150
|
t('layout.githubPatPermissionsBanner.alsoMissing', {
|
|
151
151
|
capabilities: advisory.map(capabilityLabel).join(', '),
|
|
@@ -155,7 +155,10 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
155
155
|
|
|
156
156
|
<!-- For a fine-grained token, WHICH repositories it was not granted is the whole
|
|
157
157
|
remedy: the permission list is right and the repository selection is not. -->
|
|
158
|
-
<p
|
|
158
|
+
<p
|
|
159
|
+
v-if="report && report.deniedRepos.length"
|
|
160
|
+
class="mt-1 text-xs text-app-error-200/80"
|
|
161
|
+
>
|
|
159
162
|
{{
|
|
160
163
|
t('layout.githubPatPermissionsBanner.deniedRepos', {
|
|
161
164
|
repos: report.deniedRepos.join(', '),
|
|
@@ -163,7 +166,7 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
163
166
|
}}
|
|
164
167
|
</p>
|
|
165
168
|
|
|
166
|
-
<p class="mt-2 text-xs text-
|
|
169
|
+
<p class="mt-2 text-xs text-app-error-200/80">{{ t(sourceKey) }}</p>
|
|
167
170
|
|
|
168
171
|
<div class="mt-4">
|
|
169
172
|
<UButton
|
|
@@ -185,7 +188,7 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
185
188
|
no prefill at all, so its permissions are spelled out. Saying so is the point:
|
|
186
189
|
a link that silently arrived with nothing selected reads as "already done for
|
|
187
190
|
you", which is how the missing permission got there in the first place. -->
|
|
188
|
-
<p class="mt-2 text-xs text-
|
|
191
|
+
<p class="mt-2 text-xs text-app-error-300/70">
|
|
189
192
|
{{
|
|
190
193
|
kind === 'fine_grained'
|
|
191
194
|
? t('layout.githubPatPermissionsBanner.fineGrainedHint', {
|
|
@@ -196,7 +199,10 @@ const fineGrainedPermissions = GITHUB_PAT_FINE_GRAINED_PERMISSIONS.join(', ')
|
|
|
196
199
|
</p>
|
|
197
200
|
<!-- A fine-grained verdict is a SAMPLE of the linked repositories. Declaring the
|
|
198
201
|
remainder keeps a clean-looking list from reading as a guarantee. -->
|
|
199
|
-
<p
|
|
202
|
+
<p
|
|
203
|
+
v-if="report && report.unprobedRepoCount > 0"
|
|
204
|
+
class="mt-1 text-xs text-app-error-300/60"
|
|
205
|
+
>
|
|
200
206
|
{{
|
|
201
207
|
t('layout.githubPatPermissionsBanner.sampled', {
|
|
202
208
|
checked: report.probedRepos.length,
|
|
@@ -208,8 +208,8 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
|
|
|
208
208
|
class="pointer-events-auto w-full max-w-3xl rounded-2xl border-2 p-5 shadow-2xl backdrop-blur"
|
|
209
209
|
:class="
|
|
210
210
|
card.kind === 'outage'
|
|
211
|
-
? 'border-
|
|
212
|
-
: 'border-
|
|
211
|
+
? 'border-app-error-500/70 bg-app-error-950/95'
|
|
212
|
+
: 'border-app-warning-500/70 bg-app-warning-950/95'
|
|
213
213
|
"
|
|
214
214
|
:data-testid="`infra-setup-banner-${card.area}`"
|
|
215
215
|
:data-infra-status="card.kind === 'outage' ? 'unreachable' : 'not_defined'"
|
|
@@ -218,13 +218,13 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
|
|
|
218
218
|
<UIcon
|
|
219
219
|
:name="card.kind === 'outage' ? 'i-lucide-plug-zap' : AREA_META[card.area].icon"
|
|
220
220
|
class="mt-0.5 h-9 w-9 shrink-0"
|
|
221
|
-
:class="card.kind === 'outage' ? 'text-
|
|
221
|
+
:class="card.kind === 'outage' ? 'text-app-error-400' : 'text-app-warning-400'"
|
|
222
222
|
/>
|
|
223
223
|
<div class="min-w-0 flex-1">
|
|
224
224
|
<div class="flex items-start justify-between gap-3">
|
|
225
225
|
<h2
|
|
226
226
|
class="text-lg font-semibold"
|
|
227
|
-
:class="card.kind === 'outage' ? 'text-
|
|
227
|
+
:class="card.kind === 'outage' ? 'text-app-error-100' : 'text-app-warning-100'"
|
|
228
228
|
>
|
|
229
229
|
{{ t(titleKey(card)) }}
|
|
230
230
|
</h2>
|
|
@@ -241,7 +241,7 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
|
|
|
241
241
|
</div>
|
|
242
242
|
<p
|
|
243
243
|
class="mt-1 text-sm"
|
|
244
|
-
:class="card.kind === 'outage' ? 'text-
|
|
244
|
+
:class="card.kind === 'outage' ? 'text-app-error-200/90' : 'text-app-warning-200/90'"
|
|
245
245
|
>
|
|
246
246
|
{{
|
|
247
247
|
card.kind === 'outage'
|
|
@@ -256,7 +256,7 @@ function dismissMenu(card: AreaCard): DropdownMenuItem[][] {
|
|
|
256
256
|
never the only thing that explains the card. -->
|
|
257
257
|
<p
|
|
258
258
|
v-if="card.detail"
|
|
259
|
-
class="mt-2 truncate font-mono text-xs text-
|
|
259
|
+
class="mt-2 truncate font-mono text-xs text-app-error-300/80"
|
|
260
260
|
:title="card.detail"
|
|
261
261
|
:data-testid="`infra-setup-detail-${card.area}`"
|
|
262
262
|
>
|
|
@@ -377,7 +377,7 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
377
377
|
<!-- Named for the same reason `model-providers-hub` is: the tutorial tour that explains
|
|
378
378
|
what a connection adds to a run points at this list. -->
|
|
379
379
|
<div class="space-y-5" data-testid="integrations-hub">
|
|
380
|
-
<p class="text-xs text-
|
|
380
|
+
<p class="text-xs text-muted">
|
|
381
381
|
{{ t('layout.integrationsHub.intro') }}
|
|
382
382
|
</p>
|
|
383
383
|
|
|
@@ -385,13 +385,13 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
385
385
|
run isn't blocked on hunting for them. Hidden once anything is connected. -->
|
|
386
386
|
<div
|
|
387
387
|
v-if="!anyConnected && recommendedActions.length"
|
|
388
|
-
class="rounded-lg border border-primary
|
|
388
|
+
class="rounded-lg border border-primary/40 bg-primary/10 p-3"
|
|
389
389
|
>
|
|
390
|
-
<div class="mb-2 flex items-center gap-2 text-sm font-medium text-primary
|
|
390
|
+
<div class="mb-2 flex items-center gap-2 text-sm font-medium text-primary">
|
|
391
391
|
<UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0" />
|
|
392
392
|
<span>{{ t('layout.integrationsHub.getStarted.title') }}</span>
|
|
393
393
|
</div>
|
|
394
|
-
<p class="mb-3 text-xs text-
|
|
394
|
+
<p class="mb-3 text-xs text-toned">
|
|
395
395
|
{{ t('layout.integrationsHub.getStarted.body') }}
|
|
396
396
|
</p>
|
|
397
397
|
<div class="flex flex-wrap gap-2">
|
|
@@ -417,12 +417,12 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
417
417
|
class="w-full"
|
|
418
418
|
/>
|
|
419
419
|
|
|
420
|
-
<p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-
|
|
420
|
+
<p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-dimmed">
|
|
421
421
|
{{ t('layout.integrationsHub.noMatches', { query }) }}
|
|
422
422
|
</p>
|
|
423
423
|
|
|
424
424
|
<section v-for="group in filteredGroups" :key="group.title">
|
|
425
|
-
<h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-
|
|
425
|
+
<h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
426
426
|
{{ group.title }}
|
|
427
427
|
</h3>
|
|
428
428
|
<div class="space-y-1.5">
|
|
@@ -430,20 +430,20 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
430
430
|
v-for="item in group.items"
|
|
431
431
|
:key="item.key"
|
|
432
432
|
type="button"
|
|
433
|
-
class="flex w-full items-center gap-3 rounded-lg border border-
|
|
433
|
+
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
434
|
@click="item.onClick()"
|
|
435
435
|
>
|
|
436
|
-
<UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-
|
|
436
|
+
<UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-toned" />
|
|
437
437
|
<div class="min-w-0 flex-1">
|
|
438
438
|
<div class="flex items-center gap-2">
|
|
439
|
-
<span class="truncate text-sm font-medium text-
|
|
439
|
+
<span class="truncate text-sm font-medium text-app-100">{{ item.label }}</span>
|
|
440
440
|
<UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
|
|
441
441
|
{{ item.status || t('layout.integrationsHub.status.connected') }}
|
|
442
442
|
</UBadge>
|
|
443
443
|
<UBadge v-else-if="item.attention" color="warning" variant="subtle" size="sm">
|
|
444
444
|
{{ item.attentionLabel || t('layout.integrationsHub.status.needsAttention') }}
|
|
445
445
|
</UBadge>
|
|
446
|
-
<span v-else class="text-[11px] text-
|
|
446
|
+
<span v-else class="text-[11px] text-dimmed">{{
|
|
447
447
|
t('layout.integrationsHub.status.notConnected')
|
|
448
448
|
}}</span>
|
|
449
449
|
<UBadge
|
|
@@ -455,11 +455,11 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
455
455
|
{{ t('layout.integrationsHub.status.recommended') }}
|
|
456
456
|
</UBadge>
|
|
457
457
|
</div>
|
|
458
|
-
<p class="truncate text-xs text-
|
|
458
|
+
<p class="truncate text-xs text-muted">{{ item.description }}</p>
|
|
459
459
|
</div>
|
|
460
460
|
<UIcon
|
|
461
461
|
name="i-lucide-chevron-right"
|
|
462
|
-
class="h-4 w-4 shrink-0 text-
|
|
462
|
+
class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
|
|
463
463
|
/>
|
|
464
464
|
</button>
|
|
465
465
|
</div>
|
|
@@ -468,17 +468,17 @@ const filteredGroups = computed<IntegrationGroup[]>(() => {
|
|
|
468
468
|
<button
|
|
469
469
|
v-if="group.footerLink"
|
|
470
470
|
type="button"
|
|
471
|
-
class="mt-1.5 flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-start text-xs text-
|
|
471
|
+
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
472
|
@click="group.footerLink.onClick()"
|
|
473
473
|
>
|
|
474
474
|
<UIcon :name="group.footerLink.icon" class="h-3.5 w-3.5 shrink-0" />
|
|
475
475
|
<span class="flex-1 truncate">{{ group.footerLink.label }}</span>
|
|
476
|
-
<span v-if="group.footerLink.status" class="shrink-0 text-
|
|
476
|
+
<span v-if="group.footerLink.status" class="shrink-0 text-dimmed">{{
|
|
477
477
|
group.footerLink.status
|
|
478
478
|
}}</span>
|
|
479
479
|
<UIcon
|
|
480
480
|
name="i-lucide-chevron-right"
|
|
481
|
-
class="h-3.5 w-3.5 shrink-0 text-
|
|
481
|
+
class="h-3.5 w-3.5 shrink-0 text-app-600 rtl:-scale-x-100"
|
|
482
482
|
/>
|
|
483
483
|
</button>
|
|
484
484
|
</section>
|
|
@@ -45,17 +45,17 @@ const items = computed<DropdownMenuItem[][]>(() => [
|
|
|
45
45
|
data-testid="language-switcher"
|
|
46
46
|
:aria-label="t('language.switcher')"
|
|
47
47
|
:title="collapsed ? `${t('language.switcher')}: ${current}` : undefined"
|
|
48
|
-
class="flex w-full items-center gap-2 rounded-lg border border-
|
|
48
|
+
class="flex w-full items-center gap-2 rounded-lg border border-default bg-default/60 p-2 text-start transition hover:bg-elevated/60"
|
|
49
49
|
:class="collapsed ? 'justify-center' : ''"
|
|
50
50
|
>
|
|
51
|
-
<UIcon name="i-lucide-languages" class="h-4 w-4 shrink-0 text-
|
|
51
|
+
<UIcon name="i-lucide-languages" class="h-4 w-4 shrink-0 text-muted" />
|
|
52
52
|
<div v-if="!collapsed" class="min-w-0 flex-1">
|
|
53
|
-
<div class="truncate text-[10px] uppercase tracking-wide text-
|
|
53
|
+
<div class="truncate text-[10px] uppercase tracking-wide text-dimmed">
|
|
54
54
|
{{ t('language.switcher') }}
|
|
55
55
|
</div>
|
|
56
|
-
<div class="truncate text-xs font-medium text-
|
|
56
|
+
<div class="truncate text-xs font-medium text-highlighted">{{ current }}</div>
|
|
57
57
|
</div>
|
|
58
|
-
<UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-
|
|
58
|
+
<UIcon v-if="!collapsed" name="i-lucide-chevron-up" class="h-4 w-4 shrink-0 text-dimmed" />
|
|
59
59
|
</button>
|
|
60
60
|
</UDropdownMenu>
|
|
61
61
|
</template>
|
|
@@ -171,21 +171,18 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
171
171
|
>
|
|
172
172
|
<template #body>
|
|
173
173
|
<div class="space-y-5" data-testid="model-providers-hub">
|
|
174
|
-
<p class="text-xs text-
|
|
174
|
+
<p class="text-xs text-muted">
|
|
175
175
|
{{ t('layout.modelProvidersHub.intro') }}
|
|
176
176
|
</p>
|
|
177
177
|
|
|
178
178
|
<!-- Nothing connected at all is a hard stop, not a nudge: no provider means no agent
|
|
179
179
|
step can run. Say so plainly rather than showing an empty list of options. -->
|
|
180
|
-
<div
|
|
181
|
-
|
|
182
|
-
class="rounded-lg border border-primary-500/40 bg-primary-500/10 p-3"
|
|
183
|
-
>
|
|
184
|
-
<div class="mb-1.5 flex items-center gap-2 text-sm font-medium text-primary-200">
|
|
180
|
+
<div v-if="!anyConnected" class="rounded-lg border border-primary/40 bg-primary/10 p-3">
|
|
181
|
+
<div class="mb-1.5 flex items-center gap-2 text-sm font-medium text-primary">
|
|
185
182
|
<UIcon name="i-lucide-rocket" class="h-4 w-4 shrink-0" />
|
|
186
183
|
<span>{{ t('layout.modelProvidersHub.getStarted.title') }}</span>
|
|
187
184
|
</div>
|
|
188
|
-
<p class="text-xs text-
|
|
185
|
+
<p class="text-xs text-toned">
|
|
189
186
|
{{ t('layout.modelProvidersHub.getStarted.body') }}
|
|
190
187
|
</p>
|
|
191
188
|
</div>
|
|
@@ -198,12 +195,12 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
198
195
|
class="w-full"
|
|
199
196
|
/>
|
|
200
197
|
|
|
201
|
-
<p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-
|
|
198
|
+
<p v-if="!filteredGroups.length" class="px-1 py-6 text-center text-sm text-dimmed">
|
|
202
199
|
{{ t('layout.modelProvidersHub.noMatches', { query }) }}
|
|
203
200
|
</p>
|
|
204
201
|
|
|
205
202
|
<section v-for="group in filteredGroups" :key="group.title">
|
|
206
|
-
<h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-
|
|
203
|
+
<h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
207
204
|
{{ group.title }}
|
|
208
205
|
</h3>
|
|
209
206
|
<div class="space-y-1.5">
|
|
@@ -211,18 +208,18 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
211
208
|
v-for="item in group.items"
|
|
212
209
|
:key="item.key"
|
|
213
210
|
type="button"
|
|
214
|
-
class="flex w-full items-center gap-3 rounded-lg border border-
|
|
211
|
+
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"
|
|
215
212
|
:data-testid="`model-provider-${item.key}`"
|
|
216
213
|
@click="item.onClick()"
|
|
217
214
|
>
|
|
218
|
-
<UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-
|
|
215
|
+
<UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-toned" />
|
|
219
216
|
<div class="min-w-0 flex-1">
|
|
220
217
|
<div class="flex items-center gap-2">
|
|
221
|
-
<span class="truncate text-sm font-medium text-
|
|
218
|
+
<span class="truncate text-sm font-medium text-app-100">{{ item.label }}</span>
|
|
222
219
|
<UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
|
|
223
220
|
{{ item.status || t('layout.modelProvidersHub.status.connected') }}
|
|
224
221
|
</UBadge>
|
|
225
|
-
<span v-else class="text-[11px] text-
|
|
222
|
+
<span v-else class="text-[11px] text-dimmed">{{
|
|
226
223
|
t('layout.modelProvidersHub.status.notConnected')
|
|
227
224
|
}}</span>
|
|
228
225
|
<UBadge
|
|
@@ -234,15 +231,15 @@ const filteredGroups = computed<ProviderGroup[]>(() => {
|
|
|
234
231
|
{{ t('layout.modelProvidersHub.status.recommended') }}
|
|
235
232
|
</UBadge>
|
|
236
233
|
</div>
|
|
237
|
-
<p class="truncate text-xs text-
|
|
234
|
+
<p class="truncate text-xs text-muted">{{ item.description }}</p>
|
|
238
235
|
</div>
|
|
239
236
|
<UIcon
|
|
240
237
|
name="i-lucide-chevron-right"
|
|
241
|
-
class="h-4 w-4 shrink-0 text-
|
|
238
|
+
class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
|
|
242
239
|
/>
|
|
243
240
|
</button>
|
|
244
241
|
</div>
|
|
245
|
-
<p v-if="group.note" class="mt-1.5 px-1 text-[11px] text-
|
|
242
|
+
<p v-if="group.note" class="mt-1.5 px-1 text-[11px] text-dimmed">{{ group.note }}</p>
|
|
246
243
|
</section>
|
|
247
244
|
</div>
|
|
248
245
|
</template>
|
|
@@ -406,7 +406,7 @@ function revealDecision(n: Notification) {
|
|
|
406
406
|
|
|
407
407
|
<template #content>
|
|
408
408
|
<div class="max-h-[28rem] w-[min(24rem,92vw)] overflow-y-auto p-2">
|
|
409
|
-
<div class="px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-
|
|
409
|
+
<div class="px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
410
410
|
{{ t('layout.notifications.heading') }}
|
|
411
411
|
</div>
|
|
412
412
|
<div
|
|
@@ -417,8 +417,8 @@ function revealDecision(n: Notification) {
|
|
|
417
417
|
class="rounded-lg border p-2.5 mt-1.5"
|
|
418
418
|
:class="
|
|
419
419
|
isUrgent(n)
|
|
420
|
-
? 'border-error-500/60 bg-error-500/10'
|
|
421
|
-
: 'border-
|
|
420
|
+
? 'border-app-error-500/60 bg-app-error-500/10'
|
|
421
|
+
: 'border-muted/60 bg-elevated/40'
|
|
422
422
|
"
|
|
423
423
|
>
|
|
424
424
|
<div class="flex items-start gap-2">
|
|
@@ -429,7 +429,7 @@ function revealDecision(n: Notification) {
|
|
|
429
429
|
<div class="min-w-0 flex-1">
|
|
430
430
|
<div class="flex items-center gap-1.5">
|
|
431
431
|
<button
|
|
432
|
-
class="block min-w-0 flex-1 truncate text-start text-sm font-medium text-
|
|
432
|
+
class="block min-w-0 flex-1 truncate text-start text-sm font-medium text-default hover:underline"
|
|
433
433
|
:title="n.title"
|
|
434
434
|
@click="reveal(n)"
|
|
435
435
|
>
|
|
@@ -437,18 +437,18 @@ function revealDecision(n: Notification) {
|
|
|
437
437
|
</button>
|
|
438
438
|
<span
|
|
439
439
|
v-if="isUrgent(n)"
|
|
440
|
-
class="shrink-0 rounded bg-error-500/20 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-error-400"
|
|
440
|
+
class="shrink-0 rounded bg-app-error-500/20 px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-app-error-400"
|
|
441
441
|
>
|
|
442
442
|
{{ t('layout.notifications.overdue') }}
|
|
443
443
|
</span>
|
|
444
444
|
</div>
|
|
445
|
-
<p class="mt-0.5 text-[11px] leading-snug text-
|
|
445
|
+
<p class="mt-0.5 text-[11px] leading-snug text-muted">{{ n.body }}</p>
|
|
446
446
|
<a
|
|
447
447
|
v-if="n.payload?.prUrl"
|
|
448
448
|
:href="n.payload.prUrl"
|
|
449
449
|
target="_blank"
|
|
450
450
|
rel="noopener"
|
|
451
|
-
class="mt-1 inline-flex items-center gap-1 text-[11px] text-
|
|
451
|
+
class="mt-1 inline-flex items-center gap-1 text-[11px] text-app-info-400 hover:underline"
|
|
452
452
|
>
|
|
453
453
|
<UIcon name="i-lucide-external-link" class="h-3 w-3" />
|
|
454
454
|
{{ t('layout.notifications.openPr') }}
|
|
@@ -470,8 +470,8 @@ function revealDecision(n: Notification) {
|
|
|
470
470
|
class="flex items-center gap-1 text-start text-[11px]"
|
|
471
471
|
:class="
|
|
472
472
|
canOpenFailingRun(run)
|
|
473
|
-
? 'text-
|
|
474
|
-
: 'cursor-default text-
|
|
473
|
+
? 'text-app-info-400 hover:underline'
|
|
474
|
+
: 'cursor-default text-dimmed'
|
|
475
475
|
"
|
|
476
476
|
:title="
|
|
477
477
|
canOpenFailingRun(run) ? undefined : t('layout.notifications.failingRunGone')
|
|
@@ -486,7 +486,7 @@ function revealDecision(n: Notification) {
|
|
|
486
486
|
})
|
|
487
487
|
}}</span>
|
|
488
488
|
</component>
|
|
489
|
-
<span v-if="failingRunsOmitted(n) > 0" class="text-[11px] text-
|
|
489
|
+
<span v-if="failingRunsOmitted(n) > 0" class="text-[11px] text-dimmed">
|
|
490
490
|
{{ t('layout.notifications.failingRunsMore', { count: failingRunsOmitted(n) }) }}
|
|
491
491
|
</span>
|
|
492
492
|
</div>
|
|
@@ -112,12 +112,12 @@ const groups = computed<PersonalGroup[]>(() => {
|
|
|
112
112
|
>
|
|
113
113
|
<template #body>
|
|
114
114
|
<div class="space-y-5">
|
|
115
|
-
<p class="text-xs text-
|
|
115
|
+
<p class="text-xs text-muted">
|
|
116
116
|
{{ t('layout.personalSetup.intro') }}
|
|
117
117
|
</p>
|
|
118
118
|
|
|
119
119
|
<section v-for="group in groups" :key="group.title">
|
|
120
|
-
<h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-
|
|
120
|
+
<h3 class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted">
|
|
121
121
|
{{ group.title }}
|
|
122
122
|
</h3>
|
|
123
123
|
<div class="space-y-1.5">
|
|
@@ -125,25 +125,25 @@ const groups = computed<PersonalGroup[]>(() => {
|
|
|
125
125
|
v-for="item in group.items"
|
|
126
126
|
:key="item.key"
|
|
127
127
|
type="button"
|
|
128
|
-
class="flex w-full items-center gap-3 rounded-lg border border-
|
|
128
|
+
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"
|
|
129
129
|
@click="item.onClick()"
|
|
130
130
|
>
|
|
131
|
-
<UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-
|
|
131
|
+
<UIcon :name="item.icon" class="h-5 w-5 shrink-0 text-toned" />
|
|
132
132
|
<div class="min-w-0 flex-1">
|
|
133
133
|
<div class="flex items-center gap-2">
|
|
134
|
-
<span class="truncate text-sm font-medium text-
|
|
134
|
+
<span class="truncate text-sm font-medium text-app-100">{{ item.label }}</span>
|
|
135
135
|
<UBadge v-if="item.connected" color="success" variant="subtle" size="sm">
|
|
136
136
|
{{ item.status || t('layout.personalSetup.connected') }}
|
|
137
137
|
</UBadge>
|
|
138
|
-
<span v-else class="text-[11px] text-
|
|
138
|
+
<span v-else class="text-[11px] text-dimmed">
|
|
139
139
|
{{ t('layout.personalSetup.notConnected') }}
|
|
140
140
|
</span>
|
|
141
141
|
</div>
|
|
142
|
-
<p class="truncate text-xs text-
|
|
142
|
+
<p class="truncate text-xs text-muted">{{ item.description }}</p>
|
|
143
143
|
</div>
|
|
144
144
|
<UIcon
|
|
145
145
|
name="i-lucide-chevron-right"
|
|
146
|
-
class="h-4 w-4 shrink-0 text-
|
|
146
|
+
class="h-4 w-4 shrink-0 text-dimmed rtl:-scale-x-100"
|
|
147
147
|
/>
|
|
148
148
|
</button>
|
|
149
149
|
</div>
|
|
@@ -42,14 +42,14 @@ const show = computed(() => pending.value.length > 0 && !dismissed.value)
|
|
|
42
42
|
renders only its card and re-enables pointer events on it. -->
|
|
43
43
|
<div v-if="show" class="pointer-events-auto w-full max-w-3xl">
|
|
44
44
|
<div
|
|
45
|
-
class="w-full max-w-3xl rounded-2xl border-2 border-
|
|
45
|
+
class="w-full max-w-3xl rounded-2xl border-2 border-app-warning-500/70 bg-app-warning-950/95 p-5 shadow-2xl backdrop-blur"
|
|
46
46
|
role="alert"
|
|
47
47
|
>
|
|
48
48
|
<div class="flex items-start gap-4">
|
|
49
|
-
<UIcon name="i-lucide-plug" class="mt-0.5 h-9 w-9 shrink-0 text-
|
|
49
|
+
<UIcon name="i-lucide-plug" class="mt-0.5 h-9 w-9 shrink-0 text-app-warning-400" />
|
|
50
50
|
<div class="min-w-0 flex-1">
|
|
51
51
|
<div class="flex items-start justify-between gap-3">
|
|
52
|
-
<h2 class="text-lg font-semibold text-
|
|
52
|
+
<h2 class="text-lg font-semibold text-app-warning-100">
|
|
53
53
|
{{
|
|
54
54
|
pending.length > 1
|
|
55
55
|
? t('layout.providerConfigBanner.titleMany')
|
|
@@ -69,7 +69,7 @@ const show = computed(() => pending.value.length > 0 && !dismissed.value)
|
|
|
69
69
|
"
|
|
70
70
|
/>
|
|
71
71
|
</div>
|
|
72
|
-
<p class="mt-1 text-sm text-
|
|
72
|
+
<p class="mt-1 text-sm text-app-warning-200/90">
|
|
73
73
|
{{ t('layout.providerConfigBanner.body') }}
|
|
74
74
|
</p>
|
|
75
75
|
<div class="mt-4 flex flex-wrap gap-2">
|
|
@@ -29,7 +29,7 @@ function pick(role: UiRole) {
|
|
|
29
29
|
<UModal v-model:open="open" :title="t('uiRole.prompt.title')" :ui="{ content: 'max-w-lg' }">
|
|
30
30
|
<template #body>
|
|
31
31
|
<div class="space-y-4" data-testid="role-prompt">
|
|
32
|
-
<p class="text-sm text-
|
|
32
|
+
<p class="text-sm text-toned">{{ t('uiRole.prompt.intro') }}</p>
|
|
33
33
|
<div class="space-y-2">
|
|
34
34
|
<button
|
|
35
35
|
v-for="role in UI_ROLES"
|
|
@@ -40,23 +40,23 @@ function pick(role: UiRole) {
|
|
|
40
40
|
class="flex w-full items-center gap-3 rounded-lg border p-3 text-start transition"
|
|
41
41
|
:class="
|
|
42
42
|
role === uiRole.role && uiRole.chosen
|
|
43
|
-
? 'border-
|
|
44
|
-
: 'border-
|
|
43
|
+
? 'border-primary/60 bg-primary/10'
|
|
44
|
+
: 'border-default bg-default/60 hover:border-app-600 hover:bg-elevated/60'
|
|
45
45
|
"
|
|
46
46
|
@click="pick(role)"
|
|
47
47
|
>
|
|
48
|
-
<UIcon :name="ROLE_PRESENTATION[role].icon" class="h-5 w-5 shrink-0 text-primary
|
|
48
|
+
<UIcon :name="ROLE_PRESENTATION[role].icon" class="h-5 w-5 shrink-0 text-primary" />
|
|
49
49
|
<div class="min-w-0 flex-1">
|
|
50
|
-
<div class="text-sm font-medium text-
|
|
50
|
+
<div class="text-sm font-medium text-app-100">
|
|
51
51
|
{{ t(ROLE_PRESENTATION[role].labelKey) }}
|
|
52
52
|
</div>
|
|
53
|
-
<p class="text-xs text-
|
|
53
|
+
<p class="text-xs text-muted">{{ t(ROLE_PRESENTATION[role].hintKey) }}</p>
|
|
54
54
|
</div>
|
|
55
55
|
</button>
|
|
56
56
|
</div>
|
|
57
57
|
<!-- The choice is not a commitment, and saying so is what makes the narrowed role
|
|
58
58
|
pickable: it is one dropdown at the top of the sidebar to leave again. -->
|
|
59
|
-
<p class="text-[11px] leading-snug text-
|
|
59
|
+
<p class="text-[11px] leading-snug text-dimmed">{{ t('uiRole.prompt.change') }}</p>
|
|
60
60
|
</div>
|
|
61
61
|
</template>
|
|
62
62
|
<template #footer>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// independently from the role / tier switchers at the top and the rail toggle.
|
|
14
14
|
import { useEventListener, useScrollLock } from '@vueuse/core'
|
|
15
15
|
import BoardSwitcher from '~/components/layout/BoardSwitcher.vue'
|
|
16
|
+
import AppearanceSwitcher from '~/components/layout/AppearanceSwitcher.vue'
|
|
16
17
|
import LanguageSwitcher from '~/components/layout/LanguageSwitcher.vue'
|
|
17
18
|
import UiModeSwitcher from '~/components/layout/UiModeSwitcher.vue'
|
|
18
19
|
import UiRoleSwitcher from '~/components/layout/UiRoleSwitcher.vue'
|
|
@@ -154,7 +155,7 @@ watch(
|
|
|
154
155
|
>
|
|
155
156
|
<div
|
|
156
157
|
v-if="ui.mobileNavOpen"
|
|
157
|
-
class="fixed inset-0 z-30 bg-
|
|
158
|
+
class="fixed inset-0 z-30 bg-app-950/60 backdrop-blur-sm lg:hidden"
|
|
158
159
|
data-testid="sidebar-backdrop"
|
|
159
160
|
role="button"
|
|
160
161
|
tabindex="-1"
|
|
@@ -171,7 +172,7 @@ watch(
|
|
|
171
172
|
:aria-modal="drawerOpen ? 'true' : undefined"
|
|
172
173
|
:aria-label="isCompact ? t('nav.menu') : undefined"
|
|
173
174
|
:inert="isCompact && !ui.mobileNavOpen"
|
|
174
|
-
class="fixed inset-y-0 start-0 z-40 flex h-full w-64 shrink-0 flex-col gap-4 overflow-y-auto border-e border-
|
|
175
|
+
class="fixed inset-y-0 start-0 z-40 flex h-full w-64 shrink-0 flex-col gap-4 overflow-y-auto border-e border-default bg-default/95 px-3 pt-3 pb-[calc(0.75rem+env(safe-area-inset-bottom))] backdrop-blur transition-transform duration-200 focus:outline-none lg:static lg:z-auto lg:translate-x-0 lg:bg-default/80"
|
|
175
176
|
:class="[
|
|
176
177
|
ui.mobileNavOpen
|
|
177
178
|
? 'translate-x-0'
|
|
@@ -226,7 +227,7 @@ watch(
|
|
|
226
227
|
and reach every action below. -->
|
|
227
228
|
<button
|
|
228
229
|
type="button"
|
|
229
|
-
class="flex items-center gap-2 rounded-lg border border-
|
|
230
|
+
class="flex items-center gap-2 rounded-lg border border-muted bg-elevated/60 py-2 text-start text-sm text-muted transition hover:border-app-500 hover:bg-elevated"
|
|
230
231
|
:class="railed ? 'justify-center px-0' : 'px-2.5'"
|
|
231
232
|
:aria-label="t('nav.commandBar')"
|
|
232
233
|
:title="railed ? t('nav.commandBar') : undefined"
|
|
@@ -249,7 +250,7 @@ watch(
|
|
|
249
250
|
<section>
|
|
250
251
|
<h2
|
|
251
252
|
v-if="!railed"
|
|
252
|
-
class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-
|
|
253
|
+
class="mb-2 px-1 text-[11px] font-semibold uppercase tracking-wide text-muted"
|
|
253
254
|
>
|
|
254
255
|
{{ t(section.labelKey) }}
|
|
255
256
|
</h2>
|
|
@@ -278,6 +279,7 @@ watch(
|
|
|
278
279
|
</div>
|
|
279
280
|
|
|
280
281
|
<div class="mt-auto space-y-2">
|
|
282
|
+
<AppearanceSwitcher :collapsed="railed" />
|
|
281
283
|
<LanguageSwitcher :collapsed="railed" />
|
|
282
284
|
<UserMenu :collapsed="railed" />
|
|
283
285
|
</div>
|