Added Modal to our Styleguide

This commit is contained in:
Grzegorz Leoniec 2019-01-11 14:54:21 +01:00
parent c144e12229
commit 17a52fa8e5
No known key found for this signature in database
GPG Key ID: 3AA43686D4EB1377
4 changed files with 353 additions and 0 deletions

22
store/modal.js Normal file
View File

@ -0,0 +1,22 @@
export const state = () => {
return {
open: null,
data: {}
}
}
export const mutations = {
SET_OPEN(state, ctx) {
state.open = ctx.name || null
state.data = ctx.data || {}
}
}
export const getters = {
open(state) {
return state.open
},
data(state) {
return state.data
}
}

View File

@ -0,0 +1,191 @@
<template>
<portal to="modal">
<div :key="key" class="ds-modal-wrapper">
<transition name="ds-transition-fade" appear>
<div
v-if="isOpen"
class="ds-modal-backdrop"
ref="backdrop"
@click="backdropHandler"
>
&nbsp;
</div>
</transition>
<transition name="ds-transition-modal-appear" appear>
<div
v-if="isOpen"
class="ds-modal"
tableindex="-1"
role="dialog"
ref="modal"
style="display: block"
>
<div class="ds-modal-dialog">
<div class="ds-modal-content">
<div class="ds-modal-header">
<ds-heading
tag="h3"
class="ds-modal-title"
>
{{ title }}
</ds-heading>
<ds-button
v-if="allowAbort"
class="ds-modal-close"
ghost
size="small"
icon="close"
aria-hidden="true"
@click="cancel('close')"
/>
</div>
<div
class="ds-modal-body"
ref="modalBody"
>
<!-- @slot Modal content -->
<slot/>
</div>
<div class="ds-modal-footer">
<!-- @slot Modal footer with action buttons -->
<slot
name="footer"
:confirm="confirm"
:cancel="cancel"
:cancelLabel="cancelLabel"
:confirmLabel="confirmLabel"
>
<ds-button ghost icon="close" @click.prevent="cancel('cancel')">{{ cancelLabel }}</ds-button>
<ds-button primary icon="check" @click.prevent="confirm('confirm')">{{ confirmLabel }}</ds-button>
</slot>
</div>
</div>
</div>
</div>
</transition>
</div>
</portal>
</template>
<script>
import Vue from 'vue'
import portal from 'portal-vue'
Vue.use(portal)
/* eslint-disable no-empty */
/**
* Simple Modal Component
* @version 1.0.0
*/
export default {
name: 'DsModal',
props: {
/**
* Modal title
*/
title: {
type: String,
default: null
},
/**
* Open state
*/
isOpen: {
type: Boolean,
default: false
},
/**
* Allow closing without choosing action by ESC key, close button or click on the backdrop
*/
allowAbort: {
type: Boolean,
default: true
},
/**
* Cancel button label
*/
cancelLabel: {
type: String,
default: 'Cancel'
},
/**
* Confirm button label
*/
confirmLabel: {
type: String,
default: 'Confirm'
}
},
model: {
prop: 'isOpen',
event: 'update:isOpen'
},
watch: {
isOpen: {
immediate: true,
handler(show) {
try {
if (show) {
this.$emit('opened')
document
.getElementsByTagName('body')[0]
.classList
.add('modal-open')
} else {
document
.getElementsByTagName('body')[0]
.classList
.remove('modal-open')
}
} catch (err) {}
}
}
},
methods: {
confirm (type = 'confirm') {
this.$emit('confirm')
this.close(type)
},
cancel (type = 'cancel') {
this.$emit('cancel')
this.close(type)
},
close (type) {
this.$emit('update:isOpen', false)
this.$emit('close', type)
},
backdropHandler () {
if (this.allowAbort) {
this.cancel('backdrop')
}
}
},
beforeCreate() {
// create random key string
this.key = Math.random()
.toString(36)
.replace(/[^a-z]+/g, '')
.substr(0, 5)
},
mounted() {
const keydownListener = document.addEventListener('keydown', e => {
if (this.isOpen && this.allowAbort && e.keyCode === 27) {
this.cancel('backdrop')
}
})
this.$once('hook:beforeDestroy', () => {
document.removeEventListener('keydown', keydownListener)
})
if (this.isOpen) {
this.$emit('opened')
}
}
}
</script>
<style lang="scss" src="./style.scss">
</style>
<docs src="./demo.md"></docs>

