UI updates and UX fixes

This commit is contained in:
sairaj mote 2022-04-11 17:24:03 +05:30
parent 2320a5d404
commit 798051551c
5 changed files with 205 additions and 76 deletions

View File

@ -687,6 +687,7 @@ customElements.define('sm-input',
this.clearBtn.removeEventListener('click', this.clear); this.clearBtn.removeEventListener('click', this.clear);
} }
}) })
const smNotifications = document.createElement('template') const smNotifications = document.createElement('template')
smNotifications.innerHTML = ` smNotifications.innerHTML = `
<style> <style>
@ -711,13 +712,14 @@ smNotifications.innerHTML = `
gap: 0.5rem; gap: 0.5rem;
position: fixed; position: fixed;
left: 0; left: 0;
bottom: 0; top: 0;
z-index: 100; z-index: 100;
max-height: 100%; max-height: 100%;
padding: 1rem; padding: 1rem;
overflow: hidden auto; overflow: hidden auto;
-ms-scroll-chaining: none; -ms-scroll-chaining: none;
overscroll-behavior: contain; overscroll-behavior: contain;
touch-action: none;
} }
.notification-panel:empty{ .notification-panel:empty{
display:none; display:none;
@ -728,7 +730,7 @@ smNotifications.innerHTML = `
display: flex; display: flex;
position: relative; position: relative;
border-radius: 0.3rem; border-radius: 0.3rem;
background: rgba(var(--background-color, (255,255,255)), 1); background: rgba(var(--foreground-color, (255,255,255)), 1);
overflow: hidden; overflow: hidden;
overflow-wrap: break-word; overflow-wrap: break-word;
word-wrap: break-word; word-wrap: break-word;
@ -741,6 +743,7 @@ smNotifications.innerHTML = `
max-width: 100%; max-width: 100%;
padding: 1rem; padding: 1rem;
align-items: center; align-items: center;
touch-action: none;
} }
.icon-container:not(:empty){ .icon-container:not(:empty){
margin-right: 0.5rem; margin-right: 0.5rem;
@ -804,6 +807,8 @@ smNotifications.innerHTML = `
.notification-panel{ .notification-panel{
max-width: 28rem; max-width: 28rem;
width: max-content; width: max-content;
top: auto;
bottom: 0;
} }
.notification{ .notification{
width: auto; width: auto;
@ -829,8 +834,6 @@ smNotifications.innerHTML = `
</style> </style>
<div class="notification-panel"></div> <div class="notification-panel"></div>
`; `;
customElements.define('sm-notifications', class extends HTMLElement { customElements.define('sm-notifications', class extends HTMLElement {
constructor() { constructor() {
super(); super();
@ -849,7 +852,23 @@ customElements.define('sm-notifications', class extends HTMLElement {
this.createNotification = this.createNotification.bind(this) this.createNotification = this.createNotification.bind(this)
this.removeNotification = this.removeNotification.bind(this) this.removeNotification = this.removeNotification.bind(this)
this.clearAll = this.clearAll.bind(this) this.clearAll = this.clearAll.bind(this)
this.handlePointerMove = this.handlePointerMove.bind(this)
this.startX = 0;
this.currentX = 0;
this.endX = 0;
this.swipeDistance = 0;
this.swipeDirection = '';
this.swipeThreshold = 0;
this.startTime = 0;
this.swipeTime = 0;
this.swipeTimeThreshold = 200;
this.currentTarget = null;
this.mediaQuery = window.matchMedia('(min-width: 640px)')
this.handleOrientationChange = this.handleOrientationChange.bind(this)
this.isLandscape = false
} }
randString(length) { randString(length) {
@ -884,28 +903,45 @@ customElements.define('sm-notifications', class extends HTMLElement {
push(message, options = {}) { push(message, options = {}) {
const notification = this.createNotification(message, options); const notification = this.createNotification(message, options);
this.notificationPanel.append(notification); if (this.isLandscape)
this.notificationPanel.append(notification);
else
this.notificationPanel.prepend(notification);
this.notificationPanel.animate(
[
{
transform: `translateY(${this.isLandscape ? '' : '-'}${notification.clientHeight}px)`,
},
{
transform: `none`,
},
], this.animationOptions
)
notification.animate([ notification.animate([
{ {
transform: `translateY(1rem)`, transform: `translateY(-1rem)`,
opacity: '0' opacity: '0'
}, },
{ {
transform: `none`, transform: `none`,
opacity: '1' opacity: '1'
}, },
], this.animationOptions); ], this.animationOptions).onfinish = (e) => {
e.target.commitStyles()
e.target.cancel()
}
return notification.id; return notification.id;
} }
removeNotification(notification) { removeNotification(notification, direction = 'left') {
const sign = direction === 'left' ? '-' : '+';
notification.animate([ notification.animate([
{ {
transform: `none`, transform: this.currentX ? `translateX(${this.currentX}px)` : `none`,
opacity: '1' opacity: '1'
}, },
{ {
transform: `translateY(0.5rem)`, transform: `translateX(calc(${sign}${this.currentX}px ${sign} 1rem))`,
opacity: '0' opacity: '0'
} }
], this.animationOptions).onfinish = () => { ], this.animationOptions).onfinish = () => {
@ -919,7 +955,70 @@ customElements.define('sm-notifications', class extends HTMLElement {
}); });
} }
handlePointerMove(e) {
this.currentX = e.clientX - this.startX;
this.currentTarget.style.transform = `translateX(${this.currentX}px)`;
}
handleOrientationChange(e) {
this.isLandscape = e.matches
if (e.matches) {
// landscape
} else {
// portrait
}
}
connectedCallback() { connectedCallback() {
this.handleOrientationChange(this.mediaQuery);
this.mediaQuery.addEventListener('change', this.handleOrientationChange);
this.notificationPanel.addEventListener('pointerdown', e => {
if (e.target.closest('.notification')) {
this.swipeThreshold = this.clientWidth / 2;
this.currentTarget = e.target.closest('.notification');
this.currentTarget.setPointerCapture(e.pointerId);
this.startTime = Date.now();
this.startX = e.clientX;
this.startY = e.clientY;
this.notificationPanel.addEventListener('pointermove', this.handlePointerMove);
}
});
this.notificationPanel.addEventListener('pointerup', e => {
this.endX = e.clientX;
this.endY = e.clientY;
this.swipeDistance = Math.abs(this.endX - this.startX);
this.swipeTime = Date.now() - this.startTime;
if (this.endX > this.startX) {
this.swipeDirection = 'right';
} else {
this.swipeDirection = 'left';
}
if (this.swipeTime < this.swipeTimeThreshold) {
if (this.swipeDistance > 50)
this.removeNotification(this.currentTarget, this.swipeDirection);
} else {
if (this.swipeDistance > this.swipeThreshold) {
this.removeNotification(this.currentTarget, this.swipeDirection);
} else {
this.currentTarget.animate([
{
transform: `translateX(${this.currentX}px)`,
},
{
transform: `none`,
},
], this.animationOptions).onfinish = (e) => {
e.target.commitStyles()
e.target.cancel()
}
}
}
this.notificationPanel.removeEventListener('pointermove', this.handlePointerMove)
this.notificationPanel.releasePointerCapture(e.pointerId);
this.currentX = 0;
});
this.notificationPanel.addEventListener('click', e => { this.notificationPanel.addEventListener('click', e => {
if (e.target.closest('.close')) { if (e.target.closest('.close')) {
this.removeNotification(e.target.closest('.notification')); this.removeNotification(e.target.closest('.notification'));
@ -941,7 +1040,11 @@ customElements.define('sm-notifications', class extends HTMLElement {
childList: true, childList: true,
}); });
} }
disconnectedCallback() {
mediaQueryList.removeEventListener('change', handleOrientationChange);
}
}); });
class Stack { class Stack {
constructor() { constructor() {
this.items = []; this.items = [];

View File

@ -818,9 +818,11 @@ sm-checkbox {
} }
#wallet { #wallet {
display: grid;
width: auto;
gap: 1.5rem; gap: 1.5rem;
grid-template-columns: minmax(0, 1fr);
align-content: flex-start; align-content: flex-start;
width: min(24rem, 100%);
} }
.wallet_actions__wrapper { .wallet_actions__wrapper {
@ -838,15 +840,25 @@ sm-checkbox {
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
} }
#my_assets {
gap: 0.5rem;
margin-top: 0.5rem;
}
.balance-card { .balance-card {
display: grid; display: grid;
align-items: center; align-items: center;
gap: 0.3rem 0.5rem; gap: 0 0.5rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1);
padding: 0.5rem;
} }
.balance-card.is-locked { .balance-card.is-locked {
grid-template-columns: auto 1fr auto; grid-template-columns: auto 1fr auto;
gap: 1rem; gap: 0.5rem;
}
.balance-card.is-locked .balance-card__icon {
grid-row: span 2;
} }
.balance-card:not(.is-locked) { .balance-card:not(.is-locked) {
grid-template-columns: auto 1fr auto auto; grid-template-columns: auto 1fr auto auto;
@ -869,7 +881,7 @@ sm-checkbox {
font-weight: 500; font-weight: 500;
} }
.balance-card__amount-wrapper { .balance-card__amount-wrapper {
grid-column: span 2; grid-column: 2/3;
gap: 0.3rem 1rem; gap: 0.3rem 1rem;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
@ -1093,6 +1105,12 @@ sm-checkbox {
grid-template-columns: 1fr 90vw 1fr; grid-template-columns: 1fr 90vw 1fr;
} }
.mobile-page {
padding: 2rem;
border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1);
}
.hide-on-desktop { .hide-on-desktop {
display: none !important; display: none !important;
} }
@ -1197,6 +1215,18 @@ sm-checkbox {
#asset_page__nav { #asset_page__nav {
grid-column: 1/-1; grid-column: 1/-1;
} }
#wallet {
gap: 1rem 2rem;
grid-template-columns: 20rem 24rem;
}
#wallet__header {
grid-column: 1/3;
padding-bottom: 1rem;
}
#wallet .balance-card {
border: solid thin rgba(var(--text-color), 0.2);
}
} }
@media screen and (min-width: 72rem) { @media screen and (min-width: 72rem) {
.page-layout { .page-layout {

File diff suppressed because one or more lines are too long

View File

@ -784,9 +784,11 @@ sm-checkbox {
} }
} }
#wallet { #wallet {
display: grid;
width: auto;
gap: 1.5rem; gap: 1.5rem;
grid-template-columns: minmax(0, 1fr);
align-content: flex-start; align-content: flex-start;
width: min(24rem, 100%);
} }
.wallet_actions__wrapper { .wallet_actions__wrapper {
grid-column: span 3; grid-column: span 3;
@ -801,14 +803,23 @@ sm-checkbox {
color: rgba(var(--text-color), 0.8); color: rgba(var(--text-color), 0.8);
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
} }
#my_assets {
gap: 0.5rem;
margin-top: 0.5rem;
}
.balance-card { .balance-card {
display: grid; display: grid;
align-items: center; align-items: center;
gap: 0.3rem 0.5rem; gap: 0 0.5rem;
border-radius: 0.5rem; border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1);
padding: 0.5rem;
&.is-locked { &.is-locked {
grid-template-columns: auto 1fr auto; grid-template-columns: auto 1fr auto;
gap: 1rem; gap: 0.5rem;
.balance-card__icon {
grid-row: span 2;
}
} }
&:not(.is-locked) { &:not(.is-locked) {
grid-template-columns: auto 1fr auto auto; grid-template-columns: auto 1fr auto auto;
@ -831,7 +842,7 @@ sm-checkbox {
font-weight: 500; font-weight: 500;
} }
&__amount-wrapper { &__amount-wrapper {
grid-column: span 2; grid-column: 2/3;
gap: 0.3rem 1rem; gap: 0.3rem 1rem;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
& > :nth-child(even) { & > :nth-child(even) {
@ -1011,6 +1022,11 @@ sm-checkbox {
.page-layout { .page-layout {
grid-template-columns: 1fr 90vw 1fr; grid-template-columns: 1fr 90vw 1fr;
} }
.mobile-page {
padding: 2rem;
border-radius: 0.5rem;
background-color: rgba(var(--foreground-color), 1);
}
.hide-on-desktop { .hide-on-desktop {
display: none !important; display: none !important;
} }
@ -1108,6 +1124,17 @@ sm-checkbox {
#asset_page__nav { #asset_page__nav {
grid-column: 1/-1; grid-column: 1/-1;
} }
#wallet {
gap: 1rem 2rem;
grid-template-columns: 20rem 24rem;
&__header {
grid-column: 1/3;
padding-bottom: 1rem;
}
.balance-card {
border: solid thin rgba(var(--text-color), 0.2);
}
}
} }
@media screen and (min-width: 72rem) { @media screen and (min-width: 72rem) {
.page-layout { .page-layout {

View File

@ -5,7 +5,8 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RanchiMall market</title> <title>RanchiMall exchange</title>
<meta name="description" content="Trade FLO and FLO based RanchiMall tokens.">
<script src="css/components.js" defer></script> <script src="css/components.js" defer></script>
<link rel="stylesheet" href="css/main.min.css"> <link rel="stylesheet" href="css/main.min.css">
@ -43,7 +44,16 @@
</div> </div>
</sm-form> </sm-form>
</sm-popup> </sm-popup>
<article id="home" class="page"> <div id="loading" class="page flex align-center justify-center">
<div class="grid gap-2 text-center">
<sm-spinner></sm-spinner>
<div class="grid gap-0-5">
<h4>RanchiMall Exchange</h4>
<p>Getting everything ready</p>
</div>
</div>
</div>
<article id="home" class="page hide">
<header id="main_header"> <header id="main_header">
<div class="logo"> <div class="logo">
<svg class="main-logo" viewBox="0 0 27.25 32"> <svg class="main-logo" viewBox="0 0 27.25 32">
@ -73,7 +83,7 @@
<p>Please login for exchange.</p> <p>Please login for exchange.</p>
</div> </div>
<sm-input type="password" id="login_form__priv_key" placeholder="Private key" <sm-input type="password" id="login_form__priv_key" placeholder="Private key"
error-text="Invalid private key" data-private-key animate required> error-text="Invalid private key" data-private-key autofocus animate required>
</sm-input> </sm-input>
<sm-checkbox id="remember_me" checked> <sm-checkbox id="remember_me" checked>
<span class="margin-left-0-5"> <span class="margin-left-0-5">
@ -235,7 +245,7 @@
</p> </p>
</section> </section>
<section id="wallet" class="grid mobile-page hide"> <section id="wallet" class="grid mobile-page hide">
<h4 class="flex align-center user_section__header"> <h4 id="wallet__header" class="flex align-center">
<svg xmlns="http://www.w3.org/2000/svg" class="icon margin-right-0-5" height="24px" <svg xmlns="http://www.w3.org/2000/svg" class="icon margin-right-0-5" height="24px"
viewBox="0 0 24 24" width="24px"> viewBox="0 0 24 24" width="24px">
<path d="M0 0h24v24H0V0z" fill="none" /> <path d="M0 0h24v24H0V0z" fill="none" />
@ -263,16 +273,11 @@
<div class="grid gap-0-5"> <div class="grid gap-0-5">
<div class="flex align-center space-between"> <div class="flex align-center space-between">
<h4>Balance</h4> <h4>Balance</h4>
<button onclick="refresh();" title="Refresh" style="margin-left: 1rem;"> <button class="button" onclick="refresh();" title="Refresh">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" Refresh
width="24px" fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
</svg>
</button> </button>
</div> </div>
<ul id="my_assets" class="grid gap-1"></ul> <ul id="my_assets" class="grid"></ul>
</div> </div>
</section> </section>
</section> </section>
@ -396,26 +401,6 @@
<sm-button class="danger" onclick="UI_evt.logout();">Log out</sm-button> <sm-button class="danger" onclick="UI_evt.logout();">Log out</sm-button>
</section> </section>
</sm-popup> </sm-popup>
<sm-popup id="registration_popup">
<header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<path fill="none" d="M0 0h24v24H0z" />
<path
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z" />
</svg>
</button>
<h4>Register</h4>
</header>
<div class="grid gap-1-5">
<sm-form id="register_section">
<p>Enter the private key of FLO ID you want to register.</p>
<sm-input id="get_registration_key" placeholder="Private key" type="password" required>
</sm-input>
<sm-button variant="primary" onclick="UI_evt.signup()" disabled>Register</sm-button>
</sm-form>
</div>
</sm-popup>
<sm-popup id="sign_up_popup"> <sm-popup id="sign_up_popup">
<header slot="header" class="popup__header"> <header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()"> <button class="popup__header__close" onclick="hidePopup()">
@ -438,9 +423,6 @@
<sm-copy id="generated_private_key"></sm-copy> <sm-copy id="generated_private_key"></sm-copy>
</div> </div>
</div> </div>
<sm-button id="sign_up_button" variant="primary" onclick="registerID()" style="display: none;" disabled>
Register these credentials
</sm-button>
<strong class="warning"> <strong class="warning">
Keep your private key secure and don't share with anyone. Keep your private key secure and don't share with anyone.
Once lost there is no way to recover private key. Once lost there is no way to recover private key.
@ -2078,7 +2060,14 @@
getRef('sign_in_code').value = response.code; getRef('sign_in_code').value = response.code;
getRef('sign_in_hash').value = response.hash; getRef('sign_in_hash').value = response.hash;
proxy.clear(); proxy.clear();
setTimeout(() => {
getRef('login_form__priv_key').focusIn()
}, 0);
}).catch(error => console.error(error)) }).catch(error => console.error(error))
.finally(() => {
getRef('loading').classList.add('hide')
getRef('home').classList.remove('hide')
})
} }
} else } else
console.info("refresh"); console.info("refresh");
@ -2149,26 +2138,12 @@
}) })
.finally(() => { .finally(() => {
hideProcess('login_button_wrapper') hideProcess('login_button_wrapper')
getRef('loading').classList.add('hide')
getRef('home').classList.remove('hide')
}) })
}; };
const UI_evt = { const UI_evt = {
signup(privKey) {
let code = getRef('sign_in_code').value,
hash = getRef('sign_in_hash').value;
if (!privKey)
privKey = getRef('get_registration_key').value.trim()
if (privKey !== '') {
floExchangeAPI.signUp(privKey, code, hash).then(result => {
console.info(result);
notify("Account registered!", 'success')
hidePopup()
}).catch(error => {
notify(error, 'error');
});
}
},
logout() { logout() {
getConfirmation('Log out?', { cancelText: 'Stay', confirmText: 'Log out' }).then(async res => { getConfirmation('Log out?', { cancelText: 'Stay', confirmText: 'Log out' }).then(async res => {
if (res) { if (res) {
@ -2202,12 +2177,6 @@
} }
}; };
function registerID() {
UI_evt.signup(getRef('generated_private_key').value)
hidePopup()
}
window.addEventListener('load', e => { window.addEventListener('load', e => {
floExchangeAPI.init().then(nodes => { floExchangeAPI.init().then(nodes => {
console.log(nodes); console.log(nodes);