UI/UX changes

This commit is contained in:
sairaj mote 2022-07-05 19:44:01 +05:30
parent c9eaaf8f57
commit b746e6d879
5 changed files with 2065 additions and 1953 deletions

View File

@ -730,155 +730,174 @@ customElements.define('sm-input',
this.clearBtn.removeEventListener('click', this.reset); this.clearBtn.removeEventListener('click', this.reset);
} }
}) })
//notifications
const smNotifications = document.createElement('template') const smNotifications = document.createElement('template')
smNotifications.innerHTML = ` smNotifications.innerHTML = `
<style> <style>
*{ *{
padding: 0; padding: 0;
margin: 0; margin: 0;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
} }
:host{ :host{
display: -webkit-box; display: flex;
display: -ms-flexbox; --icon-height: 1.5rem;
display: flex; --icon-width: 1.5rem;
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--danger-color: red;
--icon-height: 1.5rem;
--icon-width: 1.5rem;
}
.hide{
opacity: 0 !important;
pointer-events: none !important;
}
.notification-panel{
display: grid;
width: 100%;
gap: 0.5rem;
position: fixed;
left: 0;
bottom: 0;
z-index: 100;
max-height: 100%;
padding: 1rem;
overflow: hidden auto;
-ms-scroll-chaining: none;
overscroll-behavior: contain;
}
.notification-panel:empty{
display:none;
}
.notification{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: relative;
border-radius: 0.3rem;
background: rgba(var(--background-color), 1);
overflow: hidden;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
max-width: 100%;
padding: 1rem;
align-items: center;
}
.icon-container:not(:empty){
margin-right: 0.5rem;
height: var(--icon-height);
width: var(--icon-width);
}
h4:first-letter,
p:first-letter{
text-transform: uppercase;
}
h4{
font-weight: 400;
}
p{
line-height: 1.6;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
color: rgba(var(--text-color), 0.9);
overflow-wrap: break-word;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
max-width: 100%;
}
.notification:last-of-type{
margin-bottom: 0;
}
.icon {
height: 100%;
width: 100%;
fill: rgba(var(--text-color), 0.7);
}
.icon--success {
fill: var(--green);
}
.icon--failure,
.icon--error {
fill: var(--danger-color);
}
.close{
height: 2rem;
width: 2rem;
border: none;
cursor: pointer;
margin-left: 1rem;
border-radius: 50%;
padding: 0.3rem;
transition: background-color 0.3s, transform 0.3s;
background-color: transparent;
}
.close:active{
transform: scale(0.9);
}
@media screen and (min-width: 640px){
.notification-panel{
max-width: 28rem;
width: max-content;
}
.notification{
width: auto;
border: solid 1px rgba(var(--text-color), 0.2);
}
}
@media (any-hover: hover){
::-webkit-scrollbar{
width: 0.5rem;
}
::-webkit-scrollbar-thumb{
background: rgba(var(--text-color), 0.3);
border-radius: 1rem;
&:hover{
background: rgba(var(--text-color), 0.5);
} }
} .hide{
.close:hover{ opacity: 0 !important;
background-color: rgba(var(--text-color), 0.1); pointer-events: none !important;
} }
} .notification-panel{
</style> display: grid;
<div class="notification-panel"></div> width: 100%;
` gap: 0.5rem;
position: fixed;
left: 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;
}
.notification{
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: relative;
border-radius: 0.3rem;
background: rgba(var(--foreground-color, (255,255,255)), 1);
overflow: hidden;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
max-width: 100%;
padding: 1rem;
align-items: center;
box-shadow: 0 0.5rem 1rem 0 rgba(0,0,0,0.14);
touch-action: none;
}
.icon-container:not(:empty){
margin-right: 0.5rem;
height: var(--icon-height);
width: var(--icon-width);
}
h4:first-letter,
p:first-letter{
text-transform: uppercase;
}
h4{
font-weight: 400;
}
p{
line-height: 1.6;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
color: rgba(var(--text-color, (17,17,17)), 0.9);
overflow-wrap: break-word;
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-all;
word-break: break-word;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
max-width: 100%;
}
.notification:last-of-type{
margin-bottom: 0;
}
.icon {
height: 100%;
width: 100%;
fill: rgba(var(--text-color, (17,17,17)), 0.7);
}
.icon--success {
fill: var(--green);
}
.icon--failure,
.icon--error {
fill: var(--danger-color);
}
.close{
height: 2rem;
width: 2rem;
border: none;
cursor: pointer;
margin-left: 1rem;
border-radius: 50%;
padding: 0.3rem;
transition: background-color 0.3s, transform 0.3s;
background-color: transparent;
}
.close:active{
transform: scale(0.9);
}
.action{
display: flex;
align-items: center;
justify-content: center;
padding: 0.5rem 0.8rem;
border-radius: 0.2rem;
border: none;
background-color: rgba(var(--text-color, (17,17,17)), 0.03);
font-family: inherit;
font-size: inherit;
color: var(--accent-color, teal);
font-weight: 500;
cursor: pointer;
}
@media screen and (max-width: 640px){
.notification-panel:not(:empty){
padding-bottom: 3rem;
}
}
@media screen and (min-width: 640px){
.notification-panel{
max-width: 28rem;
width: max-content;
top: auto;
bottom: 0;
}
.notification{
width: auto;
border: solid 1px rgba(var(--text-color, (17,17,17)), 0.2);
}
}
@media (any-hover: hover){
::-webkit-scrollbar{
width: 0.5rem;
}
::-webkit-scrollbar-thumb{
background: rgba(var(--text-color, (17,17,17)), 0.3);
border-radius: 1rem;
&:hover{
background: rgba(var(--text-color, (17,17,17)), 0.5);
}
}
.close:hover{
background-color: rgba(var(--text-color, (17,17,17)), 0.1);
}
}
</style>
<div class="notification-panel"></div>
`;
customElements.define('sm-notifications', class extends HTMLElement { customElements.define('sm-notifications', class extends HTMLElement {
constructor() { constructor() {
super(); super();
@ -897,7 +916,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) {
@ -909,22 +944,27 @@ customElements.define('sm-notifications', class extends HTMLElement {
} }
createNotification(message, options = {}) { createNotification(message, options = {}) {
const { pinned = false, icon = '' } = options; const { pinned = false, icon = '', action } = options;
const notification = document.createElement('div') const notification = document.createElement('output')
notification.id = this.randString(8) notification.id = this.randString(8)
notification.classList.add('notification'); notification.classList.add('notification');
let composition = ``; let composition = ``;
composition += ` composition += `
<div class="icon-container">${icon}</div> <div class="icon-container">${icon}</div>
<p>${message}</p> <p>${message}</p>
`; `;
if (action) {
composition += `
<button class="action">${action.label}</button>
`
}
if (pinned) { if (pinned) {
notification.classList.add('pinned'); notification.classList.add('pinned');
composition += ` composition += `
<button class="close"> <button class="close">
<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> <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> </button>
`; `;
} }
notification.innerHTML = composition; notification.innerHTML = composition;
return notification; return notification;
@ -932,28 +972,47 @@ 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()
}
if (notification.querySelector('.action'))
notification.querySelector('.action').addEventListener('click', options.action.callback)
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}${Math.abs(this.currentX)}px ${sign} 1rem))`,
opacity: '0' opacity: '0'
} }
], this.animationOptions).onfinish = () => { ], this.animationOptions).onfinish = () => {
@ -967,7 +1026,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'));
@ -989,9 +1111,12 @@ customElements.define('sm-notifications', class extends HTMLElement {
childList: true, childList: true,
}); });
} }
disconnectedCallback() {
mediaQueryList.removeEventListener('change', handleOrientationChange);
}
}); });
//popup
class Stack { class Stack {
constructor() { constructor() {
this.items = []; this.items = [];
@ -1024,9 +1149,6 @@ smPopup.innerHTML = `
display: -ms-grid; display: -ms-grid;
display: grid; display: grid;
z-index: 10; z-index: 10;
--accent-color: #4d2588;
--text-color: 17, 17, 17;
--background-color: 255, 255, 255;
--width: 100%; --width: 100%;
--height: auto; --height: auto;
--min-width: auto; --min-width: auto;
@ -1081,7 +1203,7 @@ smPopup.innerHTML = `
min-height: var(--min-height); min-height: var(--min-height);
max-height: 90vh; max-height: 90vh;
border-radius: var(--border-radius); border-radius: var(--border-radius);
background: rgba(var(--background-color), 1); background: rgba(var(--background-color, (255,255,255)), 1);
-webkit-box-shadow: 0 -1rem 2rem #00000020; -webkit-box-shadow: 0 -1rem 2rem #00000020;
box-shadow: 0 -1rem 2rem #00000020; box-shadow: 0 -1rem 2rem #00000020;
} }
@ -1141,7 +1263,7 @@ smPopup.innerHTML = `
.handle{ .handle{
height: 0.3rem; height: 0.3rem;
width: 2rem; width: 2rem;
background: rgba(var(--text-color), .4); background: rgba(var(--text-color, (17,17,17)), .4);
border-radius: 1rem; border-radius: 1rem;
margin: 0.5rem 0; margin: 0.5rem 0;
} }
@ -1152,10 +1274,10 @@ smPopup.innerHTML = `
} }
::-webkit-scrollbar-thumb{ ::-webkit-scrollbar-thumb{
background: rgba(var(--text-color), 0.3); background: rgba(var(--text-color, (17,17,17)), 0.3);
border-radius: 1rem; border-radius: 1rem;
&:hover{ &:hover{
background: rgba(var(--text-color), 0.5); background: rgba(var(--text-color, (17,17,17))), 0.5);
} }
} }
} }
@ -1195,7 +1317,7 @@ customElements.define('sm-popup', class extends HTMLElement {
this.popupContainer = this.shadowRoot.querySelector('.popup-container'); this.popupContainer = this.shadowRoot.querySelector('.popup-container');
this.backdrop = this.shadowRoot.querySelector('.background'); this.backdrop = this.shadowRoot.querySelector('.background');
this.popup = this.shadowRoot.querySelector('.popup'); this.dialogBox = this.shadowRoot.querySelector('.popup');
this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot'); this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot');
this.popupHeader = this.shadowRoot.querySelector('.popup-top'); this.popupHeader = this.shadowRoot.querySelector('.popup-top');
@ -1229,7 +1351,7 @@ customElements.define('sm-popup', class extends HTMLElement {
resumeScrolling() { resumeScrolling() {
const scrollY = document.body.style.top; const scrollY = document.body.style.top;
window.scrollTo(0, parseInt(scrollY || '0') * -1); window.scrollTo(0, parseInt(scrollY || '0') * -1);
document.body.style.overflow = 'auto'; document.body.style.overflow = '';
document.body.style.top = 'initial'; document.body.style.top = 'initial';
} }
@ -1240,7 +1362,7 @@ customElements.define('sm-popup', class extends HTMLElement {
easing: 'ease' easing: 'ease'
} }
const initialAnimation = (window.innerWidth > 640) ? 'scale(1.1)' : `translateY(${this.offset ? `${this.offset}px` : '100%'})` const initialAnimation = (window.innerWidth > 640) ? 'scale(1.1)' : `translateY(${this.offset ? `${this.offset}px` : '100%'})`
this.animateTo(this.popup, [ this.animateTo(this.dialogBox, [
{ {
opacity: this.offset ? 1 : 0, opacity: this.offset ? 1 : 0,
transform: initialAnimation transform: initialAnimation
@ -1305,7 +1427,7 @@ customElements.define('sm-popup', class extends HTMLElement {
{ opacity: 1 }, { opacity: 1 },
{ opacity: 0 } { opacity: 0 }
], animOptions) ], animOptions)
this.animateTo(this.popup, [ this.animateTo(this.dialogBox, [
{ {
opacity: 1, opacity: 1,
transform: (window.innerWidth > 640) ? 'none' : `translateY(${this.offset ? `${this.offset}px` : '0'})` transform: (window.innerWidth > 640) ? 'none' : `translateY(${this.offset ? `${this.offset}px` : '0'})`
@ -1317,7 +1439,7 @@ customElements.define('sm-popup', class extends HTMLElement {
], animOptions).finished ], animOptions).finished
.finally(() => { .finally(() => {
this.popupContainer.classList.add('hide'); this.popupContainer.classList.add('hide');
this.popup.style = '' this.dialogBox.style = ''
this.removeAttribute('open'); this.removeAttribute('open');
if (this.forms.length) { if (this.forms.length) {
@ -1357,7 +1479,7 @@ customElements.define('sm-popup', class extends HTMLElement {
if (this.touchStartY < e.changedTouches[0].clientY) { if (this.touchStartY < e.changedTouches[0].clientY) {
this.offset = e.changedTouches[0].clientY - this.touchStartY; this.offset = e.changedTouches[0].clientY - this.touchStartY;
this.touchEndAnimation = window.requestAnimationFrame(() => { this.touchEndAnimation = window.requestAnimationFrame(() => {
this.popup.style.transform = `translateY(${this.offset}px)`; this.dialogBox.style.transform = `translateY(${this.offset}px)`;
}); });
} }
} }
@ -1366,7 +1488,7 @@ customElements.define('sm-popup', class extends HTMLElement {
this.touchEndTime = e.timeStamp; this.touchEndTime = e.timeStamp;
cancelAnimationFrame(this.touchEndAnimation); cancelAnimationFrame(this.touchEndAnimation);
this.touchEndY = e.changedTouches[0].clientY; this.touchEndY = e.changedTouches[0].clientY;
this.threshold = this.popup.getBoundingClientRect().height * 0.3; this.threshold = this.dialogBox.getBoundingClientRect().height * 0.3;
if (this.touchEndTime - this.touchStartTime > 200) { if (this.touchEndTime - this.touchStartTime > 200) {
if (this.touchEndY - this.touchStartY > this.threshold) { if (this.touchEndY - this.touchStartY > this.threshold) {
if (this.pinned) { if (this.pinned) {
@ -1392,7 +1514,7 @@ customElements.define('sm-popup', class extends HTMLElement {
detectFocus(e) { detectFocus(e) {
if (e.code === 'Tab') { if (e.key === 'Tab') {
const lastElement = this.focusable[this.focusable.length - 1]; const lastElement = this.focusable[this.focusable.length - 1];
const firstElement = this.focusable[0]; const firstElement = this.focusable[0];
if (e.shiftKey && document.activeElement === firstElement) { if (e.shiftKey && document.activeElement === firstElement) {
@ -1406,7 +1528,7 @@ customElements.define('sm-popup', class extends HTMLElement {
} }
updateFocusableList() { updateFocusableList() {
this.focusable = this.querySelectorAll('sm-button:not([disabled]), button:not([disabled]), [href], sm-input, input, sm-select, select, sm-checkbox, sm-textarea, textarea, [tabindex]:not([tabindex="-1"])') this.focusable = this.querySelectorAll('sm-button:not([disabled]), button:not([disabled]), [href], sm-input, input:not([readonly]), sm-select, select, sm-checkbox, sm-textarea, textarea, [tabindex]:not([tabindex="-1"])')
this.autoFocus = this.querySelector('[autofocus]') this.autoFocus = this.querySelector('[autofocus]')
} }

File diff suppressed because it is too large Load Diff

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -327,17 +327,30 @@ ul {
flex-shrink: 0; flex-shrink: 0;
} }
.button__icon { .margin-right-0-5 {
height: 1.2rem; margin-right: 0.5rem;
width: 1.2rem; }
&--left { .margin-left-0-5 {
margin-right: 0.5rem; margin-left: 0.5rem;
} }
.margin-left-auto {
&--right { margin-left: auto;
margin-left: 0.5rem; }
} .margin-bottom-0-5 {
margin-bottom: 0.5rem;
}
.margin-block-1 {
margin-block: 1rem;
}
.margin-block-1-5 {
margin-block: 1.5rem;
}
.margin-inline-1 {
margin-inline: 1rem;
}
.margin-inline-1-5 {
margin-inline: 1.5rem;
} }
.icon-button { .icon-button {
@ -527,7 +540,7 @@ sm-copy {
gap: 1rem; gap: 1rem;
padding: 1rem; padding: 1rem;
align-items: center; align-items: center;
grid-template-columns: 1fr auto auto; grid-template-columns: 1fr auto;
grid-column: 1/-1; grid-column: 1/-1;
background-color: var(--foreground-color); background-color: var(--foreground-color);
z-index: 2; z-index: 2;
@ -1050,7 +1063,7 @@ sm-copy {
} }
#main_header { #main_header {
padding: 1rem 1.5rem; padding: 1rem 1.5rem;
grid-template-columns: auto 1fr auto auto; grid-template-columns: 1fr auto auto;
} }
#options_panel { #options_panel {
top: 4.2rem; top: 4.2rem;

File diff suppressed because it is too large Load Diff