From 3600b40c40befa6a07d05c7964d4955165da2990 Mon Sep 17 00:00:00 2001 From: hyperz111 Date: Fri, 5 Dec 2025 15:41:34 +0700 Subject: [PATCH 1/5] fix: fix autocomplete bar color when validate --- packages/prompts/src/autocomplete.ts | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/packages/prompts/src/autocomplete.ts b/packages/prompts/src/autocomplete.ts index 6472a435..c7f4072d 100644 --- a/packages/prompts/src/autocomplete.ts +++ b/packages/prompts/src/autocomplete.ts @@ -112,6 +112,7 @@ export const autocomplete = (opts: AutocompleteOptions) => { } default: { + const barColor = this.state === "error" ? color.yellow : color.cyan; // Display cursor position - show plain text in navigation mode let searchText = ''; if (this.isNavigating || showPlaceholder) { @@ -132,15 +133,15 @@ export const autocomplete = (opts: AutocompleteOptions) => { // No matches message const noResults = this.filteredOptions.length === 0 && userInput - ? [`${color.cyan(S_BAR)} ${color.yellow('No matches found')}`] + ? [`${barColor(S_BAR)} ${color.yellow('No matches found')}`] : []; const validationError = - this.state === 'error' ? [`${color.yellow(S_BAR)} ${color.yellow(this.error)}`] : []; + this.state === 'error' ? [`${barColor(S_BAR)} ${color.yellow(this.error)}`] : []; headings.push( - `${color.cyan(S_BAR)}`, - `${color.cyan(S_BAR)} ${color.dim('Search:')}${searchText}${matches}`, + `${barColor(S_BAR)}`, + `${barColor(S_BAR)} ${color.dim('Search:')}${searchText}${matches}`, ...noResults, ...validationError ); @@ -153,8 +154,8 @@ export const autocomplete = (opts: AutocompleteOptions) => { ]; const footers = [ - `${color.cyan(S_BAR)} ${color.dim(instructions.join(' • '))}`, - `${color.cyan(S_BAR_END)}`, + `${barColor(S_BAR)} ${color.dim(instructions.join(' • '))}`, + `${barColor(S_BAR_END)}`, ]; // Render options with selection @@ -184,7 +185,7 @@ export const autocomplete = (opts: AutocompleteOptions) => { // Return the formatted prompt return [ ...headings, - ...displayOptions.map((option) => `${color.cyan(S_BAR)} ${option}`), + ...displayOptions.map((option) => `${barColor(S_BAR)} ${option}`), ...footers, ].join('\n'); } @@ -282,6 +283,7 @@ export const autocompleteMultiselect = (opts: AutocompleteMultiSelectOpti return `${title}${color.gray(S_BAR)} ${color.strikethrough(color.dim(userInput))}`; } default: { + const barColor = this.state === "error" ? color.yellow : color.cyan; // Instructions const instructions = [ `${color.dim('↑/↓')} to navigate`, @@ -293,22 +295,22 @@ export const autocompleteMultiselect = (opts: AutocompleteMultiSelectOpti // No results message const noResults = this.filteredOptions.length === 0 && userInput - ? [`${color.cyan(S_BAR)} ${color.yellow('No matches found')}`] + ? [`${barColor(S_BAR)} ${color.yellow('No matches found')}`] : []; const errorMessage = - this.state === 'error' ? [`${color.cyan(S_BAR)} ${color.yellow(this.error)}`] : []; + this.state === 'error' ? [`${barColor(S_BAR)} ${color.yellow(this.error)}`] : []; // Calculate header and footer line counts for rowPadding const headerLines = [ ...title.split('\n'), - `${color.cyan(S_BAR)} ${color.dim('Search:')} ${searchText}${matches}`, + `${barColor(S_BAR)} ${color.dim('Search:')} ${searchText}${matches}`, ...noResults, ...errorMessage, ]; const footerLines = [ - `${color.cyan(S_BAR)} ${color.dim(instructions.join(' • '))}`, - `${color.cyan(S_BAR_END)}`, + `${barColor(S_BAR)} ${color.dim(instructions.join(' • '))}`, + `${barColor(S_BAR_END)}`, ]; // Get limited options for display @@ -325,7 +327,7 @@ export const autocompleteMultiselect = (opts: AutocompleteMultiSelectOpti // Build the prompt display return [ ...headerLines, - ...displayOptions.map((option) => `${color.cyan(S_BAR)} ${option}`), + ...displayOptions.map((option) => `${barColor(S_BAR)} ${option}`), ...footerLines, ].join('\n'); } From 0eeff65adf51b0169aa2c46a57900b389bcccfb6 Mon Sep 17 00:00:00 2001 From: hyperz111 Date: Fri, 5 Dec 2025 19:34:24 +0700 Subject: [PATCH 2/5] update snapshots --- examples/basic/autocomplete.ts | 1 + .../__snapshots__/autocomplete.test.ts.snap | 18 +++--- .../test/__snapshots__/path.test.ts.snap | 60 +++++++++---------- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/examples/basic/autocomplete.ts b/examples/basic/autocomplete.ts index ea94ece1..41a182c0 100644 --- a/examples/basic/autocomplete.ts +++ b/examples/basic/autocomplete.ts @@ -45,6 +45,7 @@ ${color.cyan('This example demonstrates the type-ahead autocomplete feature:')} options: countries, placeholder: 'Type to search countries...', maxItems: 8, + validate: () => "Validate :)" }); if (p.isCancel(result)) { diff --git a/packages/prompts/test/__snapshots__/autocomplete.test.ts.snap b/packages/prompts/test/__snapshots__/autocomplete.test.ts.snap index e7c7fa35..b36a7677 100644 --- a/packages/prompts/test/__snapshots__/autocomplete.test.ts.snap +++ b/packages/prompts/test/__snapshots__/autocomplete.test.ts.snap @@ -429,15 +429,15 @@ exports[`autocompleteMultiselect > renders error when empty selection & required "", "▲ Select a fruit -│ Search: _ -│ Please select at least one item -│ ◻ Apple -│ ◻ Banana -│ ◻ Cherry -│ ◻ Grape -│ ◻ Orange -│ ↑/↓ to navigate • Tab: select • Enter: confirm • Type: to search -└", +│ Search: _ +│ Please select at least one item +│ ◻ Apple +│ ◻ Banana +│ ◻ Cherry +│ ◻ Grape +│ ◻ Orange +│ ↑/↓ to navigate • Tab: select • Enter: confirm • Type: to search +└", "", "", "", diff --git a/packages/prompts/test/__snapshots__/path.test.ts.snap b/packages/prompts/test/__snapshots__/path.test.ts.snap index f96e4641..ff0ceef8 100644 --- a/packages/prompts/test/__snapshots__/path.test.ts.snap +++ b/packages/prompts/test/__snapshots__/path.test.ts.snap @@ -44,12 +44,12 @@ exports[`text (isCI = false) > cannot submit unknown value 1`] = ` "", "", "▲ foo -│ -│ Search: /tmp/_█ -│ No matches found +│ +│ Search: /tmp/_█ +│ No matches found │ Please select a path -│ ↑/↓ to select • Enter: confirm • Type: to search -└", +│ ↑/↓ to select • Enter: confirm • Type: to search +└", "", "", "", @@ -211,12 +211,12 @@ exports[`text (isCI = false) > validation errors render and clear (using Error) "", "", "▲ foo -│ -│ Search: /tmp/r█ +│ +│ Search: /tmp/r█ │ should be /tmp/bar -│ ● /tmp/root.zip -│ ↑/↓ to select • Enter: confirm • Type: to search -└", +│ ● /tmp/root.zip +│ ↑/↓ to select • Enter: confirm • Type: to search +└", "", "", "", @@ -267,12 +267,12 @@ exports[`text (isCI = false) > validation errors render and clear 1`] = ` "", "", "▲ foo -│ -│ Search: /tmp/r█ +│ +│ Search: /tmp/r█ │ should be /tmp/bar -│ ● /tmp/root.zip -│ ↑/↓ to select • Enter: confirm • Type: to search -└", +│ ● /tmp/root.zip +│ ↑/↓ to select • Enter: confirm • Type: to search +└", "", "", "", @@ -345,12 +345,12 @@ exports[`text (isCI = true) > cannot submit unknown value 1`] = ` "", "", "▲ foo -│ -│ Search: /tmp/_█ -│ No matches found +│ +│ Search: /tmp/_█ +│ No matches found │ Please select a path -│ ↑/↓ to select • Enter: confirm • Type: to search -└", +│ ↑/↓ to select • Enter: confirm • Type: to search +└", "", "", "", @@ -512,12 +512,12 @@ exports[`text (isCI = true) > validation errors render and clear (using Error) 1 "", "", "▲ foo -│ -│ Search: /tmp/r█ +│ +│ Search: /tmp/r█ │ should be /tmp/bar -│ ● /tmp/root.zip -│ ↑/↓ to select • Enter: confirm • Type: to search -└", +│ ● /tmp/root.zip +│ ↑/↓ to select • Enter: confirm • Type: to search +└", "", "", "", @@ -568,12 +568,12 @@ exports[`text (isCI = true) > validation errors render and clear 1`] = ` "", "", "▲ foo -│ -│ Search: /tmp/r█ +│ +│ Search: /tmp/r█ │ should be /tmp/bar -│ ● /tmp/root.zip -│ ↑/↓ to select • Enter: confirm • Type: to search -└", +│ ● /tmp/root.zip +│ ↑/↓ to select • Enter: confirm • Type: to search +└", "", "", "", From 3bf7e5b6a2982189fa011324b01efd5c8ce34285 Mon Sep 17 00:00:00 2001 From: hyperz111 Date: Fri, 5 Dec 2025 19:40:42 +0700 Subject: [PATCH 3/5] revert examples --- examples/basic/autocomplete.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/basic/autocomplete.ts b/examples/basic/autocomplete.ts index 41a182c0..ea94ece1 100644 --- a/examples/basic/autocomplete.ts +++ b/examples/basic/autocomplete.ts @@ -45,7 +45,6 @@ ${color.cyan('This example demonstrates the type-ahead autocomplete feature:')} options: countries, placeholder: 'Type to search countries...', maxItems: 8, - validate: () => "Validate :)" }); if (p.isCancel(result)) { From 56b0adce2fee59a698e137d0fe99a4af52e4a46a Mon Sep 17 00:00:00 2001 From: hyperz111 Date: Sun, 7 Dec 2025 16:22:48 +0700 Subject: [PATCH 4/5] add changeset --- .changeset/sweet-garlics-win.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sweet-garlics-win.md diff --git a/.changeset/sweet-garlics-win.md b/.changeset/sweet-garlics-win.md new file mode 100644 index 00000000..d83fbf4c --- /dev/null +++ b/.changeset/sweet-garlics-win.md @@ -0,0 +1,5 @@ +--- +"@clack/prompts": patch +--- + +fix: fix autocomplete bar color when validate From 775dacb14d5ce3b738c11d701bfaab02fb7b78f4 Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Sun, 7 Dec 2025 14:20:06 +0000 Subject: [PATCH 5/5] chore: rework to compute prefix once --- packages/prompts/src/autocomplete.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/prompts/src/autocomplete.ts b/packages/prompts/src/autocomplete.ts index c7f4072d..ae293139 100644 --- a/packages/prompts/src/autocomplete.ts +++ b/packages/prompts/src/autocomplete.ts @@ -112,7 +112,8 @@ export const autocomplete = (opts: AutocompleteOptions) => { } default: { - const barColor = this.state === "error" ? color.yellow : color.cyan; + const guidePrefix = `${(this.state === 'error' ? color.yellow : color.cyan)(S_BAR)} `; + const guidePrefixEnd = (this.state === 'error' ? color.yellow : color.cyan)(S_BAR_END); // Display cursor position - show plain text in navigation mode let searchText = ''; if (this.isNavigating || showPlaceholder) { @@ -133,15 +134,15 @@ export const autocomplete = (opts: AutocompleteOptions) => { // No matches message const noResults = this.filteredOptions.length === 0 && userInput - ? [`${barColor(S_BAR)} ${color.yellow('No matches found')}`] + ? [`${guidePrefix}${color.yellow('No matches found')}`] : []; const validationError = - this.state === 'error' ? [`${barColor(S_BAR)} ${color.yellow(this.error)}`] : []; + this.state === 'error' ? [`${guidePrefix}${color.yellow(this.error)}`] : []; headings.push( - `${barColor(S_BAR)}`, - `${barColor(S_BAR)} ${color.dim('Search:')}${searchText}${matches}`, + `${guidePrefix.trimEnd()}`, + `${guidePrefix}${color.dim('Search:')}${searchText}${matches}`, ...noResults, ...validationError ); @@ -154,8 +155,8 @@ export const autocomplete = (opts: AutocompleteOptions) => { ]; const footers = [ - `${barColor(S_BAR)} ${color.dim(instructions.join(' • '))}`, - `${barColor(S_BAR_END)}`, + `${guidePrefix}${color.dim(instructions.join(' • '))}`, + `${guidePrefixEnd}`, ]; // Render options with selection @@ -185,7 +186,7 @@ export const autocomplete = (opts: AutocompleteOptions) => { // Return the formatted prompt return [ ...headings, - ...displayOptions.map((option) => `${barColor(S_BAR)} ${option}`), + ...displayOptions.map((option) => `${guidePrefix}${option}`), ...footers, ].join('\n'); } @@ -283,7 +284,7 @@ export const autocompleteMultiselect = (opts: AutocompleteMultiSelectOpti return `${title}${color.gray(S_BAR)} ${color.strikethrough(color.dim(userInput))}`; } default: { - const barColor = this.state === "error" ? color.yellow : color.cyan; + const barColor = this.state === 'error' ? color.yellow : color.cyan; // Instructions const instructions = [ `${color.dim('↑/↓')} to navigate`,