Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .changeset/odd-bikes-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
"@clack/prompts": minor
---

Updates the API for stopping spinners and progress bars to be clearer

Previously, both the spinner and progress bar components used a single `stop` method that accepted a code to indicate success, cancellation, or error. This update separates these into distinct methods: `stop()`, `cancel()`, and `error()`:

```diff
const spinner = prompts.spinner();
spinner.start();

// Cancelling a spinner
- spinner.stop(undefined, 1);
+ spinner.cancel();

// Stopping with an error
- spinner.stop(undefined, 2);
+ spinner.error();
```

As before, you can pass a message to each method to customize the output displayed:

```js
spinner.cancel("Operation cancelled by user");
progressBar.error("An error occurred during processing");
```
2 changes: 2 additions & 0 deletions packages/prompts/src/progress-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export function progress({
return {
start,
stop: spin.stop,
cancel: spin.cancel,
error: spin.error,
advance,
isCancelled: spin.isCancelled,
message: (msg: string) => advance(0, msg),
Expand Down
14 changes: 11 additions & 3 deletions packages/prompts/src/spinner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export interface SpinnerOptions extends CommonOptions {

export interface SpinnerResult {
start(msg?: string): void;
stop(msg?: string, code?: number): void;
stop(msg?: string): void;
cancel(msg?: string): void;
error(msg?: string): void;
message(msg?: string): void;
readonly isCancelled: boolean;
}
Expand Down Expand Up @@ -61,7 +63,7 @@ export const spinner = ({
: (cancelMessage ?? settings.messages.cancel);
isCancelled = code === 1;
if (isSpinnerActive) {
stop(msg, code);
_stop(msg, code);
if (isCancelled && typeof onCancel === 'function') {
onCancel();
}
Expand Down Expand Up @@ -163,7 +165,7 @@ export const spinner = ({
}, delay);
};

const stop = (msg = '', code = 0): void => {
const _stop = (msg = '', code = 0): void => {
if (!isSpinnerActive) return;
isSpinnerActive = false;
clearInterval(loop);
Expand All @@ -184,6 +186,10 @@ export const spinner = ({
unblock();
};

const stop = (msg = ''): void => _stop(msg, 0);
const cancel = (msg = ''): void => _stop(msg, 1);
const error = (msg = ''): void => _stop(msg, 2);

const message = (msg = ''): void => {
_message = removeTrailingDots(msg ?? _message);
};
Expand All @@ -192,6 +198,8 @@ export const spinner = ({
start,
stop,
message,
cancel,
error,
get isCancelled() {
return isCancelled;
},
Expand Down
68 changes: 64 additions & 4 deletions packages/prompts/test/__snapshots__/progress-bar.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ exports[`prompts - progress (isCI = false) > start > renders timer when indicato
]
`;

exports[`prompts - progress (isCI = false) > stop > renders cancel symbol if code = 1 1`] = `
exports[`prompts - progress (isCI = false) > stop > renders cancel symbol when calling cancel() 1`] = `
[
"<cursor.hide>",
"│
Expand All @@ -139,7 +139,7 @@ exports[`prompts - progress (isCI = false) > stop > renders cancel symbol if cod
]
`;

exports[`prompts - progress (isCI = false) > stop > renders error symbol if code > 1 1`] = `
exports[`prompts - progress (isCI = false) > stop > renders error symbol when calling error() 1`] = `
[
"<cursor.hide>",
"│
Expand Down Expand Up @@ -167,6 +167,34 @@ exports[`prompts - progress (isCI = false) > stop > renders message 1`] = `
]
`;

exports[`prompts - progress (isCI = false) > stop > renders message when cancelling 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ",
"<cursor.left count=1>",
"<erase.down>",
"■ cancelled :-(
",
"<cursor.show>",
]
`;

exports[`prompts - progress (isCI = false) > stop > renders message when erroring 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ",
"<cursor.left count=1>",
"<erase.down>",
"▲ FATAL ERROR!
",
"<cursor.show>",
]
`;

exports[`prompts - progress (isCI = false) > stop > renders message without removing dots 1`] = `
[
"<cursor.hide>",
Expand Down Expand Up @@ -382,7 +410,7 @@ exports[`prompts - progress (isCI = true) > start > renders timer when indicator
]
`;

exports[`prompts - progress (isCI = true) > stop > renders cancel symbol if code = 1 1`] = `
exports[`prompts - progress (isCI = true) > stop > renders cancel symbol when calling cancel() 1`] = `
[
"<cursor.hide>",
"│
Expand All @@ -398,7 +426,7 @@ exports[`prompts - progress (isCI = true) > stop > renders cancel symbol if code
]
`;

exports[`prompts - progress (isCI = true) > stop > renders error symbol if code > 1 1`] = `
exports[`prompts - progress (isCI = true) > stop > renders error symbol when calling error() 1`] = `
[
"<cursor.hide>",
"│
Expand Down Expand Up @@ -430,6 +458,38 @@ exports[`prompts - progress (isCI = true) > stop > renders message 1`] = `
]
`;

exports[`prompts - progress (isCI = true) > stop > renders message when cancelling 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ...",
"
",
"<cursor.left count=1>",
"<erase.down>",
"■ cancelled :-(
",
"<cursor.show>",
]
`;

exports[`prompts - progress (isCI = true) > stop > renders message when erroring 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ...",
"
",
"<cursor.left count=1>",
"<erase.down>",
"▲ FATAL ERROR!
",
"<cursor.show>",
]
`;

exports[`prompts - progress (isCI = true) > stop > renders message without removing dots 1`] = `
[
"<cursor.hide>",
Expand Down
68 changes: 64 additions & 4 deletions packages/prompts/test/__snapshots__/spinner.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ exports[`spinner (isCI = false) > start > renders timer when indicator is "timer
]
`;

exports[`spinner (isCI = false) > stop > renders cancel symbol if code = 1 1`] = `
exports[`spinner (isCI = false) > stop > renders cancel symbol when calling cancel() 1`] = `
[
"<cursor.hide>",
"│
Expand All @@ -475,7 +475,7 @@ exports[`spinner (isCI = false) > stop > renders cancel symbol if code = 1 1`] =
]
`;

exports[`spinner (isCI = false) > stop > renders error symbol if code > 1 1`] = `
exports[`spinner (isCI = false) > stop > renders error symbol when calling error() 1`] = `
[
"<cursor.hide>",
"│
Expand Down Expand Up @@ -503,6 +503,34 @@ exports[`spinner (isCI = false) > stop > renders message 1`] = `
]
`;

exports[`spinner (isCI = false) > stop > renders message when cancelling 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ",
"<cursor.left count=1>",
"<erase.down>",
"■ too dizzy — spinning cancelled
",
"<cursor.show>",
]
`;

exports[`spinner (isCI = false) > stop > renders message when erroring 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ",
"<cursor.left count=1>",
"<erase.down>",
"▲ error: spun too fast!
",
"<cursor.show>",
]
`;

exports[`spinner (isCI = false) > stop > renders message without removing dots 1`] = `
[
"<cursor.hide>",
Expand Down Expand Up @@ -789,7 +817,7 @@ exports[`spinner (isCI = true) > start > renders timer when indicator is "timer"
]
`;

exports[`spinner (isCI = true) > stop > renders cancel symbol if code = 1 1`] = `
exports[`spinner (isCI = true) > stop > renders cancel symbol when calling cancel() 1`] = `
[
"<cursor.hide>",
"│
Expand All @@ -805,7 +833,7 @@ exports[`spinner (isCI = true) > stop > renders cancel symbol if code = 1 1`] =
]
`;

exports[`spinner (isCI = true) > stop > renders error symbol if code > 1 1`] = `
exports[`spinner (isCI = true) > stop > renders error symbol when calling error() 1`] = `
[
"<cursor.hide>",
"│
Expand Down Expand Up @@ -837,6 +865,38 @@ exports[`spinner (isCI = true) > stop > renders message 1`] = `
]
`;

exports[`spinner (isCI = true) > stop > renders message when cancelling 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ...",
"
",
"<cursor.left count=1>",
"<erase.down>",
"■ too dizzy — spinning cancelled
",
"<cursor.show>",
]
`;

exports[`spinner (isCI = true) > stop > renders message when erroring 1`] = `
[
"<cursor.hide>",
"│
",
"◒ ...",
"
",
"<cursor.left count=1>",
"<erase.down>",
"▲ error: spun too fast!
",
"<cursor.show>",
]
`;

exports[`spinner (isCI = true) > stop > renders message without removing dots 1`] = `
[
"<cursor.hide>",
Expand Down
32 changes: 28 additions & 4 deletions packages/prompts/test/progress-bar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,26 @@ describe.each(['true', 'false'])('prompts - progress (isCI = %s)', (isCI) => {
expect(output.buffer).toMatchSnapshot();
});

test('renders cancel symbol if code = 1', () => {
test('renders cancel symbol when calling cancel()', () => {
const result = prompts.progress({ output });

result.start();

vi.advanceTimersByTime(80);

result.stop('', 1);
result.cancel();

expect(output.buffer).toMatchSnapshot();
});

test('renders error symbol if code > 1', () => {
test('renders error symbol when calling error()', () => {
const result = prompts.progress({ output });

result.start();

vi.advanceTimersByTime(80);

result.stop('', 2);
result.error();

expect(output.buffer).toMatchSnapshot();
});
Expand Down Expand Up @@ -134,6 +134,30 @@ describe.each(['true', 'false'])('prompts - progress (isCI = %s)', (isCI) => {

expect(output.buffer).toMatchSnapshot();
});

test('renders message when cancelling', () => {
const result = prompts.progress({ output });

result.start();

vi.advanceTimersByTime(80);

result.cancel('cancelled :-(');

expect(output.buffer).toMatchSnapshot();
});

test('renders message when erroring', () => {
const result = prompts.progress({ output });

result.start();

vi.advanceTimersByTime(80);

result.error('FATAL ERROR!');

expect(output.buffer).toMatchSnapshot();
});
});

describe('message', () => {
Expand Down
Loading
Loading