Skip to content
This repository has been archived by the owner on Mar 17, 2021. It is now read-only.

Commit

Permalink
Added modal component
Browse files Browse the repository at this point in the history
  • Loading branch information
romanslonov committed Apr 1, 2019
1 parent 128afe3 commit 9ad35a7
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 739 deletions.
225 changes: 1 addition & 224 deletions dist/modulist-vue.common.js

Large diffs are not rendered by default.

256 changes: 1 addition & 255 deletions dist/modulist-vue.esm.js

Large diffs are not rendered by default.

256 changes: 1 addition & 255 deletions dist/modulist-vue.min.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = {
'components/button',
'components/checkbox',
'components/checkbox-group',
'components/modal',
'components/progress',
'components/radio',
'components/radio-group',
Expand Down
76 changes: 76 additions & 0 deletions docs/components/modal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Modal
A classic modal overlay, in which you can include any content you want.

## Example

<div class="p-3 border rounded-2 my-3">
<v-button @click="open('modal1')" appearance="primary">Open modal 1</v-button>
<v-modal :open="modal1" @close="close('modal1')" title="Modal 1">
Modal content
<template slot="footer">
<v-button @click="close('modal1')" appearance="subtle">
Close
</v-button>
<v-button appearance="primary">Apply changes</v-button>
</template>
</v-modal>
</div>

```html
<v-button @click="open('modal1')" appearance="primary">
Open modal 1
</v-button>

<v-modal :open="modal1" @close="close('modal1')" title="Modal 1">
<div>Modal content</div>
<template slot="footer">
<v-button appearance="subtle" @click="close('modal1')">Close</v-button>
<v-button appearance="primary">Apply changes</v-button>
</template>
</v-modal>
```

```javascript
export default {
data() {
return { modal1: false };
},
methods: {
open(modal) {
this[modal] = true;
},
close(modal) {
this[modal] = false;
},
},
};
```

## Props
Name | Type | Description | Default | Required
------------------ | --------- | ----------- | ------- | --------
id | [String, Number] | Unique identifier | None | false
title | String | Modal's title | 'Modal title' | false
size | String | Modal's size ['1', '2', '3'] | '2' | false
role | String | Modal's role 'dialog' or 'alertdialog' | 'dialog' | false
open | Boolean | Modal's state | false | false
removeHeader | Boolean | Whether or not display modal's header | false | false
removeCloseButton | Boolean | Whether or not display modal's close button | false | false
dismissible | Boolean | Should modal be dismissible or not | true | false
dismissOn | String | Elements which can trigger close method | 'backdrop esc close-button' | false

<script>
export default {
data() {
return { modal1: false };
},
methods: {
open(modal) {
this[modal] = true;
},
close(modal) {
this[modal] = false;
},
},
};
</script>
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"prepublish": "bash scripts/prepublish.sh"
},
"devDependencies": {
"@modulist/css": "0.0.15",
"@modulist/css": "0.0.20",
"@vue/cli-plugin-babel": "^3.5.0",
"@vue/cli-plugin-eslint": "^3.5.0",
"@vue/cli-plugin-unit-jest": "^3.5.0",
Expand Down Expand Up @@ -51,7 +51,7 @@
"git add"
],
"ignore": [
"**/dist/*.css"
"**/dist/*.js"
]
},
"directories": {
Expand Down
8 changes: 8 additions & 0 deletions src/components/Modal/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Modal from './main.vue';

// eslint-disable-next-line func-names
Modal.install = function (Vue) {
Vue.component('VModal', Modal);
};

export default Modal;
168 changes: 168 additions & 0 deletions src/components/Modal/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<template>
<transition name="modal" @after-enter="onEnter" @after-leave="onLeave">
<div class="modal modal__mask" v-show="open" :role="role">
<div ref="backdrop" class="modal__wrapper" @click="dismissOnBackdrop && close($event)">
<div
ref="container"
class="modal__container"
tabindex="-1"
@keydown.esc="dismissOnEsc && close($event)"
>

<div class="modal__header">

<h3 class="modal__title">{{ title }}</h3>

<v-button appearance="subtle" size="1" @click="close">
<svg slot="icon" width="16" height="16">
<use xlink:href="#cross-icon"></use>
</svg>
</v-button>

</div>

<div class="modal__body">
<slot></slot>
</div>

<div class="modal__footer">
<slot name="footer"></slot>
</div>

<div tabindex="0" @focus.stop="redirectFocus"></div>
</div>
</div>
</div>
</transition>
</template>

<script>
import VButton from '../Button';
const modalOpenClass = 'modal--open';
export default {
name: 'VModal',
props: {
open: {
type: Boolean,
default: false,
},
role: {
type: String,
default: 'dialog',
validator(role) {
return ['dialog', 'alertdialog'].indexOf(role) > -1;
},
},
title: {
type: String,
default: 'Modal title',
},
dismissible: {
type: Boolean,
default: true,
},
dismissOn: {
type: String,
default: 'backdrop esc close-button',
},
},
computed: {
dismissOnBackdrop() {
return this.dismissOn.indexOf('backdrop') > -1;
},
dismissOnCloseButton() {
return this.dismissOn.indexOf('close-button') > -1;
},
dismissOnEsc() {
return this.dismissOn.indexOf('esc') > -1;
},
},
methods: {
close(e) {
if (!this.dismissible) {
return;
}
// Make sure the element clicked was the backdrop and not a child whose click
// event has bubbled up
if (e.currentTarget === this.$refs.backdrop && e.target !== e.currentTarget) {
return;
}
this.$emit('close');
},
onOpen() {
this.lastfocusedElement = document.activeElement;
this.$refs.container.focus();
document.body.classList.add(modalOpenClass);
document.addEventListener('focus', this.restrictFocus, true);
this.$emit('open');
},
onClose() {
this.teardownModal();
this.$emit('close');
},
redirectFocus() {
this.$refs.container.focus();
},
restrictFocus(e) {
if (!this.$refs.container.contains(e.target)) {
e.stopPropagation();
this.$refs.container.focus();
}
},
teardownModal() {
document.body.classList.remove(modalOpenClass);
document.removeEventListener('focus', this.restrictFocus, true);
if (this.lastfocusedElement) {
this.lastfocusedElement.focus();
}
},
onEnter() {
this.$emit('reveal');
},
onLeave() {
this.$emit('hide');
document.body.classList.remove(modalOpenClass);
},
},
components: { VButton },
watch: {
open() {
this.$nextTick(() => {
this[this.open ? 'onOpen' : 'onClose']();
});
},
},
beforeDestroy() {
if (this.open) {
this.teardownModal();
}
},
};
</script>

<style>
/*
* The following styles are auto-applied to elements with
* transition="modal" when their visibility is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
.modal-enter .modal__container,
.modal-leave-active .modal__container {
transform: scale(1.1);
}
</style>
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export { default as VBadge } from './Badge';
export { default as VButton } from './Button';
export { default as VCheckbox } from './Checkbox';
export { default as VCheckboxGroup } from './CheckboxGroup';
export { default as VModal } from './Modal';
export { default as VProgress } from './Progress';
export { default as VRadio } from './Radio';
export { default as VRadioGroup } from './RadioGroup';
Expand Down

0 comments on commit 9ad35a7

Please sign in to comment.