diff --git a/src/blog/posts/2024/4/cursed-components-dvorak-only.md b/src/blog/posts/2024/4/cursed-components-dvorak-only.md new file mode 100644 index 0000000..62c03e3 --- /dev/null +++ b/src/blog/posts/2024/4/cursed-components-dvorak-only.md @@ -0,0 +1,70 @@ +--- +title: "Cursed components: a dvorak-only text input" +date: 2024-04-17T12:31:56.557Z +tags: + - javascript + - html + - draft +--- + +This post was inspired by Terence Eden's post about [inputs that don't work with numpads](https://shkspr.mobi/blog/2024/04/i-cant-use-my-number-pad-for-2fa-codes/), and one of the [subsequent comments](https://mastodon.social/@Edent/112286509959315116). This got me thinking, wouldn't it be absolutely beyond cursed to have a text input that only allowed you to enter text if you were using a sufficiently cool keyboard layout. + +So, I present, the Dvorak-only Text Input: + +**TODO:** Make the input + + +## Detecting keyboard layout + +There's no _actual_ way to detect the keyboard layout as a named value using Javascript, but there is the [KeyboardLayoutMap](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardLayoutMap), which is currently supported in Chromium browsers and not much else[^1]. So what we can do is lookup how the user's keyboard layout maps particular keys, and then compare those to what we'd expect from a Dvorak layout. + + +```javascript +navigator.keyboard.getLayoutMap().then(layoutMap => { + if (layoutMap.get("KeyQ") === "'" + && layoutMap.get("KeyW") === "," + && layoutMap.get("KeyE") === "." + && layoutMap.get("KeyR") === "p" + && layoutMap.get("KeyT") === "y" + && layoutMap.get("KeyY") === "f") { + // The user is (probably) using Dvorak + } +}) +``` + +Because this call happens inside a Promise, it can't be directly used within an `onChange` event on the text input, so instead it rechecks every 200ms and stores the result: + +```javascript +let isDvorak = false; + +setInterval( + () => navigator.keyboard.getLayoutMap().then(layoutMap => { + isDvorak = layoutMap.get("KeyQ") === "'" + && layoutMap.get("KeyW") === "," + && layoutMap.get("KeyE") === "." + && layoutMap.get("KeyR") === "p" + && layoutMap.get("KeyT") === "y" + && layoutMap.get("KeyY") === "f"; + }), + 200 +); +``` + + +[^1]: But that's pretty on-brand for this particular use-case. + + \ No newline at end of file