Skip to content

Commit

Permalink
backport features from react-focus-lock. fixes #1, #3, #4
Browse files Browse the repository at this point in the history
  • Loading branch information
theKashey committed May 8, 2018
1 parent 7d34c4e commit 1c6401b
Show file tree
Hide file tree
Showing 8 changed files with 4,483 additions and 96 deletions.
2 changes: 2 additions & 0 deletions .storybook/addons.js
@@ -0,0 +1,2 @@
import '@storybook/addon-actions/register'
import '@storybook/addon-links/register'
7 changes: 7 additions & 0 deletions .storybook/config.js
@@ -0,0 +1,7 @@
import { configure } from '@storybook/vue'

function loadStories() {
require('../src/stories')
}

configure(loadStories, module)
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -19,7 +19,7 @@ Just wrap something with focus lock, and focus will be `moved inside` on mount.
```
Demo - https://codesandbox.io/s/l5qlpxqvnq

#WHY?
# WHY?
From [MDN Article about accessible dialogs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_dialog_role):
- The dialog must be properly labeled
- Keyboard __focus must be managed__ correctly
Expand Down
10 changes: 8 additions & 2 deletions package.json
Expand Up @@ -7,7 +7,9 @@
"build": "rm -rf ./dist && webpack --colors --hide-modules",
"prepublish": "npm run build",
"lint": "eslint src tests",
"lint:fix": "eslint src tests --fix"
"lint:fix": "eslint src tests --fix",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"repository": {
"type": "git",
Expand All @@ -27,6 +29,9 @@
},
"homepage": "https://github.com/theKashey/vue-focus-lock#readme",
"devDependencies": {
"@storybook/addon-actions": "^3.4.3",
"@storybook/addon-links": "^3.4.3",
"@storybook/vue": "^3.4.3",
"babel-core": "^6.24.0",
"babel-eslint": "7.2.3",
"babel-loader": "^6.4.1",
Expand All @@ -38,6 +43,7 @@
"css-loader": "^0.23.1",
"eslint": "4.6.0",
"eslint-plugin-vue": "^3.12.0",
"storybook": "^1.0.0",
"style-loader": "^0.15.0",
"vue": "^2.0.0",
"vue-html-loader": "^1.2.4",
Expand All @@ -50,6 +56,6 @@
"vue": "^2.0.0"
},
"dependencies": {
"focus-lock": "^0.2.4"
"focus-lock": "^0.3.0"
}
}
36 changes: 26 additions & 10 deletions src/Lock.vue
@@ -1,6 +1,13 @@
<template>
<div @focusout="onBlur">
<slot>It is a Trap</slot>
<div>
<div :tabIndex="disabled ? -1 : 0" :style="hidden"></div>
<div :tabIndex="disabled ? -1 : 1" :style="hidden"></div>

<div @focusout="onBlur" data-lock>
<slot>It is a Trap</slot>
</div>

<div :tabIndex="disabled ? -1 : 0" :style="hidden"></div>
</div>
</template>

Expand All @@ -13,7 +20,6 @@
: setTimeout(action, 1)
}
let lastActiveTrap = 0;
let lastActiveFocus = null;
const activateTrap = () => {
Expand Down Expand Up @@ -80,15 +86,24 @@
},
disabled: {
type: Boolean
},
noFocusGuards: {
type: Boolean
}
},
data(){
data() {
return {
data: {}
data: {},
hidden: ""// "width: 1px;height: 0px;padding: 0;overflow: hidden;position: fixed;top: 0;left: 0;"
}
},
computed: {
guardsEnabled() {
return !(this.disabled || this.noFocusGuards);
}
},
watch: {
disabled(){
disabled() {
this.data.disabled = this.disabled;
emitChange();
}
Expand All @@ -100,9 +115,10 @@
},
},
mounted(){
mounted() {
this.data.vue = this;
this.data.observed = this.$el;
this.data.observed = this.$el.querySelector("[data-lock]");
this.data.disabled = this.disabled;
this.data.onActivation = () => {
this.originalFocusedElement = this.originalFocusedElement || document.activeElement;
Expand All @@ -115,8 +131,8 @@
emitChange();
},
destroyed(){
instances = instances.filter(({vue}) => vue != this);
destroyed() {
instances = instances.filter(({vue}) => vue !== this);
if (!instances.length) {
detachHandler();
}
Expand Down
91 changes: 91 additions & 0 deletions src/stories/LockStory.vue
@@ -0,0 +1,91 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<button @click="active=true" v-if="!active">ENABLE TRAP</button>
<div style='background-color:#EEE'>you will be trapped here
<Trap :disabled="trapActive">
<ul>
<li>
<a href="https://vuejs.org" target="_blank">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank">Forum</a>
</li>
<li>
<a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank">Twitter</a>
</li>
<br>
<li>
<a href="http://vuejs-templates.github.io/webpack/" target="_blank">Docs for This Template</a>
</li>
</ul>
<div v-if="active">
<button @click="active=false">DISABLE TRAP</button>
</div>
</Trap>
</div>
<h2>Ecosystem</h2>
<ul>
<li>
<a href="http://router.vuejs.org/" target="_blank">vue-router</a>
</li>
<li>
<a href="http://vuex.vuejs.org/" target="_blank">vuex</a>
</li>
<li>
<a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a>
</li>
<li>
<a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a>
</li>
</ul>
</div>
</template>

<script>
import Trap from '../index';
export default {
name: 'hello',
components: {
Trap: Trap
},
computed: {
trapActive() {
return !this.active;
}
},
data () {
return {
msg: 'Welcome to Your Vue.js App',
active: false
}
}
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
11 changes: 11 additions & 0 deletions src/stories/index.js
@@ -0,0 +1,11 @@
import { storiesOf } from '@storybook/vue';
import { action } from '@storybook/addon-actions';

import LockStory from './LockStory.vue';

storiesOf('Lock', module)
.add('simple', () => ({
components: { LockStory },
template: '<lock-story></lock-story>',
methods: { action: action('clicked') },
}))

0 comments on commit 1c6401b

Please sign in to comment.