Skip to content

Commit 0ea31ac

Browse files
committed
small tweaks and ui improvments
1 parent 7ecc535 commit 0ea31ac

24 files changed

+364
-156
lines changed

src/components/Tour.vue

Lines changed: 107 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,15 @@
8282
@click="goToPrevStep()"
8383
style="transform: rotate(180deg)"
8484
>
85-
<CaretRightIcon />
85+
<CaretRightSmallIcon />
8686
</button>
8787
<button
8888
class="next"
8989
:class="{ loading: isLoading }"
9090
:disabled="disableNextStep"
9191
@click="!isLoading && goToNextStep()"
9292
>
93-
<CaretRightIcon v-if="!isLoading" />
93+
<CaretRightSmallIcon v-if="!isLoading" />
9494
<CircleSpinner v-else class="circle-spinner" />
9595
</button>
9696
</div>
@@ -102,7 +102,7 @@
102102
import { useAccountStore } from '@/stores/Account';
103103
import { useNetworkStore } from '@/stores/Network';
104104
import { useTransactionsStore } from '@/stores/Transactions';
105-
import { CircleSpinner } from '@nimiq/vue-components';
105+
import { CircleSpinner, CaretRightSmallIcon } from '@nimiq/vue-components';
106106
import {
107107
computed,
108108
defineComponent,
@@ -120,8 +120,8 @@ import {
120120
getTour,
121121
MountedReturnFn, TourBroadcast, TourStep,
122122
TourStepIndex,
123+
WalletHTMLElements,
123124
} from '../lib/tour';
124-
import CaretRightIcon from './icons/CaretRightIcon.vue';
125125
import PartyConfettiIcon from './icons/PartyConfettiIcon.vue';
126126
import TourPreviousLeftArrowIcon from './icons/TourPreviousLeftArrowIcon.vue';
127127
@@ -217,7 +217,10 @@ export default defineComponent({
217217
isLoading.value = false;
218218
219219
window.addEventListener('keyup', _onKeyDown);
220-
window.addEventListener('click', _userClicked());
220+
setTimeout(() => {
221+
window.addEventListener('click', _userClicked());
222+
}, 100); // avoid click event to be triggered by the setting button
223+
221224
// window.addEventListener('resize', _OnResize(_OnResizeEnd)); TODO
222225
223226
const app = document.querySelector('#app');
@@ -236,22 +239,26 @@ export default defineComponent({
236239
// Dont allow user to interact with the page while it is loading
237240
// But allow to end it
238241
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
242+
// TODO Avoid interaction with any of the elements when loading except tour elements (bar, manager and tooltip)
243+
// const elements = Object.values(WalletHTMLElements).filter((e) => e);
244+
// if (isLoading.value || disconnected.value) {
245+
// elements.forEach((element) => {
246+
// const el = document.querySelector(element);
247+
// if (!el) return;
248+
// el.setAttribute('data-non-interactable', 'loading');
249+
// });
250+
// } else {
251+
// elements.forEach((element) => {
252+
// const el = document.querySelector(element);
253+
// if (!el) return;
254+
// el.removeAttribute('data-non-interactable');
255+
// });
256+
// }
257+
258+
// FIXME we should wait until the buttons are rendered and the we could
248259
// 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));
260+
// it takes to render the button. I don't know how to fix it. Waiting 500ms works.
261+
await sleep(500);
255262
_toggleDisabledButtons(steps[currentStep.value]?.ui.disabledButtons, true);
256263
});
257264
@@ -274,7 +281,6 @@ export default defineComponent({
274281
const { path: currentPath, ui: currentUI } = steps[currentStepIndex]!;
275282
const { path: futurePath, ui: futureUI, lifecycle: futureLifecycle } = steps[futureStepIndex]!;
276283
277-
isLoading.value = true;
278284
tour!.stop();
279285
280286
await sleep(500);
@@ -294,6 +300,7 @@ export default defineComponent({
294300
_toggleDisabledButtons(currentUI.disabledButtons, false);
295301
_toggleDisabledButtons(futureUI.disabledButtons, true);
296302
_addAttributes(futureUI, futureStepIndex);
303+
await context.root.$nextTick();
297304
298305
if (futurePath !== currentPath) {
299306
await sleep(500);
@@ -302,14 +309,14 @@ export default defineComponent({
302309
_removeAttributes(currentStepIndex);
303310
304311
tour!.start(futureStepIndex.toString());
312+
await context.root.$nextTick();
305313
306314
// FIXME Instead of doing tour!.end and tour!.start, we could also use .nextStep() or previsousStep()
307315
// The problem with this solution is that some animations glitch the UI so it needs further
308316
// investigation
309317
// goingForward ? tour!.nextStep() : tour!.previousStep();
310318
311319
// mounted
312-
isLoading.value = false;
313320
disableNextStep.value = futureStepIndex >= nSteps.value - 1 || !!futureUI.isNextStepDisabled;
314321
315322
unmounted = await futureLifecycle?.mounted?.({
@@ -338,6 +345,17 @@ export default defineComponent({
338345
context.root.$on('nimiq-tour-event', (data: TourBroadcast) => {
339346
if (data.type === 'end-tour') endTour();
340347
});
348+
context.root.$on('nimiq-tour-event', (data: TourBroadcast) => {
349+
if (data.type === 'clicked-outside-tour') {
350+
const tourManager = document.querySelector('.tour-control-bar');
351+
if (tourManager) {
352+
tourManager.classList.add('flash');
353+
setTimeout(() => {
354+
tourManager.classList.remove('flash');
355+
}, 400);
356+
}
357+
}
358+
});
341359
}
342360
343361
function _userClicked() {
@@ -382,12 +400,17 @@ export default defineComponent({
382400
}
383401
}
384402
403+
function _onScrollLockedElement(e: Event, el: Element) {
404+
e.preventDefault();
405+
el.scrollTop = 0;
406+
}
385407
function _addAttributes(
386408
uiConfig: TourStep['ui'],
387409
stepIndex: TourStepIndex,
388410
) {
389411
const fadedElements = uiConfig.fadedElements || [];
390412
const disabledElements = uiConfig.disabledElements || [];
413+
const scrollLockedElements = uiConfig.scrollLockedElements || [];
391414
392415
disabledElements.filter((e) => e).forEach((element) => {
393416
const el = document.querySelector(element);
@@ -401,20 +424,33 @@ export default defineComponent({
401424
el.setAttribute('data-opacified', stepIndex.toString());
402425
el.setAttribute('data-non-interactable', stepIndex.toString());
403426
});
427+
428+
scrollLockedElements.filter((e) => e).forEach((element) => {
429+
const el = document.querySelector(element);
430+
if (!el) return;
431+
el.setAttribute('data-scroll-locked', stepIndex.toString());
432+
// Avoid scrolling when tooltip is instantiated
433+
el.addEventListener('scroll', (e) => _onScrollLockedElement(e, el));
434+
el.scrollTop = 0;
435+
});
404436
}
405437
406438
function _removeAttributes(stepIndex: TourStepIndex) {
407-
document
408-
.querySelectorAll(`[data-non-interactable="${stepIndex}"]`)
439+
document.querySelectorAll(`[data-non-interactable="${stepIndex}"]`)
409440
.forEach((el) => {
410441
el.removeAttribute('data-non-interactable');
411442
});
412443
413-
document
414-
.querySelectorAll(`[data-opacified="${stepIndex}"]`)
444+
document.querySelectorAll(`[data-opacified="${stepIndex}"]`)
415445
.forEach((el) => {
416446
el.removeAttribute('data-opacified');
417447
});
448+
449+
document.querySelectorAll(`[data-scroll-locked="${stepIndex}"]`)
450+
.forEach((el) => {
451+
el.removeAttribute('data-scroll-locked');
452+
el.addEventListener('scroll', (e) => _onScrollLockedElement(e, el));
453+
});
418454
}
419455
420456
async function endTour(soft = false) {
@@ -495,7 +531,7 @@ export default defineComponent({
495531
// control bar
496532
currentStep,
497533
nSteps,
498-
isLoading: disconnected || isLoading,
534+
isLoading: computed(() => disconnected.value || isLoading.value),
499535
disableNextStep,
500536
501537
// actions
@@ -509,7 +545,7 @@ export default defineComponent({
509545
};
510546
},
511547
components: {
512-
CaretRightIcon,
548+
CaretRightSmallIcon,
513549
TourPreviousLeftArrowIcon,
514550
PartyConfettiIcon,
515551
CircleSpinner,
@@ -530,24 +566,43 @@ export default defineComponent({
530566
[data-tour-active] [data-non-interactable] * {
531567
user-select: none !important;
532568
pointer-events: none !important;
569+
cursor: not-allowed;
533570
}
534571
535-
[data-tour-active]#app > *:not(.tour):not(.tour-manager) {
536-
cursor: not-allowed;
572+
[data-tour-active] [data-scroll-locked],
573+
[data-tour-active] [data-scroll-locked] * {
574+
overflow: hidden;
537575
}
538576
539-
[data-tour-active] button.highlighted {
577+
[data-tour-active] button.green-highlight {
540578
background: linear-gradient(
541579
274.28deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.2) 27.6%, rgba(255, 255, 255, 0) 53.12%,
542580
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;
581+
), var(--nimiq-green-bg) !important;
582+
background-blend-mode: hard-light, normal !important;
583+
}
584+
585+
[data-tour-active] button.gray-highlight {
586+
background: linear-gradient(
587+
274.28deg, rgba(31, 35, 72, 0) 0%, rgba(31, 35, 72, 0.07) 27.6%, rgba(31, 35, 72, 0) 53.12%,
588+
rgba(31, 35, 72, 0.07) 81.25%, rgba(31, 35, 72, 0) 100%) !important;
589+
background-blend-mode: hard-light, normal !important;
545590
}
546591
</style>
547592

548593
<style lang="scss" scoped>
549594
.tour {
550-
position: relative;
595+
font-family: Mulish, Muli, -apple-system, BlinkMacSystemFont, "Segoe UI",
596+
Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
597+
598+
position: absolute;
599+
width: 100vw;
600+
height: 100vh;
601+
pointer-events: none;
602+
603+
> * {
604+
pointer-events: initial;
605+
}
551606
552607
button {
553608
width: min-content;
@@ -571,6 +626,7 @@ export default defineComponent({
571626
border-radius: 1rem;
572627
width: clamp(200px, 255px, calc(100vw - 2rem));
573628
padding: 2rem;
629+
z-index: 10;
574630
575631
.content {
576632
display: flex;
@@ -714,9 +770,7 @@ export default defineComponent({
714770
grid-template-columns: 1fr 1fr 1fr;
715771
align-items: center;
716772
z-index: 6;
717-
718-
// TODO Cannot use CSS variables here
719-
background: radial-gradient(100% 100% at 100% 100%, #265dd7 0%, #0582ca 100%);
773+
background: var(--nimiq-light-blue-bg);
720774
721775
button {
722776
padding: 1.4rem 1.6rem 1rem 1.6rem;
@@ -749,14 +803,15 @@ export default defineComponent({
749803
}
750804
751805
&.next {
752-
padding-left: 0.75rem;
753-
754806
&.loading {
755-
padding-left: 0;
756807
cursor: inherit;
757808
758-
& ::v-deep svg path:nth-child(1) {
809+
& ::v-deep svg path {
759810
stroke: var(--nimiq-white);
811+
812+
&:nth-child(2) {
813+
opacity: 0.3;
814+
}
760815
}
761816
}
762817
}
@@ -772,6 +827,17 @@ export default defineComponent({
772827
letter-spacing: -0.4px;
773828
font-variant-numeric: tabular-nums;
774829
}
830+
831+
}
832+
833+
[data-tour-active] .flash {
834+
animation: flash 0.4s;
835+
}
836+
837+
@keyframes flash {
838+
from { background: var(--nimiq-light-blue-bg); }
839+
50% { background: radial-gradient(100% 100% at bottom right, hsl(221, 70%, 70%), hsl(202, 95%, 61%)); }
840+
to { background: var(--nimiq-light-blue-bg); }
775841
}
776842
777843
.remove_me {

0 commit comments

Comments
 (0)