diff --git a/components.js b/components.js new file mode 100644 index 0000000..ec6768b --- /dev/null +++ b/components.js @@ -0,0 +1,2693 @@ +/*jshint esversion: 6 */ +const smButton = document.createElement('template') +smButton.innerHTML = ` + +
+ +
`; +customElements.define('sm-button', + class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(smButton.content.cloneNode(true)); + } + static get observedAttributes() { + return ['disabled']; + } + + get disabled() { + return this.hasAttribute('disabled'); + } + + set disabled(value) { + if (value) { + this.setAttribute('disabled', ''); + } else { + this.removeAttribute('disabled'); + } + } + focusIn() { + this.focus(); + } + + handleKeyDown(e) { + if (!this.hasAttribute('disabled') && (e.key === 'Enter' || e.key === ' ')) { + e.preventDefault(); + this.click(); + } + } + + connectedCallback() { + if (!this.hasAttribute('disabled')) { + this.setAttribute('tabindex', '0'); + } + this.setAttribute('role', 'button'); + this.addEventListener('keydown', this.handleKeyDown); + } + attributeChangedCallback(name) { + if (name === 'disabled') { + if (this.hasAttribute('disabled')) { + this.removeAttribute('tabindex'); + } else { + this.setAttribute('tabindex', '0'); + } + this.setAttribute('aria-disabled', this.hasAttribute('disabled')); + } + } + }) +const smForm = document.createElement('template'); +smForm.innerHTML = ` + +
+ +
+`; + +customElements.define('sm-form', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smForm.content.cloneNode(true)) + + this.form = this.shadowRoot.querySelector('form'); + this.formElements + this.requiredElements + this.submitButton + this.resetButton + this.allRequiredValid = false; + + this.debounce = this.debounce.bind(this) + this._checkValidity = this._checkValidity.bind(this) + this.handleKeydown = this.handleKeydown.bind(this) + this.reset = this.reset.bind(this) + this.elementsChanged = this.elementsChanged.bind(this) + } + debounce(callback, wait) { + let timeoutId = null; + return (...args) => { + window.clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => { + callback.apply(null, args); + }, wait); + }; + } + _checkValidity() { + this.allRequiredValid = this.requiredElements.every(elem => elem.isValid) + if (!this.submitButton) return; + if (this.allRequiredValid) { + this.submitButton.disabled = false; + } + else { + this.submitButton.disabled = true; + } + } + handleKeydown(e) { + if (e.key === 'Enter' && !e.target.tagName.includes('TEXTAREA')) { + if (this.allRequiredValid) { + if (this.submitButton) { + this.submitButton.click() + } + this.dispatchEvent(new CustomEvent('submit', { + bubbles: true, + composed: true, + })) + } + else { + this.requiredElements.find(elem => !elem.isValid).vibrate() + } + } + } + reset() { + this.formElements.forEach(elem => elem.reset()) + } + elementsChanged() { + this.formElements = [...this.querySelectorAll('sm-input, sm-textarea, sm-checkbox, tags-input, file-input, sm-switch, sm-radio')] + this.requiredElements = this.formElements.filter(elem => elem.hasAttribute('required')); + this.submitButton = this.querySelector('[variant="primary"], [type="submit"]'); + this.resetButton = this.querySelector('[type="reset"]'); + if (this.resetButton) { + this.resetButton.addEventListener('click', this.reset); + } + this._checkValidity() + } + connectedCallback() { + const slot = this.shadowRoot.querySelector('slot') + slot.addEventListener('slotchange', this.elementsChanged) + this.addEventListener('input', this.debounce(this._checkValidity, 100)); + this.addEventListener('keydown', this.debounce(this.handleKeydown, 100)); + } + disconnectedCallback() { + this.removeEventListener('input', this.debounce(this._checkValidity, 100)); + this.removeEventListener('keydown', this.debounce(this.handleKeydown, 100)); + } +}) + +const smInput = document.createElement('template') +smInput.innerHTML = ` + +
+ +

+
+`; +customElements.define('sm-input', + class extends HTMLElement { + + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(smInput.content.cloneNode(true)); + + this.inputParent = this.shadowRoot.querySelector('.input'); + this.input = this.shadowRoot.querySelector('input'); + this.clearBtn = this.shadowRoot.querySelector('.clear'); + this.label = this.shadowRoot.querySelector('.label'); + this.feedbackText = this.shadowRoot.querySelector('.feedback-text'); + this.outerContainer = this.shadowRoot.querySelector('.outer-container'); + this._helperText = ''; + this._errorText = ''; + this.isRequired = false; + this.validationFunction = undefined; + this.reflectedAttributes = ['value', 'required', 'disabled', 'type', 'inputmode', 'readonly', 'min', 'max', 'pattern', 'minlength', 'maxlength', 'step']; + + this.reset = this.reset.bind(this); + this.clear = this.clear.bind(this); + this.focusIn = this.focusIn.bind(this); + this.focusOut = this.focusOut.bind(this); + this.fireEvent = this.fireEvent.bind(this); + this.checkInput = this.checkInput.bind(this); + this.vibrate = this.vibrate.bind(this); + } + + static get observedAttributes() { + return ['value', 'placeholder', 'required', 'disabled', 'type', 'inputmode', 'readonly', 'min', 'max', 'pattern', 'minlength', 'maxlength', 'step', 'helper-text', 'error-text', 'hiderequired']; + } + + get value() { + return this.input.value; + } + + set value(val) { + this.input.value = val; + this.checkInput(); + this.fireEvent(); + } + + get placeholder() { + return this.getAttribute('placeholder'); + } + + set placeholder(val) { + this.setAttribute('placeholder', val); + } + + get type() { + return this.getAttribute('type'); + } + + set type(val) { + this.setAttribute('type', val); + } + + get validity() { + return this.input.validity; + } + + get disabled() { + return this.hasAttribute('disabled'); + } + set disabled(value) { + if (value) + this.inputParent.classList.add('disabled'); + else + this.inputParent.classList.remove('disabled'); + } + get readOnly() { + return this.hasAttribute('readonly'); + } + set readOnly(value) { + if (value) { + this.setAttribute('readonly', ''); + } else { + this.removeAttribute('readonly'); + } + } + set customValidation(val) { + this.validationFunction = val; + } + set errorText(val) { + this._errorText = val; + } + set helperText(val) { + this._helperText = val; + } + get isValid() { + if (this.input.value !== '') { + const _isValid = this.input.checkValidity(); + let _customValid = true; + if (this.validationFunction) { + _customValid = Boolean(this.validationFunction(this.input.value)); + } + if (_isValid && _customValid) { + this.feedbackText.classList.remove('error'); + this.feedbackText.classList.add('success'); + this.feedbackText.textContent = ''; + } else { + if (this._errorText) { + this.feedbackText.classList.add('error'); + this.feedbackText.classList.remove('success'); + this.feedbackText.innerHTML = ` + + ${this._errorText} + `; + } + } + return (_isValid && _customValid); + } + } + reset() { + this.value = ''; + } + clear() { + this.value = ''; + this.input.focus(); + } + + focusIn() { + this.input.focus(); + } + + focusOut() { + this.input.blur(); + } + + fireEvent() { + let event = new Event('input', { + bubbles: true, + cancelable: true, + composed: true + }); + this.dispatchEvent(event); + } + + checkInput(e) { + if (!this.hasAttribute('readonly')) { + if (this.input.value.trim() !== '') { + this.clearBtn.classList.remove('hide'); + } else { + this.clearBtn.classList.add('hide'); + } + } + if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder').trim() === '') return; + if (this.input.value !== '') { + if (this.animate) + this.inputParent.classList.add('animate-placeholder'); + else + this.label.classList.add('hide'); + } else { + if (this.animate) + this.inputParent.classList.remove('animate-placeholder'); + else + this.label.classList.remove('hide'); + this.feedbackText.textContent = ''; + } + } + vibrate() { + this.outerContainer.animate([ + { transform: 'translateX(-1rem)' }, + { transform: 'translateX(1rem)' }, + { transform: 'translateX(-0.5rem)' }, + { transform: 'translateX(0.5rem)' }, + { transform: 'translateX(0)' }, + ], { + duration: 300, + easing: 'ease' + }); + } + + + connectedCallback() { + this.animate = this.hasAttribute('animate'); + this.setAttribute('role', 'textbox'); + this.input.addEventListener('input', this.checkInput); + this.clearBtn.addEventListener('click', this.clear); + } + + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + if (this.reflectedAttributes.includes(name)) { + if (this.hasAttribute(name)) { + this.input.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : ''); + } + else { + this.input.removeAttribute(name); + } + } + if (name === 'placeholder') { + this.label.textContent = newValue; + this.setAttribute('aria-label', newValue); + } + else if (this.hasAttribute('value')) { + this.checkInput(); + } + else if (name === 'type') { + if (this.hasAttribute('type') && this.getAttribute('type') === 'number') { + this.input.setAttribute('inputmode', 'numeric'); + } + } + else if (name === 'helper-text') { + this._helperText = this.getAttribute('helper-text'); + } + else if (name === 'error-text') { + this._errorText = this.getAttribute('error-text'); + } + else if (name === 'required') { + this.isRequired = this.hasAttribute('required'); + if (this.isRequired) { + this.setAttribute('aria-required', 'true'); + } + else { + this.setAttribute('aria-required', 'false'); + } + } + else if (name === 'readonly') { + if (this.hasAttribute('readonly')) { + this.inputParent.classList.add('readonly'); + } else { + this.inputParent.classList.remove('readonly'); + } + } + else if (name === 'disabled') { + if (this.hasAttribute('disabled')) { + this.inputParent.classList.add('disabled'); + } + else { + this.inputParent.classList.remove('disabled'); + } + } + } + } + disconnectedCallback() { + this.input.removeEventListener('input', this.checkInput); + this.clearBtn.removeEventListener('click', this.clear); + } + }) +const smNotifications = document.createElement('template') +smNotifications.innerHTML = ` + +
+`; + + +customElements.define('sm-notifications', class extends HTMLElement { + constructor() { + super(); + this.shadow = this.attachShadow({ + mode: 'open' + }).append(smNotifications.content.cloneNode(true)) + + this.notificationPanel = this.shadowRoot.querySelector('.notification-panel') + this.animationOptions = { + duration: 300, + fill: "forwards", + easing: "cubic-bezier(0.175, 0.885, 0.32, 1.275)" + } + + this.push = this.push.bind(this) + this.createNotification = this.createNotification.bind(this) + this.removeNotification = this.removeNotification.bind(this) + this.clearAll = this.clearAll.bind(this) + + } + + randString(length) { + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + for (let i = 0; i < length; i++) + result += characters.charAt(Math.floor(Math.random() * characters.length)); + return result; + } + + createNotification(message, options = {}) { + const { pinned = false, icon = '' } = options; + const notification = document.createElement('output') + notification.id = this.randString(8) + notification.classList.add('notification'); + let composition = ``; + composition += ` +
${icon}
+

${message}

+ `; + if (pinned) { + notification.classList.add('pinned'); + composition += ` + + `; + } + notification.innerHTML = composition; + return notification; + } + + push(message, options = {}) { + const notification = this.createNotification(message, options); + this.notificationPanel.append(notification); + notification.animate([ + { + transform: `translateY(1rem)`, + opacity: '0' + }, + { + transform: `none`, + opacity: '1' + }, + ], this.animationOptions); + return notification.id; + } + + removeNotification(notification) { + notification.animate([ + { + transform: `none`, + opacity: '1' + }, + { + transform: `translateY(0.5rem)`, + opacity: '0' + } + ], this.animationOptions).onfinish = () => { + notification.remove(); + }; + } + + clearAll() { + Array.from(this.notificationPanel.children).forEach(child => { + this.removeNotification(child); + }); + } + + connectedCallback() { + this.notificationPanel.addEventListener('click', e => { + if (e.target.closest('.close')) { + this.removeNotification(e.target.closest('.notification')); + } + }); + + const observer = new MutationObserver(mutationList => { + mutationList.forEach(mutation => { + if (mutation.type === 'childList') { + if (mutation.addedNodes.length && !mutation.addedNodes[0].classList.contains('pinned')) { + setTimeout(() => { + this.removeNotification(mutation.addedNodes[0]); + }, 5000); + } + } + }); + }); + observer.observe(this.notificationPanel, { + childList: true, + }); + } +}); + +class Stack { + constructor() { + this.items = []; + } + push(element) { + this.items.push(element); + } + pop() { + if (this.items.length == 0) + return "Underflow"; + return this.items.pop(); + } + peek() { + return this.items[this.items.length - 1]; + } +} +const popupStack = new Stack(); + +const smPopup = document.createElement('template'); +smPopup.innerHTML = ` + + +`; +customElements.define('sm-popup', class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(smPopup.content.cloneNode(true)); + + this.allowClosing = false; + this.isOpen = false; + this.pinned = false; + this.offset = 0; + this.touchStartY = 0; + this.touchEndY = 0; + this.touchStartTime = 0; + this.touchEndTime = 0; + this.touchEndAnimation = undefined; + this.focusable + this.autoFocus + this.mutationObserver + + this.popupContainer = this.shadowRoot.querySelector('.popup-container'); + this.backdrop = this.shadowRoot.querySelector('.background'); + this.popup = this.shadowRoot.querySelector('.popup'); + this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot'); + this.popupHeader = this.shadowRoot.querySelector('.popup-top'); + + this.resumeScrolling = this.resumeScrolling.bind(this); + this.setStateOpen = this.setStateOpen.bind(this); + this.show = this.show.bind(this); + this.hide = this.hide.bind(this); + this.handleTouchStart = this.handleTouchStart.bind(this); + this.handleTouchMove = this.handleTouchMove.bind(this); + this.handleTouchEnd = this.handleTouchEnd.bind(this); + this.detectFocus = this.detectFocus.bind(this); + } + + static get observedAttributes() { + return ['open']; + } + + get open() { + return this.isOpen; + } + + animateTo(element, keyframes, options) { + const anime = element.animate(keyframes, { ...options, fill: 'both' }) + anime.finished.then(() => { + anime.commitStyles() + anime.cancel() + }) + return anime + } + + resumeScrolling() { + const scrollY = document.body.style.top; + window.scrollTo(0, parseInt(scrollY || '0') * -1); + document.body.style.overflow = ''; + document.body.style.top = 'initial'; + } + + setStateOpen() { + if (!this.isOpen || this.offset) { + const animOptions = { + duration: 300, + easing: 'ease' + } + const initialAnimation = (window.innerWidth > 640) ? 'scale(1.1)' : `translateY(${this.offset ? `${this.offset}px` : '100%'})` + this.animateTo(this.popup, [ + { + opacity: this.offset ? 1 : 0, + transform: initialAnimation + }, + { + opacity: 1, + transform: 'none' + }, + ], animOptions) + + } + } + + show(options = {}) { + const { pinned = false } = options; + if (!this.isOpen) { + const animOptions = { + duration: 300, + easing: 'ease' + } + popupStack.push({ + popup: this, + permission: pinned + }); + if (popupStack.items.length > 1) { + this.animateTo(popupStack.items[popupStack.items.length - 2].popup.shadowRoot.querySelector('.popup'), [ + { transform: 'none' }, + { transform: (window.innerWidth > 640) ? 'scale(0.95)' : 'translateY(-1.5rem)' }, + ], animOptions) + } + this.popupContainer.classList.remove('hide'); + if (!this.offset) + this.backdrop.animate([ + { opacity: 0 }, + { opacity: 1 }, + ], animOptions) + this.setStateOpen() + this.dispatchEvent( + new CustomEvent("popupopened", { + bubbles: true, + detail: { + popup: this, + } + }) + ); + this.pinned = pinned; + this.isOpen = true; + document.body.style.overflow = 'hidden'; + document.body.style.top = `-${window.scrollY}px`; + const elementToFocus = this.autoFocus || this.focusable[0]; + elementToFocus.tagName.includes('SM-') ? elementToFocus.focusIn() : elementToFocus.focus(); + if (!this.hasAttribute('open')) + this.setAttribute('open', ''); + } + } + hide() { + const animOptions = { + duration: 150, + easing: 'ease' + } + this.backdrop.animate([ + { opacity: 1 }, + { opacity: 0 } + ], animOptions) + this.animateTo(this.popup, [ + { + opacity: 1, + transform: (window.innerWidth > 640) ? 'none' : `translateY(${this.offset ? `${this.offset}px` : '0'})` + }, + { + opacity: 0, + transform: (window.innerWidth > 640) ? 'scale(1.1)' : 'translateY(100%)' + }, + ], animOptions).finished + .finally(() => { + this.popupContainer.classList.add('hide'); + this.popup.style = '' + this.removeAttribute('open'); + + if (this.forms.length) { + this.forms.forEach(form => form.reset()); + } + this.dispatchEvent( + new CustomEvent("popupclosed", { + bubbles: true, + detail: { + popup: this, + } + }) + ); + this.isOpen = false; + }) + popupStack.pop(); + if (popupStack.items.length) { + this.animateTo(popupStack.items[popupStack.items.length - 1].popup.shadowRoot.querySelector('.popup'), [ + { transform: (window.innerWidth > 640) ? 'scale(0.95)' : 'translateY(-1.5rem)' }, + { transform: 'none' }, + ], animOptions) + + } else { + this.resumeScrolling(); + } + } + + handleTouchStart(e) { + this.offset = 0 + this.popupHeader.addEventListener('touchmove', this.handleTouchMove, { passive: true }); + this.popupHeader.addEventListener('touchend', this.handleTouchEnd, { passive: true }); + this.touchStartY = e.changedTouches[0].clientY; + this.touchStartTime = e.timeStamp; + } + + handleTouchMove(e) { + if (this.touchStartY < e.changedTouches[0].clientY) { + this.offset = e.changedTouches[0].clientY - this.touchStartY; + this.touchEndAnimation = window.requestAnimationFrame(() => { + this.popup.style.transform = `translateY(${this.offset}px)`; + }); + } + } + + handleTouchEnd(e) { + this.touchEndTime = e.timeStamp; + cancelAnimationFrame(this.touchEndAnimation); + this.touchEndY = e.changedTouches[0].clientY; + this.threshold = this.popup.getBoundingClientRect().height * 0.3; + if (this.touchEndTime - this.touchStartTime > 200) { + if (this.touchEndY - this.touchStartY > this.threshold) { + if (this.pinned) { + this.setStateOpen(); + return; + } else + this.hide(); + } else { + this.setStateOpen(); + } + } else { + if (this.touchEndY > this.touchStartY) + if (this.pinned) { + this.setStateOpen(); + return; + } + else + this.hide(); + } + this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, { passive: true }); + this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, { passive: true }); + } + + + detectFocus(e) { + if (e.key === 'Tab') { + const lastElement = this.focusable[this.focusable.length - 1]; + const firstElement = this.focusable[0]; + if (e.shiftKey && document.activeElement === firstElement) { + e.preventDefault(); + lastElement.tagName.includes('SM-') ? lastElement.focusIn() : lastElement.focus(); + } else if (!e.shiftKey && document.activeElement === lastElement) { + e.preventDefault(); + firstElement.tagName.includes('SM-') ? firstElement.focusIn() : firstElement.focus(); + } + } + } + + updateFocusableList() { + 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]') + } + + connectedCallback() { + this.popupBodySlot.addEventListener('slotchange', () => { + this.forms = this.querySelectorAll('sm-form'); + this.updateFocusableList() + }); + this.popupContainer.addEventListener('mousedown', e => { + if (e.target === this.popupContainer && !this.pinned) { + if (this.pinned) { + this.setStateOpen(); + } else + this.hide(); + } + }); + + const resizeObserver = new ResizeObserver(entries => { + for (let entry of entries) { + if (entry.contentBoxSize) { + // Firefox implements `contentBoxSize` as a single content rect, rather than an array + const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize; + this.threshold = contentBoxSize.blockSize.height * 0.3; + } else { + this.threshold = entry.contentRect.height * 0.3; + } + } + }); + resizeObserver.observe(this); + + this.mutationObserver = new MutationObserver(entries => { + this.updateFocusableList() + }) + this.mutationObserver.observe(this, { attributes: true, childList: true, subtree: true }) + + this.addEventListener('keydown', this.detectFocus); + this.popupHeader.addEventListener('touchstart', this.handleTouchStart, { passive: true }); + } + disconnectedCallback() { + this.removeEventListener('keydown', this.detectFocus); + resizeObserver.unobserve(); + this.mutationObserver.disconnect() + this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, { passive: true }); + } + attributeChangedCallback(name) { + if (name === 'open') { + if (this.hasAttribute('open')) { + this.show(); + } + } + } +}); +const smSwitch = document.createElement('template') +smSwitch.innerHTML = ` + +` + +customElements.define('sm-switch', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smSwitch.content.cloneNode(true)) + this.switch = this.shadowRoot.querySelector('.switch'); + this.input = this.shadowRoot.querySelector('input') + this.isChecked = false + this.isDisabled = false + + this.dispatch = this.dispatch.bind(this) + } + + static get observedAttributes() { + return ['disabled', 'checked'] + } + + get disabled() { + return this.isDisabled + } + + set disabled(val) { + if (val) { + this.setAttribute('disabled', '') + } else { + this.removeAttribute('disabled') + } + } + + get checked() { + return this.isChecked + } + + set checked(value) { + if (value) { + this.setAttribute('checked', '') + } else { + this.removeAttribute('checked') + } + } + + reset() { + + } + + dispatch() { + this.dispatchEvent(new CustomEvent('change', { + bubbles: true, + composed: true, + detail: { + value: this.isChecked + } + })) + } + + connectedCallback() { + this.addEventListener('keydown', e => { + if (e.key === ' ' && !this.isDisabled) { + e.preventDefault() + this.input.click() + } + }) + this.input.addEventListener('click', e => { + if (this.input.checked) + this.checked = true + else + this.checked = false + this.dispatch() + }) + } + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + if (name === 'disabled') { + if (this.hasAttribute('disabled')) { + this.disabled = true + } + else { + this.disabled = false + } + } + else if (name === 'checked') { + if (this.hasAttribute('checked')) { + this.isChecked = true + this.input.checked = true + } + else { + this.isChecked = false + this.input.checked = false + } + } + } + } + +}) +const themeToggle = document.createElement('template'); +themeToggle.innerHTML = ` + + +`; + +class ThemeToggle extends HTMLElement { + constructor() { + super(); + + this.attachShadow({ + mode: 'open' + }).append(themeToggle.content.cloneNode(true)); + + this.isChecked = false; + this.hasTheme = 'light'; + + this.toggleState = this.toggleState.bind(this); + this.fireEvent = this.fireEvent.bind(this); + this.handleThemeChange = this.handleThemeChange.bind(this); + } + static get observedAttributes() { + return ['checked']; + } + + daylight() { + this.hasTheme = 'light'; + document.body.dataset.theme = 'light'; + this.setAttribute('aria-checked', 'false'); + } + + nightlight() { + this.hasTheme = 'dark'; + document.body.dataset.theme = 'dark'; + this.setAttribute('aria-checked', 'true'); + } + + toggleState() { + this.toggleAttribute('checked'); + this.fireEvent(); + } + handleKeyDown(e) { + if (e.key === ' ') { + this.toggleState(); + } + } + handleThemeChange(e) { + if (e.detail.theme !== this.hasTheme) { + if (e.detail.theme === 'dark') { + this.setAttribute('checked', ''); + } + else { + this.removeAttribute('checked'); + } + } + } + + fireEvent() { + this.dispatchEvent( + new CustomEvent('themechange', { + bubbles: true, + composed: true, + detail: { + theme: this.hasTheme + } + }) + ); + } + + connectedCallback() { + this.setAttribute('role', 'switch'); + this.setAttribute('aria-label', 'theme toggle'); + if (localStorage.getItem(`${window.location.hostname}-theme`) === "dark") { + this.nightlight(); + this.setAttribute('checked', ''); + } else if (localStorage.getItem(`${window.location.hostname}-theme`) === "light") { + this.daylight(); + this.removeAttribute('checked'); + } + else { + if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) { + this.nightlight(); + this.setAttribute('checked', ''); + } else { + this.daylight(); + this.removeAttribute('checked'); + } + } + this.addEventListener("click", this.toggleState); + this.addEventListener("keydown", this.handleKeyDown); + document.addEventListener('themechange', this.handleThemeChange); + } + + disconnectedCallback() { + this.removeEventListener("click", this.toggleState); + this.removeEventListener("keydown", this.handleKeyDown); + document.removeEventListener('themechange', this.handleThemeChange); + } + + attributeChangedCallback(name, oldVal, newVal) { + if (name === 'checked') { + if (this.hasAttribute('checked')) { + this.nightlight(); + localStorage.setItem(`${window.location.hostname}-theme`, "dark"); + } else { + this.daylight(); + localStorage.setItem(`${window.location.hostname}-theme`, "light"); + } + } + } +} + +window.customElements.define('theme-toggle', ThemeToggle); + +const smCopy = document.createElement('template'); +smCopy.innerHTML = ` + +
+

+ +
+`; +customElements.define('sm-copy', + class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(smCopy.content.cloneNode(true)); + + this.copyContent = this.shadowRoot.querySelector('.copy-content'); + this.copyButton = this.shadowRoot.querySelector('.copy-button'); + + this.copy = this.copy.bind(this); + } + static get observedAttributes() { + return ['value']; + } + set value(val) { + this.setAttribute('value', val); + } + get value() { + return this.getAttribute('value'); + } + fireEvent() { + this.dispatchEvent( + new CustomEvent('copy', { + composed: true, + bubbles: true, + cancelable: true, + }) + ); + } + copy() { + navigator.clipboard.writeText(this.copyContent.textContent) + .then(res => this.fireEvent()) + .catch(err => console.error(err)); + } + connectedCallback() { + this.copyButton.addEventListener('click', this.copy); + } + attributeChangedCallback(name, oldValue, newValue) { + if (name === 'value') { + this.copyContent.textContent = newValue; + } + } + disconnectedCallback() { + this.copyButton.removeEventListener('click', this.copy); + } + }); +const spinner = document.createElement('template'); +spinner.innerHTML = ` + + + +`; +class SpinnerLoader extends HTMLElement { + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(spinner.content.cloneNode(true)); + } +} +window.customElements.define('sm-spinner', SpinnerLoader); + +//Color Grid +const colorGrid = document.createElement('template'); +colorGrid.innerHTML = ` + +
+
`; + +customElements.define('color-grid', + class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(colorGrid.content.cloneNode(true)) + + this.colorArray = [] + this.container = this.shadowRoot.querySelector('.color-tile-container') + this.handleChange = this.handleChange.bind(this) + this.setCheckMark = this.setCheckMark.bind(this) + } + + set colors(arr) { + this.colorArray = arr + this.renderTiles() + } + + set selectedColor(color) { + if (this.colorArray.includes(color) && this.container.querySelector(`[data-color="${color}"]`)) { + const selectedTile = this.container.querySelector(`[data-color="${color}"]`) + if (selectedTile) { + selectedTile.querySelector('input').checked = true + this.setCheckMark(selectedTile) + } + } + } + + randString(length) { + let result = ''; + let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + for (let i = 0; i < length; i++) + result += characters.charAt(Math.floor(Math.random() * characters.length)); + return result; + } + + renderTiles() { + this.container.innerHTML = '' + const frag = document.createDocumentFragment() + const groupName = this.randString(6) + this.colorArray.forEach(color => { + const label = document.createElement('label') + label.classList.add('color-tile') + label.setAttribute('data-color', color) + if (color.includes('--')) + label.setAttribute('style', `background-color: var(${color})`) + else + label.setAttribute('style', `background-color: ${color}`) + label.innerHTML = ` + + ` + frag.append(label) + }) + this.container.append(frag) + } + setCheckMark(target) { + target.parentNode.querySelectorAll('.checkmark').forEach(checkmark => checkmark.remove()) + const checkMark = document.createElement('div') + checkMark.classList.add('checkmark') + checkMark.innerHTML = ` + + ` + target.append(checkMark) + } + + handleChange(e) { + const clickedTile = e.target.closest('.color-tile') + this.setCheckMark(clickedTile) + const clickedTileColor = clickedTile.dataset.color + const tileSelected = new CustomEvent('colorselected', { + bubbles: true, + composed: true, + detail: { + value: clickedTileColor, + } + }) + this.dispatchEvent(tileSelected) + } + + connectedCallback() { + this.container.addEventListener('change', this.handleChange) + } + + disconnectedCallback() { + this.container.removeEventListener('change', this.handleChange) + } + }) +const stripSelect = document.createElement('template'); +stripSelect.innerHTML = ` + +
+
+ +
+ +
+ +
+
+ +`; +customElements.define('strip-select', class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(stripSelect.content.cloneNode(true)); + this.stripSelect = this.shadowRoot.querySelector('.strip-select'); + this.slottedOptions = undefined; + this._value = undefined; + this.scrollDistance = 0; + + this.scrollLeft = this.scrollLeft.bind(this); + this.scrollRight = this.scrollRight.bind(this); + this.fireEvent = this.fireEvent.bind(this); + } + get value() { + return this._value; + } + scrollLeft() { + this.stripSelect.scrollBy({ + left: -this.scrollDistance, + behavior: 'smooth' + }); + } + + scrollRight() { + this.stripSelect.scrollBy({ + left: this.scrollDistance, + behavior: 'smooth' + }); + } + fireEvent() { + this.dispatchEvent( + new CustomEvent("change", { + bubbles: true, + composed: true, + detail: { + value: this._value + } + }) + ); + } + connectedCallback() { + this.setAttribute('role', 'listbox'); + + const slot = this.shadowRoot.querySelector('slot'); + const coverLeft = this.shadowRoot.querySelector('.cover--left'); + const coverRight = this.shadowRoot.querySelector('.cover--right'); + const navButtonLeft = this.shadowRoot.querySelector('.nav-button--left'); + const navButtonRight = this.shadowRoot.querySelector('.nav-button--right'); + slot.addEventListener('slotchange', e => { + const assignedElements = slot.assignedElements(); + assignedElements.forEach(elem => { + if (elem.hasAttribute('selected')) { + elem.setAttribute('active', ''); + this._value = elem.value; + } + }); + if (!this.hasAttribute('multiline')) { + if (assignedElements.length > 0) { + firstOptionObserver.observe(slot.assignedElements()[0]); + lastOptionObserver.observe(slot.assignedElements()[slot.assignedElements().length - 1]); + } + else { + navButtonLeft.classList.add('hide'); + navButtonRight.classList.add('hide'); + coverLeft.classList.add('hide'); + coverRight.classList.add('hide'); + firstOptionObserver.disconnect(); + lastOptionObserver.disconnect(); + } + } + }); + const resObs = new ResizeObserver(entries => { + entries.forEach(entry => { + if (entry.contentBoxSize) { + // Firefox implements `contentBoxSize` as a single content rect, rather than an array + const contentBoxSize = Array.isArray(entry.contentBoxSize) ? entry.contentBoxSize[0] : entry.contentBoxSize; + + this.scrollDistance = contentBoxSize.inlineSize * 0.6; + } else { + this.scrollDistance = entry.contentRect.width * 0.6; + } + }); + }); + resObs.observe(this); + this.stripSelect.addEventListener('option-clicked', e => { + if (this._value !== e.target.value) { + this._value = e.target.value; + slot.assignedElements().forEach(elem => elem.removeAttribute('active')); + e.target.setAttribute('active', ''); + e.target.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" }); + this.fireEvent(); + } + }); + const firstOptionObserver = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + navButtonLeft.classList.add('hide'); + coverLeft.classList.add('hide'); + } + else { + navButtonLeft.classList.remove('hide'); + coverLeft.classList.remove('hide'); + } + }); + }, + { + threshold: 0.9, + root: this + }); + const lastOptionObserver = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + navButtonRight.classList.add('hide'); + coverRight.classList.add('hide'); + } + else { + navButtonRight.classList.remove('hide'); + coverRight.classList.remove('hide'); + } + }); + }, + { + threshold: 0.9, + root: this + }); + navButtonLeft.addEventListener('click', this.scrollLeft); + navButtonRight.addEventListener('click', this.scrollRight); + } + disconnectedCallback() { + navButtonLeft.removeEventListener('click', this.scrollLeft); + navButtonRight.removeEventListener('click', this.scrollRight); + } +}); + +//Strip option +const stripOption = document.createElement('template'); +stripOption.innerHTML = ` + + +`; +customElements.define('strip-option', class extends HTMLElement { + constructor() { + super(); + this.attachShadow({ + mode: 'open' + }).append(stripOption.content.cloneNode(true)); + this._value = undefined; + this.radioButton = this.shadowRoot.querySelector('input'); + + this.fireEvent = this.fireEvent.bind(this); + this.handleKeyDown = this.handleKeyDown.bind(this); + } + get value() { + return this._value; + } + fireEvent() { + this.dispatchEvent( + new CustomEvent("option-clicked", { + bubbles: true, + composed: true, + detail: { + value: this._value + } + }) + ); + } + handleKeyDown(e) { + if (e.key === 'Enter' || e.key === 'Space') { + this.fireEvent(); + } + } + connectedCallback() { + this.setAttribute('role', 'option'); + this.setAttribute('tabindex', '0'); + this._value = this.getAttribute('value'); + this.addEventListener('click', this.fireEvent); + this.addEventListener('keydown', this.handleKeyDown); + } + disconnectedCallback() { + this.removeEventListener('click', this.fireEvent); + this.removeEventListener('keydown', this.handleKeyDown); + } +}); +const smTextarea = document.createElement('template') +smTextarea.innerHTML = ` + + +`; +customElements.define('sm-textarea', + class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smTextarea.content.cloneNode(true)) + + this.textarea = this.shadowRoot.querySelector('textarea') + this.textareaBox = this.shadowRoot.querySelector('.textarea') + this.placeholder = this.shadowRoot.querySelector('.placeholder') + this.reflectedAttributes = ['disabled', 'required', 'readonly', 'rows', 'minlength', 'maxlength'] + + this.reset = this.reset.bind(this) + this.focusIn = this.focusIn.bind(this) + this.fireEvent = this.fireEvent.bind(this) + this.checkInput = this.checkInput.bind(this) + } + static get observedAttributes() { + return ['disabled', 'value', 'placeholder', 'required', 'readonly', 'rows', 'minlength', 'maxlength'] + } + get value() { + return this.textarea.value + } + set value(val) { + this.setAttribute('value', val) + this.fireEvent() + } + get disabled() { + return this.hasAttribute('disabled') + } + set disabled(val) { + if (val) { + this.setAttribute('disabled', '') + } else { + this.removeAttribute('disabled') + } + } + get isValid() { + return this.textarea.checkValidity() + } + reset() { + this.setAttribute('value', '') + } + focusIn() { + this.textarea.focus() + } + fireEvent() { + let event = new Event('input', { + bubbles: true, + cancelable: true, + composed: true + }); + this.dispatchEvent(event); + } + checkInput() { + if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '') + return; + if (this.textarea.value !== '') { + if (this.hasAttribute('animate')) + this.textareaBox.classList.add('animate-placeholder') + else + this.placeholder.classList.add('hide') + + } else { + if (this.hasAttribute('animate')) + this.textareaBox.classList.remove('animate-placeholder') + else + this.placeholder.classList.remove('hide') + } + } + connectedCallback() { + this.textarea.addEventListener('input', e => { + this.textareaBox.dataset.value = this.textarea.value + this.checkInput() + }) + } + attributeChangedCallback(name, oldValue, newValue) { + if (this.reflectedAttributes.includes(name)) { + if (this.hasAttribute(name)) { + this.textarea.setAttribute(name, this.getAttribute(name) ? this.getAttribute(name) : '') + } + else { + this.textContent.removeAttribute(name) + } + } + else if (name === 'placeholder') { + this.placeholder.textContent = this.getAttribute('placeholder') + } + else if (name === 'value') { + this.textarea.value = newValue; + this.textareaBox.dataset.value = newValue + this.checkInput() + } + } + }) \ No newline at end of file diff --git a/css/back.png b/css/back.png new file mode 100644 index 0000000..d58f4bc Binary files /dev/null and b/css/back.png differ diff --git a/css/main.css b/css/main.css index 404d97b..eae07b4 100644 --- a/css/main.css +++ b/css/main.css @@ -1,6 +1,4 @@ -*, -::before, -::after { +* { padding: 0; margin: 0; box-sizing: border-box; @@ -8,79 +6,385 @@ } :root { + font-size: clamp(1rem, 1.2vmax, 1.2rem); +} + +html, +body { height: 100%; - font-size: clamp(1rem, 1.2vmax, 3rem); - --ease-in-overshhot: cubic-bezier(0.6, -0.28, 0.735, 0.045); - --ease-out-overshhot: cubic-bezier(0.175, 0.885, 0.32, 1.275); } body { - --accent-color: #6300d4; - --text-color: 17, 17, 17; - --text-color-light: 100, 100, 100; - --foreground-color: 255, 255, 255; - --background-color: #efefef; - --error-color: red; + --accent-color: #256eff; + --text-color: 20, 20, 20; + --background-color: 240, 240, 240; + --foreground-color: 250, 250, 250; + --danger-color: rgb(255, 75, 75); + --green: #1cad59; + scrollbar-width: thin; + scrollbar-gutter: stable; color: rgba(var(--text-color), 1); - height: calc(100%); - background: rgba(var(--text-color), 0.04); + background-color: rgba(var(--background-color), 1); + transition: background-color 0.3s; + --dark-red: #d40e1e; + --red: #f50000; + --kinda-pink: #e40273; + --purple: #462191; + --shady-blue: #324de6; + --nice-blue: #256eff; + --maybe-cyan: #00b0ff; + --teal: #00bcd4; + --mint-green: #16c79a; + --yellowish-green: #66bb6a; + --greenish-yellow: #8bc34a; + --dark-teal: #11698e; + --tangerine: #ff6f00; + --orange: #ff9100; + --redish-orange: #ff3d00; } body[data-theme=dark] { - --accent-color:#c64aff; - --text-color: 240, 240, 240; - --text-color-light: 170, 170, 170; - --foreground-color: 20, 20, 20; - --error-color: rgb(255, 106, 106); - background: rgba(var(--foreground-color), 1); + --accent-color: #86afff; + --text-color: 220, 220, 220; + --background-color: 10, 10, 10; + --foreground-color: 24, 24, 24; + --danger-color: rgb(255, 106, 106); + --green: #00e676; + --dark-red: #ff5e7e; + --red: #ff6098; + --kinda-pink: #c44ae6; + --purple: #9565f7; + --shady-blue: #7084f5; + --nice-blue: #86afff; + --maybe-cyan: #66cfff; + --teal: #6aeeff; + --mint-green: #4dffd2; + --yellowish-green: #9effa2; + --greenish-yellow: #c7fc8b; + --dark-teal: #51cbff; + --tangerine: #ffac6d; + --orange: #ffbe68; + --redish-orange: #ff8560; +} +body[data-theme=dark] sm-popup::part(popup) { + background-color: rgba(var(--foreground-color), 1); +} + +p, +strong { + font-size: 0.9rem; + max-width: 65ch; + line-height: 1.7; + color: rgba(var(--text-color), 0.9); +} +p:not(:last-of-type), +strong:not(:last-of-type) { + margin-bottom: 1.5rem; +} + +a { + text-decoration: none; + color: var(--accent-color); +} +a:focus-visible { + box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset; } button { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; position: relative; - overflow: hidden; display: inline-flex; border: none; - background: none; - cursor: pointer; - outline: none; + background-color: transparent; + overflow: hidden; + color: inherit; -webkit-tap-highlight-color: transparent; + align-items: center; + font-size: 0.9rem; + font-weight: 500; + white-space: nowrap; + padding: 0.8rem; + border-radius: 0.3rem; + justify-content: center; +} +button:focus-visible { + outline: var(--accent-color) solid medium; +} +button:not(:disabled) { + cursor: pointer; } -button:focus-visible { +.button { + background-color: rgba(var(--text-color), 0.06); +} + +.button--primary, +.button--danger { + color: rgba(var(--background-color), 1); +} +.button--primary .icon, +.button--danger .icon { + fill: rgba(var(--background-color), 1); +} + +.button--primary { + background-color: var(--accent-color); +} + +.button--danger { + background-color: var(--danger-color); +} + +.cta { + text-transform: uppercase; + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 0.05em; +} + +.icon-only { + padding: 0.5rem; + border-radius: 0.3rem; +} + +button:disabled { + opacity: 0.5; +} + +a:-webkit-any-link:focus-visible { outline: rgba(var(--text-color), 1) 0.1rem solid; } +a:-moz-any-link:focus-visible { + outline: rgba(var(--text-color), 1) 0.1rem solid; +} + +a:any-link:focus-visible { + outline: rgba(var(--text-color), 1) 0.1rem solid; +} + +details { + padding: 1rem 0; +} + +details summary { + display: flex; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + align-items: center; + justify-content: space-between; + color: var(--accent-color); +} + +details[open] summary { + margin-bottom: 1rem; +} +details[open] > summary .down-arrow { + transform: rotate(180deg); +} + sm-input, sm-textarea { + font-size: 0.9rem; --border-radius: 0.3rem; - --background: rgba(var(--text-color), 0.1); + --background-color: rgba(var(--foreground-color), 1); +} +sm-input button .icon, +sm-textarea button .icon { + fill: var(--accent-color); } -sm-button[variant=primary] { - --padding: 0.8rem 1.5rem; - margin-top: 1rem; +sm-button { + --padding: 0.6rem 0.8rem; +} +sm-button[variant=primary] .icon { + fill: rgba(var(--background-color), 1); +} +sm-button[disabled] .icon { + fill: rgba(var(--text-color), 0.6); +} +sm-button.danger { + --background: var(--danger-color); + color: rgba(var(--background-color), 1); +} + +sm-spinner { + --size: 1rem; + --stroke-width: 0.1rem; +} + +sm-form { + --gap: 1rem; +} + +strip-select { + --gap: 0; + background-color: rgba(var(--text-color), 0.06); + border-radius: 0.3rem; + padding: 0.3rem; +} + +strip-option { + font-size: 0.8rem; + --border-radius: 0.2rem; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } ul { list-style: none; } +.overflow-ellipsis { + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.breakable { + overflow-wrap: break-word; + word-wrap: break-word; + word-break: break-word; + -webkit-hyphens: auto; + -ms-hyphens: auto; + hyphens: auto; +} + +.full-bleed { + grid-column: 1/-1; +} + +.h1 { + font-size: 1.5rem; +} + +.h2 { + font-size: 1.2rem; +} + +h3 { + font-size: 1.2rem; + line-height: 1.3; +} + +.h4 { + font-size: 0.9rem; +} + +.h5 { + font-size: 0.75rem; +} + +.uppercase { + text-transform: uppercase; +} + +.capitalize { + text-transform: capitalize; +} + +.sticky { + position: -webkit-sticky; + position: sticky; +} + +.top-0 { + top: 0; +} + .flex { display: flex; } +.flex-wrap { + flex-wrap: wrap; +} + .grid { display: grid; } +.flow-column { + grid-auto-flow: column; +} + +.gap-0-5 { + gap: 0.5rem; +} + +.gap-1 { + gap: 1rem; +} + +.gap-1-5 { + gap: 1.5rem; +} + +.gap-2 { + gap: 2rem; +} + +.gap-3 { + gap: 3rem; +} + +.text-align-right { + text-align: right; +} + +.align-start { + align-content: flex-start; +} + .align-center { align-items: center; } +.align-end { + align-items: flex-end; +} + +.text-center { + text-align: center; +} + +.justify-start { + justify-content: start; +} + +.justify-center { + justify-content: center; +} + .justify-right { margin-left: auto; } +.align-self-center { + align-self: center; +} + +.justify-self-center { + justify-self: center; +} + +.justify-self-start { + justify-self: start; +} + +.justify-self-end { + justify-self: end; +} + .direction-column { flex-direction: column; } @@ -89,38 +393,29 @@ ul { justify-content: space-between; } -.full-width { +.w-100 { width: 100%; } -.hide { - opacity: 0; - pointer-events: none; -} - -.hide-completely { - display: none !important; -} - -.no-transformations { - transform: none !important; -} - -.overflow-ellipsis { - width: 100%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; +.h-100 { + height: 100%; } .ripple { + height: 8rem; + width: 8rem; position: absolute; border-radius: 50%; transform: scale(0); - background: rgba(var(--text-color), 0.16); + background: radial-gradient(circle, rgba(var(--text-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%); pointer-events: none; } +.button--primary .ripple, +.button--danger .ripple { + background: radial-gradient(circle, rgba(var(--background-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%); +} + .interact { position: relative; overflow: hidden; @@ -128,18 +423,59 @@ ul { -webkit-tap-highlight-color: transparent; } +.empty-state { + display: grid; + width: 100%; + padding: 1.5rem 0; +} + .observe-empty-state:empty { display: none; } -.observe-empty-state:not(:empty) ~ .empty-state { +.observe-empty-state:not(:empty) + .empty-state { display: none; } +.bullet-point { + display: flex; + align-items: center; + justify-content: center; + margin: 0 0.8ch; +} +.bullet-point::after { + content: ""; + height: 0.4ch; + width: 0.4ch; + border-radius: 0.5em; + background-color: var(--accent-color); +} + .icon { - width: 1.5rem; - height: 1.5rem; - fill: rgba(var(--text-color), 0.7); + width: 1.2rem; + height: 1.2rem; + fill: rgba(var(--text-color), 0.8); + flex-shrink: 0; +} + +.margin-right-0-5 { + margin-right: 0.5rem; +} + +.margin-left-0-5 { + margin-left: 0.5rem; +} + +.icon-button { + padding: 0.6rem; + border-radius: 0.8rem; + background-color: rgba(var(--text-color), 0.1); + height: -webkit-max-content; + height: -moz-max-content; + height: max-content; +} +.icon-button .icon { + fill: var(--accent-color); } #confirmation_popup, @@ -166,573 +502,573 @@ ul { margin-left: auto; } +#prompt_message { + margin-bottom: 1.5rem; +} + .popup__header { - padding: 0.5rem 1.5rem 0 1rem; display: grid; - grid-template-columns: auto 1fr; gap: 0.5rem; - align-items: center; width: 100%; + padding: 0 1.5rem; + align-items: center; + grid-auto-flow: column; } .popup__header__close { padding: 0.5rem; + margin-left: -0.5rem; cursor: pointer; } -.icon-only { - height: 2.6rem; - width: 2.6rem; - padding: 0.6rem; -} - -.close-icon { - padding: 0.3rem; -} - -.initial { - display: flex; - text-align: center; - user-select: none; - align-items: center; - justify-content: center; - font-weight: 500; - color: rgba(var(--foreground-color), 1); - background-color: rgba(var(--text-color), 0.1); -} - -#contact_popup { - --body-padding: 0; -} - -#contact_popup__initial { - align-self: center; - width: 5rem; - height: 5rem; - padding: 1rem; - margin: 1rem 0; - font-size: 2rem; - border-radius: 50%; -} - -#contact_popup__name { - align-self: center; - font-weight: 700; - font-size: 1.2rem; -} - -.contact__copy-row { - padding: 0 1.5rem; - margin: 1rem 0; -} - -.copy-label { - font-weight: 500; - color: rgba(var(--text-color), 0.8); -} - -.flo-id-grid { - gap: 0.5rem; - grid-template-columns: 1fr auto; -} - -.copy-button { - padding: 0.4rem; -} - -#contact_popup__options { - padding: 1rem 0; -} - -.contact__option { - font-size: 1rem; - padding: 0.8rem 1.5rem; - font-weight: 500; - color: rgba(var(--text-color), 0.8); -} - -.button__icon { - fill: rgba(var(--text-color), 0.7); -} - -.button__title { - margin-left: 1rem; -} - -#main_card { - height: 100%; +textarea { + color: inherit; width: 100%; - grid-row: 1/3; + font-size: 1em; + display: flex; + background-color: transparent; + padding: 1em; + border-radius: 0.3rem; + border: none; + font-family: inherit; + transition: box-shadow 0.2s; + outline: none; + caret-color: var(--accent-color, teal); + resize: none; + line-height: 1.6; +} + +.textarea { + display: grid; + width: 100%; + align-self: flex-start; + position: relative; + border-radius: 0.3rem; + padding: 1rem 0.8rem; + background-color: rgba(var(--text-color), 0.06); + transition: box-shadow 0.2s; +} +.textarea > * { + padding: 0; + grid-area: 1/1/2/2; +} +.textarea .label { + align-self: flex-start; + pointer-events: none; + opacity: 0.6; + transition: transform 0.2s, color 0.2s; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transform-origin: left; + will-change: transform; +} +.textarea.label-active .label { + opacity: 1; + transform: translateY(-60%) scale(0.8); + color: var(--accent-color); +} +.textarea.label-active textarea { + transform: translateY(0.5rem); +} +.textarea:focus-within { + box-shadow: 0 0 0 0.1rem var(--accent-color) inset; +} +.textarea:focus-within > * { + box-shadow: none; +} + +#show_character_count { + font-size: 0.8rem; + margin-left: auto; +} + +#flo_data_status:not(:empty) { + color: red; + padding: 0.5rem 0; +} + +#saved_ids_popup { + --height: 80vh; } #main_header { - grid-area: header; - height: max-content; - gap: 0.2rem 1rem; + padding: 1rem 1.5rem; +} + +#main_card { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + background-color: rgba(var(--foreground-color), 1); + transition: background-color 0.3s; +} + +#pages_container { + flex: 1; + overflow-y: auto; +} + +#main_navbar { + display: flex; + background: rgba(var(--text-color), 0.03); +} +#main_navbar.hide-away { + position: absolute; +} +#main_navbar ul { + display: flex; + height: 100%; + width: 100%; +} +#main_navbar ul li { + width: 100%; +} + +.nav-item { + position: relative; + display: flex; + flex: 1; + width: 100%; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0.5rem 0.3rem; + color: var(--text-color); + font-size: 0.7rem; + border-radius: 0.3rem; +} +.nav-item .icon { + transition: transform 0.2s; +} +.nav-item__title { + margin-top: 0.3rem; + transition: opacity 0.2s, transform 0.2s; +} +.nav-item--active { + color: var(--accent-color); +} +.nav-item--active .icon { + fill: var(--accent-color); + transform: translateY(50%); +} +.nav-item--active .nav-item__title { + transform: translateY(100%); + opacity: 0; +} +.nav-item__indicator { + position: absolute; + bottom: 0; + width: 2rem; + height: 0.3rem; + background: var(--accent-color); + border-radius: 1rem 1rem 0 0; + z-index: 1; +} + +#fix_invalid_button { + margin-bottom: 1rem !important; +} + +#get_private_key_field label { + display: flex; +} +#get_private_key_field label input:checked ~ .visible { + display: none; +} +#get_private_key_field label input:not(:checked) ~ .invisible { + display: none; +} + +.multi-state-button { + display: grid; + text-align: center; + align-items: center; +} +.multi-state-button > * { + grid-area: 1/1/2/2; +} +.multi-state-button button { + z-index: 1; +} + +.clip { + -webkit-clip-path: circle(0); + clip-path: circle(0); +} + +#flo_id_warning { + padding-bottom: 1.5rem; + border-bottom: thin solid rgba(var(--text-color), 0.3); +} +#flo_id_warning .icon { + height: 4rem; + width: 4rem; padding: 1rem; + background-color: #ffc107; + border-radius: 3rem; + fill: rgba(0, 0, 0, 0.8); + margin-bottom: 1.5rem; +} + +.generated-id-card { + display: grid; + gap: 1rem; +} +.generated-id-card h5 { + margin-bottom: 0.3rem; +} + +#home { + padding: 0; +} +#home > :first-child { + overflow-y: auto; + align-content: flex-start; + padding: 0.5rem 1.5rem 4rem 1.5rem; +} + +.primary-action { + display: flex; + padding: 0.8rem 1rem; + gap: 0.5rem; + white-space: normal; + font-size: 0.8rem; + border-radius: 0.5rem; + background-color: transparent; + border: thin solid rgba(var(--text-color), 0.3); +} +.primary-action .icon { + fill: var(--accent-color); +} +.primary-action:not(:last-of-type) { + margin-right: 0.5rem; +} + +#saved_ids_list { + position: relative; + align-content: flex-start; + padding-bottom: 1.5rem; + margin-top: 1rem; + gap: 1rem; + grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); +} + +.saved-id { grid-template-columns: auto 1fr; - grid-template-areas: "logo company" "logo app"; + gap: 0 0.8rem; + border-radius: 0.3rem; + padding: 0.5rem; + background-color: rgba(var(--text-color), 0.03); + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } - -#main_header__logo { - width: 1.8rem; - height: 1.8rem; - grid-area: logo; +.saved-id.highlight { + box-shadow: 0 0 0.1rem 0.1rem var(--accent-color) inset; } - -#page_container { - grid-area: page; - overflow-y: hidden; +.saved-id .edit-saved { + grid-area: 1/1/3/2; + padding: 0.3rem; + position: relative; +} +.saved-id .edit-saved .icon { + position: absolute; + height: 1.2rem; + width: 1.2rem; + right: 0; + bottom: 0; + border-radius: 0.5rem; + padding: 0.2rem; + background-color: rgba(var(--background-color), 1); +} +.saved-id__initial { + display: flex; + align-items: center; + justify-content: center; + height: 2.4rem; + width: 2.4rem; + font-size: 1.2rem; + text-transform: uppercase; + color: rgba(var(--background-color), 1); + font-weight: 700; + line-height: 1; + background-color: var(--accent-color); + justify-self: flex-start; + border-radius: 2rem; +} +.saved-id__label { + align-self: flex-end; +} +.saved-id__flo-id { + font-size: 0.8rem; } .page { position: relative; display: flex; flex-direction: column; - height: 100%; - width: 100%; overflow-y: auto; align-content: flex-start; + padding: 0 1.5rem; + padding-bottom: 3rem; } -.header__company-name { - grid-area: company; - font-weight: 500; - color: rgba(var(--text-color), 0.7); - align-self: flex-end; -} - -.header__app-name { - align-self: flex-start; - line-height: 1; - grid-area: app; - font-weight: 700; - color: rgba(var(--text-color), 0.9); -} - -#main_navbar { - grid-area: nav; -} - -.navbar__item { +#transactions { position: relative; - display: flex; - align-items: center; - padding: 0.8rem; - border-radius: 0.5rem; + height: 100%; + padding: 0; } -.navbar__item--active .navbar__item__icon { +#transactions header { + padding: 1rem; +} +#transactions header .grid { + grid-template-columns: auto 1fr auto; +} + +#flo_id_name { + overflow: hidden; + text-overflow: ellipsis; +} + +#token_list { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} + +.token-item { + font-size: 0.9rem; + padding: 0.5rem 1rem; + background-color: rgba(var(--text-color), 0.06); + border-radius: 0.3rem; +} + +#transactions_list { + flex-direction: column; + padding-bottom: 4rem; +} + +.transaction { + gap: 1rem; + padding: 1rem; + background-color: rgba(var(--text-color), 0.03); + border-radius: 0.3rem; +} +.transaction:not(:last-of-type) { + margin-bottom: 1rem; +} +.transaction .icon { fill: var(--accent-color); } -.navbar__item--active .navbar__item__title { - color: var(--accent-color); -} - -.navbar__item__icon { - margin-right: 1rem; - fill: rgba(var(--text-color), 0.7); -} - -.navbar__item__title { +.transaction__time, .transaction__link, .transaction__receiver { font-size: 0.8rem; - font-weight: 500; - color: rgba(var(--text-color), 0.7); +} +.transaction__receiver { + margin-left: 0.5rem; + color: rgba(var(--text-color), 0.8); +} +.transaction p { + font-size: 0.9rem; + max-width: unset; +} +.transaction__time { + justify-self: flex-end; + color: rgba(var(--text-color), 0.8); } .fab { position: absolute; - display: inline-flex; - border-radius: 5rem; - aspect-ratio: 1/1; - padding: 0.7rem; - background: #FF1F1F; - box-shadow: 0 0.5rem 0.5rem rgba(0, 0, 0, 0.16); -} - -.fab__icon { - height: 1.8rem; - width: 1.8rem; - fill: white; -} - -#flo_options { - padding: 1rem; -} - -.flo-options__item { - padding: 0.8rem; - max-width: 6rem; - justify-content: center; - color: rgba(var(--text-color), 0.8); -} - -.option__icon { - height: 3rem; - width: 3rem; - padding: 0.8rem; - background: rgba(var(--text-color), 0.04); - border-radius: 1rem; -} - -.coral { - fill: #ff5e78; -} - -.violet { - fill: #845ec2; -} - -.option__title { - margin-top: 0.5rem; - font-weight: 500; -} - -#base_header { - position: relative; - width: 100%; -} - -.header__title { - font-size: 1.1rem; - font-weight: 700; - color: rgba(var(--text-color), 0.8); -} - -#search_contacts__input { - width: 100%; - --padding: 0.5rem; -} - -.search__icon { - height: 1.2rem; - width: 1.2rem; -} - -.expanding-search { - width: 14rem; -} - -.contact-option:not(:last-of-type) { - margin-right: 0.5rem; -} -.contact-option:first-of-type { - padding-right: 0.6rem; - margin-right: auto; - margin-left: -0.6rem; -} - -.contact-option__button { - display: inline-flex; - align-items: center; - border-radius: 0.3rem; - padding: 0.5rem 0.6rem; -} - -.contact-option__icon { - height: 1.2rem; - width: 1.2rem; - margin-right: 0.5rem; -} - -.contact-option__name { - font-weight: 500; - font-size: 0.9rem; - color: rgba(var(--text-color), 0.8); -} - -#contacts_container { - display: flex; - flex-direction: column; - max-height: 100%; - overflow-y: auto; - align-content: flex-start; - padding: 0 0 6rem 1rem; -} - -.contact-card { - position: relative; - overflow: hidden; - display: grid; - width: 100%; - gap: 1rem; - grid-template-columns: auto auto 1fr auto; - align-items: center; - padding: 0.5rem 0.6rem; - flex-shrink: 0; - cursor: pointer; - user-select: none; - align-self: flex-start; - justify-content: center; - border-radius: 0.3rem; - background: rgba(var(--foreground-color), 0.6); - -webkit-tap-highlight-color: transparent; -} - -.contact-card__checkbox { - --height: 1.5rem; - --width: 1.5rem; - --border-radius: 0.3rem; - --border-color: rgba(var(--text-color), 0.6); -} - -.contact-card__initial { - width: 2rem; - height: 2rem; - padding: 1.2rem; - font-size: 1.1rem; - border-radius: 50%; -} - -.contact-card__name { - font-weight: 500; - font-size: 1rem; - color: rgba(var(--text-color), 0.8); -} - -.contact-card__more { - padding: 0.4rem; -} - -#contacts_empty_state { - text-align: center; -} - -.empty-state__title { - font-weight: 400; - color: rgba(var(--text-color), 0.8); -} - -#show_contact_popup_button { right: 0; bottom: 0; margin: 1.5rem; + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2); + z-index: 2; } -.page__header { - min-height: 4rem; - padding: 1rem; +#scroll_to_top { + border-radius: 3rem; + background-color: rgba(var(--foreground-color), 1); } -.page__title { - font-size: 1.1rem; +#add_address_button { + border-radius: 0.5rem; + color: rgba(var(--background-color), 1); + background-color: var(--accent-color); +} +#add_address_button .icon { + fill: rgba(var(--background-color), 1); } -#send_flo_form { +#transaction_result { + display: grid; + gap: 0.5rem; + height: max(40vh, 24rem); + align-items: center; + justify-content: center; + text-align: center; + align-content: center; +} +#transaction_result.success .icon--failed { + display: none; +} +#transaction_result.failed .icon--success { + display: none; +} +#transaction_result h3 { + text-align: center; width: 100%; - height: 100%; - padding: 0 1rem; - gap: 0.3; } - -.form__section { - align-content: flex-start; +#transaction_result .icon { + justify-self: center; + height: 4rem; + width: 4rem; + border-radius: 5rem; + margin-bottom: 1rem; + -webkit-animation: popup 1s; + animation: popup 1s; } - -.label { - font-size: 0.9rem; - margin-bottom: 0.3rem; - color: rgba(var(--text-color), 0.9); -} -.label:not(:first-of-type) { - margin-top: 0.8rem; -} - -#sent_flo_data { - --max-height: 12rem; -} - -#send_flo_button { - margin-top: 1.5rem; -} - -#balance_card { - width: 100%; +#transaction_result .icon--success { + fill: rgba(var(--background-color), 1); padding: 1rem; - margin-bottom: 1rem; - border-radius: 0.3rem; - background-color: rgba(var(--text-color), 0.04); + background-color: #0bbe56; +} +#transaction_result .icon--failed { + background-color: rgba(var(--text-color), 0.03); + fill: var(--danger-color); +} +#transaction_result sm-copy { + font-size: 0.8rem; } -#balance_card__input { - margin-bottom: 1rem; -} - -.balance_card__title { - font-size: 1rem; - font-weight: 500; - margin-bottom: 0.5rem; - color: rgba(var(--text-color), 0.8); -} - -.balance_card__description { - font-size: 0.9rem; - margin-bottom: 0.5rem; - color: rgba(var(--text-color), 0.8); -} - -#flo_balance { - word-break: break-all; - font-size: 2rem; - margin-bottom: 1rem; -} - -.settings__section { - padding: 0 1rem; - width: min(50ch, 100%); -} -.settings__section:not(:last-of-type) { - margin-bottom: 1rem; -} - -.setting__title { - color: rgba(var(--text-color), 0.9); -} - -.setting__description { - font-size: 0.9rem; - color: rgba(var(--text-color), 0.8); -} - -.toggle-grid { - gap: 0.3rem; - margin-right: 1rem; -} - -@media all and (max-width: 640px) { - .hide-on-mobile { - display: none; +@-webkit-keyframes popup { + 0% { + opacity: 0; + transform: scale(0.2) translateY(600%); } - - #main_card { - min-height: 100%; - grid-template-rows: auto 1fr auto; - grid-template-areas: "header" "page" "nav"; + 10% { + transform: scale(0.2) translateY(5rem); + opacity: 1; } - - #main_navbar { - flex-direction: row; + 40% { + transform: scale(0.2) translateY(0); } - - .navbar__item { - flex: 1; - flex-direction: column; + 80% { + transform: scale(1.1) translateY(0); } - - .navbar__item__icon { - margin: 0 0 0.5rem 0; - } - - .navbar__item__icon { - margin: 0 0 0.5rem 0; - } - - #dashboard_page__header { - padding-top: 0; - } - - .expanding-search { - background-color: rgba(var(--foreground-color), 1); - position: absolute; - z-index: 1; - width: 100%; + 100% { + transform: scale(1) translateY(0); } } -@media all and (min-width: 640px) { + +@keyframes popup { + 0% { + opacity: 0; + transform: scale(0.2) translateY(600%); + } + 10% { + transform: scale(0.2) translateY(5rem); + opacity: 1; + } + 40% { + transform: scale(0.2) translateY(0); + } + 80% { + transform: scale(1.1) translateY(0); + } + 100% { + transform: scale(1) translateY(0); + } +} +@media screen and (max-width: 40rem) { + #main_navbar.hide-away { + bottom: 0; + left: 0; + right: 0; + } +} +@media screen and (min-width: 40rem) { body { - align-items: center; - justify-content: center; - } - body #main_card { - background: rgba(var(--foreground-color), 1); - } - - body[data-theme=dark] #main_card { - background: rgba(var(--text-color), 0.04); + background-size: cover; } sm-popup { --width: 24rem; } - .hide-on-desktop { - display: none; + .popup__header { + grid-column: 1/-1; + padding: 1rem 1.5rem 0 1.5rem; } - .popup__header { - padding: 1rem 1.5rem 0 1rem; + body { + display: flex; + align-items: center; + justify-content: center; } #main_card { - position: relative; - width: 80vw; - height: 80vh; - border-radius: 0.2rem; - overflow: hidden; - grid-template-columns: 15rem 1fr; + display: grid; + grid-template-columns: auto 1fr; grid-template-rows: auto 1fr; - grid-template-areas: "header page" "nav page"; - box-shadow: 0 1.5rem 1.5rem rgba(0, 0, 0, 0.16); + grid-template-areas: "nav header" "nav main"; + position: relative; + border-radius: 0.5rem; + overflow: hidden; + box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.05), 0 1rem 3rem rgba(0, 0, 0, 0.2); + background-color: rgba(var(--foreground-color), 0.9); } #main_header { - padding: 1.5rem; + grid-area: header; + } + + #pages_container { + grid-area: main; } #main_navbar { + grid-area: nav; + border-top: none; flex-direction: column; height: 100%; - padding: 0 1rem; - align-content: flex-start; + } + #main_navbar ul { + flex-direction: column; + gap: 0.5rem; + padding: 0.3rem; + } + #main_navbar ul li:last-of-type { + margin-top: auto; } - .navbar__item__title { - font-size: 0.9rem; + .nav-item { + aspect-ratio: 1/1; } - - #page_container { - position: relative; - grid-row: 1/3; - } - #page_container::after { - content: ""; - position: absolute; + .nav-item__indicator { + width: 0.25rem; + height: 50%; left: 0; - height: 65%; - width: 1px; - background: rgba(var(--text-color), 0.2); - top: 50%; - transform: translateY(-50%); + border-radius: 0 1rem 1rem 0; + bottom: auto; } - .page__header { - min-height: 6.2rem; - padding: 1.5rem; + #create_flo_id_popup { + --width: 28rem; } - #contacts_container { - padding: 0 1rem 8rem 1.5rem; - } - - #send_flo_form { - gap: 1rem; - grid-template-columns: 1fr 1fr; - padding: 0 1.5rem 1.5rem 1.5rem; - } - - .settings__section { - padding: 0 1.5rem; + #send sm-form::part(form) { + align-items: flex-start; + grid-template-columns: 45% 1fr; } } -@media all and (min-width: 1280px) { +@media screen and (min-width: 56rem) { #main_card { - width: 65vw; - height: 85vh; - } -} -@media all and (min-width: 1920px) { - #main_card { - width: 60vw; - height: 65vh; + height: 80vh; + width: 56rem; } } @media (any-hover: hover) { @@ -749,25 +1085,25 @@ ul { background: rgba(var(--text-color), 0.5); } - .contact-card__checkbox:not([checked]):not(:focus-within) { - opacity: 0.4; - transition: opacity 0.3s; + .interact:not([disabled]) { + transition: background-color 0.3s; + } + .interact:not([disabled]):hover { + background-color: rgba(var(--text-color), 0.06); } - .contact-card__more:not(:focus-within) { - opacity: 0; - transition: opacity 0.3s; + .button:not([disabled]) { + transition: background-color 0.3s, filter 0.3s; } - - .contact-card:hover .contact-card__checkbox, -.contact-card:hover .contact-card__more { - opacity: 1; + .button:not([disabled]):hover { + filter: contrast(2); } - - .contact-option__button { - transition: background 0.3s; - } - .contact-option__button:hover { - background-color: rgba(var(--text-color), 0.1); +} +@supports (overflow: overlay) { + body { + overflow: overlay; } +} +.hide { + display: none !important; } \ No newline at end of file diff --git a/css/main.min.css b/css/main.min.css index 74d2c93..a24ef19 100644 --- a/css/main.min.css +++ b/css/main.min.css @@ -1 +1 @@ -.option__icon,body{background:rgba(var(--text-color),.04)}.interact,.overflow-ellipsis,button{overflow:hidden}.contact-card,.interact,button{cursor:pointer;-webkit-tap-highlight-color:transparent}#contacts_empty_state,.initial{text-align:center}.button__icon,.icon{fill:rgba(var(--text-color),.7)}*,::after,::before{padding:0;margin:0;box-sizing:border-box;font-family:Roboto,sans-serif}:root{height:100%;font-size:clamp(1rem,1.2vmax,3rem);--ease-in-overshhot:cubic-bezier(0.6, -0.28, 0.735, 0.045);--ease-out-overshhot:cubic-bezier(0.175, 0.885, 0.32, 1.275)}body{--accent-color:#6300d4;--text-color:17,17,17;--text-color-light:100,100,100;--foreground-color:255,255,255;--background-color:#efefef;--error-color:red;color:rgba(var(--text-color),1);height:calc(100%)}body[data-theme=dark]{--accent-color:#c64aff;--text-color:240,240,240;--text-color-light:170,170,170;--foreground-color:20,20,20;--error-color:rgb(255, 106, 106);background:rgba(var(--foreground-color),1)}button{position:relative;display:inline-flex;border:none;background:0 0;outline:0}button:focus-visible{outline:solid rgba(var(--text-color),1)}sm-input,sm-textarea{--border-radius:0.3rem;--background:rgba(var(--text-color), 0.1)}sm-button[variant=primary]{--padding:0.8rem 1.5rem;margin-top:1rem}ul{list-style:none}.flex{display:flex}.grid{display:grid}.align-center{align-items:center}#confirmation_popup,#prompt_popup,.direction-column{flex-direction:column}.justify-right{margin-left:auto}.space-between{justify-content:space-between}.full-width{width:100%}.hide{opacity:0;pointer-events:none}.hide-completely{display:none!important}.no-transformations{transform:none!important}.overflow-ellipsis{width:100%;white-space:nowrap;text-overflow:ellipsis}.ripple{position:absolute;border-radius:50%;transform:scale(0);background:rgba(var(--text-color),.16);pointer-events:none}.interact,.navbar__item,.page{position:relative}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}.icon{width:1.5rem;height:1.5rem}#confirmation_popup h4,#prompt_popup h4{font-weight:500;margin-bottom:.5rem}#confirmation_popup sm-button,#prompt_popup sm-button{margin:0}#confirmation_popup .flex,#prompt_popup .flex{padding:0;margin-top:1rem}#confirmation_popup .flex sm-button:first-of-type,#prompt_popup .flex sm-button:first-of-type{margin-right:.6rem;margin-left:auto}.popup__header{padding:.5rem 1.5rem 0 1rem;display:grid;grid-template-columns:auto 1fr;gap:.5rem;align-items:center;width:100%}.popup__header__close{padding:.5rem;cursor:pointer}.icon-only{height:2.6rem;width:2.6rem;padding:.6rem}.close-icon{padding:.3rem}.initial{display:flex;user-select:none;align-items:center;justify-content:center;font-weight:500;color:rgba(var(--foreground-color),1);background-color:rgba(var(--text-color),.1)}#contact_popup{--body-padding:0}#contact_popup__initial{align-self:center;width:5rem;height:5rem;padding:1rem;margin:1rem 0;font-size:2rem;border-radius:50%}#contact_popup__name{align-self:center;font-weight:700;font-size:1.2rem}.contact__copy-row{padding:0 1.5rem;margin:1rem 0}.copy-label{font-weight:500;color:rgba(var(--text-color),.8)}.flo-id-grid{gap:.5rem;grid-template-columns:1fr auto}.copy-button{padding:.4rem}#contact_popup__options{padding:1rem 0}.contact__option{font-size:1rem;padding:.8rem 1.5rem;font-weight:500;color:rgba(var(--text-color),.8)}.button__title{margin-left:1rem}#main_card{height:100%;width:100%;grid-row:1/3}#main_header{grid-area:header;height:max-content;gap:.2rem 1rem;padding:1rem;grid-template-columns:auto 1fr;grid-template-areas:"logo company" "logo app"}#main_header__logo{width:1.8rem;height:1.8rem;grid-area:logo}#page_container{grid-area:page;overflow-y:hidden}#contacts_container,.page{overflow-y:auto;align-content:flex-start}.page{display:flex;flex-direction:column;height:100%;width:100%}.header__company-name{grid-area:company;font-weight:500;color:rgba(var(--text-color),.7);align-self:flex-end}.header__app-name{align-self:flex-start;line-height:1;grid-area:app;font-weight:700;color:rgba(var(--text-color),.9)}#main_navbar{grid-area:nav}.navbar__item{display:flex;align-items:center;padding:.8rem;border-radius:.5rem}.navbar__item--active .navbar__item__icon{fill:var(--accent-color)}.navbar__item--active .navbar__item__title{color:var(--accent-color)}.navbar__item__icon{margin-right:1rem;fill:rgba(var(--text-color),.7)}.navbar__item__title{font-size:.8rem;font-weight:500;color:rgba(var(--text-color),.7)}.contact-card__name,.contact-option__name,.empty-state__title,.flo-options__item,.header__title{color:rgba(var(--text-color),.8)}.fab{position:absolute;display:inline-flex;border-radius:5rem;aspect-ratio:1/1;padding:.7rem;background:#FF1F1F;box-shadow:0 .5rem .5rem rgba(0,0,0,.16)}.fab__icon{height:1.8rem;width:1.8rem;fill:#fff}#flo_options{padding:1rem}.flo-options__item{padding:.8rem;max-width:6rem;justify-content:center}.option__icon{height:3rem;width:3rem;padding:.8rem;border-radius:1rem}.coral{fill:#ff5e78}.violet{fill:#845ec2}.option__title{margin-top:.5rem;font-weight:500}#base_header{position:relative;width:100%}.header__title{font-size:1.1rem;font-weight:700}#search_contacts__input{width:100%;--padding:0.5rem}.search__icon{height:1.2rem;width:1.2rem}.expanding-search{width:14rem}.contact-option:not(:last-of-type){margin-right:.5rem}.contact-option:first-of-type{padding-right:.6rem;margin-right:auto;margin-left:-.6rem}.contact-option__button{display:inline-flex;align-items:center;border-radius:.3rem;padding:.5rem .6rem}.contact-option__icon{height:1.2rem;width:1.2rem;margin-right:.5rem}.contact-option__name{font-weight:500;font-size:.9rem}#contacts_container{display:flex;flex-direction:column;max-height:100%;padding:0 0 6rem 1rem}.contact-card{position:relative;overflow:hidden;display:grid;width:100%;gap:1rem;grid-template-columns:auto auto 1fr auto;align-items:center;padding:.5rem .6rem;flex-shrink:0;user-select:none;align-self:flex-start;justify-content:center;border-radius:.3rem;background:rgba(var(--foreground-color),.6)}.contact-card__checkbox{--height:1.5rem;--width:1.5rem;--border-radius:0.3rem;--border-color:rgba(var(--text-color), 0.6)}.contact-card__initial{width:2rem;height:2rem;padding:1.2rem;font-size:1.1rem;border-radius:50%}.contact-card__name{font-weight:500;font-size:1rem}.contact-card__more{padding:.4rem}.empty-state__title{font-weight:400}#show_contact_popup_button{right:0;bottom:0;margin:1.5rem}.page__header{min-height:4rem;padding:1rem}.page__title{font-size:1.1rem}#send_flo_form{width:100%;height:100%;padding:0 1rem;gap:.3}.form__section{align-content:flex-start}.label{font-size:.9rem;margin-bottom:.3rem;color:rgba(var(--text-color),.9)}#balance_card,#balance_card__input{margin-bottom:1rem}.label:not(:first-of-type){margin-top:.8rem}#sent_flo_data{--max-height:12rem}#send_flo_button{margin-top:1.5rem}#balance_card{width:100%;padding:1rem;border-radius:.3rem;background-color:rgba(var(--text-color),.04)}.balance_card__description,.balance_card__title{margin-bottom:.5rem;color:rgba(var(--text-color),.8)}.balance_card__title{font-size:1rem;font-weight:500}.balance_card__description{font-size:.9rem}#flo_balance{word-break:break-all;font-size:2rem;margin-bottom:1rem}.settings__section{padding:0 1rem;width:min(50ch,100%)}.settings__section:not(:last-of-type){margin-bottom:1rem}.setting__title{color:rgba(var(--text-color),.9)}.setting__description{font-size:.9rem;color:rgba(var(--text-color),.8)}.toggle-grid{gap:.3rem;margin-right:1rem}@media all and (max-width:640px){.hide-on-mobile{display:none}#main_card{min-height:100%;grid-template-rows:auto 1fr auto;grid-template-areas:"header" "page" "nav"}#main_navbar{flex-direction:row}.navbar__item{flex:1;flex-direction:column}.navbar__item__icon{margin:0 0 .5rem}#dashboard_page__header{padding-top:0}.expanding-search{background-color:rgba(var(--foreground-color),1);position:absolute;z-index:1;width:100%}}@media all and (min-width:640px){body{align-items:center;justify-content:center}body #main_card{background:rgba(var(--foreground-color),1)}body[data-theme=dark] #main_card{background:rgba(var(--text-color),.04)}sm-popup{--width:24rem}.hide-on-desktop{display:none}.popup__header{padding:1rem 1.5rem 0 1rem}#main_card{position:relative;width:80vw;height:80vh;border-radius:.2rem;overflow:hidden;grid-template-columns:15rem 1fr;grid-template-rows:auto 1fr;grid-template-areas:"header page" "nav page";box-shadow:0 1.5rem 1.5rem rgba(0,0,0,.16)}#main_header{padding:1.5rem}#main_navbar{flex-direction:column;height:100%;padding:0 1rem;align-content:flex-start}.navbar__item__title{font-size:.9rem}#page_container{position:relative;grid-row:1/3}#page_container::after{content:"";position:absolute;left:0;height:65%;width:1px;background:rgba(var(--text-color),.2);top:50%;transform:translateY(-50%)}.page__header{min-height:6.2rem;padding:1.5rem}#contacts_container{padding:0 1rem 8rem 1.5rem}#send_flo_form{gap:1rem;grid-template-columns:1fr 1fr;padding:0 1.5rem 1.5rem}.settings__section{padding:0 1.5rem}}@media all and (min-width:1280px){#main_card{width:65vw;height:85vh}}@media all and (min-width:1920px){#main_card{width:60vw;height:65vh}}@media (any-hover:hover){::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-thumb{background:rgba(var(--text-color),.3);border-radius:1rem}::-webkit-scrollbar-thumb:hover{background:rgba(var(--text-color),.5)}.contact-card__checkbox:not([checked]):not(:focus-within){opacity:.4;transition:opacity .3s}.contact-card__more:not(:focus-within){opacity:0;transition:opacity .3s}.contact-card:hover .contact-card__checkbox,.contact-card:hover .contact-card__more{opacity:1}.contact-option__button{transition:background .3s}.contact-option__button:hover{background-color:rgba(var(--text-color),.1)}} \ No newline at end of file +*{padding:0;margin:0;box-sizing:border-box;font-family:"Roboto",sans-serif}:root{font-size:clamp(1rem,1.2vmax,1.2rem)}html,body{height:100%}body{--accent-color: #256eff;--text-color: 20, 20, 20;--background-color: 240, 240, 240;--foreground-color: 250, 250, 250;--danger-color: rgb(255, 75, 75);--green: #1cad59;scrollbar-width:thin;scrollbar-gutter:stable;color:rgba(var(--text-color), 1);background-color:rgba(var(--background-color), 1);transition:background-color .3s;--dark-red: #d40e1e;--red: #f50000;--kinda-pink: #e40273;--purple: #462191;--shady-blue: #324de6;--nice-blue: #256eff;--maybe-cyan: #00b0ff;--teal: #00bcd4;--mint-green: #16c79a;--yellowish-green: #66bb6a;--greenish-yellow: #8bc34a;--dark-teal: #11698e;--tangerine: #ff6f00;--orange: #ff9100;--redish-orange: #ff3d00}body[data-theme=dark]{--accent-color: #86afff;--text-color: 220, 220, 220;--background-color: 10, 10, 10;--foreground-color: 24, 24, 24;--danger-color: rgb(255, 106, 106);--green: #00e676;--dark-red: #ff5e7e;--red: #ff6098;--kinda-pink: #c44ae6;--purple: #9565f7;--shady-blue: #7084f5;--nice-blue: #86afff;--maybe-cyan: #66cfff;--teal: #6aeeff;--mint-green: #4dffd2;--yellowish-green: #9effa2;--greenish-yellow: #c7fc8b;--dark-teal: #51cbff;--tangerine: #ffac6d;--orange: #ffbe68;--redish-orange: #ff8560}body[data-theme=dark] sm-popup::part(popup){background-color:rgba(var(--foreground-color), 1)}p,strong{font-size:.9rem;max-width:65ch;line-height:1.7;color:rgba(var(--text-color), 0.9)}p:not(:last-of-type),strong:not(:last-of-type){margin-bottom:1.5rem}a{text-decoration:none;color:var(--accent-color)}a:focus-visible{box-shadow:0 0 0 .1rem rgba(var(--text-color), 1) inset}button{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative;display:inline-flex;border:none;background-color:transparent;overflow:hidden;color:inherit;-webkit-tap-highlight-color:transparent;align-items:center;font-size:.9rem;font-weight:500;white-space:nowrap;padding:.8rem;border-radius:.3rem;justify-content:center}button:focus-visible{outline:var(--accent-color) solid medium}button:not(:disabled){cursor:pointer}.button{background-color:rgba(var(--text-color), 0.06)}.button--primary,.button--danger{color:rgba(var(--background-color), 1)}.button--primary .icon,.button--danger .icon{fill:rgba(var(--background-color), 1)}.button--primary{background-color:var(--accent-color)}.button--danger{background-color:var(--danger-color)}.cta{text-transform:uppercase;font-size:.8rem;font-weight:700;letter-spacing:.05em}.icon-only{padding:.5rem;border-radius:.3rem}button:disabled{opacity:.5}a:-webkit-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:-moz-any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}a:any-link:focus-visible{outline:rgba(var(--text-color), 1) .1rem solid}details{padding:1rem 0}details summary{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;align-items:center;justify-content:space-between;color:var(--accent-color)}details[open] summary{margin-bottom:1rem}details[open]>summary .down-arrow{transform:rotate(180deg)}sm-input,sm-textarea{font-size:.9rem;--border-radius: 0.3rem;--background-color: rgba(var(--foreground-color), 1)}sm-input button .icon,sm-textarea button .icon{fill:var(--accent-color)}sm-button{--padding: 0.6rem 0.8rem}sm-button[variant=primary] .icon{fill:rgba(var(--background-color), 1)}sm-button[disabled] .icon{fill:rgba(var(--text-color), 0.6)}sm-button.danger{--background: var(--danger-color);color:rgba(var(--background-color), 1)}sm-spinner{--size: 1rem;--stroke-width: 0.1rem}sm-form{--gap: 1rem}strip-select{--gap: 0;background-color:rgba(var(--text-color), 0.06);border-radius:.3rem;padding:.3rem}strip-option{font-size:.8rem;--border-radius: 0.2rem;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}ul{list-style:none}.overflow-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.breakable{overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto}.full-bleed{grid-column:1/-1}.h1{font-size:1.5rem}.h2{font-size:1.2rem}h3{font-size:1.2rem;line-height:1.3}.h4{font-size:.9rem}.h5{font-size:.75rem}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.sticky{position:-webkit-sticky;position:sticky}.top-0{top:0}.flex{display:flex}.flex-wrap{flex-wrap:wrap}.grid{display:grid}.flow-column{grid-auto-flow:column}.gap-0-5{gap:.5rem}.gap-1{gap:1rem}.gap-1-5{gap:1.5rem}.gap-2{gap:2rem}.gap-3{gap:3rem}.text-align-right{text-align:right}.align-start{align-content:flex-start}.align-center{align-items:center}.align-end{align-items:flex-end}.text-center{text-align:center}.justify-start{justify-content:start}.justify-center{justify-content:center}.justify-right{margin-left:auto}.align-self-center{align-self:center}.justify-self-center{justify-self:center}.justify-self-start{justify-self:start}.justify-self-end{justify-self:end}.direction-column{flex-direction:column}.space-between{justify-content:space-between}.w-100{width:100%}.h-100{height:100%}.ripple{height:8rem;width:8rem;position:absolute;border-radius:50%;transform:scale(0);background:radial-gradient(circle, rgba(var(--text-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%);pointer-events:none}.button--primary .ripple,.button--danger .ripple{background:radial-gradient(circle, rgba(var(--background-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%)}.interact{position:relative;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:transparent}.empty-state{display:grid;width:100%;padding:1.5rem 0}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)+.empty-state{display:none}.bullet-point{display:flex;align-items:center;justify-content:center;margin:0 .8ch}.bullet-point::after{content:"";height:.4ch;width:.4ch;border-radius:.5em;background-color:var(--accent-color)}.icon{width:1.2rem;height:1.2rem;fill:rgba(var(--text-color), 0.8);flex-shrink:0}.margin-right-0-5{margin-right:.5rem}.margin-left-0-5{margin-left:.5rem}.icon-button{padding:.6rem;border-radius:.8rem;background-color:rgba(var(--text-color), 0.1);height:-webkit-max-content;height:-moz-max-content;height:max-content}.icon-button .icon{fill:var(--accent-color)}#confirmation_popup,#prompt_popup{flex-direction:column}#confirmation_popup h4,#prompt_popup h4{font-weight:500;margin-bottom:.5rem}#confirmation_popup sm-button,#prompt_popup sm-button{margin:0}#confirmation_popup .flex,#prompt_popup .flex{padding:0;margin-top:1rem}#confirmation_popup .flex sm-button:first-of-type,#prompt_popup .flex sm-button:first-of-type{margin-right:.6rem;margin-left:auto}#prompt_message{margin-bottom:1.5rem}.popup__header{display:grid;gap:.5rem;width:100%;padding:0 1.5rem;align-items:center;grid-auto-flow:column}.popup__header__close{padding:.5rem;margin-left:-0.5rem;cursor:pointer}textarea{color:inherit;width:100%;font-size:1em;display:flex;background-color:transparent;padding:1em;border-radius:.3rem;border:none;font-family:inherit;transition:box-shadow .2s;outline:none;caret-color:var(--accent-color, teal);resize:none;line-height:1.6}.textarea{display:grid;width:100%;align-self:flex-start;position:relative;border-radius:.3rem;padding:1rem .8rem;background-color:rgba(var(--text-color), 0.06);transition:box-shadow .2s}.textarea>*{padding:0;grid-area:1/1/2/2}.textarea .label{align-self:flex-start;pointer-events:none;opacity:.6;transition:transform .2s,color .2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;transform-origin:left;will-change:transform}.textarea.label-active .label{opacity:1;transform:translateY(-60%) scale(0.8);color:var(--accent-color)}.textarea.label-active textarea{transform:translateY(0.5rem)}.textarea:focus-within{box-shadow:0 0 0 .1rem var(--accent-color) inset}.textarea:focus-within>*{box-shadow:none}#show_character_count{font-size:.8rem;margin-left:auto}#flo_data_status:not(:empty){color:red;padding:.5rem 0}#saved_ids_popup{--height: 80vh}#main_header{padding:1rem 1.5rem}#main_card{display:flex;flex-direction:column;height:100%;width:100%;background-color:rgba(var(--foreground-color), 1);transition:background-color .3s}#pages_container{flex:1;overflow-y:auto}#main_navbar{display:flex;background:rgba(var(--text-color), 0.03)}#main_navbar.hide-away{position:absolute}#main_navbar ul{display:flex;height:100%;width:100%}#main_navbar ul li{width:100%}.nav-item{position:relative;display:flex;flex:1;width:100%;flex-direction:column;align-items:center;justify-content:center;padding:.5rem .3rem;color:var(--text-color);font-size:.7rem;border-radius:.3rem}.nav-item .icon{transition:transform .2s}.nav-item__title{margin-top:.3rem;transition:opacity .2s,transform .2s}.nav-item--active{color:var(--accent-color)}.nav-item--active .icon{fill:var(--accent-color);transform:translateY(50%)}.nav-item--active .nav-item__title{transform:translateY(100%);opacity:0}.nav-item__indicator{position:absolute;bottom:0;width:2rem;height:.3rem;background:var(--accent-color);border-radius:1rem 1rem 0 0;z-index:1}#fix_invalid_button{margin-bottom:1rem !important}#get_private_key_field label{display:flex}#get_private_key_field label input:checked~.visible{display:none}#get_private_key_field label input:not(:checked)~.invisible{display:none}.multi-state-button{display:grid;text-align:center;align-items:center}.multi-state-button>*{grid-area:1/1/2/2}.multi-state-button button{z-index:1}.clip{-webkit-clip-path:circle(0);clip-path:circle(0)}#flo_id_warning{padding-bottom:1.5rem;border-bottom:thin solid rgba(var(--text-color), 0.3)}#flo_id_warning .icon{height:4rem;width:4rem;padding:1rem;background-color:#ffc107;border-radius:3rem;fill:rgba(0,0,0,.8);margin-bottom:1.5rem}.generated-id-card{display:grid;gap:1rem}.generated-id-card h5{margin-bottom:.3rem}#home{padding:0}#home>:first-child{overflow-y:auto;align-content:flex-start;padding:.5rem 1.5rem 4rem 1.5rem}.primary-action{display:flex;padding:.8rem 1rem;gap:.5rem;white-space:normal;font-size:.8rem;border-radius:.5rem;background-color:transparent;border:thin solid rgba(var(--text-color), 0.3)}.primary-action .icon{fill:var(--accent-color)}.primary-action:not(:last-of-type){margin-right:.5rem}#saved_ids_list{position:relative;align-content:flex-start;padding-bottom:1.5rem;margin-top:1rem;gap:1rem;grid-template-columns:repeat(auto-fill, minmax(16rem, 1fr))}.saved-id{grid-template-columns:auto 1fr;gap:0 .8rem;border-radius:.3rem;padding:.5rem;background-color:rgba(var(--text-color), 0.03);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.saved-id.highlight{box-shadow:0 0 .1rem .1rem var(--accent-color) inset}.saved-id .edit-saved{grid-area:1/1/3/2;padding:.3rem;position:relative}.saved-id .edit-saved .icon{position:absolute;height:1.2rem;width:1.2rem;right:0;bottom:0;border-radius:.5rem;padding:.2rem;background-color:rgba(var(--background-color), 1)}.saved-id__initial{display:flex;align-items:center;justify-content:center;height:2.4rem;width:2.4rem;font-size:1.2rem;text-transform:uppercase;color:rgba(var(--background-color), 1);font-weight:700;line-height:1;background-color:var(--accent-color);justify-self:flex-start;border-radius:2rem}.saved-id__label{align-self:flex-end}.saved-id__flo-id{font-size:.8rem}.page{position:relative;display:flex;flex-direction:column;overflow-y:auto;align-content:flex-start;padding:0 1.5rem;padding-bottom:3rem}#transactions{position:relative;height:100%;padding:0}#transactions header{padding:1rem}#transactions header .grid{grid-template-columns:auto 1fr auto}#flo_id_name{overflow:hidden;text-overflow:ellipsis}#token_list{display:flex;flex-wrap:wrap;gap:.5rem}.token-item{font-size:.9rem;padding:.5rem 1rem;background-color:rgba(var(--text-color), 0.06);border-radius:.3rem}#transactions_list{flex-direction:column;padding-bottom:4rem}.transaction{gap:1rem;padding:1rem;background-color:rgba(var(--text-color), 0.03);border-radius:.3rem}.transaction:not(:last-of-type){margin-bottom:1rem}.transaction .icon{fill:var(--accent-color)}.transaction__time,.transaction__link,.transaction__receiver{font-size:.8rem}.transaction__receiver{margin-left:.5rem;color:rgba(var(--text-color), 0.8)}.transaction p{font-size:.9rem;max-width:unset}.transaction__time{justify-self:flex-end;color:rgba(var(--text-color), 0.8)}.fab{position:absolute;right:0;bottom:0;margin:1.5rem;box-shadow:0 .5rem 1rem rgba(0,0,0,.2);z-index:2}#scroll_to_top{border-radius:3rem;background-color:rgba(var(--foreground-color), 1)}#add_address_button{border-radius:.5rem;color:rgba(var(--background-color), 1);background-color:var(--accent-color)}#add_address_button .icon{fill:rgba(var(--background-color), 1)}#transaction_result{display:grid;gap:.5rem;height:max(40vh,24rem);align-items:center;justify-content:center;text-align:center;align-content:center}#transaction_result.success .icon--failed{display:none}#transaction_result.failed .icon--success{display:none}#transaction_result h3{text-align:center;width:100%}#transaction_result .icon{justify-self:center;height:4rem;width:4rem;border-radius:5rem;margin-bottom:1rem;-webkit-animation:popup 1s;animation:popup 1s}#transaction_result .icon--success{fill:rgba(var(--background-color), 1);padding:1rem;background-color:#0bbe56}#transaction_result .icon--failed{background-color:rgba(var(--text-color), 0.03);fill:var(--danger-color)}#transaction_result sm-copy{font-size:.8rem}@-webkit-keyframes popup{0%{opacity:0;transform:scale(0.2) translateY(600%)}10%{transform:scale(0.2) translateY(5rem);opacity:1}40%{transform:scale(0.2) translateY(0)}80%{transform:scale(1.1) translateY(0)}100%{transform:scale(1) translateY(0)}}@keyframes popup{0%{opacity:0;transform:scale(0.2) translateY(600%)}10%{transform:scale(0.2) translateY(5rem);opacity:1}40%{transform:scale(0.2) translateY(0)}80%{transform:scale(1.1) translateY(0)}100%{transform:scale(1) translateY(0)}}@media screen and (max-width: 40rem){#main_navbar.hide-away{bottom:0;left:0;right:0}}@media screen and (min-width: 40rem){body{background-size:cover}sm-popup{--width: 24rem}.popup__header{grid-column:1/-1;padding:1rem 1.5rem 0 1.5rem}body{display:flex;align-items:center;justify-content:center}#main_card{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto 1fr;grid-template-areas:"nav header" "nav main";position:relative;border-radius:.5rem;overflow:hidden;box-shadow:0 .1rem .2rem rgba(0,0,0,.05),0 1rem 3rem rgba(0,0,0,.2);background-color:rgba(var(--foreground-color), 0.9)}#main_header{grid-area:header}#pages_container{grid-area:main}#main_navbar{grid-area:nav;border-top:none;flex-direction:column;height:100%}#main_navbar ul{flex-direction:column;gap:.5rem;padding:.3rem}#main_navbar ul li:last-of-type{margin-top:auto}.nav-item{aspect-ratio:1/1}.nav-item__indicator{width:.25rem;height:50%;left:0;border-radius:0 1rem 1rem 0;bottom:auto}#create_flo_id_popup{--width: 28rem}#send sm-form::part(form){align-items:flex-start;grid-template-columns:45% 1fr}}@media screen and (min-width: 56rem){#main_card{height:80vh;width:56rem}}@media(any-hover: hover){::-webkit-scrollbar{width:.5rem;height:.5rem}::-webkit-scrollbar-thumb{background:rgba(var(--text-color), 0.3);border-radius:1rem}::-webkit-scrollbar-thumb:hover{background:rgba(var(--text-color), 0.5)}.interact:not([disabled]){transition:background-color .3s}.interact:not([disabled]):hover{background-color:rgba(var(--text-color), 0.06)}.button:not([disabled]){transition:background-color .3s,filter .3s}.button:not([disabled]):hover{filter:contrast(2)}}@supports(overflow: overlay){body{overflow:overlay}}.hide{display:none !important} \ No newline at end of file diff --git a/css/main.scss b/css/main.scss index bfb511c..8c26a36 100644 --- a/css/main.scss +++ b/css/main.scss @@ -1,699 +1,1044 @@ -*, -::before, -::after{ - padding: 0; - margin: 0; - box-sizing: border-box; - font-family: 'Roboto', sans-serif; -} -:root{ - height: 100%; - font-size: clamp(1rem, 1.2vmax, 3rem); - --ease-in-overshhot: cubic-bezier(0.6, -0.28, 0.735, 0.045); - --ease-out-overshhot: cubic-bezier(0.175, 0.885, 0.32, 1.275); +* { + padding: 0; + margin: 0; + box-sizing: border-box; + font-family: "Roboto", sans-serif; } -body{ - --accent-color: #6300d4; - --text-color: 17, 17, 17; - --text-color-light: 100, 100, 100; - --foreground-color: 255, 255, 255; - --background-color: #efefef; - --error-color: red; - color: rgba(var(--text-color), 1); - height: calc(100%); - background: rgba(var(--text-color), 0.04); + +:root { + font-size: clamp(1rem, 1.2vmax, 1.2rem); } -body[data-theme='dark']{ - --accent-color:#c64aff; - --text-color: 240, 240, 240; - --text-color-light: 170, 170, 170; - --foreground-color: 20, 20, 20; - --error-color: rgb(255, 106, 106); - background: rgba(var(--foreground-color), 1); + +html, +body { + height: 100%; } -button{ - position: relative; - overflow: hidden; - display: inline-flex; - border: none; - background: none; + +body { + --accent-color: #256eff; + --text-color: 20, 20, 20; + --background-color: 240, 240, 240; + --foreground-color: 250, 250, 250; + --danger-color: rgb(255, 75, 75); + --green: #1cad59; + scrollbar-width: thin; + scrollbar-gutter: stable; + color: rgba(var(--text-color), 1); + background-color: rgba(var(--background-color), 1); + transition: background-color 0.3s; + // Accent colors + --dark-red: #d40e1e; + --red: #f50000; + --kinda-pink: #e40273; + --purple: #462191; + --shady-blue: #324de6; + --nice-blue: #256eff; + --maybe-cyan: #00b0ff; + --teal: #00bcd4; + --mint-green: #16c79a; + --yellowish-green: #66bb6a; + --greenish-yellow: #8bc34a; + --dark-teal: #11698e; + --tangerine: #ff6f00; + --orange: #ff9100; + --redish-orange: #ff3d00; +} + +body[data-theme="dark"] { + --accent-color: #86afff; + --text-color: 220, 220, 220; + --background-color: 10, 10, 10; + --foreground-color: 24, 24, 24; + --danger-color: rgb(255, 106, 106); + --green: #00e676; + // Accent colors + --dark-red: #ff5e7e; + --red: #ff6098; + --kinda-pink: #c44ae6; + --purple: #9565f7; + --shady-blue: #7084f5; + --nice-blue: #86afff; + --maybe-cyan: #66cfff; + --teal: #6aeeff; + --mint-green: #4dffd2; + --yellowish-green: #9effa2; + --greenish-yellow: #c7fc8b; + --dark-teal: #51cbff; + --tangerine: #ffac6d; + --orange: #ffbe68; + --redish-orange: #ff8560; + sm-popup::part(popup) { + background-color: rgba(var(--foreground-color), 1); + } +} + +p, +strong { + font-size: 0.9rem; + max-width: 65ch; + line-height: 1.7; + color: rgba(var(--text-color), 0.9); + + &:not(:last-of-type) { + margin-bottom: 1.5rem; + } +} +a { + text-decoration: none; + color: var(--accent-color); + &:focus-visible { + box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset; + } +} + +button { + user-select: none; + position: relative; + display: inline-flex; + border: none; + background-color: transparent; + overflow: hidden; + color: inherit; + -webkit-tap-highlight-color: transparent; + align-items: center; + font-size: 0.9rem; + font-weight: 500; + white-space: nowrap; + padding: 0.8rem; + border-radius: 0.3rem; + justify-content: center; + &:focus-visible { + outline: var(--accent-color) solid medium; + } + &:not(:disabled) { cursor: pointer; - outline: none; - -webkit-tap-highlight-color: transparent; + } } -button:focus-visible{ - outline: rgba(var(--text-color), 1) 0.1rem solid; +.button { + background-color: rgba(var(--text-color), 0.06); } +.button--primary, +.button--danger { + color: rgba(var(--background-color), 1); + .icon { + fill: rgba(var(--background-color), 1); + } +} +.button--primary { + background-color: var(--accent-color); +} +.button--danger { + background-color: var(--danger-color); +} +.cta { + text-transform: uppercase; + font-size: 0.8rem; + font-weight: 700; + letter-spacing: 0.05em; +} +.icon-only { + padding: 0.5rem; + border-radius: 0.3rem; +} + +button:disabled { + opacity: 0.5; +} + +a:any-link:focus-visible { + outline: rgba(var(--text-color), 1) 0.1rem solid; +} +details { + padding: 1rem 0; +} + +details summary { + display: flex; + user-select: none; + cursor: pointer; + align-items: center; + justify-content: space-between; + color: var(--accent-color); +} + +details[open] { + & summary { + margin-bottom: 1rem; + } + & > summary .down-arrow { + transform: rotate(180deg); + } +} + sm-input, -sm-textarea{ - --border-radius: 0.3rem; - --background: rgba(var(--text-color), 0.1); +sm-textarea { + font-size: 0.9rem; + --border-radius: 0.3rem; + --background-color: rgba(var(--foreground-color), 1); + button { + .icon { + fill: var(--accent-color); + } + } } -sm-button[variant="primary"]{ - --padding: 0.8rem 1.5rem; - margin-top: 1rem; +sm-button { + --padding: 0.6rem 0.8rem; + &[variant="primary"] { + .icon { + fill: rgba(var(--background-color), 1); + } + } + + &[disabled] { + .icon { + fill: rgba(var(--text-color), 0.6); + } + } + &.danger { + --background: var(--danger-color); + color: rgba(var(--background-color), 1); + } } -ul{ - list-style: none; +sm-spinner { + --size: 1rem; + --stroke-width: 0.1rem; } -.flex{ - display: flex; +sm-form { + --gap: 1rem; } -.grid{ - display: grid; +strip-select { + --gap: 0; + background-color: rgba(var(--text-color), 0.06); + border-radius: 0.3rem; + padding: 0.3rem; } -.align-center{ - align-items: center; +strip-option { + font-size: 0.8rem; + --border-radius: 0.2rem; + user-select: none; } -.justify-right{ - margin-left: auto; +ul { + list-style: none; } -.direction-column{ - flex-direction: column; + +.overflow-ellipsis { + width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } -.space-between{ - justify-content: space-between; + +.breakable { + overflow-wrap: break-word; + word-wrap: break-word; + word-break: break-word; + hyphens: auto; } -.full-width{ - width: 100%; + +.full-bleed { + grid-column: 1/-1; } -.hide{ - opacity: 0; - pointer-events: none; + +.h1 { + font-size: 1.5rem; } -.hide-completely{ - display: none !important; + +.h2 { + font-size: 1.2rem; } -.no-transformations{ - transform: none !important; + +h3 { + font-size: 1.2rem; + line-height: 1.3; } -.overflow-ellipsis{ - width: 100%; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + +.h4 { + font-size: 0.9rem; } -.ripple{ - position: absolute; - border-radius: 50%; - transform: scale(0); - background: rgba(var(--text-color), 0.16); - pointer-events: none; + +.h5 { + font-size: 0.75rem; } -.interact{ - position: relative; - overflow: hidden; - cursor: pointer; - -webkit-tap-highlight-color: transparent; +.uppercase { + text-transform: uppercase; } -.observe-empty-state:empty{ - display: none; + +.capitalize { + text-transform: capitalize; } -.observe-empty-state:not(:empty) ~ .empty-state{ - display: none; + +.sticky { + position: sticky; } -.icon{ - width: 1.5rem; - height: 1.5rem; - fill: rgba(var(--text-color), 0.7); +.top-0 { + top: 0; +} + +.flex { + display: flex; +} +.flex-wrap { + flex-wrap: wrap; +} + +.grid { + display: grid; +} +.flow-column { + grid-auto-flow: column; +} + +.gap-0-5 { + gap: 0.5rem; +} + +.gap-1 { + gap: 1rem; +} + +.gap-1-5 { + gap: 1.5rem; +} + +.gap-2 { + gap: 2rem; +} + +.gap-3 { + gap: 3rem; +} + +.text-align-right { + text-align: right; +} + +.align-start { + align-content: flex-start; +} + +.align-center { + align-items: center; +} +.align-end { + align-items: flex-end; +} + +.text-center { + text-align: center; +} + +.justify-start { + justify-content: start; +} + +.justify-center { + justify-content: center; +} + +.justify-right { + margin-left: auto; +} + +.align-self-center { + align-self: center; +} + +.justify-self-center { + justify-self: center; +} + +.justify-self-start { + justify-self: start; +} + +.justify-self-end { + justify-self: end; +} + +.direction-column { + flex-direction: column; +} + +.space-between { + justify-content: space-between; +} + +.w-100 { + width: 100%; +} +.h-100 { + height: 100%; +} + +.ripple { + height: 8rem; + width: 8rem; + position: absolute; + border-radius: 50%; + transform: scale(0); + background: radial-gradient( + circle, + rgba(var(--text-color), 0.3) 0%, + rgba(0, 0, 0, 0) 50% + ); + pointer-events: none; +} +.button--primary, +.button--danger { + .ripple { + background: radial-gradient( + circle, + rgba(var(--background-color), 0.3) 0%, + rgba(0, 0, 0, 0) 50% + ); + } +} +.interact { + position: relative; + overflow: hidden; + cursor: pointer; + -webkit-tap-highlight-color: transparent; +} +.empty-state { + display: grid; + width: 100%; + padding: 1.5rem 0; +} + +.observe-empty-state:empty { + display: none; +} + +.observe-empty-state:not(:empty) + .empty-state { + display: none; +} + +.bullet-point { + display: flex; + align-items: center; + justify-content: center; + margin: 0 0.8ch; + &::after { + content: ""; + height: 0.4ch; + width: 0.4ch; + border-radius: 0.5em; + background-color: var(--accent-color); + } +} +.icon { + width: 1.2rem; + height: 1.2rem; + fill: rgba(var(--text-color), 0.8); + flex-shrink: 0; +} +.margin-right-0-5 { + margin-right: 0.5rem; +} + +.margin-left-0-5 { + margin-left: 0.5rem; +} + +.icon-button { + padding: 0.6rem; + border-radius: 0.8rem; + background-color: rgba(var(--text-color), 0.1); + height: max-content; + .icon { + fill: var(--accent-color); + } } #confirmation_popup, #prompt_popup { - flex-direction: column; - h4 { - font-weight: 500; - margin-bottom: 0.5rem; - } - sm-button{ - margin: 0; - } - .flex { - padding: 0; - margin-top: 1rem; - sm-button:first-of-type { - margin-right: 0.6rem; - margin-left: auto; - } - } -} -.popup__header{ - padding: 0.5rem 1.5rem 0 1rem; - display: grid; - grid-template-columns: auto 1fr; - gap: 0.5rem; - align-items: center; - width: 100%; -} -.popup__header__close{ - padding: 0.5rem; - cursor: pointer; -} -.icon-only{ - height: 2.6rem; - width: 2.6rem; - padding: 0.6rem; -} -.close-icon{ - padding: 0.3rem; -} -.initial{ - display: flex; - text-align: center; - user-select: none; - align-items: center; - justify-content: center; + flex-direction: column; + h4 { font-weight: 500; - color: rgba(var(--foreground-color), 1); - background-color: rgba(var(--text-color), 0.1); + margin-bottom: 0.5rem; + } + sm-button { + margin: 0; + } + .flex { + padding: 0; + margin-top: 1rem; + sm-button:first-of-type { + margin-right: 0.6rem; + margin-left: auto; + } + } +} +#prompt_message { + margin-bottom: 1.5rem; } -#contact_popup{ - --body-padding: 0; -} -#contact_popup__initial{ - align-self: center; - width: 5rem; - height: 5rem; - padding: 1rem; - margin: 1rem 0; - font-size: 2rem; - border-radius: 50%; -} -#contact_popup__name{ - align-self: center; - font-weight: 700; - font-size: 1.2rem; -} -.contact__copy-row{ - padding: 0 1.5rem; - margin: 1rem 0; -} -.copy-label{ - font-weight: 500; - color: rgba(var(--text-color), 0.8); -} -.flo-id-grid{ - gap: 0.5rem; - grid-template-columns: 1fr auto; -} -#contact__flo_id{ -} -.copy-button{ - padding: 0.4rem; -} -#contact_popup__options{ - padding: 1rem 0; -} -.contact__option{ - font-size: 1rem; - padding: 0.8rem 1.5rem; - font-weight: 500; - color: rgba(var(--text-color), 0.8); -} -.button__icon{ - fill: rgba(var(--text-color), 0.7); -} -.button__title{ - margin-left: 1rem; +.popup__header { + display: grid; + gap: 0.5rem; + width: 100%; + padding: 0 1.5rem; + align-items: center; + grid-auto-flow: column; } +.popup__header__close { + padding: 0.5rem; + margin-left: -0.5rem; + cursor: pointer; +} -#main_card{ - height: 100%; - width: 100%; - grid-row: 1/3; +textarea { + color: inherit; + width: 100%; + font-size: 1em; + display: flex; + background-color: transparent; + padding: 1em; + border-radius: 0.3rem; + border: none; + font-family: inherit; + transition: box-shadow 0.2s; + outline: none; + caret-color: var(--accent-color, teal); + resize: none; + line-height: 1.6; } -#main_header{ - grid-area: header; - height: max-content; - gap: 0.2rem 1rem; - padding: 1rem; - grid-template-columns: auto 1fr; - grid-template-areas: 'logo company' 'logo app'; -} -#main_header__logo{ - width: 1.8rem; - height: 1.8rem; - grid-area: logo; -} -#page_container{ - grid-area: page; - overflow-y: hidden; -} -.page{ - position: relative; - display: flex; - flex-direction: column; - height: 100%; - width: 100%; - overflow-y: auto; - align-content: flex-start; -} -.header__company-name{ - grid-area: company; - font-weight: 500; - color: rgba(var(--text-color), 0.7); - align-self: flex-end; -} -.header__app-name{ +.textarea { + display: grid; + width: 100%; + align-self: flex-start; + position: relative; + border-radius: 0.3rem; + padding: 1rem 0.8rem; + background-color: rgba(var(--text-color), 0.06); + transition: box-shadow 0.2s; + & > * { + padding: 0; + grid-area: 1/1/2/2; + } + .label { align-self: flex-start; - line-height: 1; - grid-area: app; - font-weight: 700; - color: rgba(var(--text-color), 0.9); -} -#main_navbar{ - grid-area: nav; -} -.navbar__item{ - position: relative; - display: flex; - align-items: center; - padding: 0.8rem; - border-radius: 0.5rem; - &--active{ - .navbar__item__icon{ - fill: var(--accent-color); - } - .navbar__item__title{ - color: var(--accent-color); - } + pointer-events: none; + opacity: 0.6; + transition: transform 0.2s, color 0.2s; + user-select: none; + transform-origin: left; + will-change: transform; + } + &.label-active { + .label { + opacity: 1; + transform: translateY(-60%) scale(0.8); + color: var(--accent-color); } + textarea { + transform: translateY(0.5rem); + } + } + &:focus-within { + box-shadow: 0 0 0 0.1rem var(--accent-color) inset; + & > * { + box-shadow: none; + } + } } -.navbar__item__icon{ - margin-right: 1rem; - fill: rgba(var(--text-color), 0.7); -} -.navbar__item__title{ - font-size: 0.8rem; - font-weight: 500; - color: rgba(var(--text-color), 0.7); +#show_character_count { + font-size: 0.8rem; + margin-left: auto; } -.fab{ +#flo_data_status:not(:empty) { + color: red; + padding: 0.5rem 0; +} +#saved_ids_popup { + --height: 80vh; +} + +#main_header { + padding: 1rem 1.5rem; +} +#main_card { + display: flex; + flex-direction: column; + height: 100%; + width: 100%; + background-color: rgba(var(--foreground-color), 1); + transition: background-color 0.3s; +} +#pages_container { + flex: 1; + overflow-y: auto; +} + +#main_navbar { + display: flex; + background: rgba(var(--text-color), 0.03); + &.hide-away { position: absolute; - display: inline-flex; - border-radius: 5rem; - aspect-ratio: 1/1; - padding: 0.7rem; - background: #FF1F1F; - box-shadow: 0 0.5rem 0.5rem rgba(0, 0, 0, 0.16); -} -.fab__icon{ - height: 1.8rem; - width: 1.8rem; - fill: white; -} -#flo_options{ - padding: 1rem; -} -.flo-options__item{ - padding: 0.8rem; - max-width: 6rem; - justify-content: center; - color: rgba(var(--text-color), 0.8); -} -.option__icon{ - height: 3rem; - width: 3rem; - padding: 0.8rem; - background: rgba(var(--text-color), 0.04); - border-radius: 1rem; -} -.coral{ - fill: #ff5e78; -} -.violet{ - fill: #845ec2; -} -.option__title{ - margin-top: 0.5rem; - font-weight: 500; -} - -#dashboard_page__header{ -} -#base_header{ - position: relative; - width: 100%; -} -.header__title{ - font-size: 1.1rem; - font-weight: 700; - color: rgba(var(--text-color), 0.8); -} - - - -#search_contacts__input{ - width: 100%; - --padding: 0.5rem; -} -#search_contacts_button{ - -} - -.search__icon{ - height: 1.2rem; - width: 1.2rem; -} - -.expanding-search{ - width: 14rem; -} -#selected_contact_options{ - -} -.contact-option{ - &:not(:last-of-type){ - margin-right: 0.5rem; - } - &:first-of-type{ - padding-right: 0.6rem; - margin-right: auto; - margin-left: -0.6rem; - } -} -.contact-option__button{ - display: inline-flex; - align-items: center; - border-radius: 0.3rem; - padding: 0.5rem 0.6rem; -} -.contact-option__icon{ - height: 1.2rem; - width: 1.2rem; - margin-right: 0.5rem; -} -.contact-option__name{ - font-weight: 500; - font-size: 0.9rem; - color: rgba(var(--text-color), 0.8); -} - -#contacts_container{ + } + ul { display: flex; - flex-direction: column; - max-height: 100%; + height: 100%; + width: 100%; + li { + width: 100%; + } + } +} +.nav-item { + position: relative; + display: flex; + flex: 1; + width: 100%; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 0.5rem 0.3rem; + color: var(--text-color); + font-size: 0.7rem; + border-radius: 0.3rem; + .icon { + transition: transform 0.2s; + } + &__title { + margin-top: 0.3rem; + transition: opacity 0.2s, transform 0.2s; + } + &--active { + color: var(--accent-color); + .icon { + fill: var(--accent-color); + transform: translateY(50%); + } + .nav-item__title { + transform: translateY(100%); + opacity: 0; + } + } + &__indicator { + position: absolute; + bottom: 0; + width: 2rem; + height: 0.3rem; + background: var(--accent-color); + border-radius: 1rem 1rem 0 0; + z-index: 1; + } +} + +#fix_invalid_button { + margin-bottom: 1rem !important; +} + +#get_private_key_field { + label { + display: flex; + input:checked ~ .visible { + display: none; + } + input:not(:checked) ~ .invisible { + display: none; + } + } +} +.multi-state-button { + display: grid; + text-align: center; + align-items: center; + & > * { + grid-area: 1/1/2/2; + } + button { + z-index: 1; + } +} +.clip { + clip-path: circle(0); +} + +#flo_id_warning { + padding-bottom: 1.5rem; + border-bottom: thin solid rgba(var(--text-color), 0.3); + .icon { + height: 4rem; + width: 4rem; + padding: 1rem; + background-color: #ffc107; + border-radius: 3rem; + fill: rgba(0, 0, 0, 0.8); + margin-bottom: 1.5rem; + } +} +.generated-id-card { + display: grid; + gap: 1rem; + h5 { + margin-bottom: 0.3rem; + } +} + +#home { + padding: 0; + & > :first-child { overflow-y: auto; align-content: flex-start; - padding: 0 0 6rem 1rem; + padding: 0.5rem 1.5rem 4rem 1.5rem; + } } -.contact-card{ +.primary-action { + display: flex; + padding: 0.8rem 1rem; + gap: 0.5rem; + white-space: normal; + font-size: 0.8rem; + border-radius: 0.5rem; + background-color: transparent; + border: thin solid rgba(var(--text-color), 0.3); + .icon { + fill: var(--accent-color); + } + &:not(:last-of-type) { + margin-right: 0.5rem; + } +} +#saved_ids_list { + position: relative; + align-content: flex-start; + padding-bottom: 1.5rem; + margin-top: 1rem; + gap: 1rem; + grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); +} +.saved-id { + grid-template-columns: auto 1fr; + gap: 0 0.8rem; + border-radius: 0.3rem; + padding: 0.5rem; + background-color: rgba(var(--text-color), 0.03); + user-select: none; + &.highlight { + box-shadow: 0 0 0.1rem 0.1rem var(--accent-color) inset; + } + .edit-saved { + grid-area: 1/1/3/2; + padding: 0.3rem; position: relative; - overflow: hidden; - display: grid; - width: 100%; - gap: 1rem; - grid-template-columns: auto auto 1fr auto; + .icon { + position: absolute; + height: 1.2rem; + width: 1.2rem; + right: 0; + bottom: 0; + border-radius: 0.5rem; + padding: 0.2rem; + background-color: rgba(var(--background-color), 1); + } + } + &__initial { + display: flex; align-items: center; - padding: 0.5rem 0.6rem; - flex-shrink: 0; - cursor: pointer; - user-select: none; - align-self: flex-start; justify-content: center; - border-radius: 0.3rem; - background: rgba(var(--foreground-color), 0.6); - -webkit-tap-highlight-color: transparent; + height: 2.4rem; + width: 2.4rem; + font-size: 1.2rem; + text-transform: uppercase; + color: rgba(var(--background-color), 1); + font-weight: 700; + line-height: 1; + background-color: var(--accent-color); + justify-self: flex-start; + border-radius: 2rem; + } + &__label { + align-self: flex-end; + } + &__flo-id { + font-size: 0.8rem; + } } -.contact-card__checkbox{ - --height: 1.5rem; - --width: 1.5rem; - --border-radius: 0.3rem; - --border-color: rgba(var(--text-color), 0.6); + +.page { + position: relative; + display: flex; + flex-direction: column; + overflow-y: auto; + align-content: flex-start; + padding: 0 1.5rem; + padding-bottom: 3rem; } -.contact-card__initial{ - width: 2rem; - height: 2rem; - padding: 1.2rem; - font-size: 1.1rem; - border-radius: 50%; + +#transactions { + position: relative; + height: 100%; + padding: 0; + header { + padding: 1rem; + .grid { + grid-template-columns: auto 1fr auto; + } + } } -.contact-card__name{ - font-weight: 500; - font-size: 1rem; +#flo_id_name { + overflow: hidden; + text-overflow: ellipsis; +} +#token_list { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; +} +.token-item { + font-size: 0.9rem; + padding: 0.5rem 1rem; + background-color: rgba(var(--text-color), 0.06); + border-radius: 0.3rem; +} +#transactions_list { + flex-direction: column; + padding-bottom: 4rem; +} +.transaction { + gap: 1rem; + padding: 1rem; + background-color: rgba(var(--text-color), 0.03); + border-radius: 0.3rem; + &:not(:last-of-type) { + margin-bottom: 1rem; + } + .icon { + fill: var(--accent-color); + } + &__time, + &__link, + &__receiver { + font-size: 0.8rem; + } + &__receiver { + margin-left: 0.5rem; color: rgba(var(--text-color), 0.8); + } + p { + font-size: 0.9rem; + max-width: unset; + } + &__time { + justify-self: flex-end; + color: rgba(var(--text-color), 0.8); + } } -.contact-card__more{ - padding: 0.4rem; +.fab { + position: absolute; + right: 0; + bottom: 0; + margin: 1.5rem; + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2); + z-index: 2; } -#contacts_empty_state{ +#scroll_to_top { + border-radius: 3rem; + background-color: rgba(var(--foreground-color), 1); +} +#add_address_button { + border-radius: 0.5rem; + color: rgba(var(--background-color), 1); + background-color: var(--accent-color); + .icon { + fill: rgba(var(--background-color), 1); + } +} + +#transaction_result { + display: grid; + gap: 0.5rem; + height: max(40vh, 24rem); + align-items: center; + justify-content: center; + text-align: center; + align-content: center; + &.success { + .icon--failed { + display: none; + } + } + &.failed { + .icon--success { + display: none; + } + } + h3 { text-align: center; -} -.empty-state__title{ - font-weight: 400; - color: rgba(var(--text-color), 0.8); -} - -#show_contact_popup_button{ - right: 0; - bottom: 0; - margin: 1.5rem; -} - -.page__header{ - min-height: 4rem; - padding: 1rem; -} -.page__title{ - font-size: 1.1rem; -} - -#send_flo_form{ width: 100%; + } + .icon { + justify-self: center; + height: 4rem; + width: 4rem; + border-radius: 5rem; + margin-bottom: 1rem; + animation: popup 1s; + &--success { + fill: rgba(var(--background-color), 1); + padding: 1rem; + background-color: #0bbe56; + } + &--failed { + background-color: rgba(var(--text-color), 0.03); + fill: var(--danger-color); + } + } + sm-copy { + font-size: 0.8rem; + } +} +@keyframes popup { + 0% { + opacity: 0; + transform: scale(0.2) translateY(600%); + } + 10% { + transform: scale(0.2) translateY(5rem); + opacity: 1; + } + 40% { + transform: scale(0.2) translateY(0); + } + 80% { + transform: scale(1.1) translateY(0); + } + 100% { + transform: scale(1) translateY(0); + } +} + +#settings { +} + +@media screen and (max-width: 40rem) { + #main_navbar { + &.hide-away { + bottom: 0; + left: 0; + right: 0; + } + } +} +@media screen and (min-width: 40rem) { + body { + // background: url("back.png") no-repeat; + background-size: cover; + } + sm-popup { + --width: 24rem; + } + .popup__header { + grid-column: 1/-1; + padding: 1rem 1.5rem 0 1.5rem; + } + + body { + display: flex; + align-items: center; + justify-content: center; + } + + #main_card { + display: grid; + grid-template-columns: auto 1fr; + grid-template-rows: auto 1fr; + grid-template-areas: "nav header" "nav main"; + position: relative; + border-radius: 0.5rem; + overflow: hidden; + box-shadow: 0 0.1rem 0.2rem rgba(0, 0, 0, 0.05), + 0 1rem 3rem rgba(0, 0, 0, 0.2); + // backdrop-filter: blur(2rem); + background-color: rgba(var(--foreground-color), 0.9); + } + #main_header { + grid-area: header; + } + #pages_container { + grid-area: main; + } + + #main_navbar { + grid-area: nav; + border-top: none; + flex-direction: column; height: 100%; - padding: 0 1rem; - gap: 0.3; + ul { + flex-direction: column; + gap: 0.5rem; + padding: 0.3rem; + + li:last-of-type { + margin-top: auto; + } + } + } + .nav-item { + aspect-ratio: 1/1; + &__indicator { + width: 0.25rem; + height: 50%; + left: 0; + border-radius: 0 1rem 1rem 0; + bottom: auto; + } + } + #create_flo_id_popup { + --width: 28rem; + } + #send { + sm-form::part(form) { + align-items: flex-start; + grid-template-columns: 45% 1fr; + } + } } -.form__section{ - align-content: flex-start; +@media screen and (min-width: 56rem) { + #main_card { + height: 80vh; + width: 56rem; + } } -.label{ - font-size: 0.9rem; - margin-bottom: 0.3rem; - color: rgba(var(--text-color), 0.9); - &:not(:first-of-type){ - margin-top: 0.8rem; +@media (any-hover: hover) { + ::-webkit-scrollbar { + width: 0.5rem; + height: 0.5rem; + } + + ::-webkit-scrollbar-thumb { + background: rgba(var(--text-color), 0.3); + border-radius: 1rem; + + &:hover { + background: rgba(var(--text-color), 0.5); } -} -#sent_flo_data{ - --max-height: 12rem; -} -#send_flo_button{ - margin-top: 1.5rem; + } + .interact:not([disabled]) { + transition: background-color 0.3s; + &:hover { + background-color: rgba(var(--text-color), 0.06); + } + } + .button:not([disabled]) { + transition: background-color 0.3s, filter 0.3s; + &:hover { + filter: contrast(2); + } + } } - - -#balance_card{ - width: 100%; - padding: 1rem; - margin-bottom: 1rem; - border-radius: 0.3rem; - background-color: rgba(var(--text-color), 0.04); -} -#balance_card__input{ - margin-bottom: 1rem; -} -.balance_card__title{ - font-size: 1rem; - font-weight: 500; - margin-bottom: 0.5rem; - color: rgba(var(--text-color), 0.8); -} -.balance_card__description{ - font-size: 0.9rem; - margin-bottom: 0.5rem; - color: rgba(var(--text-color), 0.8); -} -#flo_balance{ - word-break: break-all; - font-size: 2rem; - margin-bottom: 1rem; +@supports (overflow: overlay) { + body { + overflow: overlay; + } } - - -.settings__section{ - padding: 0 1rem; - width: min(50ch, 100%); - &:not(:last-of-type){ - margin-bottom: 1rem; - } +.hide { + display: none !important; } -.setting__title{ - color: rgba(var(--text-color), 0.9); -} -.setting__description{ - font-size: 0.9rem; - color: rgba(var(--text-color), 0.8); -} -.toggle-grid{ - gap: 0.3rem; - margin-right: 1rem; -} - - -// mobile only styles -@media all and (max-width: 640px){ - .hide-on-mobile{ - display: none; - } - #main_card{ - min-height: 100%; - grid-template-rows: auto 1fr auto; - grid-template-areas: 'header' 'page' 'nav'; - } - #main_navbar{ - flex-direction: row; - } - .navbar__item{ - flex: 1; - flex-direction: column; - } - .navbar__item__icon{ - margin: 0 0 0.5rem 0; - } - .navbar__item__icon{ - margin: 0 0 0.5rem 0; - } - #dashboard_page__header{ - padding-top: 0; - } - .expanding-search{ - background-color: rgba(var(--foreground-color), 1); - position: absolute; - z-index: 1; - width: 100%; - } - .back-button{ - - } -} - -// desktop only styles -@media all and (min-width: 640px){ - body{ - align-items: center; - justify-content: center; - #main_card{ - background: rgba(var(--foreground-color), 1); - } - } - body[data-theme='dark']{ - #main_card{ - background: rgba(var(--text-color), 0.04); - } - } - sm-popup{ - --width: 24rem; - } - .hide-on-desktop{ - display: none; - } - .popup__header{ - padding: 1rem 1.5rem 0 1rem; - } - #main_card{ - position: relative; - width: 80vw; - height: 80vh; - border-radius: 0.2rem; - overflow: hidden; - grid-template-columns: 15rem 1fr; - grid-template-rows: auto 1fr; - grid-template-areas: 'header page' 'nav page'; - box-shadow: 0 1.5rem 1.5rem rgba(0, 0, 0, 0.16); - } - #main_header{ - padding: 1.5rem; - } - #main_navbar{ - flex-direction: column; - height: 100%; - padding: 0 1rem; - align-content: flex-start; - } - .navbar__item__title{ - font-size: 0.9rem; - } - #page_container{ - position: relative; - grid-row: 1/3; - &::after{ - content: ''; - position: absolute; - left: 0; - height: 65%; - width: 1px; - background: rgba(var(--text-color), 0.2); - top: 50%; - transform: translateY(-50%); - } - } - .page__header{ - min-height: 6.2rem; - padding: 1.5rem; - } - #contacts_container{ - padding: 0 1rem 8rem 1.5rem; - } - #send_flo_form{ - gap: 1rem; - grid-template-columns: 1fr 1fr; - padding: 0 1.5rem 1.5rem 1.5rem; - } - .settings__section{ - padding: 0 1.5rem; - } -} -@media all and (min-width: 1080px){ - -} -@media all and (min-width: 1280px){ - #main_card{ - width: 65vw; - height: 85vh; - } -} -@media all and (min-width: 1920px){ - #main_card{ - width: 60vw; - height: 65vh; - } -} -@media (any-hover: hover){ - ::-webkit-scrollbar{ - width: 0.5rem; - height: 0.5rem; - } - - ::-webkit-scrollbar-thumb{ - background: rgba(var(--text-color), 0.3); - border-radius: 1rem; - &:hover{ - background: rgba(var(--text-color), 0.5); - } - } - .contact-card__checkbox:not([checked]):not(:focus-within){ - opacity: 0.4; - transition: opacity 0.3s; - } - .contact-card__more:not(:focus-within){ - opacity: 0; - transition: opacity 0.3s; - } - .contact-card:hover .contact-card__checkbox, - .contact-card:hover .contact-card__more{ - opacity: 1; - } - .contact-option__button{ - transition: background 0.3s; - &:hover{ - background-color: rgba(var(--text-color), 0.1); - } - } -} \ No newline at end of file diff --git a/index.html b/index.html index 4d37813..5310cbd 100644 --- a/index.html +++ b/index.html @@ -2,1792 +2,15 @@ - FLO web wallet + FLO Web Wallet - + + + + - -
-
- There seems to be a problem connecting to the internet. + + + +

+

+
+ Cancel + OK
-
- -
-
-