82
82
@click =" goToPrevStep()"
83
83
style =" transform : rotate (180deg )"
84
84
>
85
- <CaretRightIcon />
85
+ <CaretRightSmallIcon />
86
86
</button >
87
87
<button
88
88
class =" next"
89
89
:class =" { loading: isLoading }"
90
90
:disabled =" disableNextStep"
91
91
@click =" !isLoading && goToNextStep()"
92
92
>
93
- <CaretRightIcon v-if =" !isLoading" />
93
+ <CaretRightSmallIcon v-if =" !isLoading" />
94
94
<CircleSpinner v-else class =" circle-spinner" />
95
95
</button >
96
96
</div >
102
102
import { useAccountStore } from ' @/stores/Account' ;
103
103
import { useNetworkStore } from ' @/stores/Network' ;
104
104
import { useTransactionsStore } from ' @/stores/Transactions' ;
105
- import { CircleSpinner } from ' @nimiq/vue-components' ;
105
+ import { CircleSpinner , CaretRightSmallIcon } from ' @nimiq/vue-components' ;
106
106
import {
107
107
computed ,
108
108
defineComponent ,
@@ -121,7 +121,6 @@ import {
121
121
MountedReturnFn , TourBroadcast , TourStep ,
122
122
TourStepIndex ,
123
123
} from ' ../lib/tour' ;
124
- import CaretRightIcon from ' ./icons/CaretRightIcon.vue' ;
125
124
import PartyConfettiIcon from ' ./icons/PartyConfettiIcon.vue' ;
126
125
import TourPreviousLeftArrowIcon from ' ./icons/TourPreviousLeftArrowIcon.vue' ;
127
126
@@ -137,8 +136,7 @@ export default defineComponent({
137
136
const { state : $network } = useNetworkStore ();
138
137
const disconnected = computed (() => $network .consensus !== ' established' );
139
138
140
- const { state : tourStore, setTour, activeAccountInfo } = useAccountStore ();
141
- activeAccountInfo .value ! .fileExported = false ;
139
+ const { state : tourStore, setTour } = useAccountStore ();
142
140
143
141
let tour: VueTour .Tour | null = null ;
144
142
const tourOptions: any = {
@@ -217,7 +215,10 @@ export default defineComponent({
217
215
isLoading .value = false ;
218
216
219
217
window .addEventListener (' keyup' , _onKeyDown );
220
- window .addEventListener (' click' , _userClicked ());
218
+ setTimeout (() => {
219
+ window .addEventListener (' click' , _userClicked ());
220
+ }, 100 ); // avoid click event to be triggered by the setting button
221
+
221
222
// window.addEventListener('resize', _OnResize(_OnResizeEnd)); TODO
222
223
223
224
const app = document .querySelector (' #app' );
@@ -236,22 +237,26 @@ export default defineComponent({
236
237
// Dont allow user to interact with the page while it is loading
237
238
// But allow to end it
238
239
watch ([isLoading , disconnected ], async () => {
239
- const app = document .querySelector (' #app main' ) as HTMLDivElement ;
240
-
241
- if (isLoading .value || disconnected .value ) {
242
- app .setAttribute (' data-non-interactable' , ' ' );
243
- } else {
244
- app .removeAttribute (' data-non-interactable' );
245
- }
246
-
247
- // FIXME we should wait until the button is rendered and the we could
240
+ // TODO Avoid interaction with any of the elements when loading except tour elements (bar, manager and tooltip)
241
+ // const elements = Object.values(WalletHTMLElements).filter((e) => e);
242
+ // if (isLoading.value || disconnected.value) {
243
+ // elements.forEach((element) => {
244
+ // const el = document.querySelector(element);
245
+ // if (!el) return;
246
+ // el.setAttribute('data-non-interactable', 'loading');
247
+ // });
248
+ // } else {
249
+ // elements.forEach((element) => {
250
+ // const el = document.querySelector(element);
251
+ // if (!el) return;
252
+ // el.removeAttribute('data-non-interactable');
253
+ // });
254
+ // }
255
+
256
+ // FIXME we should wait until the buttons are rendered and the we could
248
257
// execute _toggleDisabledButtons but it is kind of random the amount of time
249
- // it takes to render the button. I don't know how to fix it.
250
-
251
- // Ensure that we disabled 'Receive Free NIM' button
252
- await sleep (500 ); // TODO
253
- // TODO Remove this code for the network, find other way
254
- // steps = Object.values(getTour(tourStore.tour?.name, context));
258
+ // it takes to render the button. I don't know how to fix it. Waiting 500ms works.
259
+ await sleep (500 );
255
260
_toggleDisabledButtons (steps [currentStep .value ]?.ui .disabledButtons , true );
256
261
});
257
262
@@ -274,7 +279,6 @@ export default defineComponent({
274
279
const { path : currentPath, ui : currentUI } = steps [currentStepIndex ]! ;
275
280
const { path : futurePath, ui : futureUI, lifecycle : futureLifecycle } = steps [futureStepIndex ]! ;
276
281
277
- isLoading .value = true ;
278
282
tour ! .stop ();
279
283
280
284
await sleep (500 );
@@ -294,6 +298,7 @@ export default defineComponent({
294
298
_toggleDisabledButtons (currentUI .disabledButtons , false );
295
299
_toggleDisabledButtons (futureUI .disabledButtons , true );
296
300
_addAttributes (futureUI , futureStepIndex );
301
+ await context .root .$nextTick ();
297
302
298
303
if (futurePath !== currentPath ) {
299
304
await sleep (500 );
@@ -302,14 +307,14 @@ export default defineComponent({
302
307
_removeAttributes (currentStepIndex );
303
308
304
309
tour ! .start (futureStepIndex .toString ());
310
+ await context .root .$nextTick ();
305
311
306
312
// FIXME Instead of doing tour!.end and tour!.start, we could also use .nextStep() or previsousStep()
307
313
// The problem with this solution is that some animations glitch the UI so it needs further
308
314
// investigation
309
315
// goingForward ? tour!.nextStep() : tour!.previousStep();
310
316
311
317
// mounted
312
- isLoading .value = false ;
313
318
disableNextStep .value = futureStepIndex >= nSteps .value - 1 || !! futureUI .isNextStepDisabled ;
314
319
315
320
unmounted = await futureLifecycle ?.mounted ?.({
@@ -338,6 +343,17 @@ export default defineComponent({
338
343
context .root .$on (' nimiq-tour-event' , (data : TourBroadcast ) => {
339
344
if (data .type === ' end-tour' ) endTour ();
340
345
});
346
+ context .root .$on (' nimiq-tour-event' , (data : TourBroadcast ) => {
347
+ if (data .type === ' clicked-outside-tour' ) {
348
+ const tourManager = document .querySelector (' .tour-control-bar' );
349
+ if (tourManager ) {
350
+ tourManager .classList .add (' flash' );
351
+ setTimeout (() => {
352
+ tourManager .classList .remove (' flash' );
353
+ }, 400 );
354
+ }
355
+ }
356
+ });
341
357
}
342
358
343
359
function _userClicked() {
@@ -382,12 +398,17 @@ export default defineComponent({
382
398
}
383
399
}
384
400
401
+ function _onScrollLockedElement(e : Event , el : Element ) {
402
+ e .preventDefault ();
403
+ el .scrollTop = 0 ;
404
+ }
385
405
function _addAttributes(
386
406
uiConfig : TourStep [' ui' ],
387
407
stepIndex : TourStepIndex ,
388
408
) {
389
409
const fadedElements = uiConfig .fadedElements || [];
390
410
const disabledElements = uiConfig .disabledElements || [];
411
+ const scrollLockedElements = uiConfig .scrollLockedElements || [];
391
412
392
413
disabledElements .filter ((e ) => e ).forEach ((element ) => {
393
414
const el = document .querySelector (element );
@@ -401,20 +422,33 @@ export default defineComponent({
401
422
el .setAttribute (' data-opacified' , stepIndex .toString ());
402
423
el .setAttribute (' data-non-interactable' , stepIndex .toString ());
403
424
});
425
+
426
+ scrollLockedElements .filter ((e ) => e ).forEach ((element ) => {
427
+ const el = document .querySelector (element );
428
+ if (! el ) return ;
429
+ el .setAttribute (' data-scroll-locked' , stepIndex .toString ());
430
+ // Avoid scrolling when tooltip is instantiated
431
+ el .addEventListener (' scroll' , (e ) => _onScrollLockedElement (e , el ));
432
+ el .scrollTop = 0 ;
433
+ });
404
434
}
405
435
406
436
function _removeAttributes(stepIndex : TourStepIndex ) {
407
- document
408
- .querySelectorAll (` [data-non-interactable="${stepIndex }"] ` )
437
+ document .querySelectorAll (` [data-non-interactable="${stepIndex }"] ` )
409
438
.forEach ((el ) => {
410
439
el .removeAttribute (' data-non-interactable' );
411
440
});
412
441
413
- document
414
- .querySelectorAll (` [data-opacified="${stepIndex }"] ` )
442
+ document .querySelectorAll (` [data-opacified="${stepIndex }"] ` )
415
443
.forEach ((el ) => {
416
444
el .removeAttribute (' data-opacified' );
417
445
});
446
+
447
+ document .querySelectorAll (` [data-scroll-locked="${stepIndex }"] ` )
448
+ .forEach ((el ) => {
449
+ el .removeAttribute (' data-scroll-locked' );
450
+ el .addEventListener (' scroll' , (e ) => _onScrollLockedElement (e , el ));
451
+ });
418
452
}
419
453
420
454
async function endTour(soft = false ) {
@@ -495,7 +529,7 @@ export default defineComponent({
495
529
// control bar
496
530
currentStep ,
497
531
nSteps ,
498
- isLoading: disconnected || isLoading ,
532
+ isLoading: computed (() => disconnected . value || isLoading . value ) ,
499
533
disableNextStep ,
500
534
501
535
// actions
@@ -509,7 +543,7 @@ export default defineComponent({
509
543
};
510
544
},
511
545
components: {
512
- CaretRightIcon ,
546
+ CaretRightSmallIcon ,
513
547
TourPreviousLeftArrowIcon ,
514
548
PartyConfettiIcon ,
515
549
CircleSpinner ,
@@ -530,24 +564,43 @@ export default defineComponent({
530
564
[data-tour-active ] [data-non-interactable ] * {
531
565
user-select : none !important ;
532
566
pointer-events : none !important ;
567
+ cursor : not-allowed ;
533
568
}
534
569
535
- [data-tour-active ]#app > * :not (.tour ):not (.tour-manager ) {
536
- cursor : not-allowed ;
570
+ [data-tour-active ] [data-scroll-locked ],
571
+ [data-tour-active ] [data-scroll-locked ] * {
572
+ overflow : hidden ;
537
573
}
538
574
539
- [data-tour-active ] button .highlighted {
575
+ [data-tour-active ] button .green-highlight {
540
576
background : linear-gradient (
541
577
274.28deg , rgba (255 , 255 , 255 , 0 ) 0% , rgba (255 , 255 , 255 , 0.2 ) 27.6% , rgba (255 , 255 , 255 , 0 ) 53.12% ,
542
578
rgba (255 , 255 , 255 , 0.2 ) 81.25% , rgba (255 , 255 , 255 , 0 ) 100%
543
- ),
544
- radial-gradient (100% 100% at 100% 100% , #41A38E 0% , #21BCA5 100% ) !important ;
579
+ ), var (--nimiq-green-bg ) !important ;
580
+ background-blend-mode : hard-light , normal !important ;
581
+ }
582
+
583
+ [data-tour-active ] button .gray-highlight {
584
+ background : linear-gradient (
585
+ 274.28deg , rgba (31 , 35 , 72 , 0 ) 0% , rgba (31 , 35 , 72 , 0.07 ) 27.6% , rgba (31 , 35 , 72 , 0 ) 53.12% ,
586
+ rgba (31 , 35 , 72 , 0.07 ) 81.25% , rgba (31 , 35 , 72 , 0 ) 100% ) !important ;
587
+ background-blend-mode : hard-light , normal !important ;
545
588
}
546
589
</style >
547
590
548
591
<style lang="scss" scoped>
549
592
.tour {
550
- position : relative ;
593
+ font-family : Mulish, Muli, -apple-system , BlinkMacSystemFont, " Segoe UI" ,
594
+ Roboto, Oxygen- Sans, Ubuntu, Cantarell, " Helvetica Neue" , sans-serif ;
595
+
596
+ position : absolute ;
597
+ width : 100vw ;
598
+ height : 100vh ;
599
+ pointer-events : none ;
600
+
601
+ > * {
602
+ pointer-events : initial ;
603
+ }
551
604
552
605
button {
553
606
width : min-content ;
@@ -571,6 +624,7 @@ export default defineComponent({
571
624
border-radius : 1rem ;
572
625
width : clamp (200px , 255px , calc (100vw - 2rem ));
573
626
padding : 2rem ;
627
+ z-index : 10 ;
574
628
575
629
.content {
576
630
display : flex ;
@@ -714,9 +768,7 @@ export default defineComponent({
714
768
grid-template-columns : 1fr 1fr 1fr ;
715
769
align-items : center ;
716
770
z-index : 6 ;
717
-
718
- // TODO Cannot use CSS variables here
719
- background : radial-gradient (100% 100% at 100% 100% , #265dd7 0% , #0582ca 100% );
771
+ background : var (--nimiq-light-blue-bg );
720
772
721
773
button {
722
774
padding : 1.4rem 1.6rem 1rem 1.6rem ;
@@ -749,14 +801,15 @@ export default defineComponent({
749
801
}
750
802
751
803
& .next {
752
- padding-left : 0.75rem ;
753
-
754
804
& .loading {
755
- padding-left : 0 ;
756
805
cursor : inherit ;
757
806
758
- & ::v- deep svg path: nth-child ( 1 ) {
807
+ & ::v- deep svg path {
759
808
stroke : var (--nimiq-white );
809
+
810
+ & :nth-child (2 ) {
811
+ opacity : 0.3 ;
812
+ }
760
813
}
761
814
}
762
815
}
@@ -772,6 +825,17 @@ export default defineComponent({
772
825
letter-spacing : -0.4px ;
773
826
font-variant-numeric : tabular-nums ;
774
827
}
828
+
829
+ }
830
+
831
+ [data-tour-active ] .flash {
832
+ animation : flash 0.4s ;
833
+ }
834
+
835
+ @keyframes flash {
836
+ from { background : var (--nimiq-light-blue-bg ); }
837
+ 50% { background : radial-gradient (100% 100% at bottom right , hsl (221 , 70% , 70% ), hsl (202 , 95% , 61% )); }
838
+ to { background : var (--nimiq-light-blue-bg ); }
775
839
}
776
840
777
841
.remove_me {
0 commit comments