Skip to content

Commit 9296daf

Browse files
feat: allow class array in containerClass and wrapperClass theme
1 parent dbe5c01 commit 9296daf

File tree

6 files changed

+63
-139
lines changed

6 files changed

+63
-139
lines changed

README.md

+22-4
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ const { $nt } = useNuxtApp()
7272

7373
$nt.show({
7474
/**
75-
* The content of the toast, can be a render function
75+
* The content of the toast, can be a render function (a.k.a stateless component)
7676
*
77+
* @type {string | number | Record<string, any> | (() => Component)}
7778
* @required
7879
*/
7980
content: 'Hello world',
@@ -84,7 +85,6 @@ $nt.show({
8485
* @default 5000
8586
*/
8687
duration: 5000,
87-
8888

8989
/**
9090
* Pause the duration timer on hover, or focus
@@ -122,8 +122,26 @@ $nt.show({
122122
* The theme used for the toast
123123
*/
124124
theme: {
125+
/**
126+
* The container id where the toast will be rendered
127+
* If not exists, it will be created automatically
128+
*
129+
* @default 'nt-container'
130+
*/
125131
containerId: 'nt-container',
132+
/**
133+
* The class name for the toaster container (applyed to toast container)
134+
*
135+
* @type {string | string[]}
136+
* @default ''
137+
*/
126138
containerClass: 'nt-container-class',
139+
/**
140+
* The class name for the toast wrapper (applyed to each toast)
141+
*
142+
* @type {string | string[]}
143+
* @default ''
144+
*/
127145
wrapperClass: 'nt-wrapper-class',
128146
}
129147
})
@@ -245,11 +263,11 @@ export default defineNuxtPlugin(() => {
245263
'flex-col-reverse',
246264
'items-start',
247265
'gap-2'
248-
].join(' '),
266+
],
249267
wrapperClass: [
250268
'pointer-events-auto',
251269
'cursor-pointer',
252-
].join(' '),
270+
],
253271
}
254272

255273
// set default show options here

playground/app.vue

