Last active
August 27, 2021 10:44
-
-
Save vicainelli/ab6e34a91616a8f9e597bccb24ec8e81 to your computer and use it in GitHub Desktop.
Toast Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// tailwind.config.js | |
module.exports = { | |
purge: [], | |
darkMode: false, // or 'media' or 'class' | |
theme: { | |
extend: {}, | |
}, | |
variants: { | |
extend: { | |
boxShadow: { | |
toast: '0px 8px 16px 0px #40404014', | |
}, | |
transitionTimingFunction: { | |
'in-toast': 'cubic-bezier(0.7, 0, 0.84, 0)', | |
'out-toast': 'cubic-bezier(0.16, 1, 0.3, 1)', | |
'in-out-toast': 'cubic-bezier(0.87, 0, 0.13, 1)', | |
}, | |
}, | |
}, | |
plugins: [], | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { mount } from '@cypress/vue'; | |
import Toast from '@/components/toast'; | |
import '@/assets/css/style.css'; | |
const toastTemplate = { | |
template: ` | |
<div class="w-screen h-screen bg-grey-200"> | |
<div class="text-center pt-8"> | |
<button @click="$refs.toast.success({ title: 'New action, pushing the previous one', description: 'Description for the action, containing links' })">Success</button> | |
<button @click="$refs.toast.error({ title: 'Action failed', description: 'Sorry, your action didn’t come through' })">Error</button> | |
<button @click="$refs.toast.info({ title: 'Action performed', description: 'Description for the action that spans up to two lines, due to extensive text' })">Info</button> | |
</div> | |
<Toast ref="toast" /> | |
</div>`, | |
components: { Toast }, | |
}; | |
describe('Toast UI', () => { | |
it('should have correct notifications', () => { | |
mount(toastTemplate); | |
cy.get('button').contains(/success/i).click(); | |
cy.get('div').contains(/New action, pushing the previous one/i).should('be.visible'); | |
cy.get('button').contains(/error/i).click(); | |
cy.get('button').contains(/info/i).click(); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Toast from '@/components/toast'; | |
export default { | |
title: 'Components / Toast', | |
excludeStories: /.*Data$/, | |
}; | |
export const Default = () => ({ | |
components: { Toast }, | |
template: ` | |
<div> | |
<div class="text-center pt-8"> | |
<button @click="$refs.toast.success({ title: 'New action, pushing the previous one', description: 'Description for the action, containing links' })">Success</button> | |
<button @click="$refs.toast.error({ title: 'Action failed', description: 'Sorry, your action didn’t come through' })">Error</button> | |
<button @click="$refs.toast.info({ title: 'Action performed', description: 'Description for the action that spans up to two lines, due to extensive text' })">Info</button> | |
</div> | |
<Toast ref="toast" /> | |
</div> | |
`, | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="fixed z-40 w-full bottom-0 left-0"> | |
<transition-group | |
tag="div" | |
enter-active-class="transition ease-out-toast duration-200" | |
leave-active-class="transition ease-in-toast duration-200 absolute w-full" | |
enter-class="transform translate-y-3 opacity-0" | |
enter-to-class="transform translate-y-0 opacity-100" | |
leave-class="transform translate-y-0 opacity-100" | |
leave-to-class="transform translate-y-1/4 opacity-0" | |
move-class="ease-in-out-toast duration-200" | |
class="grid grid-cols-1 gap-5 p-5" | |
> | |
<div v-for="event in events" :key="event.id"> | |
<div | |
:data-testid="`toast_${event.id}`" | |
class="font-sans w-full max-w-col-4 bg-white shadow-toast rounded-lg p-4 flex justify-between items-start" | |
> | |
<div class="w-full flex-1"> | |
<div> | |
<div class="w-full"> | |
<div> | |
<div class="flex items-center justify-between"> | |
<h3 | |
class="font-bold text-xs text-grey-700" | |
:class="[ | |
{ | |
'text-green-500': event.type && event.type === 'success', | |
'text-red-500': event.type && event.type === 'error', | |
}, | |
]" | |
> | |
{{ event.content.title }} | |
</h3> | |
<button @click="remove(event)"> | |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg> | |
</button> | |
</div> | |
</div> | |
<p v-if="event.content.description !== ''" class="text-xs text-grey-700"> | |
{{ event.content.description }} | |
</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</transition-group> | |
</div> | |
</template> | |
<script> | |
export default { | |
name: 'v-toast', | |
props: { | |
duration: { | |
type: Number, | |
default: 5000, | |
}, | |
}, | |
data() { | |
return { | |
events: [], | |
}; | |
}, | |
methods: { | |
success(content) { | |
this.add(content, 'success'); | |
}, | |
info(content) { | |
this.add(content, 'info'); | |
}, | |
error(content) { | |
this.add(content, 'error'); | |
}, | |
add(content, type = null) { | |
const event = { | |
id: Math.random() | |
.toString(36), | |
content, | |
type, | |
}; | |
this.events.push(event); | |
this.setTimer(event); | |
}, | |
remove(event) { | |
this.events = this.events.filter((e) => e.id !== event.id); | |
}, | |
setTimer(event) { | |
setTimeout(() => { | |
this.remove(event); | |
}, this.duration); | |
}, | |
}, | |
}; | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment