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
19 changes: 15 additions & 4 deletions apps/web/src/components/ComposerPromptEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,14 @@ interface ComposerPromptEditorProps {
skills: ReadonlyArray<ServerProviderSkill>;
disabled: boolean;
placeholder: string;
ariaLabel?: string | undefined;
/**
* Suggestion-menu wiring for screen readers. `suggestionListId` marks an
* editor that can open a suggestion list at all, so editors without menus
* (the Settings font preview) are not announced as having autocomplete.
* `activeSuggestionId` is the highlighted option while that list is
* rendered; it drives aria-activedescendant and aria-controls.
*/
suggestionListId?: string | undefined;
activeSuggestionId?: string | undefined;
containerClassName?: string;
Expand Down Expand Up @@ -1635,6 +1643,7 @@ function ComposerPromptEditorInner({
skills,
disabled,
placeholder,
ariaLabel,
suggestionListId,
activeSuggestionId,
containerClassName,
Expand Down Expand Up @@ -1995,12 +2004,12 @@ function ComposerPromptEditorInner({
className,
)}
data-testid="composer-editor"
ariaLabel="Message"
ariaLabel={ariaLabel}
ariaMultiline={true}
ariaAutoComplete="list"
ariaControls={suggestionListId}
ariaAutoComplete={suggestionListId ? "list" : undefined}
ariaControls={activeSuggestionId ? suggestionListId : undefined}
ariaActiveDescendant={activeSuggestionId}
aria-haspopup="listbox"
aria-haspopup={suggestionListId ? "listbox" : undefined}
aria-placeholder={placeholder}
placeholder={<span />}
onKeyDown={(event) => {
Expand Down Expand Up @@ -2088,6 +2097,7 @@ export function ComposerPromptEditor({
skills,
disabled,
placeholder,
ariaLabel,
suggestionListId,
activeSuggestionId,
containerClassName,
Expand Down Expand Up @@ -2137,6 +2147,7 @@ export function ComposerPromptEditor({
skills={skills}
disabled={disabled}
placeholder={placeholder}
ariaLabel={ariaLabel}
suggestionListId={suggestionListId}
activeSuggestionId={activeSuggestionId}
{...(containerClassName ? { containerClassName } : {})}
Expand Down
5 changes: 2 additions & 3 deletions apps/web/src/components/chat/ChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6698,9 +6698,8 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
) : null}
<ComposerContextActionsContext value={composerContextActions}>
<ComposerPromptEditor
suggestionListId={
composerSuggestionListVisible ? composerSuggestionListId : undefined
}
ariaLabel="Message"
suggestionListId={composerSuggestionListId}
activeSuggestionId={
composerSuggestionListVisible && activeComposerMenuItem
? composerSuggestionOptionId(
Expand Down
9 changes: 8 additions & 1 deletion apps/web/src/components/chat/ComposerCommandMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const ComposerCommandMenu = memo(function ComposerCommandMenu(props: {
{props.items.length > 0 ? (
<CommandList
id={props.listId}
aria-label="Composer suggestions"
aria-label={props.triggerKind ? LISTBOX_LABEL_BY_TRIGGER[props.triggerKind] : undefined}
className="max-h-72 min-h-0 scroll-pb-6"
>
<CommandGroup>
Expand Down Expand Up @@ -227,6 +227,13 @@ export function composerSuggestionOptionId(listId: string, itemId: string): stri
return `${listId}-${encodeURIComponent(itemId)}`;
}

const LISTBOX_LABEL_BY_TRIGGER: Record<ComposerTriggerKind, string> = {
path: "Files and folders",
"pull-request": "Pull requests",
"slash-command": "Commands",
skill: "Skills",
};

const SKILL_SOURCE_ICON_BY_KIND: Record<ProviderSkillSourceKind, LucideIcon> = {
app: BlocksIcon,
repo: FolderIcon,
Expand Down
Loading