Skip to content

Commit

Permalink
adds focusgroup attribute basic support (#46)
Browse files Browse the repository at this point in the history
* adds focusgroup attribute basic support

* fixed code style

* ignore tabindex for items
  • Loading branch information
mezhnin authored Oct 29, 2024
1 parent 82e3ec0 commit fc209be
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 2 deletions.
8 changes: 7 additions & 1 deletion focus-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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}]`)
}

Expand All @@ -43,6 +46,9 @@ function getToolbarItems(group) {
}

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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
"import": {
"./index.js": "{ startKeyUX, hotkeyKeyUX, pressKeyUX, focusGroupKeyUX, jumpKeyUX, hiddenKeyUX, likelyWithKeyboard, getHotKeyHint, hotkeyOverrides, hotkeyMacCompat }"
},
"limit": "2194 B"
"limit": "2240 B"
}
],
"clean-publish": {
Expand Down
15 changes: 15 additions & 0 deletions test/demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,21 @@
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 button:not(:last-child) {
margin-right: 1em;
}
.focusgroup[focusgroup='block'] button {
display: block;
margin-bottom: 1em;
}
.toolbar {
margin-top: 1em;
display: flex;
Expand Down
54 changes: 54 additions & 0 deletions test/demo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,57 @@ const Toolbar: FC = () => {
)
}

const FocusGroup: FC = () => {
return (
<>
<div
className="focusgroup"
// @ts-expect-error
focusgroup={''}
tabIndex={0}
>
<button role="button" tabIndex={-1}>Red</button>
<button role="button" tabIndex={-1}>Yellow</button>
<button role="button" tabIndex={-1}>Green</button>
</div>
</>
)
}

const FocusGroupInline: FC = () => {
return (
<>
<div
className="focusgroup"
// @ts-expect-error
focusgroup="inline"
tabIndex={0}
>
<button role="button" tabIndex={-1}>Mac</button>
<button role="button" tabIndex={-1}>Windows</button>
<button role="button" tabIndex={-1}>Linux</button>
</div>
</>
)
}

const FocusGroupBlock: FC = () => {
return (
<>
<div
className="focusgroup"
// @ts-expect-error
focusgroup="block"
tabIndex={0}
>
<button role="button" tabIndex={-1}>Dog</button>
<button role="button" tabIndex={-1}>Cat</button>
<button role="button" tabIndex={-1}>Turtle</button>
</div>
</>
)
}

const App: FC = () => {
let [, setUpdate] = useState({})
let [router, setRouter] = useState('home')
Expand All @@ -399,6 +450,9 @@ const App: FC = () => {
/>
<Tabs />
<Toolbar />
<FocusGroup />
<FocusGroupInline />
<FocusGroupBlock />
</>
)
}
Expand Down
100 changes: 100 additions & 0 deletions test/focus-group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
'<div focusgroup tabIndex="-1">' +
'<button role="button" tabindex="-1">Mac</button>' +
'<button role="button" tabindex="-1">Windows</button>' +
'<button role="button" tabindex="-1">Linux</button>' +
'</div>'
let buttons = window.document.querySelectorAll('button')
buttons[0].focus()

equal(window.document.activeElement, buttons[0])

press(window, 'ArrowRight')
equal(window.document.activeElement, buttons[1])

press(window, 'ArrowLeft')
equal(window.document.activeElement, buttons[0])

press(window, 'End')
equal(window.document.activeElement, buttons[2])

press(window, 'Home')
equal(window.document.activeElement, buttons[0])

press(window, 'ArrowLeft')
equal(window.document.activeElement, buttons[2])

press(window, 'ArrowRight')
equal(window.document.activeElement, buttons[0])
})

test('adds focusgroup inline widget', () => {
let window = new JSDOM().window
startKeyUX(window, [focusGroupKeyUX()])
window.document.body.innerHTML =
'<div focusgroup="inline" tabIndex="-1">' +
'<button role="button" tabindex="-1">Mac</button>' +
'<button role="button" tabindex="-1">Windows</button>' +
'<button role="button" tabindex="-1">Linux</button>' +
'</div>'
let buttons = window.document.querySelectorAll('button')
buttons[0].focus()

equal(window.document.activeElement, buttons[0])

press(window, 'ArrowRight')
equal(window.document.activeElement, buttons[1])

press(window, 'ArrowLeft')
equal(window.document.activeElement, buttons[0])

press(window, 'End')
equal(window.document.activeElement, buttons[2])

press(window, 'Home')
equal(window.document.activeElement, buttons[0])

press(window, 'ArrowLeft')
equal(window.document.activeElement, buttons[2])

press(window, 'ArrowRight')
equal(window.document.activeElement, buttons[0])
})

test('adds focusgroup block widget', () => {
let window = new JSDOM().window
startKeyUX(window, [focusGroupKeyUX()])
window.document.body.innerHTML =
'<div focusgroup="block" tabIndex="-1">' +
'<button role="button" tabindex="-1">Dog</button>' +
'<button role="button" tabindex="-1">Cat</button>' +
'<button role="button" tabindex="-1">Turtle</button>' +
'</div>'
let buttons = window.document.querySelectorAll('button');
// @ts-ignore
buttons[0].focus()

equal(window.document.activeElement, buttons[0])

press(window, 'ArrowDown')
equal(window.document.activeElement, buttons[1])

press(window, 'ArrowUp')
equal(window.document.activeElement, buttons[0])

press(window, 'End')
equal(window.document.activeElement, buttons[2])

press(window, 'Home')
equal(window.document.activeElement, buttons[0])

press(window, 'ArrowLeft')
equal(window.document.activeElement, buttons[0])

press(window, 'ArrowRight')
equal(window.document.activeElement, buttons[0])
})

0 comments on commit fc209be

Please # to comment.