= 0) {
+ const end = tagEnd(templateSource, start);
+ const tag = templateSource.slice(start, end + 1);
+ if (tag.includes("settings-item")) return tag;
+ start = templateSource.lastIndexOf("
= 0) {
+ const end = tagEnd(templateSource, start);
+ const tag = templateSource.slice(start, end + 1);
+ if (tag.includes("rounded") && tag.includes("border")) return tag;
+ start = templateSource.lastIndexOf("
{
+ it("marks representative editor, navigation, data, toolbar, and update setting rows for the shared hover treatment", () => {
+ for (const key of ["showStatementRunButtons", "externalSqlEditorMaxMb", "dataGridTypeColorScheme", "exclusiveRightSidebarPanels", "updateDownloadSource"] as const) {
+ expect(borderedSettingDivForKey(key)).toContain("settings-item");
+ }
+ });
+
+ it("keeps hover feedback off rows while their controls are disabled", () => {
+ expect(settingItemDivForText('id="web-sql-file-upload-max-mb"')).toContain("'settings-item-disabled': !webSqlFileUploadMaxMbLoaded || webSqlFileUploadMaxMbLoading");
+ expect(settingItemDivForText('id="mcp-http-enabled"')).toContain("'settings-item-disabled': mcpHttpLoading || mcpHttpSaving");
+ expect(styleSource).toMatch(/\.settings-item:not\(\.settings-item-disabled\):not\(\.opacity-50\):hover/);
+ });
+
+ it("provides legacy color fallbacks before progressively enhancing hover colors", () => {
+ const fallbackStart = styleSource.indexOf(".settings-item:not(.settings-item-disabled):not(.opacity-50):hover");
+ const enhancementStart = styleSource.indexOf("@supports (background: color-mix(in oklab, black, white))");
+ expect(fallbackStart).toBeGreaterThan(-1);
+ expect(enhancementStart).toBeGreaterThan(fallbackStart);
+ expect(styleSource.slice(fallbackStart, enhancementStart)).toContain("background-color: var(--muted);");
+ expect(styleSource.slice(fallbackStart, enhancementStart)).toContain("border-color: var(--muted-foreground);");
+ expect(styleSource.slice(enhancementStart)).toContain("color-mix(in oklab");
+ });
+
+ it("limits shared hover feedback to independent rows instead of composite and informational containers", () => {
+ expect(divTagForAttribute('data-settings-search-id="data-grid-filter-view"')).not.toContain("settings-item");
+ expect(borderedSettingDivForKey("dataGridKeepFilterEditorExpanded")).toContain("settings-item");
+
+ for (const text of ['t("settings.mcpHttpWebServiceTitle")', 't("settings.mcpHttpUnsavedChangesHint")', "{{ mcpStatus.bin_path }}", 't("settings.mcpCursorConfigPath")', 't("settings.mcpQoderConfigPath")', 't("settings.supportInfoTitle")'] as const) {
+ expect(borderedDivForText(text)).not.toContain("settings-item");
+ }
+ });
+
+ it("uses direct selectors without styling nested descendants", () => {
+ expect(styleSource).not.toContain(".settings-item *");
+ expect(styleSource).not.toContain(".settings-item:hover *");
+ });
+
+ it("leaves choice cards and shortcut rows on their existing interaction styles", () => {
+ expect(borderedSettingDivForKey("showStatementRunButtons")).not.toContain("settings-choice-card");
+ expect(templateSource).toContain("settings-shortcut-row group");
+ });
+});
diff --git a/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts b/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts
index 753a20da0c..9935a0f62a 100644
--- a/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts
+++ b/apps/desktop/src/components/editor/__tests__/EditorSettingsDialog.previewPosition.spec.ts
@@ -71,10 +71,10 @@ describe("EditorSettingsDialog live preview placement", () => {
expect(completionTriggerMode).toBeGreaterThan(completionSection);
expect(selectFirstCompletion).toBeGreaterThan(completionTriggerMode);
expect(editorSection).not.toContain('t("settings.sqlCompletionSection")');
- expect(editorSection).toContain('class="flex items-start justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2" data-editor-completion-trigger-mode');
+ expect(editorSection).toContain('class="settings-item flex items-start justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2" data-editor-completion-trigger-mode');
expect(editorSection).toContain('');
expect(editorSection).toContain('class="grid gap-4 md:grid-cols-2" data-editor-execution-settings');
- expect(editorSection).toContain('class="flex items-center justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2 md:col-span-2" data-editor-execute-mode');
+ expect(editorSection).toContain('class="settings-item flex items-center justify-between gap-4 rounded-md border bg-muted/20 px-3 py-2 md:col-span-2" data-editor-execute-mode');
expect(editorSection.match(/:model-value="editCompletionTriggerMode"/g)).toHaveLength(1);
expect(editorSection.match(/id="editor-select-first-completion-on-open"/g)).toHaveLength(1);
});