diff --git a/packages/cli/src/test-utils/render.tsx b/packages/cli/src/test-utils/render.tsx index 9dd0f96758..1978efd92e 100644 --- a/packages/cli/src/test-utils/render.tsx +++ b/packages/cli/src/test-utils/render.tsx @@ -74,6 +74,7 @@ vi.mock('../ui/utils/terminalUtils.js', () => ({ isLowColorDepth: vi.fn(() => false), getColorDepth: vi.fn(() => 24), isITerm2: vi.fn(() => false), + isAppleTerminal: vi.fn(() => false), })); type TerminalState = { diff --git a/packages/cli/src/ui/components/shared/HalfLinePaddedBox.test.tsx b/packages/cli/src/ui/components/shared/HalfLinePaddedBox.test.tsx index b81294ffb2..976d92f9be 100644 --- a/packages/cli/src/ui/components/shared/HalfLinePaddedBox.test.tsx +++ b/packages/cli/src/ui/components/shared/HalfLinePaddedBox.test.tsx @@ -8,7 +8,7 @@ import { renderWithProviders } from '../../../test-utils/render.js'; import { HalfLinePaddedBox } from './HalfLinePaddedBox.js'; import { Text, useIsScreenReaderEnabled } from 'ink'; import { describe, it, expect, vi, afterEach } from 'vitest'; -import { isITerm2 } from '../../utils/terminalUtils.js'; +import { isITerm2, isAppleTerminal } from '../../utils/terminalUtils.js'; vi.mock('ink', async () => { const actual = await vi.importActual('ink'); @@ -25,34 +25,55 @@ describe('', () => { vi.restoreAllMocks(); }); - it('renders standard background and blocks when not iTerm2', async () => { + it('renders standard background and blocks when not iTerm2 or Apple Terminal', async () => { vi.mocked(isITerm2).mockReturnValue(false); + vi.mocked(isAppleTerminal).mockReturnValue(false); - const { lastFrame, unmount } = await renderWithProviders( + const renderResult = await renderWithProviders( Content , { width: 10 }, ); - expect(lastFrame()).toMatchSnapshot(); + await renderResult.waitUntilReady(); + await expect(renderResult).toMatchSvgSnapshot(); - unmount(); + renderResult.unmount(); }); it('renders iTerm2-specific blocks when iTerm2 is detected', async () => { vi.mocked(isITerm2).mockReturnValue(true); + vi.mocked(isAppleTerminal).mockReturnValue(false); - const { lastFrame, unmount } = await renderWithProviders( + const renderResult = await renderWithProviders( Content , { width: 10 }, ); - expect(lastFrame()).toMatchSnapshot(); + await renderResult.waitUntilReady(); + await expect(renderResult).toMatchSvgSnapshot(); - unmount(); + renderResult.unmount(); + }); + + it('renders Apple Terminal-specific blocks when Apple Terminal is detected', async () => { + vi.mocked(isITerm2).mockReturnValue(false); + vi.mocked(isAppleTerminal).mockReturnValue(true); + + const renderResult = await renderWithProviders( + + Content + , + { width: 10 }, + ); + + await renderResult.waitUntilReady(); + await expect(renderResult).toMatchSvgSnapshot(); + + renderResult.unmount(); }); it('renders nothing when useBackgroundColor is false', async () => { diff --git a/packages/cli/src/ui/components/shared/HalfLinePaddedBox.tsx b/packages/cli/src/ui/components/shared/HalfLinePaddedBox.tsx index add5353245..51ae231c37 100644 --- a/packages/cli/src/ui/components/shared/HalfLinePaddedBox.tsx +++ b/packages/cli/src/ui/components/shared/HalfLinePaddedBox.tsx @@ -14,7 +14,11 @@ import { resolveColor, getSafeLowColorBackground, } from '../../themes/color-utils.js'; -import { isLowColorDepth, isITerm2 } from '../../utils/terminalUtils.js'; +import { + isLowColorDepth, + isITerm2, + isAppleTerminal, +} from '../../utils/terminalUtils.js'; export interface HalfLinePaddedBoxProps { /** @@ -108,6 +112,33 @@ const HalfLinePaddedBoxInternal: React.FC = ({ ); } + const isMacOSTerminal = isAppleTerminal(); + + if (isMacOSTerminal) { + return ( + + + + {'▅'.repeat(terminalWidth)} + + + {children} + + + {'▄'.repeat(terminalWidth)} + + + + ); + } + return ( + + + + + ▅▅▅▅▅▅▅▅▅▅ + + Content + + ▄▄▄▄▄▄▄▄▄▄ + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox--HalfLinePaddedBox-renders-iTerm2-specific-blocks-when-iTerm2-is-detected.snap.svg b/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox--HalfLinePaddedBox-renders-iTerm2-specific-blocks-when-iTerm2-is-detected.snap.svg new file mode 100644 index 0000000000..e03dcc8230 --- /dev/null +++ b/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox--HalfLinePaddedBox-renders-iTerm2-specific-blocks-when-iTerm2-is-detected.snap.svg @@ -0,0 +1,12 @@ + + + + + ▄▄▄▄▄▄▄▄▄▄ + + Content + ▀▀▀▀▀▀▀▀▀▀ + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox--HalfLinePaddedBox-renders-standard-background-and-blocks-when-not-iTerm2-or-Apple-Terminal.snap.svg b/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox--HalfLinePaddedBox-renders-standard-background-and-blocks-when-not-iTerm2-or-Apple-Terminal.snap.svg new file mode 100644 index 0000000000..71113cee03 --- /dev/null +++ b/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox--HalfLinePaddedBox-renders-standard-background-and-blocks-when-not-iTerm2-or-Apple-Terminal.snap.svg @@ -0,0 +1,14 @@ + + + + + + ▀▀▀▀▀▀▀▀▀▀ + + Content + + ▄▄▄▄▄▄▄▄▄▄ + + \ No newline at end of file diff --git a/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox.test.tsx.snap b/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox.test.tsx.snap index dbb9af2991..e9e53cb3a2 100644 --- a/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox.test.tsx.snap +++ b/packages/cli/src/ui/components/shared/__snapshots__/HalfLinePaddedBox.test.tsx.snap @@ -1,10 +1,15 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[` > renders Apple Terminal-specific blocks when Apple Terminal is detected 1`] = ` +"▅▅▅▅▅▅▅▅▅▅ +Content +▄▄▄▄▄▄▄▄▄▄" +`; + exports[` > renders iTerm2-specific blocks when iTerm2 is detected 1`] = ` "▄▄▄▄▄▄▄▄▄▄ Content -▀▀▀▀▀▀▀▀▀▀ -" +▀▀▀▀▀▀▀▀▀▀" `; exports[` > renders nothing when screen reader is enabled 1`] = ` @@ -17,9 +22,8 @@ exports[` > renders nothing when useBackgroundColor is fals " `; -exports[` > renders standard background and blocks when not iTerm2 1`] = ` +exports[` > renders standard background and blocks when not iTerm2 or Apple Terminal 1`] = ` "▀▀▀▀▀▀▀▀▀▀ Content -▄▄▄▄▄▄▄▄▄▄ -" +▄▄▄▄▄▄▄▄▄▄" `; diff --git a/packages/cli/src/ui/utils/terminalUtils.ts b/packages/cli/src/ui/utils/terminalUtils.ts index 18cd08f952..5b2518640f 100644 --- a/packages/cli/src/ui/utils/terminalUtils.ts +++ b/packages/cli/src/ui/utils/terminalUtils.ts @@ -36,6 +36,13 @@ export function isITerm2(): boolean { return cachedIsITerm2; } +/** + * Returns true if the current terminal is macOS Terminal. + */ +export function isAppleTerminal(): boolean { + return process.env['TERM_PROGRAM'] === 'Apple_Terminal'; +} + /** * Resets the cached iTerm2 detection value. * Primarily used for testing.