Skip to content

Commit 35ad41a

Browse files
committed
Fix welcome screen theme violation and unwanted profile display
Fixes #1005 - Add welcome suppression logic to useWelcomeOnboarding hook when user has configured profiles/models via defaultProfile, LLXPRT_PROFILE env var, or active provider/runtime - Fix theme color application in all WelcomeOnboarding components by explicitly setting color={Colors.Foreground} on all text elements that were using default white - Components fixed: WelcomeStep, ProviderSelectStep, ModelSelectStep, AuthMethodStep, AuthenticationStep, CompletionStep, SkipExitStep
1 parent 2304bc7 commit 35ad41a

File tree

8 files changed

+117
-37
lines changed

8 files changed

+117
-37
lines changed

packages/cli/src/ui/components/WelcomeOnboarding/AuthMethodStep.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ export const AuthMethodStep: React.FC<AuthMethodStepProps> = ({
8888
<Text bold color={Colors.AccentCyan}>
8989
Step 3 of 5: Choose Authentication Method
9090
</Text>
91-
<Text> </Text>
92-
<Text>How would you like to authenticate with {providerDisplay}?</Text>
91+
<Text color={Colors.Foreground}>
92+
How would you like to authenticate with {providerDisplay}?
93+
</Text>
9394
</Box>
9495

9596
{error && (

packages/cli/src/ui/components/WelcomeOnboarding/AuthenticationStep.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,18 @@ export const AuthenticationStep: React.FC<AuthenticationStepProps> = ({
119119
<Text color={Colors.AccentYellow}>
120120
<Spinner type="dots" />
121121
</Text>{' '}
122-
Opening browser for OAuth authentication...
122+
<Text color={Colors.Foreground}>
123+
Opening browser for OAuth authentication...
124+
</Text>
123125
</Text>
124126
</Box>
125127

126-
<Text>Please complete the authentication in your browser.</Text>
127-
<Text>This window will update when done.</Text>
128+
<Text color={Colors.Foreground}>
129+
Please complete the authentication in your browser.
130+
</Text>
131+
<Text color={Colors.Foreground}>
132+
This window will update when done.
133+
</Text>
128134

129135
<Box marginTop={1}>
130136
<Text color={Colors.Gray}>Press Esc to cancel and go back</Text>
@@ -149,18 +155,20 @@ export const AuthenticationStep: React.FC<AuthenticationStepProps> = ({
149155
<Text color={Colors.AccentYellow}>
150156
<Spinner type="dots" />
151157
</Text>{' '}
152-
Validating API key...
158+
<Text color={Colors.Foreground}>Validating API key...</Text>
153159
</Text>
154160
</Box>
155161
) : (
156162
<>
157163
<Box marginBottom={1}>
158-
<Text>Enter your {providerDisplay} API key:</Text>
164+
<Text color={Colors.Foreground}>
165+
Enter your {providerDisplay} API key:
166+
</Text>
159167
</Box>
160168

161169
<Box>
162-
<Text>API Key: </Text>
163-
<Text>{maskedValue}</Text>
170+
<Text color={Colors.Foreground}>API Key: </Text>
171+
<Text color={Colors.Foreground}>{maskedValue}</Text>
164172
<Text color={Colors.AccentCyan}></Text>
165173
</Box>
166174
</>

packages/cli/src/ui/components/WelcomeOnboarding/CompletionStep.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,22 +94,23 @@ export const CompletionStep: React.FC<CompletionStepProps> = ({
9494
<Text bold color={Colors.AccentCyan}>
9595
Step 5 of 5: Save Your Profile
9696
</Text>
97-
<Text> </Text>
9897
<Text bold color={Colors.AccentGreen}>
99-
{'✓ Authentication complete!'}
98+
[OK] Authentication complete!
10099
</Text>
101100
</Box>
102101

103102
<Box flexDirection="column" marginBottom={1}>
104-
<Text>Provider: {providerDisplay}</Text>
105-
{model && <Text>Model: {model}</Text>}
106-
<Text>Authentication: {authDisplay}</Text>
103+
<Text color={Colors.Foreground}>Provider: {providerDisplay}</Text>
104+
{model && <Text color={Colors.Foreground}>Model: {model}</Text>}
105+
<Text color={Colors.Foreground}>Authentication: {authDisplay}</Text>
107106
</Box>
108107

109108
{showProfilePrompt ? (
110109
<Box flexDirection="column">
111110
<Box marginBottom={1}>
112-
<Text bold>Save this setup as a profile</Text>
111+
<Text bold color={Colors.Foreground}>
112+
Save this setup as a profile
113+
</Text>
113114
</Box>
114115

115116
<Text color={Colors.Gray}>
@@ -127,11 +128,11 @@ export const CompletionStep: React.FC<CompletionStepProps> = ({
127128
)}
128129

129130
{saving ? (
130-
<Text>Saving profile...</Text>
131+
<Text color={Colors.Foreground}>Saving profile...</Text>
131132
) : (
132133
<Box>
133-
<Text>Profile name: </Text>
134-
<Text>{profileName}</Text>
134+
<Text color={Colors.Foreground}>Profile name: </Text>
135+
<Text color={Colors.Foreground}>{profileName}</Text>
135136
<Text color={Colors.AccentCyan}></Text>
136137
</Box>
137138
)}
@@ -146,7 +147,7 @@ export const CompletionStep: React.FC<CompletionStepProps> = ({
146147
) : (
147148
<Box flexDirection="column">
148149
<Box marginBottom={1}>
149-
<Text>Try asking me something like:</Text>
150+
<Text color={Colors.Foreground}>Try asking me something like:</Text>
150151
<Text color={Colors.AccentCyan}>
151152
{'"Explain how async/await works in JavaScript"'}
152153
</Text>

packages/cli/src/ui/components/WelcomeOnboarding/ModelSelectStep.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ export const ModelSelectStep: React.FC<ModelSelectStepProps> = ({
8080
<Text bold color={Colors.AccentCyan}>
8181
Step 2 of 5: Choose Your Model
8282
</Text>
83-
<Text> </Text>
84-
<Text>Select a model for {providerDisplay}:</Text>
83+
<Text color={Colors.Foreground}>
84+
{' '}
85+
Select a model for {providerDisplay}:
86+
</Text>
8587
</Box>
8688

8789
{modelsLoadStatus === 'loading' && (

packages/cli/src/ui/components/WelcomeOnboarding/ProviderSelectStep.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,9 @@ export const ProviderSelectStep: React.FC<ProviderSelectStepProps> = ({
6969
<Text bold color={Colors.AccentCyan}>
7070
Step 1 of 5: Choose Your AI Provider
7171
</Text>
72-
<Text> </Text>
73-
<Text>{"Select which AI provider you'd like to use:"}</Text>
72+
<Text color={Colors.Foreground}>
73+
{"Select which AI provider you'd like to use:"}
74+
</Text>
7475
</Box>
7576

7677
<RadioButtonSelect

packages/cli/src/ui/components/WelcomeOnboarding/SkipExitStep.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,22 @@ export const SkipExitStep: React.FC<SkipExitStepProps> = ({
3030
return (
3131
<Box flexDirection="column">
3232
<Box flexDirection="column" marginBottom={1}>
33-
<Text bold>Setup skipped</Text>
33+
<Text bold color={Colors.Foreground}>
34+
Setup skipped
35+
</Text>
3436
</Box>
3537

3638
<Box flexDirection="column" marginBottom={1}>
37-
<Text>To configure llxprt manually:</Text>
38-
<Text> </Text>
39-
<Text>
39+
<Text color={Colors.Foreground}>To configure llxprt manually:</Text>
40+
<Text color={Colors.Foreground}>
4041
• Use <Text color={Colors.AccentCyan}>/auth &lt;provider&gt;</Text> to
4142
set up authentication
4243
</Text>
43-
<Text>
44+
<Text color={Colors.Foreground}>
4445
• Use <Text color={Colors.AccentCyan}>/provider</Text> to select your
4546
AI provider
4647
</Text>
47-
<Text>
48+
<Text color={Colors.Foreground}>
4849
• Type <Text color={Colors.AccentCyan}>/help</Text> for more commands
4950
</Text>
5051
</Box>

packages/cli/src/ui/components/WelcomeOnboarding/WelcomeStep.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,20 @@ export const WelcomeStep: React.FC<WelcomeStepProps> = ({
4242
<Text bold color={Colors.AccentCyan}>
4343
Welcome to llxprt!
4444
</Text>
45-
<Text> </Text>
46-
<Text>{"Let's get you set up in just a few steps."}</Text>
47-
<Text>
45+
<Text color={Colors.Foreground}>
46+
{' '}
47+
{"Let's get you set up in just a few steps."}
48+
</Text>
49+
<Text color={Colors.Foreground}>
4850
{"You'll choose an AI provider and configure authentication"}
4951
</Text>
50-
<Text>so llxprt can work its magic.</Text>
52+
<Text color={Colors.Foreground}>so llxprt can work its magic.</Text>
5153
</Box>
5254

5355
<Box flexDirection="column" marginBottom={1}>
54-
<Text bold>What would you like to do?</Text>
56+
<Text bold color={Colors.Foreground}>
57+
What would you like to do?
58+
</Text>
5559
</Box>
5660

5761
<RadioButtonSelect

packages/cli/src/ui/hooks/useWelcomeOnboarding.ts

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import { useState, useCallback, useEffect } from 'react';
7+
import { useState, useCallback, useEffect, useMemo } from 'react';
88
import { DebugLogger } from '@vybestack/llxprt-code-core';
99
import { type LoadedSettings } from '../../config/settings.js';
1010
import {
@@ -15,6 +15,8 @@ import { useRuntimeApi } from '../contexts/RuntimeContext.js';
1515

1616
const debug = new DebugLogger('llxprt:ui:useWelcomeOnboarding');
1717

18+
const PLACEHOLDER_MODEL_NAMES = new Set(['placeholder-model']);
19+
1820
export type WelcomeStep =
1921
| 'welcome'
2022
| 'provider'
@@ -81,8 +83,68 @@ export const useWelcomeOnboarding = (
8183
isWelcomeCompleted(),
8284
);
8385

84-
// Only show welcome after folder trust is complete
85-
const showWelcome = !welcomeCompleted && isFolderTrustComplete;
86+
const isSystemDefaultModelName = useCallback((modelName: string): boolean => {
87+
return PLACEHOLDER_MODEL_NAMES.has(modelName);
88+
}, []);
89+
90+
const shouldSuppressWelcome = useMemo(() => {
91+
// Always prefer showing onboarding until the user explicitly completes/skips it.
92+
if (!isFolderTrustComplete || welcomeCompleted) {
93+
return false;
94+
}
95+
96+
// Non-interactive signals (CLI/env) that indicate the user already configured things.
97+
// Keep this conservative: avoid treating system defaults as user configuration.
98+
99+
if (process.env.LLXPRT_PROFILE) {
100+
debug.log('Welcome suppressed: LLXPRT_PROFILE environment variable set');
101+
return true;
102+
}
103+
104+
// If a provider is already active (typically set via CLI flags or prior usage),
105+
// suppress welcome.
106+
const providerManager = runtime.getCliProviderManager();
107+
if (providerManager) {
108+
try {
109+
const providerName = providerManager.getActiveProviderName();
110+
const hasActiveProvider =
111+
providerManager.hasActiveProvider?.() ?? false;
112+
113+
if (providerName || hasActiveProvider) {
114+
debug.log('Welcome suppressed: active provider configured');
115+
return true;
116+
}
117+
} catch (error) {
118+
debug.log('Could not check for active provider:', error);
119+
}
120+
}
121+
122+
try {
123+
const activeModel = runtime.getActiveModelName();
124+
if (activeModel && !isSystemDefaultModelName(activeModel)) {
125+
debug.log('Welcome suppressed: active model configured');
126+
return true;
127+
}
128+
} catch (error) {
129+
debug.log('Could not check for active model:', error);
130+
}
131+
132+
// Intentionally do NOT suppress based solely on defaultProfile. A profile can be
133+
// present due to system defaults and should not skip onboarding unless the user
134+
// has explicitly completed it.
135+
136+
return false;
137+
}, [
138+
isFolderTrustComplete,
139+
isSystemDefaultModelName,
140+
runtime,
141+
welcomeCompleted,
142+
]);
143+
144+
// Show welcome after folder trust is complete unless it was completed/skipped,
145+
// or we detect a non-interactive configuration state.
146+
const showWelcome =
147+
!welcomeCompleted && isFolderTrustComplete && !shouldSuppressWelcome;
86148

87149
const [state, setState] = useState<WelcomeState>({
88150
step: 'welcome',

0 commit comments

Comments
 (0)