View File

@ -0,0 +1,65 @@
## Basic Modal
Basic modal usage
You will need to add the portal-target to the end of your html body to get the modal working properly
```html
<!-- put the following tag as last element to your html body / layout -->
<!-- make sure you only include it once! -->
<portal-target name="modal" style="position: absolute" />
```
```
<template>
<div>
<ds-modal
v-model="isOpen"
title="Modal Title"
>
<p>Hello World</p>
</ds-modal>
<ds-button primary icon="rocket" @click="isOpen = true">Open Modal</ds-button>
</div>
</template>
<script>
export default {
data() {
return {
isOpen: false
}
}
}
</script>
```
Customize button labels
```
<template>
<div>
<ds-modal
v-if="isOpen"
v-model="isOpen"
title="Custom Button Labels"
:allow-abort="false"
confirm-label="All right"
cancel-label="Please not"
>
<p>Culpa amet sunt aperiam ratione est sed. Molestiae minus doloremque libero. Beatae nam repellendus aliquid maxime.</p>
<p>Sint quasi provident natus id earum debitis. Et facilis a iure ullam. Velit autem eveniet ea reprehenderit ducimus doloribus earum quo.</p>
<p>Consequatur ratione repudiandae aliquid ea. Ut eum architecto assumenda. Autem eaque provident quia et.</p>
<p>Eaque quia aut dolorum sunt ea consequuntur. Labore reprehenderit placeat pariatur molestiae sit laborum nostrum. Deserunt est commodi et suscipit tenetur ipsa voluptas cupiditate. Porro laborum quidem ut corrupti. Dolorum et est placeat qui.</p>
<p>Adipisci beatae cumque esse harum. Error quis nulla illo nemo est. Enim est quis explicabo voluptatem. Omnis maxime qui similique consequatur voluptatibus. Est necessitatibus iure aliquid omnis eum. Ut voluptatibus vel error exercitationem temporibus qui expedita.</p>
</ds-modal>
<ds-button primary icon="rocket" @click="isOpen = true">Open Modal</ds-button>
</div>
</template>
<script>
export default {
data() {
return {
isOpen: false
}
}
}
</script>
```

View File

@ -0,0 +1,75 @@
.ds-modal-wrapper {
padding: $space-base;
position: relative;
}
.ds-modal {
position: fixed;
z-index: $z-index-modal;
left: 50%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
display: flex;
flex-direction: column;
max-width: 600px;
width: calc(90vw - 40px);
max-height: 90vh;
background: white;
border-radius: $border-radius-large;
padding: 0 $space-base;
box-shadow: $box-shadow-x-large;
}
.ds-modal-close {
position: absolute;
top: $space-small;
right: $space-small;
}
.ds-modal-body {
flex: 1;
overflow-y: auto;
height: auto;
min-height: 100px;
max-height: 60vh;
}
.ds-modal-header {
padding-top: $space-base;
.ds-modal-title {
margin-bottom: 0;
}
}
.ds-modal-backdrop {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: $z-index-modal - 1;
background: rgba(0, 0, 0, 0.7);
}
.ds-modal-footer {
display: flex;
padding: $space-base 0;
flex-shrink: 0;
justify-content: flex-end;
& > button {
margin-left: $space-x-small;
}
}
$easeOut: cubic-bezier(0.19, 1, 0.22, 1);
.ds-transition-modal-appear-enter-active {
opacity: 1;
transition: all 180ms $easeOut;
transition-delay: 0;
transform: translate3d(-50%, -50%, 0) scale(1);
}
.ds-transition-modal-appear-enter,
.ds-transition-modal-appear-leave-active {
opacity: 0;
transition-delay: 0;
transform: translate3d(-50%, -50%, 0) scale(0.9);
}