UI updates and UX fixes
This commit is contained in:
parent
2320a5d404
commit
798051551c
@ -687,6 +687,7 @@ customElements.define('sm-input',
|
||||
this.clearBtn.removeEventListener('click', this.clear);
|
||||
}
|
||||
})
|
||||
|
||||
const smNotifications = document.createElement('template')
|
||||
smNotifications.innerHTML = `
|
||||
<style>
|
||||
@ -711,13 +712,14 @@ smNotifications.innerHTML = `
|
||||
gap: 0.5rem;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
max-height: 100%;
|
||||
padding: 1rem;
|
||||
overflow: hidden auto;
|
||||
-ms-scroll-chaining: none;
|
||||
overscroll-behavior: contain;
|
||||
touch-action: none;
|
||||
}
|
||||
.notification-panel:empty{
|
||||
display:none;
|
||||
@ -728,7 +730,7 @@ smNotifications.innerHTML = `
|
||||
display: flex;
|
||||
position: relative;
|
||||
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-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
@ -741,6 +743,7 @@ smNotifications.innerHTML = `
|
||||
max-width: 100%;
|
||||
padding: 1rem;
|
||||
align-items: center;
|
||||
touch-action: none;
|
||||
}
|
||||
.icon-container:not(:empty){
|
||||
margin-right: 0.5rem;
|
||||
@ -804,6 +807,8 @@ smNotifications.innerHTML = `
|
||||
.notification-panel{
|
||||
max-width: 28rem;
|
||||
width: max-content;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
.notification{
|
||||
width: auto;
|
||||
@ -829,8 +834,6 @@ smNotifications.innerHTML = `
|
||||
</style>
|
||||
<div class="notification-panel"></div>
|
||||
`;
|
||||
|
||||
|
||||
customElements.define('sm-notifications', class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
@ -849,7 +852,23 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
||||
this.createNotification = this.createNotification.bind(this)
|
||||
this.removeNotification = this.removeNotification.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) {
|
||||
@ -884,28 +903,45 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
||||
|
||||
push(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([
|
||||
{
|
||||
transform: `translateY(1rem)`,
|
||||
transform: `translateY(-1rem)`,
|
||||
opacity: '0'
|
||||
},
|
||||
{
|
||||
transform: `none`,
|
||||
opacity: '1'
|
||||
},
|
||||
], this.animationOptions);
|
||||
], this.animationOptions).onfinish = (e) => {
|
||||
e.target.commitStyles()
|
||||
e.target.cancel()
|
||||
}
|
||||
return notification.id;
|
||||
}
|
||||
|
||||
removeNotification(notification) {
|
||||
removeNotification(notification, direction = 'left') {
|
||||
const sign = direction === 'left' ? '-' : '+';
|
||||
notification.animate([
|
||||
{
|
||||
transform: `none`,
|
||||
transform: this.currentX ? `translateX(${this.currentX}px)` : `none`,
|
||||
opacity: '1'
|
||||
},
|
||||
{
|
||||
transform: `translateY(0.5rem)`,
|
||||
transform: `translateX(calc(${sign}${this.currentX}px ${sign} 1rem))`,
|
||||
opacity: '0'
|
||||
}
|
||||
], 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() {
|
||||
|
||||
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 => {
|
||||
if (e.target.closest('.close')) {
|
||||
this.removeNotification(e.target.closest('.notification'));
|
||||
@ -941,7 +1040,11 @@ customElements.define('sm-notifications', class extends HTMLElement {
|
||||
childList: true,
|
||||
});
|
||||
}
|
||||
disconnectedCallback() {
|
||||
mediaQueryList.removeEventListener('change', handleOrientationChange);
|
||||
}
|
||||
});
|
||||
|
||||
class Stack {
|
||||
constructor() {
|
||||
this.items = [];
|
||||
|
||||
@ -818,9 +818,11 @@ sm-checkbox {
|
||||
}
|
||||
|
||||
#wallet {
|
||||
display: grid;
|
||||
width: auto;
|
||||
gap: 1.5rem;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
align-content: flex-start;
|
||||
width: min(24rem, 100%);
|
||||
}
|
||||
|
||||
.wallet_actions__wrapper {
|
||||
@ -838,15 +840,25 @@ sm-checkbox {
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
#my_assets {
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
gap: 0.3rem 0.5rem;
|
||||
gap: 0 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
padding: 0.5rem;
|
||||
}
|
||||
.balance-card.is-locked {
|
||||
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) {
|
||||
grid-template-columns: auto 1fr auto auto;
|
||||
@ -869,7 +881,7 @@ sm-checkbox {
|
||||
font-weight: 500;
|
||||
}
|
||||
.balance-card__amount-wrapper {
|
||||
grid-column: span 2;
|
||||
grid-column: 2/3;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
@ -1093,6 +1105,12 @@ sm-checkbox {
|
||||
grid-template-columns: 1fr 90vw 1fr;
|
||||
}
|
||||
|
||||
.mobile-page {
|
||||
padding: 2rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
}
|
||||
|
||||
.hide-on-desktop {
|
||||
display: none !important;
|
||||
}
|
||||
@ -1197,6 +1215,18 @@ sm-checkbox {
|
||||
#asset_page__nav {
|
||||
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) {
|
||||
.page-layout {
|
||||
|
||||
2
docs/css/main.min.css
vendored
2
docs/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -784,9 +784,11 @@ sm-checkbox {
|
||||
}
|
||||
}
|
||||
#wallet {
|
||||
display: grid;
|
||||
width: auto;
|
||||
gap: 1.5rem;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
align-content: flex-start;
|
||||
width: min(24rem, 100%);
|
||||
}
|
||||
.wallet_actions__wrapper {
|
||||
grid-column: span 3;
|
||||
@ -801,14 +803,23 @@ sm-checkbox {
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
#my_assets {
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.balance-card {
|
||||
display: grid;
|
||||
align-items: center;
|
||||
gap: 0.3rem 0.5rem;
|
||||
gap: 0 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
padding: 0.5rem;
|
||||
&.is-locked {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
gap: 1rem;
|
||||
gap: 0.5rem;
|
||||
.balance-card__icon {
|
||||
grid-row: span 2;
|
||||
}
|
||||
}
|
||||
&:not(.is-locked) {
|
||||
grid-template-columns: auto 1fr auto auto;
|
||||
@ -831,7 +842,7 @@ sm-checkbox {
|
||||
font-weight: 500;
|
||||
}
|
||||
&__amount-wrapper {
|
||||
grid-column: span 2;
|
||||
grid-column: 2/3;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
& > :nth-child(even) {
|
||||
@ -1011,6 +1022,11 @@ sm-checkbox {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 90vw 1fr;
|
||||
}
|
||||
.mobile-page {
|
||||
padding: 2rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: rgba(var(--foreground-color), 1);
|
||||
}
|
||||
.hide-on-desktop {
|
||||
display: none !important;
|
||||
}
|
||||
@ -1108,6 +1124,17 @@ sm-checkbox {
|
||||
#asset_page__nav {
|
||||
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) {
|
||||
.page-layout {
|
||||
|
||||
@ -5,7 +5,8 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<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>
|
||||
<link rel="stylesheet" href="css/main.min.css">
|
||||
@ -43,7 +44,16 @@
|
||||
</div>
|
||||
</sm-form>
|
||||
</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">
|
||||
<div class="logo">
|
||||
<svg class="main-logo" viewBox="0 0 27.25 32">
|
||||
@ -73,7 +83,7 @@
|
||||
<p>Please login for exchange.</p>
|
||||
</div>
|
||||
<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-checkbox id="remember_me" checked>
|
||||
<span class="margin-left-0-5">
|
||||
@ -235,7 +245,7 @@
|
||||
</p>
|
||||
</section>
|
||||
<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"
|
||||
viewBox="0 0 24 24" width="24px">
|
||||
<path d="M0 0h24v24H0V0z" fill="none" />
|
||||
@ -263,16 +273,11 @@
|
||||
<div class="grid gap-0-5">
|
||||
<div class="flex align-center space-between">
|
||||
<h4>Balance</h4>
|
||||
<button onclick="refresh();" title="Refresh" style="margin-left: 1rem;">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||
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 class="button" onclick="refresh();" title="Refresh">
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
<ul id="my_assets" class="grid gap-1"></ul>
|
||||
<ul id="my_assets" class="grid"></ul>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@ -396,26 +401,6 @@
|
||||
<sm-button class="danger" onclick="UI_evt.logout();">Log out</sm-button>
|
||||
</section>
|
||||
</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">
|
||||
<header slot="header" class="popup__header">
|
||||
<button class="popup__header__close" onclick="hidePopup()">
|
||||
@ -438,9 +423,6 @@
|
||||
<sm-copy id="generated_private_key"></sm-copy>
|
||||
</div>
|
||||
</div>
|
||||
<sm-button id="sign_up_button" variant="primary" onclick="registerID()" style="display: none;" disabled>
|
||||
Register these credentials
|
||||
</sm-button>
|
||||
<strong class="warning">
|
||||
Keep your private key secure and don't share with anyone.
|
||||
Once lost there is no way to recover private key.
|
||||
@ -2078,7 +2060,14 @@
|
||||
getRef('sign_in_code').value = response.code;
|
||||
getRef('sign_in_hash').value = response.hash;
|
||||
proxy.clear();
|
||||
setTimeout(() => {
|
||||
getRef('login_form__priv_key').focusIn()
|
||||
}, 0);
|
||||
}).catch(error => console.error(error))
|
||||
.finally(() => {
|
||||
getRef('loading').classList.add('hide')
|
||||
getRef('home').classList.remove('hide')
|
||||
})
|
||||
}
|
||||
} else
|
||||
console.info("refresh");
|
||||
@ -2149,26 +2138,12 @@
|
||||
})
|
||||
.finally(() => {
|
||||
hideProcess('login_button_wrapper')
|
||||
getRef('loading').classList.add('hide')
|
||||
getRef('home').classList.remove('hide')
|
||||
})
|
||||
};
|
||||
|
||||
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() {
|
||||
getConfirmation('Log out?', { cancelText: 'Stay', confirmText: 'Log out' }).then(async res => {
|
||||
if (res) {
|
||||
@ -2202,12 +2177,6 @@
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function registerID() {
|
||||
UI_evt.signup(getRef('generated_private_key').value)
|
||||
hidePopup()
|
||||
}
|
||||
|
||||
window.addEventListener('load', e => {
|
||||
floExchangeAPI.init().then(nodes => {
|
||||
console.log(nodes);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user