{refreshError}
: null} - + ); } diff --git a/packages/dashboard/app/components/EngineStatusBanner.css b/packages/dashboard/app/components/EngineStatusBanner.css index 6d5a435fdd..9c705b1da7 100644 --- a/packages/dashboard/app/components/EngineStatusBanner.css +++ b/packages/dashboard/app/components/EngineStatusBanner.css @@ -1,87 +1,7 @@ -.engine-status-banner { - display: flex; - align-items: flex-start; - gap: var(--space-md); - margin: var(--space-md) var(--space-lg) 0; - padding: var(--space-md) var(--space-lg); - background: linear-gradient( - 90deg, - color-mix(in srgb, var(--color-warning) 12%, transparent), - color-mix(in srgb, var(--surface) 92%, transparent) - ); - border: var(--btn-border-width) solid color-mix(in srgb, var(--color-warning) 35%, transparent); - border-radius: var(--radius-md); -} - -.engine-status-banner__indicator { - display: inline-flex; - align-items: center; - padding-top: calc(var(--space-xs) / 2); - flex-shrink: 0; -} - -.engine-status-banner__content { - flex: 1; - min-width: 0; - display: flex; - flex-direction: column; - gap: var(--space-xs); -} - -.engine-status-banner__title { - font-weight: 600; - color: var(--text); -} - -.engine-status-banner__body, -.engine-status-banner__error { - margin: 0; - color: var(--text-muted); - line-height: 1.5; -} - -.engine-status-banner__body code { - background: color-mix(in srgb, var(--text) 6%, transparent); - padding: 0 var(--space-xs); - border-radius: var(--radius-sm); - color: var(--text); -} - -.engine-status-banner__error { - color: var(--color-error); -} - -.engine-status-banner__actions { - display: flex; - align-items: center; - justify-content: flex-end; - flex-shrink: 0; -} - -.engine-status-banner__start { - display: inline-flex; - align-items: center; - gap: var(--space-xs); - white-space: nowrap; -} - -@media (max-width: 768px) { - .engine-status-banner { - flex-direction: column; - gap: var(--space-sm); - margin-inline: var(--space-md); - } - - .engine-status-banner__actions, - .engine-status-banner__start { - width: 100%; - } - - .engine-status-banner__actions { - justify-content: stretch; - } - - .engine-status-banner__start { - justify-content: center; - } -} +.engine-status-banner { margin: var(--space-md) var(--space-lg) 0; } +.engine-status-banner__indicator { display: inline-flex; align-items: center; padding-top: calc(var(--space-xs) / 2); } +.engine-status-banner__body, .engine-status-banner__error { margin: 0; line-height: 1.5; } +.engine-status-banner__body code { background: color-mix(in srgb, var(--text) 6%, transparent); padding: 0 var(--space-xs); border-radius: var(--radius-sm); color: var(--text); } +.engine-status-banner__error { color: var(--color-error); } +.engine-status-banner__start { display: inline-flex; align-items: center; gap: var(--space-xs); white-space: nowrap; } +@media (max-width: 768px) { .engine-status-banner { margin-inline: var(--space-md); } .engine-status-banner__start { width: 100%; justify-content: center; } } diff --git a/packages/dashboard/app/components/EngineStatusBanner.tsx b/packages/dashboard/app/components/EngineStatusBanner.tsx index 77e3d1a0a2..2ad20872fb 100644 --- a/packages/dashboard/app/components/EngineStatusBanner.tsx +++ b/packages/dashboard/app/components/EngineStatusBanner.tsx @@ -1,6 +1,7 @@ import { useTranslation } from "react-i18next"; import { Loader2 } from "lucide-react"; import { useEngineStatus } from "../hooks/useEngineStatus"; +import { Banner } from "./Banner"; import "./EngineStatusBanner.css"; interface EngineStatusBannerProps { @@ -24,39 +25,28 @@ export function EngineStatusBanner({ projectId }: EngineStatusBannerProps) { : t("engineBanner.dashboardOnly", "This dashboard cannot start engines from the current process. Run `fn serve` for this project to enable task execution and live automation."); return ( -+
{isDashboardOnly ? (
<>
{t("engineBanner.dashboardOnlyPrefix", "This dashboard cannot start engines from the current process. Run")} fn serve {t("engineBanner.dashboardOnlySuffix", "for this project to enable task execution and live automation.")}
>
) : body}
-
- {t("engineBanner.error", "Start failed: {{message}}", { message: error })} -
- )} -{t("engineBanner.error", "Start failed: {{message}}", { message: error })}
} + ); } diff --git a/packages/dashboard/app/components/EngineUnavailableBanner.css b/packages/dashboard/app/components/EngineUnavailableBanner.css index 4e9d7d36ce..4c948d2ad6 100644 --- a/packages/dashboard/app/components/EngineUnavailableBanner.css +++ b/packages/dashboard/app/components/EngineUnavailableBanner.css @@ -1,54 +1,18 @@ -.engine-unavailable-banner { - display: flex; - align-items: flex-start; - gap: var(--space-sm); - margin-bottom: var(--space-md); - padding: var(--space-sm) var(--space-md); - border-radius: var(--radius-md); - border-inline-start: var(--space-xs) solid var(--color-warning); - background: color-mix(in srgb, var(--color-warning) 10%, transparent); - color: var(--text); -} - .engine-unavailable-banner__icon { width: 1.1rem; height: 1.1rem; margin-top: 0.15rem; - color: var(--color-warning); - flex: 0 0 auto; -} - -.engine-unavailable-banner__copy { - display: flex; - flex-direction: column; - gap: var(--space-xs); - min-width: 0; } .engine-unavailable-banner__title { margin: 0; font-size: var(--font-size-base); line-height: var(--line-height-tight); - color: var(--text); } -.engine-unavailable-banner__body { - margin: 0; - color: var(--text-muted); -} - -.engine-unavailable-banner code { - color: var(--text); - white-space: nowrap; -} +.engine-unavailable-banner__body { margin: 0; } +.engine-unavailable-banner code { color: var(--text); white-space: nowrap; } @media (max-width: 768px) { - .engine-unavailable-banner { - padding: var(--space-sm); - } - - .engine-unavailable-banner code { - white-space: normal; - overflow-wrap: anywhere; - } + .engine-unavailable-banner code { white-space: normal; overflow-wrap: anywhere; } } diff --git a/packages/dashboard/app/components/EngineUnavailableBanner.tsx b/packages/dashboard/app/components/EngineUnavailableBanner.tsx index 7f69b71f9d..b503f12f3e 100644 --- a/packages/dashboard/app/components/EngineUnavailableBanner.tsx +++ b/packages/dashboard/app/components/EngineUnavailableBanner.tsx @@ -1,5 +1,6 @@ import { AlertTriangle } from "lucide-react"; import { Trans, useTranslation } from "react-i18next"; +import { Banner } from "./Banner"; import "./EngineUnavailableBanner.css"; @@ -18,11 +19,16 @@ export function EngineUnavailableBanner({ isVisible }: EngineUnavailableBannerPr * When the dashboard is served without an in-process AI engine, users need an explicit operational banner with the exact restart command because task execution, review, and merge automation cannot run from a UI-only process. */ return ( -+ } + title={
@@ -152,23 +155,6 @@ export function OAuthReloginBanner({ : t("auth.reloginRequiredMultiple", "Re-login required: {{providers}}", { providers: providerList })}
{t("setup.compactWarning", "⚠ Setup incomplete — AI and/or GitHub features will be limited.")}
- {dismissButton} -{recommendedAction}
{refreshError ?{refreshError}
: null} - + ); } diff --git a/packages/dashboard/app/components/TestModeBanner.css b/packages/dashboard/app/components/TestModeBanner.css index 4f0db41a9b..e69de29bb2 100644 --- a/packages/dashboard/app/components/TestModeBanner.css +++ b/packages/dashboard/app/components/TestModeBanner.css @@ -1,18 +0,0 @@ -.test-mode-banner { - display: flex; - align-items: center; - gap: var(--space-sm); - margin-bottom: var(--space-md); - padding: var(--space-sm) var(--space-md); - border-radius: var(--radius-md); - border-inline-start: var(--space-xs) solid var(--color-warning); - background: color-mix(in srgb, var(--color-warning) 18%, transparent); - color: var(--text); -} - -@media (max-width: 768px) { - .test-mode-banner { - padding: var(--space-sm); - align-items: flex-start; - } -} diff --git a/packages/dashboard/app/components/TestModeBanner.tsx b/packages/dashboard/app/components/TestModeBanner.tsx index aa638a6406..c87fe309bf 100644 --- a/packages/dashboard/app/components/TestModeBanner.tsx +++ b/packages/dashboard/app/components/TestModeBanner.tsx @@ -1,5 +1,6 @@ import { useTranslation } from "react-i18next"; import { FlaskConical } from "lucide-react"; +import { Banner } from "./Banner"; import "./TestModeBanner.css"; interface TestModeBannerProps { @@ -8,14 +9,11 @@ interface TestModeBannerProps { export function TestModeBanner({ isActive }: TestModeBannerProps) { const { t } = useTranslation("app"); - if (!isActive) { - return null; - } + if (!isActive) return null; return ( -