Skip to content

Commit 227583e

Browse files
authored
feat(core): add accessible prompt option (#595)
1 parent b20fa2b commit 227583e

3 files changed

Lines changed: 70 additions & 1 deletion

File tree

‎.changeset/dirty-forks-study.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@clack/core': minor
3+
---
4+
5+
Add an `accessible` option to the shared `PromptOptions` and a resolved `accessible` getter on the base `Prompt`, so any prompt can opt into accessible mode individually. Resolution order: per-prompt option > `updateSettings({ accessible })` > the `ACCESSIBLE` environment variable.

‎packages/core/src/prompts/prompt.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
CANCEL_SYMBOL,
1010
diffLines,
1111
getRows,
12+
isAccessible,
1213
isActionKey,
1314
setRawMode,
1415
settings,
@@ -18,6 +19,11 @@ import { runValidation } from '../utils/validation.js';
1819

1920
export interface PromptOptions<TValue, Self extends Prompt<TValue>> {
2021
render(this: Omit<Self, 'prompt'>): string | undefined;
22+
/**
23+
* Whether to render this prompt in accessible (static, screen-reader friendly) mode.
24+
* Takes precedence over the global `accessible` setting and the `ACCESSIBLE` env var.
25+
*/
26+
accessible?: boolean;
2127
initialValue?: any;
2228
initialUserInput?: string;
2329

@@ -50,6 +56,15 @@ export default class Prompt<TValue> {
5056
public value: TValue | undefined;
5157
public userInput = '';
5258

59+
/**
60+
* Whether accessible (static, screen-reader friendly) output is enabled for
61+
* this prompt, resolved from the `accessible` option, the global setting,
62+
* and the `ACCESSIBLE` env var.
63+
*/
64+
public get accessible(): boolean {
65+
return isAccessible(this.opts.accessible);
66+
}
67+
5368
constructor(options: PromptOptions<TValue, Prompt<TValue>>, trackValue = true) {
5469
const { input = stdin, output = stdout, render, signal, ...opts } = options;
5570

‎packages/core/test/prompts/prompt.test.ts‎

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { type } from 'arktype';
22
import { cursor } from 'sisteransi';
33
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest';
44
import { default as Prompt } from '../../src/prompts/prompt.js';
5-
import { isCancel } from '../../src/utils/index.js';
5+
import { isCancel, settings } from '../../src/utils/index.js';
66
import { MockReadable } from '../mock-readable.js';
77
import { MockWritable } from '../mock-writable.js';
88

@@ -315,6 +315,55 @@ describe('Prompt', () => {
315315
});
316316
});
317317

318+
describe('accessible', () => {
319+
const originalEnv = process.env.ACCESSIBLE;
320+
321+
afterEach(() => {
322+
if (originalEnv === undefined) {
323+
delete process.env.ACCESSIBLE;
324+
} else {
325+
process.env.ACCESSIBLE = originalEnv;
326+
}
327+
settings.accessible = undefined;
328+
});
329+
330+
test('accessible: true option enables it', () => {
331+
const instance = new Prompt({
332+
input,
333+
output,
334+
render: () => 'foo',
335+
accessible: true,
336+
});
337+
338+
expect(instance.accessible).to.equal(true);
339+
});
340+
341+
test('accessible: false option overrides the env var', () => {
342+
process.env.ACCESSIBLE = '1';
343+
const instance = new Prompt({
344+
input,
345+
output,
346+
render: () => 'foo',
347+
accessible: false,
348+
});
349+
350+
expect(instance.accessible).to.equal(false);
351+
});
352+
353+
test('falls through to the env var when option is unset', () => {
354+
delete process.env.ACCESSIBLE;
355+
const instance = new Prompt({
356+
input,
357+
output,
358+
render: () => 'foo',
359+
});
360+
361+
expect(instance.accessible).to.equal(false);
362+
process.env.ACCESSIBLE = '1';
363+
expect(instance.accessible).to.equal(true);
364+
});
365+
});
366+
318367
describe('standard schema', () => {
319368
test('accepts invalid initial value', () => {
320369
const instance = new Prompt<string>({

0 commit comments

Comments
 (0)