From e20d282088f77bb2fef21bc6f3f48af5689bec47 Mon Sep 17 00:00:00 2001
From: Adib234 <30782825+Adib234@users.noreply.github.com>
Date: Thu, 20 Nov 2025 08:52:15 -0800
Subject: [PATCH] Update banner design (#13420)
---
packages/cli/src/ui/components/AppHeader.tsx | 17 ++---
packages/cli/src/ui/components/Banner.tsx | 71 +++++++++++++++----
.../ui/components/GradientRegression.test.tsx | 2 +-
3 files changed, 63 insertions(+), 27 deletions(-)
diff --git a/packages/cli/src/ui/components/AppHeader.tsx b/packages/cli/src/ui/components/AppHeader.tsx
index d66fad4a95..05e528f6c7 100644
--- a/packages/cli/src/ui/components/AppHeader.tsx
+++ b/packages/cli/src/ui/components/AppHeader.tsx
@@ -10,11 +10,9 @@ import { Tips } from './Tips.js';
import { useSettings } from '../contexts/SettingsContext.js';
import { useConfig } from '../contexts/ConfigContext.js';
import { useUIState } from '../contexts/UIStateContext.js';
-import { Banner } from './Banner.js';
-import { theme } from '../semantic-colors.js';
-import { Colors } from '../colors.js';
import { persistentState } from '../../utils/persistentState.js';
-import { useState, useEffect, useRef } from 'react';
+import { useEffect, useRef, useState } from 'react';
+import { Banner } from './Banner.js';
interface AppHeaderProps {
version: string;
@@ -35,11 +33,8 @@ export const AppHeader = ({ version }: AppHeaderProps) => {
warningText === '' &&
!config.getPreviewFeatures() &&
defaultBannerShownCount < 5;
- const bannerText = showDefaultBanner ? defaultText : warningText;
- const unescapedBannerText = bannerText.replace(/\\n/g, '\n');
- const defaultColor = Colors.AccentBlue;
- const fontColor = warningText === '' ? defaultColor : theme.status.warning;
+ const bannerText = showDefaultBanner ? defaultText : warningText;
const hasIncrementedRef = useRef(false);
useEffect(() => {
@@ -55,11 +50,11 @@ export const AppHeader = ({ version }: AppHeaderProps) => {
{!(settings.merged.ui?.hideBanner || config.getScreenReader()) && (
<>
- {bannerVisible && unescapedBannerText && (
+ {bannerVisible && bannerText && (
)}
>
diff --git a/packages/cli/src/ui/components/Banner.tsx b/packages/cli/src/ui/components/Banner.tsx
index 460bef540f..99f573a68e 100644
--- a/packages/cli/src/ui/components/Banner.tsx
+++ b/packages/cli/src/ui/components/Banner.tsx
@@ -6,24 +6,65 @@
import { Box, Text } from 'ink';
import { ThemedGradient } from './ThemedGradient.js';
+import { theme } from '../semantic-colors.js';
+import type { ReactNode } from 'react';
+
+export function getFormattedBannerContent(
+ rawText: string,
+ isWarning: boolean,
+ subsequentLineColor: string,
+): ReactNode {
+ if (isWarning) {
+ return (
+ {rawText.replace(/\\n/g, '\n')}
+ );
+ }
+
+ const text = rawText.replace(/\\n/g, '\n');
+ const lines = text.split('\n');
+
+ return lines.map((line, index) => {
+ if (index === 0) {
+ return (
+
+ {line}
+
+ );
+ }
+
+ return (
+
+ {line}
+
+ );
+ });
+}
interface BannerProps {
bannerText: string;
- color: string;
+ isWarning: boolean;
width: number;
}
-export const Banner = ({ bannerText, color, width }: BannerProps) => (
-
-
- {bannerText}
-
-
-);
+export const Banner = ({ bannerText, isWarning, width }: BannerProps) => {
+ const subsequentLineColor = theme.text.primary;
+
+ const formattedBannerContent = getFormattedBannerContent(
+ bannerText,
+ isWarning,
+ subsequentLineColor,
+ );
+
+ return (
+
+ {formattedBannerContent}
+
+ );
+};
diff --git a/packages/cli/src/ui/components/GradientRegression.test.tsx b/packages/cli/src/ui/components/GradientRegression.test.tsx
index af6d5c1df0..ab0990b370 100644
--- a/packages/cli/src/ui/components/GradientRegression.test.tsx
+++ b/packages/cli/src/ui/components/GradientRegression.test.tsx
@@ -88,7 +88,7 @@ describe('Gradient Crash Regression Tests', () => {
it(' should not crash when theme.ui.gradient is empty', () => {
const { lastFrame } = renderWithProviders(
- ,
+ ,
{
width: 120,
},