{"id":15024825,"url":"https://github.com/pdanpdan/vue-keyboard-trap","last_synced_at":"2025-06-22T19:05:45.186Z","repository":{"id":42027331,"uuid":"482017775","full_name":"pdanpdan/vue-keyboard-trap","owner":"pdanpdan","description":"Vue2 and Vue3 directive and composable for keyboard navigation / TAB trapping - roving movement and trapping inside container","archived":false,"fork":false,"pushed_at":"2024-09-21T17:12:52.000Z","size":3165,"stargazers_count":42,"open_issues_count":0,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-13T11:22:47.625Z","etag":null,"topics":["a11y","accessibility","composable","cycle","directive","focusgroup","grid","gridcell","keyboard","navigation","roving","tab","tabindex","trap","use","vue","vue2","vue3","wai-aria"],"latest_commit_sha":null,"homepage":"https://pdanpdan.github.io/vue-keyboard-trap/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pdanpdan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["pdanpdan"]}},"created_at":"2022-04-15T16:24:28.000Z","updated_at":"2025-04-16T06:38:37.000Z","dependencies_parsed_at":"2024-06-19T11:14:02.604Z","dependency_job_id":"a4040d3b-05ae-401d-bebe-fc653f315007","html_url":"https://github.com/pdanpdan/vue-keyboard-trap","commit_stats":{"total_commits":106,"total_committers":2,"mean_commits":53.0,"dds":0.009433962264150941,"last_synced_commit":"cdbb54ed52e0c653ccd4fd129e2976f39820e110"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdanpdan%2Fvue-keyboard-trap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdanpdan%2Fvue-keyboard-trap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdanpdan%2Fvue-keyboard-trap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdanpdan%2Fvue-keyboard-trap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pdanpdan","download_url":"https://codeload.github.com/pdanpdan/vue-keyboard-trap/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pdanpdan%2Fvue-keyboard-trap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258509785,"owners_count":22712734,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a11y","accessibility","composable","cycle","directive","focusgroup","grid","gridcell","keyboard","navigation","roving","tab","tabindex","trap","use","vue","vue2","vue3","wai-aria"],"created_at":"2024-09-24T20:01:01.728Z","updated_at":"2025-06-22T19:05:40.172Z","avatar_url":"https://github.com/pdanpdan.png","language":"JavaScript","funding_links":["https://github.com/sponsors/pdanpdan"],"categories":[],"sub_categories":[],"readme":"# VueKeyboardTrap (vue-keyboard-trap)\n\n[![License: MIT](https://img.shields.io/github/license/pdanpdan/vue-keyboard-trap?style=for-the-badge)](https://opensource.org/licenses/MIT) \u0026nbsp;\n[![minzip](https://img.shields.io/bundlephobia/minzip/@pdanpdan/vue-keyboard-trap/latest?style=for-the-badge)](https://bundlephobia.com/result?p=@pdanpdan/vue-keyboard-trap) \u0026nbsp;\n![github release](https://img.shields.io/github/v/tag/pdanpdan/vue-keyboard-trap?sort=semver\u0026style=for-the-badge) \u0026nbsp;\n![jsdelivr hits](https://img.shields.io/jsdelivr/gh/hm/pdanpdan/vue-keyboard-trap?style=for-the-badge) \u0026nbsp;\n![npm release](https://img.shields.io/npm/v/@pdanpdan/vue-keyboard-trap?style=for-the-badge) \u0026nbsp;\n![npm downloads](https://img.shields.io/npm/dm/@pdanpdan/vue-keyboard-trap?style=for-the-badge)\n\n## Project description\n\nVue directive and composable for keyboard navigation - roving movement and trapping inside container.\n\nWorks both for Vue3 and Vue2, as a directive (`v-kbd-trap`) or as a composable (`useKeyboardTrap`).\n\n[Demo codepen](https://codepen.io/pdanpdan/pen/MWrzLdM)\n\n[Docs and examples](https://pdanpdan.github.io/vue-keyboard-trap/)\n\n[Source code, Issues, Discussions](https://github.com/pdanpdan/vue-keyboard-trap)\n\n## Install\n\n```bash\npnpm add @pdanpdan/vue-keyboard-trap\n```\nor\n```bash\nyarn add @pdanpdan/vue-keyboard-trap\n```\nor\n```bash\nnpm install @pdanpdan/vue-keyboard-trap\n```\n\n## Playground\n\n[Demo codepen](https://codepen.io/pdanpdan/pen/MWrzLdM)\n\n## Usage\n\n### Usage as ESM\n\n#### As composable (both Vue3 and Vue2)\n\n```html\n\u003cscript setup\u003e\n  import { ref } from 'vue';\n  import { useKeyboardTrapFactory } from '@pdanpdan/vue-keyboard-trap';\n\n  // you can do this in another file and import the configured `useKeyboardTrap`\n  const useKeyboardTrap = useKeyboardTrapFactory({\n    // ...options if required\n  });\n\n  const elRef = ref(null);\n  useKeyboardTrap(\n    // element (reactive)\n    elRef,\n    // modifiers (optional, reactive, default all modifiers are false)\n    {\n      roving: true,\n    },\n    // active (optional, reactive, default true)\n    true\n  );\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cdiv ref=\"elRef\"\u003e\n    ...\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\n#### As plugin on Vue3 - directive\n\n```javascript\nimport { createApp } from 'vue';\nimport { VueKeyboardTrapDirectivePlugin } from '@pdanpdan/vue-keyboard-trap';\nimport App from './App.vue';\n\nconst app = createApp(App);\n\napp.use(VueKeyboardTrapDirectivePlugin, {\n  // ...options if required\n});\n\napp.mount('#app');\n```\n\n#### As plugin on Vue2 - directive\n\n```javascript\nimport Vue from 'vue';\nimport { VueKeyboardTrapDirectivePlugin } from '@pdanpdan/vue-keyboard-trap';\nimport App from './App.vue';\n\nVue.use(VueKeyboardTrapDirectivePlugin, {\n  // ...options if required\n});\n\nnew Vue({\n  el: '#app',\n});\n```\n\n#### Included in specific components (Vue3 script setup) - directive\n\n```html\n\u003cscript setup\u003e\n  import { VueKeyboardTrapDirectiveFactory } from '@pdanpdan/vue-keyboard-trap';\n\n  const vKbdTrap = VueKeyboardTrapDirectiveFactory({\n    // ...options if required\n  }).directive;\n\u003c/script\u003e\n```\n\n#### Included in specific components (Vue3 script) - directive\n\n```html\n\u003cscript\u003e\n  import { defineComponent } from 'vue';\n  import { VueKeyboardTrapDirectiveFactory } from '@pdanpdan/vue-keyboard-trap';\n\n  const KbdTrap = VueKeyboardTrapDirectiveFactory({\n    // ...options if required\n  }).directive;\n\n  export default defineComponent({\n    directives: {\n      KbdTrap,\n    },\n  });\n\u003c/script\u003e\n```\n\n#### Included in specific components (Vue2) - directive\n\n```html\n\u003cscript\u003e\n  import { VueKeyboardTrapDirectiveFactory } from '@pdanpdan/vue-keyboard-trap';\n\n  const KbdTrap = VueKeyboardTrapDirectiveFactory({\n    // ...options if required\n  }).directive;\n\n  export default {\n    directives: {\n      KbdTrap,\n    },\n  };\n\u003c/script\u003e\n```\n\n#### User hint styles (cosmetic)\n\nThe directive does not require any CSS styles to work, but for cosmetic purposes (as user hints) some example styles are provided in `dist/styles/index.sass`.\n\nin Javascript\n```javascript\nimport '@pdanpdan/vue-keyboard-trap/styles';\n```\n\nor in SASS\n```sass\n@import '@pdanpdan/vue-keyboard-trap/styles'\n```\n\nor (if the `/styles` export is not used by your bundler)\n\nin Javascript\n```javascript\nimport '@pdanpdan/vue-keyboard-trap/dist/styles/index.sass';\n```\n\nor in SASS\n```sass\n@import '@pdanpdan/vue-keyboard-trap/dist/styles/index.sass'\n```\n\n### Usage as UMD\n\nLoad the javascript from [https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/index.umd.js](https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/index.umd.js).\n\nIt will expose a global object `VueKeyboardTrap` with `VueKeyboardTrapDirectivePlugin` and `VueKeyboardTrapDirectiveFactory` keys.\n\nIn order to work it requires that `VueDemi` is already loaded on the page. You can do it like this:\n\n```html\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/vue-demi/lib/index.iife.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/index.umd.js\"\u003e\u003c/script\u003e\n\n```\n\n#### As composable (both Vue3 and Vue2)\n\n```javascript\nconst { ref } = Vue;\n\nconst { useKeyboardTrapFactory } = VueKeyboardTrap;\nconst useKeyboardTrap = useKeyboardTrapFactory({\n  // ...options if required\n});\n\nconst elRef = ref(null);\nuseKeyboardTrap(\n  // element (reactive)\n  elRef,\n  // modifiers (optional, reactive, default all modifiers are false)\n  {\n    roving: true,\n  },\n  // active (optional, reactive, default true)\n  true\n);\n```\n\n#### As plugin on Vue3 - directive\n\n```javascript\nconst { createApp } = Vue;\nconst { VueKeyboardTrapDirectivePlugin } = VueKeyboardTrap;\n\nconst app = createApp({});\n\napp.use(VueKeyboardTrapDirectivePlugin, {\n  // ...options if required\n});\n\napp.mount('#app');\n```\n\n#### As plugin on Vue2 - directive\n\n```javascript\nconst { VueKeyboardTrapDirectivePlugin } = VueKeyboardTrap;\n\nVue.use(VueKeyboardTrapDirectivePlugin, {\n  // ...options if required\n});\n\nnew Vue({\n  el: '#app',\n});\n```\n\n#### As directive on Vue3 - directive\n\n```javascript\nconst { createApp } = Vue;\nconst { VueKeyboardTrapDirectiveFactory } = VueKeyboardTrap;\n\nconst app = createApp({});\n\nconst { name, directive } = VueKeyboardTrapDirectiveFactory({\n  // ...options if required\n});\n\napp.directive(name, directive);\n\napp.mount('#app');\n```\n\n#### As directive on Vue2 - directive\n\n```javascript\nconst { VueKeyboardTrapDirectiveFactory } = VueKeyboardTrap;\n\nconst { name, directive } = VueKeyboardTrapDirectiveFactory({\n  // ...options if required\n});\n\nVue.directive(name, directive);\n```\n\n#### User hint styles (cosmetic)\n\nIf you want you can access the CSS cosmetic style (user hints) from [https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/styles/index.css](https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/styles/index.css).\n\n### Directive configuration options\n\n| Option | Description | Default |\n|--------|-------------|:-------:|\n| `name` | snake-case name of the directive (without `v-` prefix) | `kbd-trap` |\n| `datasetName` | camelCase name of the `data-attribute` to be set on element when trap is enabled | `v${PascalCase from name}` |\n| `focusableSelector` | CSS selector for focusable elements | [see here](#default-focusableselector) |\n| `rovingSkipSelector` | CSS selector for elements that should not respond to roving key navigation (input, textarea, ...) | [see here](#default-rovingskipselector) |\n| `gridSkipSelector` | CSS selector that will be applied in .roving.grid mode to exclude elements - must be a series of `:not()` selectors | [see here](#default-gridskipselector) |\n| `autofocusSelector` | CSS selector for the elements that should be autofocused | [see here](#default-autofocusselector) |\n| `trapTabIndex` | tabIndex value to be used when trap element has a tabIndex of -1 and has no `tabindex` attribute | -9999 |\n\n#### Default `focusableSelector`:\n\n```css\n:focus,\na[href]:not([tabindex^=\"-\"]),\narea[href]:not([tabindex^=\"-\"]),\nvideo[controls]:not([tabindex^=\"-\"]),\naudio[controls]:not([tabindex^=\"-\"]),\niframe:not([tabindex^=\"-\"]),\n[tabindex]:not(slot):not([tabindex^=\"-\"]),\n[contenteditable]:not([contenteditable=\"false\"]):not([tabindex^=\"-\"]),\ndetails \u003e summary:first-of-type:not([tabindex^=\"-\"]),\ninput:not([type=\"hidden\"]):not(fieldset[disabled] input):not([disabled]):not([tabindex^=\"-\"]),\nselect:not(fieldset[disabled] input):not([disabled]):not([tabindex^=\"-\"]),\ntextarea:not(fieldset[disabled] input):not([disabled]):not([tabindex^=\"-\"]),\nbutton:not(fieldset[disabled] input):not([disabled]):not([tabindex^=\"-\"]),\nfieldset[disabled]:not(fieldset[disabled] fieldset) \u003e legend input:not([type=\"hidden\"]):not([disabled]):not([tabindex^=\"-\"]),\nfieldset[disabled]:not(fieldset[disabled] fieldset) \u003e legend select:not([disabled]):not([tabindex^=\"-\"]),\nfieldset[disabled]:not(fieldset[disabled] fieldset) \u003e legend textarea:not([disabled]):not([tabindex^=\"-\"]),\nfieldset[disabled]:not(fieldset[disabled] fieldset) \u003e legend button:not([disabled]):not([tabindex^=\"-\"]),\n[class*=\"focusable\"]:not([disabled]):not([tabindex^=\"-\"])\n```\n\nBy default `a` tags without href are not focusable - add a `tabindex=\"0\"` attribute on them to make them focusable.\nThis can be done for all other elements if you want them to be focusable.\n\n#### Default `rovingSkipSelector`:\n\n```css\ninput:not([disabled]):not([type=\"button\"]):not([type=\"checkbox\"]):not([type=\"file\"]):not([type=\"image\"]):not([type=\"radio\"]):not([type=\"reset\"]):not([type=\"submit\"]),\nselect:not([disabled]),\nselect:not([disabled]) *,\ntextarea:not([disabled]),\n[contenteditable]:not([contenteditable=\"false\"]),\n[contenteditable]:not([contenteditable=\"false\"]) *\n```\n\n#### Default `gridSkipSelector`:\n\n```css\n:not([disabled]),\n:not([tabindex^=\"-\"])\n```\n\n#### Default `autofocusSelector`:\n\n```css\n[autofocus]:not([disabled]):not([autofocus=\"false\"]),\n[data-autofocus]:not([disabled]):not([data-autofocus=\"false\"])\n```\n\n### Dynamic enable/disable\n\nUse the value of the directive (boolean) to enable/disable it.\n\n```html\n\u003cdiv v-kbd-trap=\"directiveEnabled\"\u003e\n```\n\nThe modifiers are reactive so if you use render functions you can dynamically change the behaviour.\n\n### Directive modifiers\n\n| Modifier | Description |\n|----------|-------------|\n| `.autofocus` | autofocuses the first element that matches [autofocusSelector](#default-autofocusselector) or (if no such element is found) the first focusable child element **when the directive is mounted or enabled** (**only if it not covered by another element**) |\n| `.roving` or `.roving.vertical.horizontal` | allow roving navigation (`Home`, `End`, `ArrowKeys`) |\n| `.roving.vertical` | allow roving navigation (`Home`, `End`, `ArrowUp`, `ArrowDown`) |\n| `.roving.horizontal` | allow roving navigation (`Home`, `End`, `ArrowLeft`, `ArrowRight`) |\n| `.roving.grid` | allow roving navigation (`Home`, `End`, `ArrowKeys`) using dataset attrs on elements `[data-${camelCase from datasetName}-(row/col)]`; `[data-${camelCase from datasetName}-(row/col)~=\"*\"]` is a catchall |\n| `.roving` used on an element with `[role=\"grid\"]` | allow roving navigation (`Home`, `End`, `ArrowKeys`) using role attrs on elements `[role=\"row/gridcell\"]` |\n| `.roving.tabinside` | `Tab` key navigates to next/prev element inside trap (by default `Tab` key navigates to next/prev element outside trap in roving mode) |\n| `.escrefocus` | refocus element that was in focus before activating the trap on `Esc` |\n| `.escexits` | refocus a parent trap on `Esc` (has priority over `.escrefocus`) |\n| `.indexorder` used without `.grid` modifier and on elements without `[role=\"grid\"]` | force usage of order in `tabindex` (`tabindex` in ascending order and then DOM order) |\n\n## Keyboard navigation\n\n- `TAB` / `SHIFT`+`TAB` key\n  - moves to next / previous focusable element inside the trap group (moves from last one to first one or from first one to last one when no more focusable elements are available in the group)\n  - if `.roving` modifier is used moves to next / previous trap group or focusable element outside the current trap group\n  - if `.roving.tabinside` modifiers are used then move inside the trap group\n  - if `.indexorder` modifier is used without `.grid` and on elements without `[role=\"grid\"]` - the order of tabindex will be used\n- `ESC` key\n  - disables / enables the current tab group\n  - if `.escexits` modifier is used then refocus the last active focusable element in a parent trap group\n  - if `.escrefocus` modifier is used then refocus the last focusable element that was active before the current trap group got focus\n  - if `.escexits` or `.escrefocus` are used then press `SHIFT + ESC` to disable / enable the current tab group\n- `HOME` / `END` when `.roving` modifier is used\n  - move to first / last focusable element in the current trap group\n- `ARROW_KEYS` when `.roving` modifier is used (`.roving.horizontal.vertical` is the same as `.roving`)\n  - if only `.horizontal` modifier is used then only `ARROW_LEFT` / `ARROW_RIGHT` keys can be used\n  - if only `.vertical` modifier is used then only `ARROW_UP` / `ARROW_DOWN` keys can be used\n  - `ARROW_LEFT` / `ARROW_UP` move to the previous focusable element inside the trap group\n  - `ARROW_RIGHT` / `ARROW_DOWN` move to the next focusable element inside the trap group\n  - if `.indexorder` modifier is used without `.grid` and on elements without `[role=\"grid\"]` - the order of tabindex will be used\n- `ARROW_KEYS` when `.roving.grid` modifiers are used or `.roving` modifier on a trap element with [role=\"grid\"]\n  - move in the grid inside the current trap group\n\n### Keyboard navigation inside `.roving.grid` trap groups\n\nIn order to specify the navigation pattern you must use 2 dataset attributes on the focusable elements inside the `.roving` trap group:\n\n- `data-v-kbd-trap-row` specifies the numeric identifier of the row the element belongs to (numbers need not be consecutive, but their natural order determines the navigation order)\n- `data-v-kbd-trap-col` specifies the numeric identifier of the column the element belongs to (numbers need not be consecutive, but their natural order determines the navigation order)\n\nAny or both attributes can have a value of `*` that means that it is an alement that can be focused from elements having any coresponding (row or col) attribute.\n\n#### Navigation rules\n\n- the first focusable element on the row / col (based on direction of movement) is focused\n- an element with `*` for row or col is considered to belong to any row / col\n\n### Keyboard navigation inside `.roving` trap groups with `[role=\"grid\"]`\n\nIn order to specify the navigation pattern you must use role attributes `[role=\"row\"]` and `[role=\"gridcell\"]`.\n\nAll focusable element must have `[role=\"gridcell\"]` and must be inside `[role=\"row\"]` elements inside `[role=\"grid\"]` trap element.\n\nThe `gridcell`s will be considered inline-start aligned in every row.\n\n#### Navigation rules\n\n- the first focusable element on the row / col (based on direction of movement) is focused\n\n### RTL / LTR\n\nThe directive checks the closest parent DOM Element of the active element that has a `[dir=\"rtl\"]` or `[dir=\"ltr`]` attribute.\n\nIf the direction is RTL the `ARROW_LEFT` and `ARROW_RIGHT` keys move in reverse (according to document order of the focusable elements) but consistent to the way the elements are ordered on screen.\n\n## CSS (visual hints for users)\n\nThe directive does not require any styles, but it might help the users to have visual hints for navigation.\n\nA default style is provided as SASS in `dist/styles/index.sass` (can be imported as `import '@pdapdan/vue-keyboard-trap/styles'`, as `import '@pdapdan/vue-keyboard-trap/dist/styles/index.sass'` (if the bundler does not use the `/styles` export) or included from [https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/styles/index.sass](https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/styles/index.sass)).\n\nThe default style is also provided as CSS in `dist/styles/index.css` (can be imported as `import '@pdapdan/vue-keyboard-trap/dist/styles/index.css'` or included from [https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/styles/index.css](https://cdn.jsdelivr.net/gh/pdanpdan/vue-keyboard-trap/dist/styles/index.css)).\n\nThere are some CSS variables that can be used to customize the aspect of the hints:\n\n| Variable | Role | Default |\n|----------|------|:-------:|\n| `--color-v-kbd-trap-enabled` | the text color when directive is enabled | `#c33` \u003cspan style=\"color: #c33\"\u003e■\u003c/span\u003e |\n| `--color-v-kbd-trap-disabled` | the text color when directive is disabled | `#999` \u003cspan style=\"color: #999\"\u003e■\u003c/span\u003e |\n| `--color-v-kbd-trap-background` | the background color of the hint area | `#eeee` \u003cspan style=\"color: #eeee\"\u003e■\u003c/span\u003e |\n| `--text-v-kbd-trap-separator` | separator between elements | `/` |\n| `--text-v-kbd-trap-enabled` | indicator for enabled but not active trap | `Trap` |\n| `--text-v-kbd-trap-esc` | indicator for `Esc` key active | `Esc` |\n| `--text-v-kbd-trap-esc-refocus` | indicator for `Esc` key active when it refocuses | `Esc\\2949` / `Esc⥉` |\n| `--text-v-kbd-trap-esc-exits` | indicator for `Esc` key active when it exits trap | `Esc\\2923` / `Esc⤣` |\n| `--text-v-kbd-trap-tab` | indicator for `Tab` key active inside trap | `Tab` |\n| `--text-v-kbd-trap-tab-exits` | indicator for `Tab` key active when it exits trap | `Tab\\21C5` / `Tab⇅` |\n| `--text-v-kbd-trap-grid` | indicator for grid mode active | `\\229E` / `⊞` |\n| `--text-v-kbd-trap-arrows-all` | indicator for move keys active in roving mode | `\\2962\\2963\\2965\\2964` / `⥢⥣⥥⥤` |\n| `--text-v-kbd-trap-arrows-horizontal` | indicator for move keys active in roving mode horizontal | `\\2962\\2964` / `⥢⥤` |\n| `--text-v-kbd-trap-arrows-vertical` | indicator for move keys active in roving mode vertical | `\\2963\\2965` / `⥣⥥` |\n\nIn the default style the hint is positioned on the top-right corner of the trap group.\n\n\u003c\u003c\u003c @/../src/public/styles/index.sass\n\n## Development\n\n### Install the dependencies\n\n```bash\npnpm i\n```\n\n### Start development mode (hot-code reloading, error reporting, etc.)\n\n```bash\npnpm dev\n```\n\n### Lint the files\n\n```bash\npnpm lint\n```\n\n### Build for production\n\n```bash\npnpm build\n```\n\n## Source code, issues, bug reports, feature requests\n\n[Vue Keyboard Trap (vue-keyboard-trap)](https://github.com/pdanpdan/vue-keyboard-trap)\n\n## Author\n\n* Name: Dan Popescu (PDan)\n* Email: [pdan.popescu@gmail.com](mailto:pdan.popescu@gmail.com)\n* Website: https://github.com/pdanpdan/\n* Github: [@pdanpdan](https://github.com/pdanpdan)\n\n## License\n\nCopyright © 2022-present [Dan Popescu](https://github.com/pdanpdan).\n\nThis application is distributed under [![License: MIT](https://img.shields.io/github/license/pdanpdan/vue-keyboard-trap?style=for-the-badge)](https://opensource.org/licenses/MIT), see LICENSE for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpdanpdan%2Fvue-keyboard-trap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpdanpdan%2Fvue-keyboard-trap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpdanpdan%2Fvue-keyboard-trap/lists"}