feat(ui): redesign header to be compact with ASCII icon

This commit is contained in:
Keith Guerin
2026-02-09 23:05:54 -08:00
parent 39754c5093
commit c6561682e5
3 changed files with 18 additions and 28 deletions
@@ -93,13 +93,11 @@ export const AppHeader = ({ version, showDetails = true }: AppHeaderProps) => {
<Box height={1} /> <Box height={1} />
{/* Lines 3 & 4: User Identity info (Email /auth and Plan /upgrade) */} {/* Lines 3 & 4: User Identity info (Email /auth and Plan /upgrade) */}
<Box>
{settings.merged.ui.showUserIdentity !== false && ( {settings.merged.ui.showUserIdentity !== false && (
<UserIdentity config={config} /> <UserIdentity config={config} />
)} )}
</Box> </Box>
</Box> </Box>
</Box>
)} )}
{bannerVisible && bannerText && ( {bannerVisible && bannerText && (
@@ -45,12 +45,12 @@ describe('<UserIdentity />', () => {
await waitUntilReady(); await waitUntilReady();
const output = lastFrame(); const output = lastFrame();
expect(output).toContain('Logged in with Google: test@example.com'); expect(output).toContain('test@example.com');
expect(output).toContain('/auth'); expect(output).toContain('/auth');
unmount(); unmount();
}); });
it('should render login message without colon if email is missing', async () => { it('should render login message if email is missing', async () => {
// Modify the mock for this specific test // Modify the mock for this specific test
vi.mocked(UserAccountManager).mockImplementationOnce( vi.mocked(UserAccountManager).mockImplementationOnce(
() => () =>
@@ -73,12 +73,11 @@ describe('<UserIdentity />', () => {
const output = lastFrame(); const output = lastFrame();
expect(output).toContain('Logged in with Google'); expect(output).toContain('Logged in with Google');
expect(output).not.toContain('Logged in with Google:');
expect(output).toContain('/auth'); expect(output).toContain('/auth');
unmount(); unmount();
}); });
it('should render plan name on a separate line if provided', async () => { it('should render plan name and upgrade indicator', async () => {
const mockConfig = makeFakeConfig(); const mockConfig = makeFakeConfig();
vi.spyOn(mockConfig, 'getContentGeneratorConfig').mockReturnValue({ vi.spyOn(mockConfig, 'getContentGeneratorConfig').mockReturnValue({
authType: AuthType.LOGIN_WITH_GOOGLE, authType: AuthType.LOGIN_WITH_GOOGLE,
@@ -92,18 +91,10 @@ describe('<UserIdentity />', () => {
await waitUntilReady(); await waitUntilReady();
const output = lastFrame(); const output = lastFrame();
expect(output).toContain('Logged in with Google: test@example.com'); expect(output).toContain('test@example.com');
expect(output).toContain('/auth'); expect(output).toContain('/auth');
expect(output).toContain('Plan: Premium Plan'); expect(output).toContain('Premium Plan');
expect(output).toContain('/upgrade');
// Check for two lines (or more if wrapped, but here it should be separate)
const lines = output?.split('\n').filter((line) => line.trim().length > 0);
expect(lines?.some((line) => line.includes('Logged in with Google'))).toBe(
true,
);
expect(lines?.some((line) => line.includes('Plan: Premium Plan'))).toBe(
true,
);
unmount(); unmount();
}); });
@@ -37,25 +37,26 @@ export const UserIdentity: React.FC<UserIdentityProps> = ({ config }) => {
} }
return ( return (
<Box marginTop={1} flexDirection="column"> <Box flexDirection="column">
{/* User Email /auth */}
<Box> <Box>
<Text color={theme.text.primary}> <Text color={theme.text.primary}>
{authType === AuthType.LOGIN_WITH_GOOGLE ? ( {authType === AuthType.LOGIN_WITH_GOOGLE ? (
<Text> <Text>{email ?? 'Logged in with Google'}</Text>
<Text bold>Logged in with Google{email ? ':' : ''}</Text>
{email ? ` ${email}` : ''}
</Text>
) : ( ) : (
`Authenticated with ${authType}` `Authenticated with ${authType}`
)} )}
</Text> </Text>
<Text color={theme.text.secondary}> /auth</Text> <Text color={theme.text.secondary}> /auth</Text>
</Box> </Box>
{tierName && (
{/* Tier Name /upgrade */}
<Box>
<Text color={theme.text.primary}> <Text color={theme.text.primary}>
<Text bold>Plan:</Text> {tierName} {tierName ?? 'Gemini Code Assist for individuals'}
</Text> </Text>
)} <Text color={theme.text.secondary}> /upgrade</Text>
</Box>
</Box> </Box>
); );
}; };