Skip to content
Merged
Changes from 1 commit
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
19 changes: 18 additions & 1 deletion packages/cli/src/ui/components/RewindViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import type React from 'react';
import { useMemo, useState } from 'react';
import { Box, Text } from 'ink';
import { Box, Text, useIsScreenReaderEnabled } from 'ink';
import { useUIState } from '../contexts/UIStateContext.js';
import {
type ConversationRecord,
Expand Down Expand Up @@ -50,6 +50,7 @@ export const RewindViewer: React.FC<RewindViewerProps> = ({
}) => {
const [isRewinding, setIsRewinding] = useState(false);
const { terminalWidth, terminalHeight } = useUIState();
const isScreenReaderEnabled = useIsScreenReaderEnabled();
const {
selectedMessageId,
getStats,
Expand Down Expand Up @@ -182,6 +183,22 @@ export const RewindViewer: React.FC<RewindViewerProps> = ({
);
}

if (isScreenReaderEnabled) {
return (
<Box flexDirection="column" width={terminalWidth}>
<Text bold>Rewind - Select a conversation point:</Text>
{items.map((item, idx) => (
<Text key={item.key}>
{idx + 1}.{' '}
{item.value.id === 'current-position'
? 'Stay at current position'
: getCleanedRewindText(item.value)}
</Text>
))}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The current implementation for the screen reader view renders a static list of items using items.map(). This makes the list non-interactive, as the key press handlers for navigation (arrow keys) and selection (Enter) from BaseSelectionList are not being used. As a result, screen reader users can see the list but cannot interact with it, which prevents them from using the rewind functionality and negates the goal of this accessibility fix.

To address this, you should use the BaseSelectionList component for the screen reader view as well, but with a simplified renderItem function that produces plain text output. This will provide the necessary keyboard interactivity.

As a follow-up, you could extract the onSelect handler into a named function to avoid duplicating it between the screen reader and visual rendering paths.

        <BaseSelectionList
          items={items}
          initialIndex={items.length - 1}
          isFocused={true}
          showNumbers={false}
          wrapAround={false}
          onSelect={(item: MessageRecord) => {
            if (item?.id) {
              if (item.id === 'current-position') {
                onExit();
              } else {
                selectMessage(item.id);
              }
            }
          }}
          renderItem={(itemWrapper) => {
            const item = itemWrapper.value;
            const text =
              item.id === 'current-position'
                ? 'Stay at current position'
                : getCleanedRewindText(item);
            return (
              <Text>
                {itemWrapper.index + 1}. {text}
              </Text>
            );
          }}
        />
References
  1. Maintain consistency with existing UI behavior across components. Defer non-standard UX pattern improvements to be addressed holistically rather than in a single component.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated successfully

<Text>Press Esc to exit, Enter to select, arrow keys to navigate.</Text>
</Box>
);
}
return (
<Box
borderStyle="round"
Expand Down