+19-131
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function showCustomToast() {
2020
message: `Hello ${i} from Nuxt module playground!`
2121
}),
2222
transition: {
23-
name: 'fadeOut'
23+
name: 'toaster'
2424
},
2525
maxToasts: 5,
2626
theme: {
@@ -34,7 +34,7 @@ function showCustomToast() {
3434
'flex-col-reverse',
3535
'items-start',
3636
'gap-2'
37-
].join(' '),
37+
],
3838
wrapperClass: 'pointer-events-auto cursor-pointer'
3939
}
4040
})
@@ -60,7 +60,7 @@ async function showAdvancedToast() {
6060
'flex-col',
6161
'items-end',
6262
'gap-2'
63-
].join(' '),
63+
],
6464
wrapperClass: [
6565
'pointer-events-auto',
6666
'rounded',
@@ -70,7 +70,7 @@ async function showAdvancedToast() {
7070
'focus:outline-2',
7171
'focus-within:outline',
7272
'focus-within:outline-2'
73-
].join(' ')
73+
]
7474
},
7575
transition: {
7676
enterActiveClass: 'transition duration-300 ease-out',
@@ -129,137 +129,25 @@ function clearTopLeftToast() {
129129
</template>
130130

131131
<style>
132-
// Animations are taken from animate.css
133-
// https://daneden.github.io/animate.css
134-
.fadeOut {
135-
animation-name: fadeOut;
132+
.toaster-enter-active,
133+
.toaster-leave-active {
134+
transform: translateY(0);
135+
transition: transform 0.25s ease-out, opacity 0.25s ease-out;
136136
}
137-
.fadeInDown {
138-
animation-name: fadeInDown;
139-
}
140-
.fadeInUp {
141-
animation-name: fadeInUp;
142-
}
143-
.fade-enter-active {
144-
transition: opacity 300ms ease-in;
145-
}
146-
.fade-leave-active {
147-
transition: opacity 150ms ease-out;
148-
}
149-
.fade-enter,
150-
.fade-leave-to {
137+
138+
.toaster-enter-from {
139+
transform: translateY(100%);
151140
opacity: 0;
152141
}
153-
@-moz-keyframes fadeOut {
154-
from {
155-
opacity: 1;
156-
}
157-
to {
158-
opacity: 0;
159-
}
160-
}
161-
@-webkit-keyframes fadeOut {
162-
from {
163-
opacity: 1;
164-
}
165-
to {
166-
opacity: 0;
167-
}
168-
}
169-
@-o-keyframes fadeOut {
170-
from {
171-
opacity: 1;
172-
}
173-
to {
174-
opacity: 0;
175-
}
176-
}
177-
@keyframes fadeOut {
178-
from {
179-
opacity: 1;
180-
}
181-
to {
182-
opacity: 0;
183-
}
184-
}
185-
@-moz-keyframes fadeInDown {
186-
from {
187-
opacity: 0.5;
188-
transform: translate3d(0, -100%, 0);
189-
}
190-
to {
191-
opacity: 1;
192-
transform: none;
193-
}
194-
}
195-
@-webkit-keyframes fadeInDown {
196-
from {
197-
opacity: 0.5;
198-
transform: translate3d(0, -100%, 0);
199-
}
200-
to {
201-
opacity: 1;
202-
transform: none;
203-
}
204-
}
205-
@-o-keyframes fadeInDown {
206-
from {
207-
opacity: 0.5;
208-
transform: translate3d(0, -100%, 0);
209-
}
210-
to {
211-
opacity: 1;
212-
transform: none;
213-
}
214-
}
215-
@keyframes fadeInDown {
216-
from {
217-
opacity: 0.5;
218-
transform: translate3d(0, -100%, 0);
219-
}
220-
to {
221-
opacity: 1;
222-
transform: none;
223-
}
224-
}
225-
@-moz-keyframes fadeInUp {
226-
from {
227-
opacity: 0.5;
228-
transform: translate3d(0, 100%, 0);
229-
}
230-
to {
231-
opacity: 1;
232-
transform: none;
233-
}
234-
}
235-
@-webkit-keyframes fadeInUp {
236-
from {
237-
opacity: 0.5;
238-
transform: translate3d(0, 100%, 0);
239-
}
240-
to {
241-
opacity: 1;
242-
transform: none;
243-
}
244-
}
245-
@-o-keyframes fadeInUp {
246-
from {
247-
opacity: 0.5;
248-
transform: translate3d(0, 100%, 0);
249-
}
250-
to {
251-
opacity: 1;
252-
transform: none;
253-
}
142+
143+
.toaster-leave-to {
144+
opacity: 0;
254145
}
255-
@keyframes fadeInUp {
256-
from {
257-
opacity: 0.5;
258-
transform: translate3d(0, 100%, 0);
259-
}
260-
to {
261-
opacity: 1;
262-
transform: none;
146+
147+
@media (prefers-reduced-motion: reduce) {
148+
.toaster-enter-active,
149+
.toaster-leave-active {
150+
transition: none;
263151
}
264152
}
265153
</style>

src/runtime/components/NinjaToaster.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,10 @@ export default defineComponent({
221221
{
222222
role: 'alert',
223223
tabindex: 0,
224-
class: props.theme?.wrapperClass,
224+
class:
225+
props.theme && Array.isArray(props.theme?.wrapperClass)
226+
? props.theme.wrapperClass.join(' ')
227+
: props.theme?.wrapperClass,
225228
onMouseover,
226229
onMouseleave,
227230
onFocus,

src/runtime/composables/useNinjaToasterContainer.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ export function useNinjaToasterContainer(theme?: NinjaToasterTheme) {
1818
}
1919

2020
if (theme?.containerClass) {
21-
container.value.className = theme.containerClass
21+
container.value.className = Array.isArray(theme.containerClass)
22+
? theme.containerClass.join(' ')
23+
: theme.containerClass
2224
}
2325
})
2426

src/runtime/create.ts

+13
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,15 @@ export interface NinjaToasterShow {
4242
close: () => void
4343
}
4444

45+
function ensureClassesArray(theme: NinjaToasterTheme) {
46+
if (theme?.containerClass && !Array.isArray(theme.containerClass)) {
47+
theme.containerClass = [theme.containerClass]
48+
}
49+
if (theme?.wrapperClass && !Array.isArray(theme.wrapperClass)) {
50+
theme.wrapperClass = [theme.wrapperClass]
51+
}
52+
}
53+
4554
export function createNinjaToaster(
4655
createProps: Omit<NinjaToasterProps, 'content'> = {}
4756
) {
@@ -59,6 +68,10 @@ export function createNinjaToaster(
5968
? { content: options }
6069
: options
6170

71+
ensureClassesArray(userProps.theme)
72+
ensureClassesArray(createProps.theme)
73+
ensureClassesArray(appConfigProps.theme)
74+
6275
const props: NinjaToasterProps = defu(
6376
userProps,
6477
createProps,

src/theme.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export interface NinjaToasterTheme {
22
containerId: string;
3-
containerClass?: string;
4-
wrapperClass?: string;
3+
containerClass?: string | string[];
4+
wrapperClass?: string | string[];
55
}

0 commit comments

Comments
 (0)