Remove non-action aria labels

This commit is contained in:
murashit 2026-06-13 15:32:41 +09:00
parent c55e0c457d
commit a573a86246
14 changed files with 31 additions and 53 deletions

View file

@ -119,7 +119,6 @@ export function ComposerShell({
className="codex-panel-ui__text-input codex-panel__composer-input"
placeholder={sendMode.canInterrupt ? "Add steering message..." : normalPlaceholder}
role="combobox"
aria-label={sendMode.canInterrupt ? "Steering message" : "Message"}
aria-autocomplete="list"
aria-expanded={suggestions.length > 0 ? "true" : "false"}
aria-controls={`${viewId}-composer-suggestions`}

View file

@ -171,7 +171,6 @@ export function GoalPanel({
<textarea
ref={objectiveRef}
className="codex-panel-ui__text-input codex-panel__goal-objective-input"
aria-label="Goal objective"
value={objective}
onInput={(event) => {
actions.onObjectiveDraftChange(event.currentTarget.value);

View file

@ -232,7 +232,6 @@ function UserInputQuestions({
})}
{question.isOther ? (
<OtherUserInputOption
questionText={question.question}
groupName={`codex-panel-${String(input.requestId)}-${question.id}`}
current={current}
optionLabels={new Set(question.options.map((option) => option.label))}
@ -243,13 +242,7 @@ function UserInputQuestions({
) : null}
</>
) : (
<FreeformUserInput
questionText={question.question}
isSecret={question.isSecret}
current={current}
question={question}
actions={actions}
/>
<FreeformUserInput isSecret={question.isSecret} current={current} question={question} actions={actions} />
)}
</div>
</div>
@ -260,7 +253,6 @@ function UserInputQuestions({
}
function OtherUserInputOption({
questionText,
groupName,
current,
optionLabels,
@ -268,7 +260,6 @@ function OtherUserInputOption({
userInputDrafts,
actions,
}: {
questionText: string;
groupName: string;
current: string;
optionLabels: ReadonlySet<string>;
@ -324,7 +315,6 @@ function OtherUserInputOption({
<input
className="codex-panel__user-input-text codex-panel__user-input-other-text"
type="text"
aria-label={`Other answer: ${questionText}`}
value={inputValue}
tabIndex={otherSelected ? 0 : -1}
placeholder="Other answer"
@ -341,13 +331,11 @@ function OtherUserInputOption({
}
function FreeformUserInput({
questionText,
isSecret,
current,
question,
actions,
}: {
questionText: string;
isSecret: boolean;
current: string;
question: PendingUserInputQuestionViewModel;
@ -357,7 +345,6 @@ function FreeformUserInput({
<input
className="codex-panel__user-input-text"
type={isSecret ? "password" : "text"}
aria-label={questionText}
value={current}
onInput={(event) => {
actions.setUserInputDraft(question.draftKey, event.currentTarget.value);

View file

@ -198,7 +198,6 @@ function RateLimitPanel({ rateLimit }: { rateLimit: RateLimitSummary | null }):
.filter(Boolean)
.join(" ")}
role="progressbar"
aria-label={row.title}
aria-valuemin={0}
aria-valuemax={100}
aria-valuenow={row.percent}
@ -419,7 +418,6 @@ function ThreadRenameRow({ thread, actions }: { thread: ToolbarThreadRow; action
className="codex-panel-ui__nav-inline-input codex-panel__thread-rename-input"
type="text"
value={draft}
aria-label={`Rename ${thread.title}`}
onInput={(event) => {
actions.updateRenameDraft(thread.threadId, event.currentTarget.value);
}}

View file

@ -181,7 +181,6 @@ export class SelectionRewritePopover {
private createElements(): SelectionRewriteElements {
const root = activeDocument.body.createDiv({ cls: "codex-panel-selection-rewrite" });
root.setAttr("role", "dialog");
root.setAttr("aria-label", "Rewrite selection");
const elements: SelectionRewriteElements = { root, instruction: null, applyButton: null };
this.renderView(elements);
return elements;
@ -488,7 +487,6 @@ function SelectionRewritePopoverView({
<textarea
ref={instructionRef}
className="codex-panel-ui__text-input codex-panel-selection-rewrite__instruction"
aria-label="Rewrite instruction"
disabled={generating}
onInput={(event) => {
onInstructionInput(event.currentTarget.value);

View file

@ -216,7 +216,6 @@ function RenameRow({ row, actions, className }: { row: ThreadsRowModel; actions:
ref={inputRef}
className="codex-panel-ui__nav-inline-input codex-panel-threads__rename-input"
type="text"
aria-label="Thread name"
value={row.rename.draft}
onInput={(event) => {
actions.updateRename(row.thread.id, event.currentTarget.value);

View file

@ -92,7 +92,6 @@ function renderArchiveExportSettings(containerEl: HTMLElement, state: ArchivedTh
.setName("Saved note folder")
.setDesc("Vault-relative folder for saved thread notes. The folder is created when needed.")
.addText((text) => {
text.inputEl.ariaLabel = "Saved note folder";
text
.setPlaceholder("Codex archives")
.setValue(state.exportFolderTemplate)
@ -105,7 +104,6 @@ function renderArchiveExportSettings(containerEl: HTMLElement, state: ArchivedTh
.setName("Saved note filename")
.setDesc("Filename template. Variables: {{date}}, {{time}}, {{title}}, {{id}}, {{shortId}}. Existing files get a numeric suffix.")
.addText((text) => {
text.inputEl.ariaLabel = "Saved note filename";
text
.setPlaceholder("{{date}} {{time}} {{title}} {{shortId}}.md")
.setValue(state.exportFilenameTemplate)
@ -118,7 +116,6 @@ function renderArchiveExportSettings(containerEl: HTMLElement, state: ArchivedTh
.setName("Saved note tags")
.setDesc("Comma-separated fixed tags for saved notes. Leave empty to omit tags.")
.addText((text) => {
text.inputEl.ariaLabel = "Saved note tags";
text
.setPlaceholder("Codex, archive")
.setValue(state.exportTags)

View file

@ -75,7 +75,6 @@ export class CodexPanelSettingTab extends PluginSettingTab {
.setName("Codex executable")
.setDesc("Path used to start `codex app-server`. Use an absolute path if Obsidian cannot find `codex`.")
.addText((text) => {
text.inputEl.ariaLabel = "Codex executable";
text
.setPlaceholder(DEFAULT_CODEX_PATH)
.setValue(this.plugin.settings.codexPath)
@ -103,7 +102,6 @@ export class CodexPanelSettingTab extends PluginSettingTab {
"Choose how the composer sends messages. Shift+Enter inserts a newline when Enter sends. Obsidian hotkeys may intercept Cmd/Ctrl+Enter.",
)
.addDropdown((dropdown) => {
dropdown.selectEl.ariaLabel = "Send shortcut";
dropdown.addOption("enter", SEND_SHORTCUT_LABELS.enter);
dropdown.addOption("mod-enter", SEND_SHORTCUT_LABELS["mod-enter"]);
dropdown.setValue(this.plugin.settings.sendShortcut).onChange(async (value) => {
@ -130,7 +128,6 @@ export class CodexPanelSettingTab extends PluginSettingTab {
.addDropdown((dropdown) => {
const current = this.plugin.settings.threadNamingModel;
const options = this.modelMetadata();
dropdown.selectEl.ariaLabel = "Automatic thread naming model";
dropdown.addOption(CODEX_DEFAULT_VALUE, "Codex default");
if (current && !options.some((model) => model.model === current || model.id === current)) {
dropdown.addOption(current, `${current} (saved)`);
@ -150,7 +147,6 @@ export class CodexPanelSettingTab extends PluginSettingTab {
.addDropdown((dropdown) => {
const current = this.plugin.settings.threadNamingEffort;
const options = this.effortOptions(this.plugin.settings.threadNamingModel);
dropdown.selectEl.ariaLabel = "Automatic thread naming effort";
dropdown.addOption(CODEX_DEFAULT_VALUE, "Codex default");
if (current && !options.includes(current)) {
dropdown.addOption(current, `${current} (saved)`);
@ -170,7 +166,6 @@ export class CodexPanelSettingTab extends PluginSettingTab {
.addDropdown((dropdown) => {
const current = this.plugin.settings.rewriteSelectionModel;
const options = this.modelMetadata();
dropdown.selectEl.ariaLabel = "Selection rewrite model";
dropdown.addOption(CODEX_DEFAULT_VALUE, "Codex default");
if (current && !options.some((model) => model.model === current || model.id === current)) {
dropdown.addOption(current, `${current} (saved)`);
@ -190,7 +185,6 @@ export class CodexPanelSettingTab extends PluginSettingTab {
.addDropdown((dropdown) => {
const current = this.plugin.settings.rewriteSelectionEffort;
const options = this.effortOptions(this.plugin.settings.rewriteSelectionModel);
dropdown.selectEl.ariaLabel = "Selection rewrite effort";
dropdown.addOption(CODEX_DEFAULT_VALUE, "Codex default");
if (current && !options.includes(current)) {
dropdown.addOption(current, `${current} (saved)`);

View file

@ -81,9 +81,7 @@ describe("pending request renderer decisions", () => {
};
render();
expect(parent.querySelector<HTMLInputElement>(".codex-panel__user-input-other-text")?.getAttribute("aria-label")).toBe(
"Other answer: How broad?",
);
expect(parent.querySelector<HTMLInputElement>(".codex-panel__user-input-other-text")?.getAttribute("aria-label")).toBeNull();
actEvent(() => {
changeInputValue(expectPresent(parent.querySelector<HTMLInputElement>(".codex-panel__user-input-other-text")), "Custom scope");
});
@ -244,7 +242,7 @@ describe("pending request renderer decisions", () => {
);
const inputElement = parent.querySelector<HTMLInputElement>(".codex-panel__user-input-text");
expect(inputElement?.getAttribute("aria-label")).toBe("How broad?");
expect(inputElement?.getAttribute("aria-label")).toBeNull();
expect(document.activeElement).toBe(inputElement);
} finally {
unmountUiRootInAct(parent);

View file

@ -104,7 +104,7 @@ describe("ComposerShell decisions", () => {
);
expect(composer.getAttribute("placeholder")).toBe("Ask Codex to work on “Refactor terminal streaming”...");
expect(composer.getAttribute("aria-label")).toBe("Message");
expect(composer.getAttribute("aria-label")).toBeNull();
mountComposerShell(parent, "view", "", false, false, "Ask Codex to work on “Renamed thread”...", [], 0, callbacks);
@ -480,7 +480,7 @@ describe("ComposerShell decisions", () => {
expect(sendButton?.getAttribute("aria-label")).toBe("Interrupt");
expect(composer.getAttribute("placeholder")).toBe("Add steering message...");
expect(composer.getAttribute("aria-label")).toBe("Steering message");
expect(composer.getAttribute("aria-label")).toBeNull();
expect(sendButton?.classList.contains("is-interrupt")).toBe(true);
expect(sendButton?.classList.contains("is-steer")).toBe(false);
expect(sendButton?.dataset["icon"]).toBe("square");

View file

@ -35,7 +35,7 @@ describe("GoalPanel", () => {
expect(parent.textContent).toContain("Goal");
expect(document.activeElement).toBe(parent.querySelector("textarea"));
expect(parent.querySelector("textarea")?.getAttribute("aria-label")).toBe("Goal objective");
expect(parent.querySelector("textarea")?.getAttribute("aria-label")).toBeNull();
await input(parent, "textarea", "New objective");
await click(parent, '[aria-label="Save goal"]');

View file

@ -152,7 +152,7 @@ describe("Toolbar decisions", () => {
expect(meters[1]?.classList.contains("codex-panel__limit-panel-meter--7")).toBe(true);
expect(meters.map((meter) => meter.getAttribute("role"))).toEqual(["progressbar", "progressbar"]);
expect(meters.map((meter) => meter.getAttribute("aria-valuenow"))).toEqual(["42", "21"]);
expect(meters.map((meter) => meter.getAttribute("aria-label"))).toEqual(["Codex 5h: 42% used.", "Codex 1w: 21% used."]);
expect(meters.map((meter) => meter.getAttribute("aria-label"))).toEqual([null, null]);
});
it("renders connection diagnostics in the status menu", () => {

View file

@ -261,7 +261,7 @@ describe("selection rewrite popover", () => {
openPopover(popover);
const instruction = expectPresent(document.querySelector<HTMLTextAreaElement>(".codex-panel-selection-rewrite__instruction"));
expect(instruction.getAttribute("aria-label")).toBe("Rewrite instruction");
expect(instruction.getAttribute("aria-label")).toBeNull();
void act(() => {
setTextareaValue(instruction, "Make it concise.");
instruction.dispatchEvent(new Event("input", { bubbles: true }));

View file

@ -86,8 +86,8 @@ describe("settings tab", () => {
const tab = newSettingsTab({ saveSettings });
tab.display();
expect(inputForSetting(tab, "Codex executable")?.getAttribute("aria-label")).toBe("Codex executable");
const shortcut = tab.containerEl.querySelector<HTMLSelectElement>('select[aria-label="Send shortcut"]');
expect(inputForSetting(tab, "Codex executable")?.getAttribute("aria-label")).toBeNull();
const shortcut = selectForSetting(tab, "Send shortcut");
if (!shortcut) throw new Error("Missing send shortcut dropdown");
shortcut.value = "mod-enter";
@ -143,9 +143,9 @@ describe("settings tab", () => {
const filename = inputForSetting(tab, "Saved note filename");
const tags = inputForSetting(tab, "Saved note tags");
if (!toggle || !folder || !filename || !tags) throw new Error("Missing archive export controls");
expect(folder.getAttribute("aria-label")).toBe("Saved note folder");
expect(filename.getAttribute("aria-label")).toBe("Saved note filename");
expect(tags.getAttribute("aria-label")).toBe("Saved note tags");
expect(folder.getAttribute("aria-label")).toBeNull();
expect(filename.getAttribute("aria-label")).toBeNull();
expect(tags.getAttribute("aria-label")).toBeNull();
toggle.checked = true;
toggle.dispatchEvent(new Event("change"));
@ -340,8 +340,8 @@ describe("settings tab", () => {
tab.display();
expect(selectOptions(tab, "Automatic thread naming effort")).toEqual(["Codex default", "saved-custom-effort (saved)", "extreme"]);
expect(selectOptions(tab, "Selection rewrite effort")).toEqual(["Codex default", "extreme"]);
expect(selectOptions(tab, "Automatic thread naming", 1)).toEqual(["Codex default", "saved-custom-effort (saved)", "extreme"]);
expect(selectOptions(tab, "Selection rewrite", 1)).toEqual(["Codex default", "extreme"]);
});
it("keeps successful sections when one settings data request fails", async () => {
@ -596,14 +596,23 @@ function clickButtonByLabel(tab: CodexPanelSettingTab, label: string): void {
}
function inputForSetting(tab: CodexPanelSettingTab, name: string): HTMLInputElement | null {
const setting = Array.from(tab.containerEl.querySelectorAll(".setting-item")).find(
(element) => element.querySelector(".setting-item-name")?.textContent === name,
);
return setting?.querySelector("input") ?? null;
return settingElement(tab, name)?.querySelector("input") ?? null;
}
function selectOptions(tab: CodexPanelSettingTab, ariaLabel: string): string[] {
const select = tab.containerEl.querySelector<HTMLSelectElement>(`select[aria-label="${ariaLabel}"]`);
if (!select) throw new Error(`Missing select: ${ariaLabel}`);
function settingElement(tab: CodexPanelSettingTab, name: string): Element | null {
return (
Array.from(tab.containerEl.querySelectorAll(".setting-item")).find(
(element) => element.querySelector(".setting-item-name")?.textContent === name,
) ?? null
);
}
function selectForSetting(tab: CodexPanelSettingTab, name: string): HTMLSelectElement | null {
return settingElement(tab, name)?.querySelector("select") ?? null;
}
function selectOptions(tab: CodexPanelSettingTab, name: string, index = 0): string[] {
const select = settingElement(tab, name)?.querySelectorAll<HTMLSelectElement>("select")[index] ?? null;
if (!select) throw new Error(`Missing select: ${name}`);
return Array.from(select.options).map((option) => option.textContent);
}