From c3a9b7b37a989623a6b7b471afeb624e200fb967 Mon Sep 17 00:00:00 2001
From: Dmitriy Mezhnin <59breeder@gmail.com>
Date: Tue, 29 Oct 2024 17:23:27 +0100
Subject: [PATCH 1/3] adds focusgroup attribute basic support
---
focus-group.js | 14 +++++-
package.json | 2 +-
test/demo/index.html | 11 +++++
test/demo/index.tsx | 54 +++++++++++++++++++++
test/focus-group.test.ts | 100 +++++++++++++++++++++++++++++++++++++++
5 files changed, 178 insertions(+), 3 deletions(-)
diff --git a/focus-group.js b/focus-group.js
index 53ecdfb..e537a72 100644
--- a/focus-group.js
+++ b/focus-group.js
@@ -13,6 +13,9 @@ function focus(current, next) {
}
function findGroupNodeByEventTarget(target) {
+ let fg = target.closest('[focusgroup]');
+ if (fg) return fg;
+
let itemRole = target.role || target.type || target.tagName
if (!itemRole) return null
@@ -26,7 +29,7 @@ function findGroupNodeByEventTarget(target) {
}
function getItems(target, group) {
- if (group.role === 'toolbar') return getToolbarItems(group)
+ if (group.role === 'toolbar' || group.hasAttribute('focusgroup')) return getToolbarItems(group)
return group.querySelectorAll(`[role=${target.role}]`)
}
@@ -37,12 +40,19 @@ function getToolbarItems(group) {
item.role === 'button' ||
item.type === 'button' ||
item.role === 'checkbox' ||
- item.type === 'checkbox'
+ item.type === 'checkbox' ||
+ item.hasAttribute('tabindex')
)
})
}
function isHorizontalOrientation(group) {
+ let fg = group.getAttribute('focusgroup')
+ if (fg !== null)
+ {
+ return !fg.split(' ').includes('block');
+ }
+
let ariaOrientation = group.getAttribute('aria-orientation')
if (ariaOrientation === 'vertical') return false
if (ariaOrientation === 'horizontal') return true
diff --git a/package.json b/package.json
index 34e8f1c..a7be2b4 100644
--- a/package.json
+++ b/package.json
@@ -85,7 +85,7 @@
"import": {
"./index.js": "{ startKeyUX, hotkeyKeyUX, pressKeyUX, focusGroupKeyUX, jumpKeyUX, hiddenKeyUX, likelyWithKeyboard, getHotKeyHint, hotkeyOverrides, hotkeyMacCompat }"
},
- "limit": "2194 B"
+ "limit": "2248 B"
}
],
"clean-publish": {
diff --git a/test/demo/index.html b/test/demo/index.html
index bef977c..b13128a 100644
--- a/test/demo/index.html
+++ b/test/demo/index.html
@@ -124,6 +124,17 @@
border: 1px solid #aaa;
padding: 1em;
}
+ .focusgroup {
+ margin-top: 1em;
+ gap: 16px;
+ align-items: center;
+ border: 1px solid #aaa;
+ padding: 0.5em 1em;
+ background: #eee;
+ }
+ .focusgroup-item {
+ padding: 0.5em 1em;
+ }
.toolbar {
margin-top: 1em;
display: flex;
diff --git a/test/demo/index.tsx b/test/demo/index.tsx
index bfaf9a3..883a575 100644
--- a/test/demo/index.tsx
+++ b/test/demo/index.tsx
@@ -381,6 +381,57 @@ const Toolbar: FC = () => {
)
}
+const FocusGroup: FC = () => {
+ return (
+ <>
+
+ Red
+ Yellow
+ Green
+
+ >
+ )
+}
+
+const FocusGroupInline: FC = () => {
+ return (
+ <>
+
+ Mac
+ Windows
+ Linux
+
+ >
+ )
+}
+
+const FocusGroupBlock: FC = () => {
+ return (
+ <>
+
+ >
+ )
+}
+
const App: FC = () => {
let [, setUpdate] = useState({})
let [router, setRouter] = useState('home')
@@ -399,6 +450,9 @@ const App: FC = () => {
/>
+
+
+
>
)
}
diff --git a/test/focus-group.test.ts b/test/focus-group.test.ts
index 1ebd8ed..73666c1 100644
--- a/test/focus-group.test.ts
+++ b/test/focus-group.test.ts
@@ -456,3 +456,103 @@ test('adds toolbar widget', () => {
press(window, 'ArrowRight')
equal(window.document.activeElement, buttons[0])
})
+
+test('adds focusgroup widget', () => {
+ let window = new JSDOM().window
+ startKeyUX(window, [focusGroupKeyUX()])
+ window.document.body.innerHTML =
+ '' +
+ 'Mac' +
+ 'Windows' +
+ 'Linux' +
+ '
'
+ let inlineElements = window.document.querySelectorAll('span')
+ inlineElements[0].focus()
+
+ equal(window.document.activeElement, inlineElements[0])
+
+ press(window, 'ArrowRight')
+ equal(window.document.activeElement, inlineElements[1])
+
+ press(window, 'ArrowLeft')
+ equal(window.document.activeElement, inlineElements[0])
+
+ press(window, 'End')
+ equal(window.document.activeElement, inlineElements[2])
+
+ press(window, 'Home')
+ equal(window.document.activeElement, inlineElements[0])
+
+ press(window, 'ArrowLeft')
+ equal(window.document.activeElement, inlineElements[2])
+
+ press(window, 'ArrowRight')
+ equal(window.document.activeElement, inlineElements[0])
+})
+
+test('adds focusgroup inline widget', () => {
+ let window = new JSDOM().window
+ startKeyUX(window, [focusGroupKeyUX()])
+ window.document.body.innerHTML =
+ '' +
+ 'Mac' +
+ 'Windows' +
+ 'Linux' +
+ '
'
+ let inlineElements = window.document.querySelectorAll('span')
+ inlineElements[0].focus()
+
+ equal(window.document.activeElement, inlineElements[0])
+
+ press(window, 'ArrowRight')
+ equal(window.document.activeElement, inlineElements[1])
+
+ press(window, 'ArrowLeft')
+ equal(window.document.activeElement, inlineElements[0])
+
+ press(window, 'End')
+ equal(window.document.activeElement, inlineElements[2])
+
+ press(window, 'Home')
+ equal(window.document.activeElement, inlineElements[0])
+
+ press(window, 'ArrowLeft')
+ equal(window.document.activeElement, inlineElements[2])
+
+ press(window, 'ArrowRight')
+ equal(window.document.activeElement, inlineElements[0])
+})
+
+test('adds focusgroup block widget', () => {
+ let window = new JSDOM().window
+ startKeyUX(window, [focusGroupKeyUX()])
+ window.document.body.innerHTML =
+ '' +
+ '
Dog
' +
+ '
Cat
' +
+ '
Turtle
' +
+ '
'
+ let blockElements = window.document.querySelectorAll('div:not([focusgroup="block"])');
+ // @ts-ignore
+ blockElements[0].focus()
+
+ equal(window.document.activeElement, blockElements[0])
+
+ press(window, 'ArrowDown')
+ equal(window.document.activeElement, blockElements[1])
+
+ press(window, 'ArrowUp')
+ equal(window.document.activeElement, blockElements[0])
+
+ press(window, 'End')
+ equal(window.document.activeElement, blockElements[2])
+
+ press(window, 'Home')
+ equal(window.document.activeElement, blockElements[0])
+
+ press(window, 'ArrowLeft')
+ equal(window.document.activeElement, blockElements[0])
+
+ press(window, 'ArrowRight')
+ equal(window.document.activeElement, blockElements[0])
+})
From 110bc4c5c0ea021647a499890fe36d7f7658a4cb Mon Sep 17 00:00:00 2001
From: Dmitriy Mezhnin <59breeder@gmail.com>
Date: Tue, 29 Oct 2024 17:27:42 +0100
Subject: [PATCH 2/3] fixed code style
---
focus-group.js | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/focus-group.js b/focus-group.js
index e537a72..a1bf126 100644
--- a/focus-group.js
+++ b/focus-group.js
@@ -48,10 +48,7 @@ function getToolbarItems(group) {
function isHorizontalOrientation(group) {
let fg = group.getAttribute('focusgroup')
- if (fg !== null)
- {
- return !fg.split(' ').includes('block');
- }
+ if (fg !== null) return !fg.split(' ').includes('block');
let ariaOrientation = group.getAttribute('aria-orientation')
if (ariaOrientation === 'vertical') return false
From 7f854eb7fd233a7f1873450f428ca61da2a2ab02 Mon Sep 17 00:00:00 2001
From: Dmitriy Mezhnin <59breeder@gmail.com>
Date: Tue, 29 Oct 2024 19:30:57 +0100
Subject: [PATCH 3/3] ignore tabindex for items
---
focus-group.js | 3 +-
package.json | 2 +-
test/demo/index.html | 8 +++--
test/demo/index.tsx | 18 +++++-----
test/focus-group.test.ts | 72 ++++++++++++++++++++--------------------
5 files changed, 53 insertions(+), 50 deletions(-)
diff --git a/focus-group.js b/focus-group.js
index a1bf126..6e34a83 100644
--- a/focus-group.js
+++ b/focus-group.js
@@ -40,8 +40,7 @@ function getToolbarItems(group) {
item.role === 'button' ||
item.type === 'button' ||
item.role === 'checkbox' ||
- item.type === 'checkbox' ||
- item.hasAttribute('tabindex')
+ item.type === 'checkbox'
)
})
}
diff --git a/package.json b/package.json
index a7be2b4..fe56595 100644
--- a/package.json
+++ b/package.json
@@ -85,7 +85,7 @@
"import": {
"./index.js": "{ startKeyUX, hotkeyKeyUX, pressKeyUX, focusGroupKeyUX, jumpKeyUX, hiddenKeyUX, likelyWithKeyboard, getHotKeyHint, hotkeyOverrides, hotkeyMacCompat }"
},
- "limit": "2248 B"
+ "limit": "2240 B"
}
],
"clean-publish": {
diff --git a/test/demo/index.html b/test/demo/index.html
index b13128a..9c31218 100644
--- a/test/demo/index.html
+++ b/test/demo/index.html
@@ -132,8 +132,12 @@
padding: 0.5em 1em;
background: #eee;
}
- .focusgroup-item {
- padding: 0.5em 1em;
+ .focusgroup button:not(:last-child) {
+ margin-right: 1em;
+ }
+ .focusgroup[focusgroup='block'] button {
+ display: block;
+ margin-bottom: 1em;
}
.toolbar {
margin-top: 1em;
diff --git a/test/demo/index.tsx b/test/demo/index.tsx
index 883a575..582a94f 100644
--- a/test/demo/index.tsx
+++ b/test/demo/index.tsx
@@ -390,9 +390,9 @@ const FocusGroup: FC = () => {
focusgroup={''}
tabIndex={0}
>
- Red
- Yellow
- Green
+
+
+
>
)
@@ -407,9 +407,9 @@ const FocusGroupInline: FC = () => {
focusgroup="inline"
tabIndex={0}
>
- Mac
- Windows
- Linux
+
+
+
>
)
@@ -424,9 +424,9 @@ const FocusGroupBlock: FC = () => {
focusgroup="block"
tabIndex={0}
>
- Dog
- Cat
- Turtle
+
+
+
>
)
diff --git a/test/focus-group.test.ts b/test/focus-group.test.ts
index 73666c1..773cb03 100644
--- a/test/focus-group.test.ts
+++ b/test/focus-group.test.ts
@@ -462,32 +462,32 @@ test('adds focusgroup widget', () => {
startKeyUX(window, [focusGroupKeyUX()])
window.document.body.innerHTML =
'' +
- 'Mac' +
- 'Windows' +
- 'Linux' +
+ '' +
+ '' +
+ '' +
'
'
- let inlineElements = window.document.querySelectorAll('span')
- inlineElements[0].focus()
+ let buttons = window.document.querySelectorAll('button')
+ buttons[0].focus()
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowRight')
- equal(window.document.activeElement, inlineElements[1])
+ equal(window.document.activeElement, buttons[1])
press(window, 'ArrowLeft')
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'End')
- equal(window.document.activeElement, inlineElements[2])
+ equal(window.document.activeElement, buttons[2])
press(window, 'Home')
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowLeft')
- equal(window.document.activeElement, inlineElements[2])
+ equal(window.document.activeElement, buttons[2])
press(window, 'ArrowRight')
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
})
test('adds focusgroup inline widget', () => {
@@ -495,32 +495,32 @@ test('adds focusgroup inline widget', () => {
startKeyUX(window, [focusGroupKeyUX()])
window.document.body.innerHTML =
'' +
- 'Mac' +
- 'Windows' +
- 'Linux' +
+ '' +
+ '' +
+ '' +
'
'
- let inlineElements = window.document.querySelectorAll('span')
- inlineElements[0].focus()
+ let buttons = window.document.querySelectorAll('button')
+ buttons[0].focus()
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowRight')
- equal(window.document.activeElement, inlineElements[1])
+ equal(window.document.activeElement, buttons[1])
press(window, 'ArrowLeft')
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'End')
- equal(window.document.activeElement, inlineElements[2])
+ equal(window.document.activeElement, buttons[2])
press(window, 'Home')
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowLeft')
- equal(window.document.activeElement, inlineElements[2])
+ equal(window.document.activeElement, buttons[2])
press(window, 'ArrowRight')
- equal(window.document.activeElement, inlineElements[0])
+ equal(window.document.activeElement, buttons[0])
})
test('adds focusgroup block widget', () => {
@@ -528,31 +528,31 @@ test('adds focusgroup block widget', () => {
startKeyUX(window, [focusGroupKeyUX()])
window.document.body.innerHTML =
'' +
- '
Dog
' +
- '
Cat
' +
- '
Turtle
' +
+ '
' +
+ '
' +
+ '
' +
'
'
- let blockElements = window.document.querySelectorAll('div:not([focusgroup="block"])');
+ let buttons = window.document.querySelectorAll('button');
// @ts-ignore
- blockElements[0].focus()
+ buttons[0].focus()
- equal(window.document.activeElement, blockElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowDown')
- equal(window.document.activeElement, blockElements[1])
+ equal(window.document.activeElement, buttons[1])
press(window, 'ArrowUp')
- equal(window.document.activeElement, blockElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'End')
- equal(window.document.activeElement, blockElements[2])
+ equal(window.document.activeElement, buttons[2])
press(window, 'Home')
- equal(window.document.activeElement, blockElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowLeft')
- equal(window.document.activeElement, blockElements[0])
+ equal(window.document.activeElement, buttons[0])
press(window, 'ArrowRight')
- equal(window.document.activeElement, blockElements[0])
+ equal(window.document.activeElement, buttons[0])
})