Skip to content

Commit ee7bb5c

Browse files
committed
feat: switching JS does not collide with inputs.
1 parent 635c03b commit ee7bb5c

File tree

2 files changed

+110
-7
lines changed

2 files changed

+110
-7
lines changed

resources/js/theme-switch-two-states/theme-switch.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
(function __FUNCTION_NAME__() {
22
document.addEventListener("keydown", (event) => {
3-
if (
4-
// @todo Check if focus is on an input, textarea, or select element to avoid conflicts with typing
5-
event.key === "__TOGGLE_KEY__" &&
6-
!event.ctrlKey &&
7-
!event.altKey &&
8-
!event.metaKey
9-
) {
3+
const activeElement = document.activeElement;
4+
5+
const isInputFocused =
6+
activeElement && (["INPUT", "TEXTAREA", "SELECT"].includes(activeElement.tagName) || activeElement.isContentEditable);
7+
8+
if (!isInputFocused && event.key === "__TOGGLE_KEY__" && !event.ctrlKey && !event.altKey && !event.metaKey) {
109
event.preventDefault();
1110

1211
const isDark = document.documentElement.classList.toggle("__DARK__");

tests/js/theme-switch-two-states/theme-switch.test.js

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,108 @@ describe("ThemeSwitchScript.js IIFE behavior", () => {
9999
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(true);
100100
expect(localStorage.getItem("theme")).toBe(DEFAULT_DARK);
101101
});
102+
103+
it("does not toggle when an input field is focused", () => {
104+
runThemeSwitchScript();
105+
106+
// Create and focus an input element
107+
const input = document.createElement("input");
108+
document.body.appendChild(input);
109+
input.focus();
110+
111+
expect(document.activeElement).toBe(input);
112+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
113+
114+
// Try to toggle while input is focused - should not work
115+
dispatchKeydown(DEFAULT_TOGGLE_KEY);
116+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
117+
expect(localStorage.getItem("theme")).toBe(null);
118+
119+
// Clean up
120+
document.body.removeChild(input);
121+
});
122+
123+
it("does not toggle when a textarea is focused", () => {
124+
runThemeSwitchScript();
125+
126+
// Create and focus a textarea element
127+
const textarea = document.createElement("textarea");
128+
document.body.appendChild(textarea);
129+
textarea.focus();
130+
131+
expect(document.activeElement).toBe(textarea);
132+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
133+
134+
// Try to toggle while textarea is focused - should not work
135+
dispatchKeydown(DEFAULT_TOGGLE_KEY);
136+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
137+
expect(localStorage.getItem("theme")).toBe(null);
138+
139+
// Clean up
140+
document.body.removeChild(textarea);
141+
});
142+
143+
it("does not toggle when a select field is focused", () => {
144+
runThemeSwitchScript();
145+
146+
// Create and focus a select element
147+
const select = document.createElement("select");
148+
const option = document.createElement("option");
149+
option.value = "test";
150+
option.text = "Test Option";
151+
select.appendChild(option);
152+
document.body.appendChild(select);
153+
select.focus();
154+
155+
expect(document.activeElement).toBe(select);
156+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
157+
158+
// Try to toggle while select is focused - should not work
159+
dispatchKeydown(DEFAULT_TOGGLE_KEY);
160+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
161+
expect(localStorage.getItem("theme")).toBe(null);
162+
163+
// Clean up
164+
document.body.removeChild(select);
165+
});
166+
167+
it("does not toggle when a contentEditable element is focused", () => {
168+
runThemeSwitchScript();
169+
170+
// Create and focus a contentEditable element
171+
const div = document.createElement("div");
172+
div.contentEditable = "true";
173+
document.body.appendChild(div);
174+
div.focus();
175+
176+
expect(document.activeElement).toBe(div);
177+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
178+
179+
// Try to toggle while contentEditable is focused - should not work
180+
dispatchKeydown(DEFAULT_TOGGLE_KEY);
181+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
182+
expect(localStorage.getItem("theme")).toBe(null);
183+
184+
// Clean up
185+
document.body.removeChild(div);
186+
});
187+
188+
it("toggles normally when input is unfocused", () => {
189+
runThemeSwitchScript();
190+
191+
// Create an input but don't focus it
192+
const input = document.createElement("input");
193+
document.body.appendChild(input);
194+
195+
expect(document.activeElement).not.toBe(input);
196+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(false);
197+
198+
// Toggle should work normally when input exists but is not focused
199+
dispatchKeydown(DEFAULT_TOGGLE_KEY);
200+
expect(document.documentElement.classList.contains(DEFAULT_DARK)).toBe(true);
201+
expect(localStorage.getItem("theme")).toBe(DEFAULT_DARK);
202+
203+
// Clean up
204+
document.body.removeChild(input);
205+
});
102206
});

0 commit comments

Comments
 (0)