-
Notifications
You must be signed in to change notification settings - Fork 21
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
1060202
commit 6a24e4d
Showing
7 changed files
with
479 additions
and
2 deletions.
There are no files selected for viewing
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
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,190 @@ | ||
# Toaster | ||
|
||
**KToaster** - a popup notification typically used to show the result of an action. The toaster can close on its own but can also be manually dismissed. | ||
|
||
KToaster is used via the a `ToastManager` instance. All rendering is controlled from ToastManager via an intuitive, imperative api. It is recommended that you initialize it as a singleton in your app such as `this.$toaster`. | ||
|
||
```js | ||
import Vue from 'vue'; | ||
import { ToastManager } from '@kongponents/ktoaster'; | ||
|
||
// optional singleton to allow any part of your app access ToastManager | ||
Vue.prototype.$toaster = new ToastManager() | ||
``` | ||
|
||
Once `ToastManager` is registered as a singleton, you can access it's methods via `this.$toaster` e.g.: | ||
|
||
<KButton @click="$toaster.open('Basic Notification')">Open Toaster</KButton> | ||
|
||
```vue | ||
<KButton @click="$toaster.open('Basic Toaster')">Open Toaster</KButton> | ||
``` | ||
|
||
## Arguments | ||
|
||
### message | ||
|
||
The default argument passed to the toaster is the message. | ||
|
||
<KButton @click="$toaster.open('Default message here')">Open Toaster</KButton> | ||
|
||
```vue | ||
<KButton @click="$toaster.open('Default message here')">Open Toaster</KButton> | ||
``` | ||
|
||
### appearance | ||
|
||
The Toaster uses the same appearance values as [KAlert](/components/alert) and are applied the same way. | ||
|
||
<KButton appearance="primary" @click="openNotification({'appearance': 'info', 'message':'This toaster is a info appeareance'})">Open Toaster</KButton> | ||
<KButton class="success" appearance="primary" @click="openNotification({'appearance': 'success', 'message':'This toaster is a success appeareance'})">Open Toaster</KButton> | ||
<KButton appearance="danger" @click="openNotification({'appearance': 'danger', 'message':'This toaster is a danger appeareance'})">Open Toaster</KButton> | ||
<KButton class="warning" appearance="primary" @click="openNotification({'appearance': 'warning', 'message':'This toaster is a warning appeareance'})">Open Toaster</KButton> | ||
|
||
```vue | ||
<template> | ||
<KButton @click="openNotification(toasterOptions)">Open Toaster</KButton> | ||
</template> | ||
<script> | ||
export default { | ||
data () { | ||
return { | ||
toasterOptions: { | ||
appearance: 'danger', | ||
message: 'This toaster is a danger appearance' | ||
} | ||
} | ||
}, | ||
methods: { | ||
openNotification(options) { | ||
this.$toaster.open(options) | ||
} | ||
} | ||
} | ||
</script> | ||
``` | ||
|
||
### timeout | ||
|
||
The default timeout is 5000ms (5 seconds) however you can change this to by passing an override argument. | ||
|
||
- `timeoutMilliseconds` | ||
|
||
<KButton :disabled="timeLeft <= 3" @click="openNotificationElapse({timeoutMilliseconds: 3000, 'appearance': 'success', 'message': `This toaster has a 3 second timeout`})">{{timeLeft > 3 ? 'Open Toaster' : `Closing in ${timeLeft} seconds` }}</KButton> | ||
|
||
```vue | ||
<template> | ||
<KButton @click="openNotification(toasterOptions)">Open Toaster</KButton> | ||
</template> | ||
<script> | ||
export default { | ||
data () { | ||
return { | ||
toasterOptions: { | ||
appearance: 'success', | ||
timeoutMilliseconds: 3000, | ||
message: 'This toaster has a 3 second timeout' | ||
}, | ||
} | ||
}, | ||
methods: { | ||
openNotification(options) { | ||
this.$toaster.open(options) | ||
} | ||
} | ||
} | ||
</script> | ||
``` | ||
|
||
## Toaster State | ||
|
||
You can view the current state of active toasters by calling `this.$toaster.toasters`. Click the buttons below to watch the state change | ||
|
||
<KButton class="success" appearance="primary" @click="openNotification({timeoutMilliseconds: 10000, message: 'Success Notification', appearance: 'success'})">Open Toaster</KButton> | ||
<KButton appearance="danger" @click="openNotification({'appearance': 'danger', 'message': 'Danger Notification'})">Open Toaster</KButton> | ||
<KButton @click="openNotification('Basic Notification')">Open Toaster</KButton> | ||
|
||
<pre class="language-json"> | ||
<code> | ||
{{ JSON.stringify(toasters || [], null, 2) }} | ||
</code> | ||
</pre> | ||
|
||
```vue | ||
<template> | ||
<KButton class="success" appearance="primary" @click="openNotification({timeoutMilliseconds: 10000, message: 'Success Notification', appearance: 'success'})">Open Toaster</KButton> | ||
<KButton appearance="danger" @click="openNotification({'appearance': 'danger', 'message': 'Danger Notification'})">Open Toaster</KButton> | ||
<KButton @click="openNotification('Basic Notification')">Open Toaster</KButton> | ||
</template> | ||
<script> | ||
export default { | ||
data: function () { | ||
return { | ||
toasters: [] | ||
} | ||
}, | ||
methods: { | ||
openNotification(options) { | ||
this.$toaster.open(options) | ||
this.toasters = this.$toaster.toasters | ||
} | ||
} | ||
} | ||
</script> | ||
``` | ||
|
||
## Variations | ||
|
||
### Long Content | ||
|
||
<br> | ||
<KButton @click="openNotification(`Before you release that email you're writing to spin up a new centralized decision-making group, it's worth talking about the four ways these groups consistently fail. They tend to be domineering, bottlenecked, status-oriented, or inert.`)">Prose</KButton> | ||
|
||
<KButton @click="openNotification({message:`Proxy error: Could not proxy request /api/service_packages?fields=&s=%7B%22%24and%22%3A%5B%7B%22name%22%3A%7B%22%24contL%22%3A%22%22%7D%7D%5D%7D&filter=&or=&sort=created_at%2CDESC&join=&limit=100&offset=0&page=1 from localhost:8080 to http://localhost:3000 (ECONNREFUSED).`, appearance: 'danger'})">Raw error message</KButton> | ||
|
||
<script lang="ts"> | ||
import { defineComponent } from 'vue' | ||
|
||
export default defineComponent({ | ||
data: function () { | ||
return { | ||
toasters: [], | ||
timeLeft: 4 | ||
} | ||
}, | ||
methods: { | ||
openNotification(options) { | ||
this.$toaster.open(options) | ||
this.toasters = this.$toaster.toasters | ||
}, | ||
openNotificationElapse(options) { | ||
this.$toaster.open(options) | ||
this.toasters = this.$toaster.toasters | ||
this.timeLeft -= 1 | ||
const interval = setInterval(() => { | ||
this.timeLeft -= 1 | ||
if (this.timeLeft === 0){ | ||
this.timeLeft = 4 | ||
clearInterval(interval) | ||
} | ||
}, 1000) | ||
}, | ||
} | ||
}) | ||
</script> | ||
|
||
<style lang="scss"> | ||
.success.k-button { | ||
--KButtonPrimaryBase: var(--green-400); | ||
--KButtonPrimaryHover: var(--green-300); | ||
--KButtonPrimaryActive: var(--green-500) | ||
} | ||
.warning.k-button { | ||
--KButtonPrimaryBase: var(--yellow-300); | ||
--KButtonPrimaryHover: var(--yellow-200); | ||
--KButtonPrimaryActive: var(--yellow-200); | ||
color: var(--black-70) !important; | ||
} | ||
</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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { mount } from '@cypress/vue' | ||
import KToaster from '@/components/KToaster/KToaster.vue' | ||
import ToastManager from '@/components/KToaster/ToastManager' | ||
|
||
describe('KToaster', () => { | ||
// describe('KToaster.vue', () => { | ||
// it('renders toaster', () => { | ||
// const wrapper = mount(KToaster) | ||
|
||
// expect(wrapper.findAll('.toaster-container-outer span')).toHaveLength(0) | ||
|
||
// wrapper.vm.toasterState.push({ message: 'hey toasty' }) | ||
// wrapper.vm.toasterState.push({ appearance: 'success', message: 'hey toasty' }) | ||
// wrapper.vm.toasterState.push({ appearance: 'danger', message: 'hey toasty' }) | ||
// wrapper.vm.toasterState.push({ appearance: 'danger', message: 'hey toasty' }) | ||
|
||
// expect(wrapper.findAll('div[role="alert"].success')).toHaveLength(1) | ||
// expect(wrapper.findAll('div[role="alert"].danger')).toHaveLength(2) | ||
// expect(wrapper.findAll('.toaster-container-outer div.k-alert-msg')).toHaveLength(4) | ||
|
||
// expect(wrapper).toMatchSnapshot() | ||
// }) | ||
// }) | ||
|
||
// describe('ToastManager', () => { | ||
// it('opens toasters', () => { | ||
// const tm = new ToastManager() | ||
|
||
// tm.open('hey toasty') | ||
// tm.open({message: 'yo toasty'}) | ||
// tm.open({key: 2, message: 'there has been an alert'}) | ||
// expect(tm.toasters).toHaveLength(3) | ||
// }) | ||
|
||
// it('opens toasters - invalid appearance', () => { | ||
// const tm = new ToastManager() | ||
|
||
// tm.open({message: 'yo', appearance: 'ugly'}) | ||
// expect(tm.toasters).toHaveLength(1) | ||
// expect(tm.toasters[0].appearance).toBe('info') | ||
// }) | ||
|
||
// it('dismisses toasters after default timeout', () => { | ||
// const tm = new ToastManager() | ||
|
||
// tm.open('hey toasty') | ||
// tm.open('hey toasty') | ||
// expect(tm.toasters).toHaveLength(2) | ||
// jest.advanceTimersByTime(4999) | ||
// expect(tm.toasters).toHaveLength(2) | ||
// jest.advanceTimersByTime(1) | ||
// expect(tm.toasters).toHaveLength(0) | ||
// }) | ||
|
||
// it('dismisses toasters after timeout per toast', () => { | ||
// const tm = new ToastManager() | ||
|
||
// tm.open({ message: 'hey toasty', timeoutMilliseconds: 1000 }) | ||
// tm.open({ message: 'hey toasty', timeoutMilliseconds: 2000 }) | ||
// tm.open({ message: 'hey toasty', timeoutMilliseconds: 3000 }) | ||
// tm.open({ message: 'hey toasty' }) // default 5000 milliseconds | ||
|
||
// expect(tm.toasters).toHaveLength(4) | ||
// jest.advanceTimersByTime(1000) | ||
// expect(tm.toasters).toHaveLength(3) | ||
// jest.advanceTimersByTime(1000) | ||
// expect(tm.toasters).toHaveLength(2) | ||
// jest.advanceTimersByTime(1000) | ||
// expect(tm.toasters).toHaveLength(1) | ||
// jest.advanceTimersByTime(1000) | ||
// expect(tm.toasters).toHaveLength(1) | ||
// jest.advanceTimersByTime(1000) | ||
// expect(tm.toasters).toHaveLength(0) | ||
// }) | ||
|
||
// it('closes toasters', () => { | ||
// const tm = new ToastManager() | ||
|
||
// tm.open({ key: '#123', message: 'hey toasty' }) | ||
// tm.open({ key: '#345', message: 'hey toasty' }) | ||
|
||
// expect(tm.toasters).toHaveLength(2) | ||
|
||
// tm.close('#345') | ||
|
||
// expect(tm.toasters).toHaveLength(1) | ||
// expect(tm.toasters[0].key).toBe('#123') | ||
// }) | ||
// }) | ||
}) |
Oops, something went wrong.