-
Notifications
You must be signed in to change notification settings - Fork 393
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9085e1c
commit d78fc72
Showing
8 changed files
with
288 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { describe, beforeEach, test, expect } from 'vitest'; | ||
import { fireEvent, render, RenderResult } from '@testing-library/vue'; | ||
import VueToast from './VueToast.vue'; | ||
import { addToast } from '@/components/utils'; | ||
import { sleep } from '@/test/test-utils'; | ||
|
||
describe('VueToast.vue', () => { | ||
let harness: RenderResult; | ||
|
||
beforeEach(() => { | ||
harness = render(VueToast); | ||
}); | ||
|
||
test('displays toast for a user specified time (100ms)', async () => { | ||
const { queryAllByText } = harness; | ||
|
||
addToast({ title: 'info', text: 'this is a test', displayTimeInMs: 100 }); | ||
await sleep(10); | ||
|
||
expect(queryAllByText('info')).toHaveLength(1); | ||
expect(queryAllByText('this is a test')).toHaveLength(1); | ||
|
||
await sleep(150); | ||
|
||
expect(queryAllByText('info')).toHaveLength(0); | ||
expect(queryAllByText('this is a test')).toHaveLength(0); | ||
}); | ||
|
||
test('displays toast for until user clicks close icon', async () => { | ||
const { queryAllByText, getByTestId } = harness; | ||
|
||
addToast({ title: 'warning', text: 'this is a test', type: 'warning' }); | ||
await sleep(50); | ||
|
||
expect(queryAllByText('warning')).toHaveLength(1); | ||
expect(queryAllByText('this is a test')).toHaveLength(1); | ||
|
||
await fireEvent.click(getByTestId('toast-close-button')); | ||
|
||
expect(queryAllByText('info')).toHaveLength(0); | ||
expect(queryAllByText('this is a test')).toHaveLength(0); | ||
}); | ||
}); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import VueToast from './VueToast.vue'; | ||
import { addToast } from '@/components/utils'; | ||
import VueInline from '@/components/layout/VueInline/VueInline.vue'; | ||
import VueButton from '@/components/input-and-actions/VueButton/VueButton.vue'; | ||
import ComponentDocs from '~/assets/design-system/docs/components/ComponentDocs.vue'; | ||
|
||
export default { | ||
title: 'Data Display/Toast', | ||
component: VueToast, | ||
argTypes: {}, | ||
}; | ||
|
||
const Template = (args) => ({ | ||
components: { | ||
VueToast, | ||
VueButton, | ||
ComponentDocs, | ||
VueInline, | ||
}, | ||
|
||
setup() { | ||
return { | ||
args, | ||
onSuccessToastClick() { | ||
addToast({ | ||
title: 'This is a success message!', | ||
type: 'success', | ||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod', | ||
}); | ||
}, | ||
onInfoToastClick() { | ||
addToast({ | ||
title: 'This is an information!', | ||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod', | ||
}); | ||
}, | ||
onWarningToastClick() { | ||
addToast({ | ||
title: 'This is a warning!', | ||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod', | ||
type: 'warning', | ||
displayTimeInMs: 15000, | ||
}); | ||
}, | ||
onDangerToastClick() { | ||
addToast({ | ||
title: 'This is an error!', | ||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod', | ||
type: 'danger', | ||
displayTimeInMs: 30000, | ||
}); | ||
}, | ||
}; | ||
}, | ||
|
||
template: `<component-docs | ||
component-name="Toast" | ||
usage="Used to communicate messages from the system to the user." | ||
story="Show toast messages with their different properties." | ||
> | ||
<vue-toast /> | ||
<vue-inline stack-phone stack-tablet-portrait stack-tablet-landscape stack-small-desktop stack-large-desktop> | ||
<vue-button look="primary" @click="onSuccessToastClick">add success toast</vue-button> | ||
<vue-button look="secondary" @click="onInfoToastClick">add info toast</vue-button> | ||
<vue-button look="outline" @click="onWarningToastClick">add warning toast</vue-button> | ||
<vue-button look="danger" @click="onDangerToastClick">add danger toast</vue-button> | ||
</vue-inline> | ||
</component-docs>`, | ||
}); | ||
|
||
export const Default = Template.bind({}); | ||
|
||
Default.args = {}; |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
<template> | ||
<div :class="$style.vueToast"> | ||
<transition-group name="list" tag="div"> | ||
<vue-box v-for="toast in orderedToasts" :key="toast.id" padding="16" :class="[$style.toast, $style[toast.type]]"> | ||
<vue-columns space="12" align-y="top"> | ||
<vue-column width="content"> | ||
<vue-text :color="toast.type"> | ||
<vue-icon-info v-if="['info', 'success'].includes(toast.type)" /> | ||
<vue-icon-exclamation v-if="['warning', 'danger'].includes(toast.type)" /> | ||
</vue-text> | ||
</vue-column> | ||
<vue-column> | ||
<vue-stack space="4"> | ||
<vue-text :color="toast.type" weight="semi-bold">{{ toast.title }}</vue-text> | ||
<vue-text look="label" :color="toast.type">{{ toast.text }}</vue-text> | ||
</vue-stack> | ||
</vue-column> | ||
|
||
<vue-column width="content"> | ||
<vue-text | ||
tabindex="0" | ||
aria-label="close" | ||
:color="toast.type" | ||
data-testid="toast-close-button" | ||
as="a" | ||
href="#" | ||
@click.native.stop.prevent="removeToast(toast)" | ||
> | ||
<vue-icon-times /> | ||
</vue-text> | ||
</vue-column> | ||
</vue-columns> | ||
</vue-box> | ||
</transition-group> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { computed, onMounted, ref } from 'vue'; | ||
import { EventBus } from '~/services/EventBus'; | ||
import { IToast } from '@/interfaces/IToast'; | ||
import VueBox from '@/components/layout/VueBox/VueBox.vue'; | ||
import VueColumns from '@/components/layout/VueColumns/VueColumns.vue'; | ||
import VueColumn from '@/components/layout/VueColumns/VueColumn/VueColumn.vue'; | ||
import VueStack from '@/components/layout/VueStack/VueStack.vue'; | ||
import VueText from '@/components/typography/VueText/VueText.vue'; | ||
import VueIconInfo from '@/components/icons/VueIconInfoCircle.vue'; | ||
import VueIconTimes from '@/components/icons/VueIconTimes.vue'; | ||
import VueIconExclamation from '@/components/icons/VueIconExclamation.vue'; | ||
import { getGUID } from '~/components/utils'; | ||
const toasts = ref<IToast[]>([]); | ||
const orderedToasts = computed<IToast[]>(() => toasts.value.slice(0).reverse()); | ||
const removeToast = (n: IToast) => { | ||
toasts.value = toasts.value.filter((toast) => toast.id !== n.id); | ||
}; | ||
const addToast = (n: IToast) => { | ||
n.id = getGUID(); | ||
n.type = n.type || 'info'; | ||
n.displayTimeInMs = n.displayTimeInMs || 10000; | ||
toasts.value.push(n); | ||
setTimeout(() => removeToast(n), n.displayTimeInMs); | ||
}; | ||
onMounted(() => { | ||
EventBus.on('toast.add', addToast); | ||
}); | ||
</script> | ||
|
||
<style lang="scss" module> | ||
@import 'assets/_design-system'; | ||
.vueToast { | ||
position: fixed; | ||
top: $toast-position-top; | ||
right: $space-16; | ||
z-index: $toast-index; | ||
width: calc(100% - #{$space-32}); | ||
max-width: $toast-max-width; | ||
:global { | ||
.list-move { | ||
transition: $toast-transition; | ||
} | ||
.list-enter { | ||
opacity: 0; | ||
transform: translateY(-100%); | ||
} | ||
.list-enter-active { | ||
transition: $toast-transition; | ||
} | ||
.list-enter-to { | ||
opacity: 1; | ||
transform: translateY(0); | ||
} | ||
.list-leave { | ||
opacity: 1; | ||
transform: translateY(0); | ||
} | ||
.list-leave-active { | ||
transition: $toast-transition; | ||
} | ||
.list-leave-to { | ||
opacity: 0; | ||
transform: translateY(100%); | ||
} | ||
} | ||
.toast { | ||
border-radius: $toast-border-radius; | ||
box-shadow: $toast-elevation; | ||
margin-bottom: $toast-gap; | ||
i { | ||
width: $toast-icons-size; | ||
height: $toast-icons-size; | ||
} | ||
&.info { | ||
background: $toast-info-bg; | ||
border: $toast-info-border; | ||
} | ||
&.warning { | ||
background: $toast-warning-bg; | ||
border: $toast-warning-border; | ||
} | ||
&.danger { | ||
background: $toast-danger-bg; | ||
border: $toast-danger-border; | ||
} | ||
&.success { | ||
background: $toast-success-bg; | ||
border: $toast-success-border; | ||
} | ||
} | ||
} | ||
</style> |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import mitt from 'mitt'; | ||
|
||
export const EventBus = mitt(); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Services | ||
|
||
**This directory is not required, you can delete it if you don't want to use it.** | ||
|
||
This directory contains services that can be used outside the vue and nuxt life-cycle. |