ai/keyux
ai/keyux là dự án mã nguồn mở trên GitHub, viết chủ yếu bằng TypeScript, với 542 sao. JS library to improve keyboard UI of web apps
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
Snapshot
Cộng tác viên hàng đầu
Xem cộng tác viên hàng đầu
KeyUX
JS library to improve the keyboard UI of web apps. It is designed not only for a11y, but also to create professions tools where users prefer to use the keyboard.
- Add hotkeys with
aria-keyshortcuts. - Show a button’s
:activestate when a hotkey is pressed. - Enable navigation with keyboard arrows in
role="menu"lists. - Jump to the next section according to
aria-controlsand back with Esc. - Show and hide submenus of
role="menu". - Allow users to override hotkeys.
- 2 KB (minified and brotlied). No dependencies.
- Vanilla JS and works with any framework including React, Vue, Svelte.
export const Button = ({ hotkey, children }) => {
return (
<button aria-keyshortcuts={hotkey}>
{children}
{likelyWithKeyboard(window) && <kbd>{getHotKeyHint(window, hotkey)}</kbd>}
</button>
)
}
See demo page and example:
https://github.com/user-attachments/assets/bcd78271-cf76-45a3-8beb-4f3cea69c143
- Install
- Hotkeys
- Hotkeys Hint
- Pressed State
- Hotkeys Override
- Hotkeys for List
- Meta instead of Ctrl on Mac
- Focus Groups
focusgroupattribute- Menu
- Listbox
- Tablist
- Toolbar
- Focus Jumps
- Nested Menu
KeyUX is built by Evil Martians, an American design and engineering consultancy for developer tools, AI, and cybersecurity startups.
Install
npm install keyux
Then add the startKeyUX call with the necessary features to the main JS file.
import {
hiddenKeyUX,
hotkeyKeyUX,
hotkeyOverrides,
jumpKeyUX,
focusGroupKeyUX,
focusGroupPolyfill,
pressKeyUX,
startKeyUX
} from 'keyux'
const overrides = hotkeyOverrides({})
startKeyUX(window, [
hotkeyKeyUX([overrides]),
focusGroupKeyUX(),
focusGroupPolyfill(),
pressKeyUX('is-pressed'),
jumpKeyUX(),
hiddenKeyUX()
])
Hotkeys
When the user presses a hotkey, KeyUX will click on the button or link
with the same hotkey in aria-keyshortcuts.
For instance, KeyUX will click on this button if user press Alt+B or ⌥ B.
<button aria-keyshortcuts="alt+b">Bold</button>
You can use hotkey to move focus to text input or textarea:
<input type="search" aria-keyshortcuts="s" placeholder="S" />
The hotkey pattern should contain modifiers like meta+ctrl+alt+shift+b
in this exact order.
To enable this feature, call hotkeyKeyUX:
import { hotkeyKeyUX, startKeyUX } from 'keyux'
startKeyUX(window, [hotkeyKeyUX()])
Hotkeys inside block with inert or aria-hidden attribute will be ignored.
You can use it, to disable page’s hotkeys when dialog is shown:
<main inert>
<button aria-keyshortcuts="h">Help</button>
<!-- Will be ignored -->
</main>
<dialog>…</dialog>
Hotkeys Hint
You can render the hotkey hint from the aria-keyshortcuts pattern in
a prettier way:
import { likelyWithKeyboard, getHotKeyHint } from 'keyux'
export const Button = ({ hokey, children }) => {
return (
<button aria-keyshortcuts={hotkey}>
{children}
{likelyWithKeyboard(window) && <kbd>{getHotKeyHint(window, hotkey)}</kbd>}
</button>
)
}
likelyWithKeyboard() returns false on mobile devices where user is unlikely
to be able to use hotkeys (but it is still possible by connecting an
external keyboard).
getHotKeyHint() replaces modifiers for Mac and makes text prettier.
For instance, for alt+b it will return Alt + B on Windows/Linux or ⌥ B
on Mac.
If you’re using overrides, pass the same override config both to hotkeyKeyUX()
and getHotKeyHint() for accurate hints:
import { getHotKeyHint, hotkeyOverrides, hotkeyKeyUX, startKeyUX } from 'keyux'
let config = { 'alt+b': 'b' }
startKeyUX(window, [
hotkeyKeyUX([hotkeyOverrides(config)]) // Override B to Alt + B
])
getHotKeyHint(window, 'b', [hotkeyOverrides(config)]) // Alt + B
One-letter hotkeys (like B) will be ignored if user’s focus is inside text inputs or focus groups. This is why for general hotkeys we recommend add some modifier like Alt+B.
Pressed State
KeyUX can set class to show pressed state for a button when user presses a hotkey. It will make the UI more responsive.
import { hotkeyKeyUX, startKeyUX, pressKeyUX } from 'keyux'
startKeyUX(window, [pressKeyUX('is-pressed'), hotkeyKeyUX()])
button {
&:active,
&.is-pressed {
transform: scale(0.95);
}
}
overriding
You can use
postcss-pseudo-classes
to automatically add class for every :active state in your CSS.
Hotkeys Override
Many users want to override hotkeys because your hotkeys can conflict with their browser’s extensions, system, or screen reader.
KeyUX allows overriding hotkeys using tranforms. Use the hotkeyOverrides()
tranformer with hotkeyKeyUX() and getHotKeyHint().
You will need to create some UI for users to fill this object like:
const overrides = {
'alt+b': 'b' // Override B to Alt + B
}
Then KeyUX will click on aria-keyshortcuts="b" when
Alt+B is pressed, and
getHotKeyHint(window, 'b', [hotkeyOverrides(overrides)]) will return
Alt + B/⌥ B.
Hotkeys for List
Websites may have hotkeys for each list element. For instance, for “Add to card” button in shopping list.
To implement it:
- Hide list item’s buttons by
data-keyux-ignore-hotkeysfrom global search. - Make list item focusable by
tabindex="0". When item has a focus, KeyUX ignoresdata-keyux-ignore-hotkeys.
<li data-keyux-ignore-hotkeys tabIndex={0}>
{product.title}
<button aria-keyshortcuts="a" tabIndex={-1}>
Add to card
</button>
</li>
If you have common panel with actions for focused item, you can use
data-keyux-hotkeys with ID of item’s panel.
<ul>
{products.map(product => {
return <li data-keyux-hotkeys="panel" tabIndex={0} key={product.id}>
{product.title}
</li>
})}
</ul>
<div id="panel" data-keyux-ignore-hotkeys>
<button aria-keyshortcuts="a" tabIndex={-1}>Add to card</button>
</div>
Meta instead of Ctrl on Mac
It’s common to use the Meta (or ⌘) modifier for hotkeys on Mac, while Windows and Linux usually favor the Ctrl key. To provide familiar experience on all platforms, enable the Mac compatibility transform:
import { hotkeyMacCompat, hotkeyKeyUX, startKeyUX, getHotKeyHint } from 'keyux'
const mac = hotkeyMacCompat()
startKeyUX(window, [hotkeyKeyUX([mac])])
getHotKeyHint(window, 'ctrl+b', [mac]) // Ctrl+B on Windows/Linux and ⌘+b on Mac
Hotkeys pressed with the Meta modifier will work as if the Ctrl modifier was pressed.
Focus Groups
Using only Tab for navigation is not very useful. User may need to press it too many times to get to their button (also non-screen-reader users don’t have quick navigation).
focusgroup attribute
Key UX has limited polyfill for focusgroup attribute to mark groups where user will move :focus
by arrows.
<div focusgroup>
<button type="button">Copy</button>
<button type="button">Paste</button>
<button type="button">Cut</button>
</div>
Key UX supports (you can combine these features):
focusgroup="block"for vertical arrows.focusgroup="no-memory"to not restore last focus position.focusgroup="wrap"enables cyclic focus movement within a group.focusgroup="none"excludes element from arrow key navigation.
Key UX doesn’t support grid feature.
To enable this feature, call focusGroupPolyfill.
import { focusGroupPolyfill } from 'keyux'
startKeyUX(window, [focusGroupPolyfill()])
Menu
To reduce Tab-list you can group website’s menu
into role="menu"
with arrow navigation.
<nav role="menu">
<a href="/" role="menuitem">Home</a>
<a href="/catalog" role="menuitem">Catalog</a>
<a href="/contacts" role="menuitem">Contacts</a>
</nav>
Users will use Tab to get inside the menu, and will use either arrows or Home, End or an item name to navigate inside. User can search the menu item by typing the first characters of the item text.
To enable this feature, call focusGroupKeyUX.
import { focusGroupKeyUX } from 'keyux'
startKeyUX(window, [focusGroupKeyUX()])
Listbox
The role="listbox"
is used for lists from which a user may select one or
more items which are static and, unlike HTML <select> elements,
may contain images.
<ul role="listbox">
<li tabindex="0" role="option">Pizza</li>
<li tabindex="0" role="option">Sushi</li>
<li tabindex="0" role="option">Ramen</li>
</ul>
Users will use Tab to get inside the listbox, and will use either arrows or Home, End or an item name to navigate inside.
To enable this feature, call focusGroupKeyUX.
import { focusGroupKeyUX } from 'keyux'
startKeyUX(window, [focusGroupKeyUX()])
Tablist
The role="tablist"
identifies the element that serves as the container for a set of tabs.
The tab content should be marked by [role="tabpanel'].
<div role="tablist">
<button role="tab">Home</button>
<button role="tab">About</button>
<button role="tab">Contact</button>
</div>
Users will use Tab to get inside the tablist, and will use either arrows or Home, End.
To enable this feature, call focusGroupKeyUX.
import { focusGroupKeyUX } from 'keyux'
startKeyUX(window, [focusGroupKeyUX()])
Toolbar
The role="toolbar"
defines the containing element as a collection of commonly used function buttons
or controls represented in a compact visual forms. Buttons inside the toolbar
must have type="button" attribute because the default one is submit.
<div role="toolbar">
<div>
<button type="button">Copy</button>
<button type="button">Paste</button>
<button type="button">Cut</button>
</div>
<div>
<input type="checkbox" />
</div>
</div>
Users will use Tab to get inside the tablist, and will use either arrows or Home, End.
To enable this feature, call focusGroupKeyUX.
import { focusGroupKeyUX } from 'keyux'
startKeyUX(window, [focusGroupKeyUX()])
Focus Jumps
After finishing in one section, you can move user’s focus to the next step to save time. For example, you can move the cursor to the page after the user selects it from the menu. Or, you can move the focus to the item’s form after the user selects an item in the list.
You can control where the focus moves next with aria-controls.
<div role="menu">
{products.map(({ id, name }) =>
<button role="menuitem" aria-controls="product_form">{name}</button>
)}
</div>
<div id="product_form">
…
</div>
On Esc the focus will jump back.
You can add aria-controls to <input> to make the focus jump
on Enter.
<input type="search" aria-controls="search_results" />
To enable this feature, call jumpKeyUX.
import { focusGroupKeyUX, jumpKeyUX } from 'keyux'
startKeyUX(window, [focusGroupKeyUX(), jumpKeyUX()])
Nested Menu
You can make nested menus with KeyUX with aria-controls
and aria-hidden="true".
<button aria-controls="edit" aria-haspopup="menu">Edit</button>
<div id="edit" hidden aria-hidden="true" role="menu">
<button role="menuitem">Undo</button>
<button role="menuitem" aria-controls="find" aria-haspopup="menu">
Find
</button>
</div>
<div id="find" hidden aria-hidden="true" role="menu">
<button role="menuitem">Find…</button>
<button role="menuitem">Replace…</button>
</div>
You can make the nested menu visible by diabling hidden, but you will
have to set tabindex="-1" manually.
To enable this feature, call hiddenKeyUX.
import { focusGroupKeyUX, jumpKeyUX, hiddenKeyUX } from 'keyux'
startKeyUX(window, [focusGroupKeyUX(), jumpKeyUX(), hiddenKeyUX()])
Repo liên quan
Master programming by recreating your favorite technologies from scratch.
A curated meta-list of curated lists organized by technology domain. The repository acts as a directory pointing to hundreds of specialized awesome lists covering programming languages, platforms, frameworks, and tooling. All content is community-contributed under the CC0 public domain dedication.
Public APIs is a community-curated GitHub repository listing free, publicly accessible APIs across a wide range of categories, with auth type, HTTPS, and CORS noted for each entry. It's a browsable reference, not a library to install.
freeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.
Trả lời nhanh
ai/keyux có bao nhiêu sao?
ai/keyux có 542 sao GitHub — tải lại trang để xem số mới nhất, hoặc xem trực tiếp github.com/ai/keyux. TopGit phản chiếu số sao của GitHub nhưng không cam kết đến từng phút.
ai/keyux có phải mã nguồn mở không?
Có — ai/keyux phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/ai/keyux.
ai/keyux có tag gì không?
Bản đồng bộ chưa ghi nhận topic GitHub nào cho ai/keyux. GitHub topics hiển thị ở thanh bên phải trang repo — đó là nơi đáng kiểm tra nhất.
ai/keyux có trang demo không?
Dự án có trang chủ ở https://ai.github.io/keyux/. Tab "Readme" ở trang này thường có ảnh chụp và hướng dẫn bắt đầu nhanh.
ai/keyux còn đang phát triển không?
Commit gần nhất trên ai/keyux là 18 ngày trước (theo timestamp GitHub). Repo có 29 fork — một chỉ báo về mức độ quan tâm của cộng đồng.
Đọc thêm về ai/keyux ở đâu?
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/ai/keyux là nguồn chính thức.
Đọc đầy đủ README ở tab phía trên.