diff --git a/components-old.js b/components-old.js new file mode 100644 index 0000000..62b535b --- /dev/null +++ b/components-old.js @@ -0,0 +1,3640 @@ +/*jshint esversion: 6 */ +//Button +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)) + } + + get disabled() { + return this.isDisabled + } + + set disabled(value) { + if (value && !this.isDisabled) { + this.isDisabled = true + this.setAttribute('disabled', '') + this.button.removeAttribute('tabindex') + } else if (!value && this.isDisabled) { + this.isDisabled = false + this.removeAttribute('disabled') + } + } + + dispatch() { + if (this.isDisabled) { + this.dispatchEvent(new CustomEvent('disabled', { + bubbles: true, + composed: true + })) + } else { + this.dispatchEvent(new CustomEvent('clicked', { + bubbles: true, + composed: true + })) + } + } + + connectedCallback() { + this.isDisabled = false + this.button = this.shadowRoot.querySelector('.button') + if (this.hasAttribute('disabled') && !this.isDisabled) + this.isDisabled = true + this.addEventListener('click', (e) => { + this.dispatch() + }) + } + }) + +//Input +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)) + } + + static get observedAttributes() { + return ['placeholder'] + } + + get value() { + return this.shadowRoot.querySelector('input').value + } + + set value(val) { + this.shadowRoot.querySelector('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') + } + + get isValid() { + return this.shadowRoot.querySelector('input').checkValidity() + } + + get validity() { + return this.shadowRoot.querySelector('input').validity + } + + set disabled(value) { + if (value) + this.shadowRoot.querySelector('.input').classList.add('disabled') + else + this.shadowRoot.querySelector('.input').classList.remove('disabled') + } + set readOnly(value) { + if (value) { + this.shadowRoot.querySelector('input').setAttribute('readonly', '') + this.shadowRoot.querySelector('.input').classList.add('readonly') + } else { + this.shadowRoot.querySelector('input').removeAttribute('readonly') + this.shadowRoot.querySelector('.input').classList.remove('readonly') + } + } + + setValidity = (message) => { + this.feedbackText.textContent = message + } + + showValidity = () => { + this.feedbackText.classList.remove('hide-completely') + } + + hideValidity = () => { + this.feedbackText.classList.add('hide-completely') + } + + 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.readonly) { + if (this.input.value !== '') { + this.clearBtn.classList.remove('hide') + } else { + this.clearBtn.classList.add('hide') + } + } + if (!this.hasAttribute('placeholder') || this.getAttribute('placeholder') === '') return; + if (this.input.value !== '') { + if (this.animate) + this.inputParent.classList.add('animate-label') + else + this.label.classList.add('hide') + } else { + if (this.animate) + this.inputParent.classList.remove('animate-label') + else + this.label.classList.remove('hide') + } + } + + + connectedCallback() { + this.inputParent = this.shadowRoot.querySelector('.input') + this.clearBtn = this.shadowRoot.querySelector('.clear') + this.label = this.shadowRoot.querySelector('.label') + this.feedbackText = this.shadowRoot.querySelector('.feedback-text') + this.valueChanged = false; + this.readonly = false + this.isNumeric = false + this.min + this.max + this.animate = this.hasAttribute('animate') + this.input = this.shadowRoot.querySelector('input') + this.shadowRoot.querySelector('.label').textContent = this.getAttribute('placeholder') + if (this.hasAttribute('value')) { + this.input.value = this.getAttribute('value') + this.checkInput() + } + if (this.hasAttribute('required')) { + this.input.setAttribute('required', '') + } + if (this.hasAttribute('min')) { + let minValue = this.getAttribute('min') + this.input.setAttribute('min', minValue) + this.min = parseInt(minValue) + } + if (this.hasAttribute('max')) { + let maxValue = this.getAttribute('max') + this.input.setAttribute('max', maxValue) + this.max = parseInt(maxValue) + } + if (this.hasAttribute('minlength')) { + const minValue = this.getAttribute('minlength') + this.input.setAttribute('minlength', minValue) + } + if (this.hasAttribute('maxlength')) { + const maxValue = this.getAttribute('maxlength') + this.input.setAttribute('maxlength', maxValue) + } + if (this.hasAttribute('step')) { + const steps = this.getAttribute('step') + this.input.setAttribute('step', steps) + } + if (this.hasAttribute('pattern')) { + this.input.setAttribute('pattern', this.getAttribute('pattern')) + } + if (this.hasAttribute('readonly')) { + this.input.setAttribute('readonly', '') + this.readonly = true + } + if (this.hasAttribute('disabled')) { + this.inputParent.classList.add('disabled') + } + if (this.hasAttribute('error-text')) { + this.feedbackText.textContent = this.getAttribute('error-text') + } + if (this.hasAttribute('type')) { + if (this.getAttribute('type') === 'number') { + this.input.setAttribute('inputmode', 'numeric') + this.input.setAttribute('type', 'number') + this.isNumeric = true + } else + this.input.setAttribute('type', this.getAttribute('type')) + } else + this.input.setAttribute('type', 'text') + this.input.addEventListener('input', e => { + this.checkInput(e) + }) + this.clearBtn.addEventListener('click', e => { + this.value = '' + }) + } + + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + if (name === 'placeholder') { + this.shadowRoot.querySelector('.label').textContent = newValue; + this.setAttribute('aria-label', newValue); + } + } + } + }) + +//textarea +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') + } + get value() { + return this.textarea.value + } + set value(val) { + this.textarea.value = val; + this.textareaBox.dataset.value = val + this.checkInput() + this.fireEvent() + } + 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 !== '') { + this.placeholder.classList.add('hide') + } else { + this.placeholder.classList.remove('hide') + } + } + connectedCallback() { + this.textareaBox = this.shadowRoot.querySelector('.textarea') + this.placeholder = this.shadowRoot.querySelector('.placeholder') + + if(this.hasAttribute('placeholder')) + this.placeholder.textContent = this.getAttribute('placeholder') + + if (this.hasAttribute('value')) { + this.textarea.value = this.getAttribute('value') + this.checkInput() + } + if (this.hasAttribute('required')) { + this.textarea.setAttribute('required', '') + } + if (this.hasAttribute('readonly')) { + this.textarea.setAttribute('readonly', '') + } + if (this.hasAttribute('rows')) { + this.textarea.setAttribute('rows', this.getAttribute('rows')) + } + this.textarea.addEventListener('input', e => { + this.textareaBox.dataset.value = this.textarea.value + this.checkInput() + }) + } + }) + +// tab +const smTab = document.createElement('template') +smTab.innerHTML = ` + +
+ +
+`; + +customElements.define('sm-tab', class extends HTMLElement { + constructor() { + super() + this.shadow = this.attachShadow({ + mode: 'open' + }).append(smTab.content.cloneNode(true)) + } +}) + +//chcekbox + +const smCheckbox = document.createElement('template') +smCheckbox.innerHTML = ` + +` +customElements.define('sm-checkbox', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smCheckbox.content.cloneNode(true)) + + this.checkbox = this.shadowRoot.querySelector('.checkbox'); + this.input = this.shadowRoot.querySelector('input') + + this.isChecked = false + this.isDisabled = false + } + + 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') + } + } + + set value(val) { + this.val = val + this.setAttribute('value', value) + } + + get value() { + return getAttribute('value') + } + + dispatch = () => { + this.dispatchEvent(new CustomEvent('change', { + bubbles: true, + composed: true + })) + } + handleKeyup = e => { + if ((e.code === "Enter" || e.code === "Space") && this.isDisabled == false) { + if (this.hasAttribute('checked')) { + this.input.checked = false + this.removeAttribute('checked') + } + else { + this.input.checked = true + this.setAttribute('checked', '') + } + } + } + handleChange = e => { + if (this.input.checked) { + this.setAttribute('checked', '') + } + else { + this.removeAttribute('checked') + } + } + + connectedCallback() { + this.val = '' + this.addEventListener('keyup', this.handleKeyup) + this.input.addEventListener('change', this.handleChange) + } + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + if (name === 'disabled') { + if (newValue === 'true') { + this.isDisabled = true + } else { + this.isDisabled = false + } + } + else if (name === 'checked') { + if (this.hasAttribute('checked')) { + this.isChecked = true + this.input.checked = true + } + else { + this.input.checked = false + this.isChecked = false + } + this.dispatch() + } + } + } + disconnectedCallback() { + this.removeEventListener('keyup', this.handleKeyup) + this.removeEventListener('change', this.handleChange) + } +}) + +//switch + +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 + } + + 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') + } + } + + dispatch = () => { + this.dispatchEvent(new CustomEvent('change', { + bubbles: true, + composed: true, + detail: { + value: this.isChecked + } + })) + } + + connectedCallback() { + this.addEventListener('keyup', e => { + if ((e.code === "Enter" || e.code === "Space") && !this.isDisabled) { + 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 + } + } + } + } + +}) + +// select +const smSelect = document.createElement('template') +smSelect.innerHTML = ` + +
+
+
+ + + +
+
+ +
+
`; +customElements.define('sm-select', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smSelect.content.cloneNode(true)) + } + static get observedAttributes() { + return ['value'] + } + get value() { + return this.getAttribute('value') + } + set value(val) { + this.setAttribute('value', val) + } + + collapse() { + this.chevron.classList.remove('rotate') + this.optionList.animate(this.slideUp, this.animationOptions) + .onfinish = () => { + this.optionList.classList.add('hide') + this.open = false + } + } + connectedCallback() { + this.availableOptions + this.optionList = this.shadowRoot.querySelector('.options') + this.chevron = this.shadowRoot.querySelector('.toggle') + let slot = this.shadowRoot.querySelector('.options slot'), + selection = this.shadowRoot.querySelector('.selection'), + previousOption + this.open = false; + this.slideDown = [{ + transform: `translateY(-0.5rem)`, + opacity: 0 + }, + { + transform: `translateY(0)`, + opacity: 1 + } + ] + this.slideUp = [{ + transform: `translateY(0)`, + opacity: 1 + }, + { + transform: `translateY(-0.5rem)`, + opacity: 0 + } + ] + this.animationOptions = { + duration: 300, + fill: "forwards", + easing: 'ease' + } + selection.addEventListener('click', e => { + if (!this.open) { + this.optionList.classList.remove('hide') + this.optionList.animate(this.slideDown, this.animationOptions) + this.chevron.classList.add('rotate') + this.open = true + } else { + this.collapse() + } + }) + selection.addEventListener('keydown', e => { + if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { + e.preventDefault() + this.availableOptions[0].focus() + } + if (e.code === 'Enter' || e.code === 'Space') + if (!this.open) { + this.optionList.classList.remove('hide') + this.optionList.animate(this.slideDown, this.animationOptions) + this.chevron.classList.add('rotate') + this.open = true + } else { + this.collapse() + } + }) + this.optionList.addEventListener('keydown', e => { + if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { + e.preventDefault() + if (document.activeElement.previousElementSibling) { + document.activeElement.previousElementSibling.focus() + } + } + if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { + e.preventDefault() + if (document.activeElement.nextElementSibling) + document.activeElement.nextElementSibling.focus() + } + }) + this.addEventListener('optionSelected', e => { + if (previousOption !== e.target) { + this.setAttribute('value', e.detail.value) + this.shadowRoot.querySelector('.option-text').textContent = e.detail.text; + this.dispatchEvent(new CustomEvent('change', { + bubbles: true, + composed: true, + detail: { + value: e.detail.value + } + })) + if (previousOption) { + previousOption.classList.remove('check-selected') + } + previousOption = e.target; + } + if (!e.detail.switching) + this.collapse() + + e.target.classList.add('check-selected') + }) + slot.addEventListener('slotchange', e => { + this.availableOptions = slot.assignedElements() + if (this.availableOptions[0]) { + let firstElement = this.availableOptions[0]; + previousOption = firstElement; + firstElement.classList.add('check-selected') + this.setAttribute('value', firstElement.getAttribute('value')) + this.shadowRoot.querySelector('.option-text').textContent = firstElement.textContent + this.availableOptions.forEach((element, index) => { + element.setAttribute('data-rank', index + 1); + element.setAttribute('tabindex', "0"); + }) + } + }); + document.addEventListener('mousedown', e => { + if (!this.contains(e.target) && this.open) { + this.collapse() + } + }) + } +}) + +// option +const smOption = document.createElement('template') +smOption.innerHTML = ` + +
+ + + + +
`; +customElements.define('sm-option', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smOption.content.cloneNode(true)) + } + + sendDetails(switching) { + let optionSelected = new CustomEvent('optionSelected', { + bubbles: true, + composed: true, + detail: { + text: this.textContent, + value: this.getAttribute('value'), + switching: switching + } + }) + this.dispatchEvent(optionSelected) + } + + connectedCallback() { + let validKey = [ + 'ArrowUp', + 'ArrowDown', + 'ArrowLeft', + 'ArrowRight' + ] + this.addEventListener('click', e => { + this.sendDetails() + }) + this.addEventListener('keyup', e => { + if (e.code === 'Enter' || e.code === 'Space') { + e.preventDefault() + this.sendDetails(false) + } + if (validKey.includes(e.code)) { + e.preventDefault() + this.sendDetails(true) + } + }) + if (this.hasAttribute('default')) { + setTimeout(() => { + this.sendDetails() + }, 0); + } + } +}) + +// strip select +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 + this._value + this.scrollDistance + } + 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() { + 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 (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) + } +}) + +const stripOption = document.createElement('template') +stripOption.innerHTML = ` + + +` + +//Strip option +customElements.define('strip-option', class extends HTMLElement{ + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(stripOption.content.cloneNode(true)) + this._value + this.radioButton = this.shadowRoot.querySelector('input') + } + 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._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) + } +}) + + +//popup +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 + } + + get open() { + return this.isOpen + } + + resumeScrolling = () => { + const scrollY = document.body.style.top; + window.scrollTo(0, parseInt(scrollY || '0') * -1); + setTimeout(() => { + document.body.style.overflow = 'auto'; + document.body.style.top= 'initial' + }, 300); + } + + show = (pinned, popupStack) => { + if (popupStack) + this.popupStack = popupStack + if (this.popupStack && !this.hasAttribute('open')) { + this.popupStack.push({ + popup: this, + permission: pinned + }) + if (this.popupStack.items.length > 1) { + this.popupStack.items[this.popupStack.items.length - 2].popup.classList.add('stacked') + } + this.dispatchEvent( + new CustomEvent("popupopened", { + bubbles: true, + detail: { + popup: this, + popupStack: this.popupStack + } + }) + ) + this.setAttribute('open', '') + this.pinned = pinned + this.isOpen = true + } + this.popupContainer.classList.remove('hide') + this.popup.style.transform = 'none'; + document.body.style.overflow = 'hidden'; + document.body.style.top= `-${window.scrollY}px` + return this.popupStack + } + hide = () => { + if (window.innerWidth < 640) + this.popup.style.transform = 'translateY(100%)'; + else + this.popup.style.transform = 'translateY(3rem)'; + this.popupContainer.classList.add('hide') + this.removeAttribute('open') + if (typeof this.popupStack !== 'undefined') { + this.popupStack.pop() + if (this.popupStack.items.length) { + this.popupStack.items[this.popupStack.items.length - 1].popup.classList.remove('stacked') + } else { + this.resumeScrolling() + } + } else { + this.resumeScrolling() + } + + if (this.inputFields.length) { + setTimeout(() => { + this.inputFields.forEach(field => { + if (field.type === 'radio' || field.tagName === 'SM-CHECKBOX') + field.checked = false + if (field.tagName === 'SM-INPUT' || field.tagName === 'TEXTAREA'|| field.tagName === 'SM-TEXTAREA') + field.value = '' + }) + }, 300); + } + setTimeout(() => { + this.dispatchEvent( + new CustomEvent("popupclosed", { + bubbles: true, + detail: { + popup: this, + popupStack: this.popupStack + } + }) + ) + this.isOpen = false + }, 300); + } + + handleTouchStart = (e) => { + this.touchStartY = e.changedTouches[0].clientY + this.popup.style.transition = 'transform 0.1s' + this.touchStartTime = e.timeStamp + } + + handleTouchMove = (e) => { + if (this.touchStartY < e.changedTouches[0].clientY) { + this.offset = e.changedTouches[0].clientY - this.touchStartY; + this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup()) + } + /*else { + this.offset = this.touchStartY - e.changedTouches[0].clientY; + this.popup.style.transform = `translateY(-${this.offset}px)` + }*/ + } + + handleTouchEnd = (e) => { + this.touchEndTime = e.timeStamp + cancelAnimationFrame(this.touchEndAnimataion) + this.touchEndY = e.changedTouches[0].clientY + this.popup.style.transition = 'transform 0.3s' + 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.show() + return + } else + this.hide() + } else { + this.show() + } + } else { + if (this.touchEndY > this.touchStartY) + if (this.pinned) { + this.show() + return + } + else + this.hide() + } + } + + movePopup = () => { + this.popup.style.transform = `translateY(${this.offset}px)` + } + + connectedCallback() { + this.pinned = false + this.popupStack + this.popupContainer = this.shadowRoot.querySelector('.popup-container') + this.popup = this.shadowRoot.querySelector('.popup') + this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot') + this.offset + this.popupHeader = this.shadowRoot.querySelector('.popup-top') + this.touchStartY = 0 + this.touchEndY = 0 + this.touchStartTime = 0 + this.touchEndTime = 0 + this.touchEndAnimataion; + this.threshold = this.popup.getBoundingClientRect().height * 0.3 + + if (this.hasAttribute('open')) + this.show() + this.popupContainer.addEventListener('mousedown', e => { + if (e.target === this.popupContainer && !this.pinned) { + if (this.pinned) { + this.show() + return + } else + this.hide() + } + }) + + this.popupBodySlot.addEventListener('slotchange', () => { + setTimeout(() => { + this.threshold = this.popup.getBoundingClientRect().height * 0.3 + }, 200); + this.inputFields = this.querySelectorAll('sm-input', 'sm-checkbox', 'textarea', 'sm-textarea', 'radio') + }) + + this.popupHeader.addEventListener('touchstart', (e) => { this.handleTouchStart(e) }, {passive: true}) + this.popupHeader.addEventListener('touchmove', (e) => {this.handleTouchMove(e)}, {passive: true}) + this.popupHeader.addEventListener('touchend', (e) => {this.handleTouchEnd(e)}, {passive: true}) + } + disconnectedCallback() { + this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, {passive: true}) + this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, {passive: true}) + this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, {passive: true}) + } +}) + +//carousel + +const smCarousel = document.createElement('template') +smCarousel.innerHTML = ` + + +`; + +customElements.define('sm-carousel', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smCarousel.content.cloneNode(true)) + + this.isAutoPlaying = false + this.autoPlayInterval = 5000 + this.autoPlayTimeout + this.initialTimeout + this.activeSlideNum = 0 + this.carouselItems + this.indicators + this.showIndicator = false + this.carousel = this.shadowRoot.querySelector('.carousel') + this.carouselContainer = this.shadowRoot.querySelector('.carousel-container') + this.carouselSlot = this.shadowRoot.querySelector('slot') + this.nextArrow = this.shadowRoot.querySelector('.carousel__button--right') + this.previousArrow = this.shadowRoot.querySelector('.carousel__button--left') + this.indicatorsContainer = this.shadowRoot.querySelector('.indicators') + } + + static get observedAttributes() { + return ['indicator', 'autoplay', 'interval'] + } + + scrollLeft = () => { + this.carousel.scrollBy({ + left: -this.scrollDistance, + behavior: 'smooth' + }) + } + + scrollRight = () => { + this.carousel.scrollBy({ + left: this.scrollDistance, + behavior: 'smooth' + }) + } + + handleIndicatorClick = (e) => { + if (e.target.closest('.dot')) { + const slideNum = parseInt(e.target.closest('.dot').dataset.rank) + if (this.activeSlideNum !== slideNum) { + this.showSlide(slideNum) + } + } + } + + showSlide = (slideNum) => { + this.carousel.scrollTo({ + left: (this.carouselItems[slideNum].getBoundingClientRect().left - this.carousel.getBoundingClientRect().left + this.carousel.scrollLeft), + behavior: 'smooth' + }) + } + + nextSlide = () => { + if (!this.carouselItems) return + let showSlideNo = (this.activeSlideNum + 1) < this.carouselItems.length ? this.activeSlideNum + 1 : 0 + this.showSlide(showSlideNo) + } + + autoPlay = () => { + this.nextSlide() + if (this.isAutoPlaying) { + this.autoPlayTimeout = setTimeout(() => { + this.autoPlay() + }, this.autoPlayInterval); + } + } + + startAutoPlay = () => { + this.setAttribute('autoplay', '') + } + + stopAutoPlay = () => { + this.removeAttribute('autoplay') + } + + connectedCallback() { + this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 + let frag = document.createDocumentFragment(); + if (this.hasAttribute('indicator')) + this.showIndicator = true + + + let firstVisible = false, + lastVisible = false + const allElementsObserver = new IntersectionObserver(entries => { + entries.forEach(entry => { + if (this.showIndicator) { + const activeRank = parseInt(entry.target.dataset.rank) + if (entry.isIntersecting) { + this.indicators[activeRank].classList.add('active') + this.activeSlideNum = activeRank + } + else + this.indicators[activeRank].classList.remove('active') + } + if (!entry.target.previousElementSibling) + if (entry.isIntersecting) { + this.previousArrow.classList.remove('expand') + firstVisible = true + } + else { + this.previousArrow.classList.add('expand') + firstVisible = false + } + if (!entry.target.nextElementSibling) + if (entry.isIntersecting) { + this.nextArrow.classList.remove('expand') + lastVisible = true + } + else { + this.nextArrow.classList.add('expand') + lastVisible = false + } + if (firstVisible && lastVisible) + this.indicatorsContainer.classList.add('hide') + else + this.indicatorsContainer.classList.remove('hide') + }) + }, { + root: this.carouselContainer, + threshold: 0.9 + }) + + const carouselObserver = new IntersectionObserver(entries => { + if (entries[0].isIntersecting) { + this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 + } + }) + + carouselObserver.observe(this.carouselContainer) + + this.carouselSlot.addEventListener('slotchange', e => { + this.carouselItems = this.carouselSlot.assignedElements() + this.carouselItems.forEach(item => allElementsObserver.observe(item)) + if (this.showIndicator) { + this.indicatorsContainer.innerHTML = `` + this.carouselItems.forEach((item, index) => { + let dot = document.createElement('div') + dot.classList.add('dot') + dot.dataset.rank = index + frag.append(dot) + item.dataset.rank = index + }) + this.indicatorsContainer.append(frag) + this.indicators = this.indicatorsContainer.children + } + }) + + this.addEventListener('keyup', e => { + if (e.code === 'ArrowLeft') + this.scrollRight() + else if (e.code === 'ArrowRight') + this.scrollRight() + }) + + this.nextArrow.addEventListener('click', this.scrollRight) + this.previousArrow.addEventListener('click', this.scrollLeft) + this.indicatorsContainer.addEventListener('click', this.handleIndicatorClick) + } + + async attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + if (name === 'indicator') { + if (this.hasAttribute('indicator')) + this.showIndicator = true + else + this.showIndicator = false + } + if (name === 'autoplay') { + if (this.hasAttribute('autoplay')) { + this.initialTimeout = setTimeout(() => { + this.isAutoPlaying = true + this.autoPlay() + }, this.autoPlayInterval); + } + else { + this.isAutoPlaying = false + clearTimeout(this.autoPlayTimeout) + clearTimeout(this.initialTimeout) + } + + } + if (name === 'interval') { + if (this.hasAttribute('interval') && this.getAttribute('interval').trim() !== '') { + this.autoPlayInterval = Math.abs(parseInt(this.getAttribute('interval').trim())) + } + else { + this.autoPlayInterval = 5000 + } + } + } + } + + disconnectedCallback() { + this.nextArrow.removeEventListener('click', this.scrollRight) + this.previousArrow.removeEventListener('click', this.scrollLeft) + this.indicatorsContainer.removeEventListener('click', this.handleIndicatorClick) + } +}) + +//notifications + +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)) + } + + handleTouchStart = (e) => { + this.notification = e.target.closest('.notification') + this.touchStartX = e.changedTouches[0].clientX + this.notification.style.transition = 'initial' + this.touchStartTime = e.timeStamp + } + + handleTouchMove = (e) => { + e.preventDefault() + if (this.touchStartX < e.changedTouches[0].clientX) { + this.offset = e.changedTouches[0].clientX - this.touchStartX; + this.touchEndAnimataion = requestAnimationFrame(this.movePopup) + } else { + this.offset = -(this.touchStartX - e.changedTouches[0].clientX); + this.touchEndAnimataion = requestAnimationFrame(this.movePopup) + } + } + + handleTouchEnd = (e) => { + this.notification.style.transition = 'transform 0.3s, opacity 0.3s' + this.touchEndTime = e.timeStamp + cancelAnimationFrame(this.touchEndAnimataion) + this.touchEndX = e.changedTouches[0].clientX + if (this.touchEndTime - this.touchStartTime > 200) { + if (this.touchEndX - this.touchStartX > this.threshold) { + this.removeNotification(this.notification) + } else if (this.touchStartX - this.touchEndX > this.threshold) { + this.removeNotification(this.notification, true) + } else { + this.resetPosition() + } + } else { + if (this.touchEndX > this.touchStartX) { + this.removeNotification(this.notification) + } else { + this.removeNotification(this.notification, true) + } + } + } + + movePopup = () => { + this.notification.style.transform = `translateX(${this.offset}px)` + } + + resetPosition = () => { + this.notification.style.transform = `translateX(0)` + } + + push = (messageBody, type, pinned) => { + let notification = document.createElement('div'), + composition = `` + notification.classList.add('notification') + if (pinned) + notification.classList.add('pinned') + if (type === 'error') { + composition += ` + + + + + ` + } else if (type === 'success') { + composition += ` + + + ` + } + composition += ` +

${messageBody}

+ + Close + + + ` + notification.innerHTML = composition + this.notificationPanel.prepend(notification) + if (window.innerWidth > 640) { + notification.animate([{ + transform: `translateX(1rem)`, + opacity: '0' + }, + { + transform: 'translateX(0)', + opacity: '1' + } + ], this.animationOptions).onfinish = () => { + notification.setAttribute('style', `transform: none;`); + } + } else { + notification.setAttribute('style', `transform: translateY(0); opacity: 1`) + } + notification.addEventListener('touchstart', this.handleTouchStart) + notification.addEventListener('touchmove', this.handleTouchMove) + notification.addEventListener('touchend', this.handleTouchEnd) + } + + removeNotification = (notification, toLeft) => { + if (!this.offset) + this.offset = 0; + + if (toLeft) + notification.animate([{ + transform: `translateX(${this.offset}px)`, + opacity: '1' + }, + { + transform: `translateX(-100%)`, + opacity: '0' + } + ], this.animationOptions).onfinish = () => { + notification.remove() + } + else { + notification.animate([{ + transform: `translateX(${this.offset}px)`, + opacity: '1' + }, + { + transform: `translateX(100%)`, + opacity: '0' + } + ], this.animationOptions).onfinish = () => { + notification.remove() + } + } + } + + clearAll = () => { + Array.from(this.notificationPanel.children).forEach(child => { + this.removeNotification(child) + }) + } + + connectedCallback() { + this.notificationPanel = this.shadowRoot.querySelector('.notification-panel') + this.animationOptions = { + duration: 300, + fill: "forwards", + easing: "ease" + } + this.fontSize = Number(window.getComputedStyle(document.body).getPropertyValue('font-size').match(/\d+/)[0]) + this.notification + this.offset + this.touchStartX = 0 + this.touchEndX = 0 + this.touchStartTime = 0 + this.touchEndTime = 0 + this.threshold = this.notificationPanel.getBoundingClientRect().width * 0.3 + this.touchEndAnimataion; + + 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) { + if (!mutation.addedNodes[0].classList.contains('pinned')) + setTimeout(() => { + this.removeNotification(mutation.addedNodes[0]) + }, 5000); + if (window.innerWidth > 640) + this.notificationPanel.style.padding = '1.5rem 0 3rem 1.5rem'; + else + this.notificationPanel.style.padding = '1rem 1rem 2rem 1rem'; + } else if (mutation.removedNodes.length && !this.notificationPanel.children.length) { + this.notificationPanel.style.padding = 0; + } + } + }) + }) + observer.observe(this.notificationPanel, { + attributes: true, + childList: true, + subtree: true + }) + } +}) + + + +// sm-menu +const smMenu = document.createElement('template') +smMenu.innerHTML = ` + +
+ +
+ +
+
`; +customElements.define('sm-menu', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smMenu.content.cloneNode(true)) + } + static get observedAttributes() { + return ['value'] + } + get value() { + return this.getAttribute('value') + } + set value(val) { + this.setAttribute('value', val) + } + expand = () => { + if (!this.open) { + this.optionList.classList.remove('hide') + this.optionList.classList.add('no-transformations') + this.open = true + this.icon.classList.add('focused') + this.availableOptions.forEach(option => { + option.setAttribute('tabindex', '0') + }) + } + } + collapse() { + if (this.open) { + this.open = false + this.icon.classList.remove('focused') + this.optionList.classList.add('hide') + this.optionList.classList.remove('no-transformations') + this.availableOptions.forEach(option => { + option.removeAttribute('tabindex') + }) + } + } + connectedCallback() { + this.availableOptions + this.containerDimensions + this.optionList = this.shadowRoot.querySelector('.options') + let slot = this.shadowRoot.querySelector('.options slot'), + menu = this.shadowRoot.querySelector('.menu') + this.icon = this.shadowRoot.querySelector('.icon') + this.open = false; + menu.addEventListener('click', e => { + if (!this.open) { + this.expand() + } else { + this.collapse() + } + }) + menu.addEventListener('keydown', e => { + if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { + e.preventDefault() + this.availableOptions[0].focus() + } + if (e.code === 'Enter' || e.code === 'Space') { + e.preventDefault() + if (!this.open) { + this.expand() + } else { + this.collapse() + } + } + }) + this.optionList.addEventListener('keydown', e => { + if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { + e.preventDefault() + if (document.activeElement.previousElementSibling) { + document.activeElement.previousElementSibling.focus() + } + } + if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { + e.preventDefault() + if (document.activeElement.nextElementSibling) + document.activeElement.nextElementSibling.focus() + } + }) + this.optionList.addEventListener('click', e => { + this.collapse() + }) + slot.addEventListener('slotchange', e => { + this.availableOptions = slot.assignedElements() + this.containerDimensions = this.optionList.getBoundingClientRect() + }); + window.addEventListener('mousedown', e => { + if (!this.contains(e.target) && e.button !== 2) { + this.collapse() + } + }) + } +}) + +// option +const smMenuOption = document.createElement('template') +smMenuOption.innerHTML = ` + +
+ +
`; +customElements.define('sm-menu-option', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smMenuOption.content.cloneNode(true)) + } + + connectedCallback() { + this.addEventListener('keyup', e => { + if (e.code === 'Enter' || e.code === 'Space') { + e.preventDefault() + this.click() + } + }) + } +}) + +// tab-header + +const smTabHeader = document.createElement('template') +smTabHeader.innerHTML = ` + +
+
+ +
+
+
+`; + +customElements.define('sm-tab-header', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smTabHeader.content.cloneNode(true)) + + this.indicator = this.shadowRoot.querySelector('.indicator'); + this.tabSlot = this.shadowRoot.querySelector('slot'); + this.tabHeader = this.shadowRoot.querySelector('.tab-header'); + } + + sendDetails(element) { + this.dispatchEvent( + new CustomEvent("switchtab", { + bubbles: true, + detail: { + target: this.target, + rank: parseInt(element.getAttribute('rank')) + } + }) + ) + } + + moveIndiactor(tabDimensions) { + //if(this.isTab) + this.indicator.setAttribute('style', `width: ${tabDimensions.width}px; transform: translateX(${tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px)`) + //else + //this.indicator.setAttribute('style', `width: calc(${tabDimensions.width}px - 1.6rem); transform: translateX(calc(${ tabDimensions.left - this.tabHeader.getBoundingClientRect().left + this.tabHeader.scrollLeft}px + 0.8rem)`) + } + + connectedCallback() { + if (!this.hasAttribute('target') || this.getAttribute('target').value === '') return; + this.prevTab + this.allTabs + this.activeTab + this.isTab = false + this.target = this.getAttribute('target') + + if (this.hasAttribute('variant') && this.getAttribute('variant') === 'tab') { + this.isTab = true + } + + this.tabSlot.addEventListener('slotchange', () => { + this.tabSlot.assignedElements().forEach((tab, index) => { + tab.setAttribute('rank', index) + }) + }) + this.allTabs = this.tabSlot.assignedElements(); + + this.tabSlot.addEventListener('click', e => { + if (e.target === this.prevTab || !e.target.closest('sm-tab')) + return + if (this.prevTab) + this.prevTab.classList.remove('active') + e.target.classList.add('active') + + e.target.scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'center' + }) + this.moveIndiactor(e.target.getBoundingClientRect()) + this.sendDetails(e.target) + this.prevTab = e.target; + this.activeTab = e.target; + }) + let resizeObserver = new ResizeObserver(entries => { + entries.forEach((entry) => { + if (this.prevTab) { + let tabDimensions = this.activeTab.getBoundingClientRect(); + this.moveIndiactor(tabDimensions) + } + }) + }) + resizeObserver.observe(this) + let observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + this.indicator.style.transition = 'none' + if (this.activeTab) { + let tabDimensions = this.activeTab.getBoundingClientRect(); + this.moveIndiactor(tabDimensions) + } else { + this.allTabs[0].classList.add('active') + let tabDimensions = this.allTabs[0].getBoundingClientRect(); + this.moveIndiactor(tabDimensions) + this.sendDetails(this.allTabs[0]) + this.prevTab = this.tabSlot.assignedElements()[0]; + this.activeTab = this.prevTab; + } + } + }) + }, { + threshold: 1.0 + }) + observer.observe(this) + } +}) + +// tab-panels + +const smTabPanels = document.createElement('template') +smTabPanels.innerHTML = ` + +
+ Nothing to see here. +
+`; + +customElements.define('sm-tab-panels', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smTabPanels.content.cloneNode(true)) + this.panelSlot = this.shadowRoot.querySelector('slot'); + } + connectedCallback() { + + //animations + let flyInLeft = [{ + opacity: 0, + transform: 'translateX(-1rem)' + }, + { + opacity: 1, + transform: 'none' + } + ], + flyInRight = [{ + opacity: 0, + transform: 'translateX(1rem)' + }, + { + opacity: 1, + transform: 'none' + } + ], + flyOutLeft = [{ + opacity: 1, + transform: 'none' + }, + { + opacity: 0, + transform: 'translateX(-1rem)' + } + ], + flyOutRight = [{ + opacity: 1, + transform: 'none' + }, + { + opacity: 0, + transform: 'translateX(1rem)' + } + ], + animationOptions = { + duration: 300, + fill: 'forwards', + easing: 'ease' + } + this.prevPanel + this.allPanels + this.previousRank + + this.panelSlot.addEventListener('slotchange', () => { + this.panelSlot.assignedElements().forEach((panel) => { + panel.classList.add('hide-completely') + }) + }) + this.allPanels = this.panelSlot.assignedElements() + this._targetBodyFlyRight = (targetBody) => { + targetBody.classList.remove('hide-completely') + targetBody.animate(flyInRight, animationOptions) + } + this._targetBodyFlyLeft = (targetBody) => { + targetBody.classList.remove('hide-completely') + targetBody.animate(flyInLeft, animationOptions) + } + document.addEventListener('switchtab', e => { + if (e.detail.target !== this.id) + return + + if (this.prevPanel) { + let targetBody = this.allPanels[e.detail.rank], + currentBody = this.prevPanel; + if (this.previousRank < e.detail.rank) { + if (currentBody && !targetBody) + currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { + currentBody.classList.add('hide-completely') + } + else if (targetBody && !currentBody) { + this._targetBodyFlyRight(targetBody) + } else if (currentBody && targetBody) { + currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { + currentBody.classList.add('hide-completely') + this._targetBodyFlyRight(targetBody) + } + } + } else { + if (currentBody && !targetBody) + currentBody.animate(flyOutRight, animationOptions).onfinish = () => { + currentBody.classList.add('hide-completely') + } + else if (targetBody && !currentBody) { + this._targetBodyFlyLeft(targetBody) + } else if (currentBody && targetBody) { + currentBody.animate(flyOutRight, animationOptions).onfinish = () => { + currentBody.classList.add('hide-completely') + this._targetBodyFlyLeft(targetBody) + } + } + } + } else { + this.allPanels[e.detail.rank].classList.remove('hide-completely') + } + this.previousRank = e.detail.rank + this.prevPanel = this.allPanels[e.detail.rank]; + }) + } +}) diff --git a/components.js b/components.js index 62b535b..c1e2b37 100644 --- a/components.js +++ b/components.js @@ -1,5 +1,3 @@ -/*jshint esversion: 6 */ -//Button const smButton = document.createElement('template') smButton.innerHTML = ` -`; +`; customElements.define('sm-button', class extends HTMLElement { constructor() { @@ -117,48 +104,452 @@ customElements.define('sm-button', mode: 'open' }).append(smButton.content.cloneNode(true)) } + static get observedAttributes() { + return ['disabled']; + } get disabled() { - return this.isDisabled + return this.hasAttribute('disabled') } set disabled(value) { - if (value && !this.isDisabled) { - this.isDisabled = true + if (value) { this.setAttribute('disabled', '') - this.button.removeAttribute('tabindex') - } else if (!value && this.isDisabled) { - this.isDisabled = false + }else { this.removeAttribute('disabled') } } - dispatch() { - if (this.isDisabled) { - this.dispatchEvent(new CustomEvent('disabled', { - bubbles: true, - composed: true - })) - } else { - this.dispatchEvent(new CustomEvent('clicked', { - bubbles: true, - composed: true - })) + handleKeyDown(e) { + if (!this.hasAttribute('disabled') && (e.key === 'Enter' || e.code === 'Space')) { + e.preventDefault() + this.click() } } connectedCallback() { - this.isDisabled = false - this.button = this.shadowRoot.querySelector('.button') - if (this.hasAttribute('disabled') && !this.isDisabled) - this.isDisabled = true - this.addEventListener('click', (e) => { - this.dispatch() - }) + if (!this.hasAttribute('disabled')) { + this.setAttribute('tabindex', '0') + } + this.setAttribute('role', 'button') + this.addEventListener('keydown', this.handleKeyDown) + } + attributeChangedCallback(name, oldVal, newVal) { + if (name === 'disabled') { + this.removeAttribute('tabindex') + this.setAttribute('aria-disabled', 'true') + } + else { + this.setAttribute('tabindex', '0') + this.setAttribute('aria-disabled', 'false') + } } }) +const smCheckbox = document.createElement('template') +smCheckbox.innerHTML = ` + +` +customElements.define('sm-checkbox', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smCheckbox.content.cloneNode(true)) + + this.checkbox = this.shadowRoot.querySelector('.checkbox'); + + this.reset = this.reset.bind(this) + this.dispatch = this.dispatch.bind(this) + this.handleKeyDown = this.handleKeyDown.bind(this) + this.handleClick = this.handleClick.bind(this) + } + + static get observedAttributes() { + return ['value', 'disabled', 'checked'] + } + + get disabled() { + return this.hasAttribute('disabled') + } + + set disabled(val) { + if (val) { + this.setAttribute('disabled', '') + } else { + this.removeAttribute('disabled') + } + } + + get checked() { + return this.hasAttribute('checked') + } + + set checked(value) { + if (value) { + this.setAttribute('checked', '') + } + else { + this.removeAttribute('checked') + } + } + + set value(val) { + this.setAttribute('value', val) + } + + get value() { + return this.getAttribute('value') + } + + reset() { + this.removeAttribute('checked') + } + + dispatch(){ + this.dispatchEvent(new CustomEvent('change', { + bubbles: true, + composed: true + })) + } + handleKeyDown(e){ + if (e.code === "Space") { + e.preventDefault() + this.click() + } + } + handleClick(e){ + this.toggleAttribute('checked') + } + + connectedCallback() { + if (!this.hasAttribute('disabled')) { + this.setAttribute('tabindex', '0') + } + this.setAttribute('role', 'checkbox') + if (!this.hasAttribute('checked')) { + this.setAttribute('aria-checked', 'false') + } + this.addEventListener('keydown', this.handleKeyDown) + this.addEventListener('click', this.handleClick) + } + attributeChangedCallback(name, oldValue, newValue) { + if (oldValue !== newValue) { + if (name === 'checked') { + this.setAttribute('aria-checked', this.hasAttribute('checked')) + this.dispatch() + } + else if (name === 'disabled') { + if (this.hasAttribute('disabled')) { + this.removeAttribute('tabindex') + } + else { + this.setAttribute('tabindex', '0') + } + } + } + } + disconnectedCallback() { + this.removeEventListener('keydown', this.handleKeyDown) + this.removeEventListener('change', this.handleClick) + } +}) +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 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.handleInput = this.handleInput.bind(this) + this.handleKeydown = this.handleKeydown.bind(this) + this.reset = this.reset.bind(this) + } + debounce(callback, wait) { + let timeoutId = null; + return (...args) => { + window.clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => { + callback.apply(null, args); + }, wait); + }; + } + handleInput(e) { + 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 !== 'SM-TEXTAREA' ) { + if (this.allRequiredValid) { + this.submitButton.click() + } + else { + this.requiredElements.find(elem => !elem.isValid).vibrate() + } + } + } + reset() { + this.formElements.forEach(elem => elem.reset()) + } + connectedCallback() { + const slot = this.shadowRoot.querySelector('slot') + slot.addEventListener('slotchange', e => { + 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 = e.target.assignedElements().find(elem => elem.getAttribute('variant') === 'primary' || elem.getAttribute('type') === 'submit'); + this.resetButton = e.target.assignedElements().find(elem => elem.getAttribute('type') === 'reset'); + if (this.resetButton) { + this.resetButton.addEventListener('click', this.reset) + } + }) + this.addEventListener('input', this.debounce(this.handleInput, 100)) + this.addEventListener('keydown', this.debounce(this.handleKeydown, 100)) + } + disconnectedCallback() { + this.removeEventListener('input', this.debounce(this.handleInput, 100)) + this.removeEventListener('keydown', this.debounce(this.handleKeydown, 100)) + } +}) -//Input const smInput = document.createElement('template') smInput.innerHTML = ` +
+ +
+ +
+
`; +customElements.define('sm-menu', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(smMenu.content.cloneNode(true)) -//textarea -const smTextarea = document.createElement('template') -smTextarea.innerHTML = ` + this.isOpen = false; + this.availableOptions + this.containerDimensions + this.animOptions = { + duration: 200, + easing: 'ease' + } + + this.optionList = this.shadowRoot.querySelector('.options') + this.menu = this.shadowRoot.querySelector('.menu') + this.icon = this.shadowRoot.querySelector('.icon') + + this.expand = this.expand.bind(this) + this.collapse = this.collapse.bind(this) + this.toggle = this.toggle.bind(this) + this.handleKeyDown = this.handleKeyDown.bind(this) + this.handleClickoutSide = this.handleClickoutSide.bind(this) + + } + static get observedAttributes() { + return ['value'] + } + get value() { + return this.getAttribute('value') + } + set value(val) { + this.setAttribute('value', val) + } + expand() { + if (!this.isOpen) { + this.optionList.classList.remove('hide') + this.optionList.animate([ + { + transform: window.innerWidth < 640 ? 'translateY(1.5rem)' : 'translateY(-1rem)', + opacity: '0' + }, + { + transform: 'none', + opacity: '1' + }, + ], this.animOptions) + .onfinish = () => { + this.isOpen = true + this.icon.classList.add('focused') + } + } + } + collapse() { + if (this.isOpen) { + this.optionList.animate([ + { + transform: 'none', + opacity: '1' + }, + { + transform: window.innerWidth < 640 ? 'translateY(1.5rem)' : 'translateY(-1rem)', + opacity: '0' + }, + ], this.animOptions) + .onfinish = () => { + this.isOpen = false + this.icon.classList.remove('focused') + this.optionList.classList.add('hide') + } + } + } + toggle() { + if (!this.isOpen) { + this.expand() + } else { + this.collapse() + } + } + handleKeyDown(e) { + // If key is pressed on menu button + if (e.target === this) { + if (e.code === 'ArrowDown') { + e.preventDefault() + this.availableOptions[0].focus() + } + else if (e.code === 'Enter' || e.code === 'Space') { + e.preventDefault() + this.toggle() + } + } else { // If mey is pressed over menu options + if (e.code === 'ArrowUp') { + e.preventDefault() + if (document.activeElement.previousElementSibling) { + document.activeElement.previousElementSibling.focus() + } else { + this.availableOptions[this.availableOptions.length - 1].focus() + } + } + else if (e.code === 'ArrowDown') { + e.preventDefault() + if (document.activeElement.nextElementSibling) { + document.activeElement.nextElementSibling.focus() + } else { + this.availableOptions[0].focus() + } + } + else if (e.code === 'Enter' || e.code === 'Space') { + e.preventDefault() + e.target.click() + } + } + } + handleClickoutSide(e) { + if (!this.contains(e.target) && e.button !== 2) { + this.collapse() + } + } + connectedCallback() { + this.setAttribute('role', 'listbox') + this.setAttribute('aria-label', 'dropdown menu') + const slot = this.shadowRoot.querySelector('.options slot') + slot.addEventListener('slotchange', e => { + this.availableOptions = e.target.assignedElements() + this.containerDimensions = this.optionList.getBoundingClientRect() + }); + this.addEventListener('click', this.toggle) + this.addEventListener('keydown', this.handleKeyDown) + document.addEventListener('mousedown', this.handleClickoutSide) + } + disconnectedCallback() { + this.removeEventListener('click', this.toggle) + this.removeEventListener('keydown', this.handleKeyDown) + document.removeEventListener('mousedown', this.handleClickoutSide) + } +}) + +// option +const menuOption = document.createElement('template') +menuOption.innerHTML = ` + +
+ +
`; +customElements.define('menu-option', class extends HTMLElement { + constructor() { + super() + this.attachShadow({ + mode: 'open' + }).append(menuOption.content.cloneNode(true)) + } + + connectedCallback() { + this.setAttribute('role', 'option') + this.addEventListener('keyup', e => { + if (e.code === 'Enter' || e.code === 'Space') { + e.preventDefault() + this.click() + } + }) + } +}) +const smPopup = document.createElement('template') +smPopup.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') - } - get value() { - return this.textarea.value - } - set value(val) { - this.textarea.value = val; - this.textareaBox.dataset.value = val - this.checkInput() - this.fireEvent() - } - 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 !== '') { - this.placeholder.classList.add('hide') - } else { - this.placeholder.classList.remove('hide') - } - } - connectedCallback() { - this.textareaBox = this.shadowRoot.querySelector('.textarea') - this.placeholder = this.shadowRoot.querySelector('.placeholder') - - if(this.hasAttribute('placeholder')) - this.placeholder.textContent = this.getAttribute('placeholder') - - if (this.hasAttribute('value')) { - this.textarea.value = this.getAttribute('value') - this.checkInput() - } - if (this.hasAttribute('required')) { - this.textarea.setAttribute('required', '') - } - if (this.hasAttribute('readonly')) { - this.textarea.setAttribute('readonly', '') - } - if (this.hasAttribute('rows')) { - this.textarea.setAttribute('rows', this.getAttribute('rows')) - } - this.textarea.addEventListener('input', e => { - this.textareaBox.dataset.value = this.textarea.value - this.checkInput() - }) - } - }) - -// tab -const smTab = document.createElement('template') -smTab.innerHTML = ` - -
- + `; - -customElements.define('sm-tab', class extends HTMLElement { - constructor() { - super() - this.shadow = this.attachShadow({ - mode: 'open' - }).append(smTab.content.cloneNode(true)) - } -}) - -//chcekbox - -const smCheckbox = document.createElement('template') -smCheckbox.innerHTML = ` - -` -customElements.define('sm-checkbox', class extends HTMLElement { +customElements.define('sm-popup', class extends HTMLElement { constructor() { super() this.attachShadow({ mode: 'open' - }).append(smCheckbox.content.cloneNode(true)) + }).append(smPopup.content.cloneNode(true)) - this.checkbox = this.shadowRoot.querySelector('.checkbox'); - this.input = this.shadowRoot.querySelector('input') + this.allowClosing = false + this.isOpen = false + this.pinned = false + this.popupStack + this.offset + this.touchStartY = 0 + this.touchEndY = 0 + this.touchStartTime = 0 + this.touchEndTime = 0 + this.touchEndAnimataion - this.isChecked = false - this.isDisabled = false + this.popupContainer = this.shadowRoot.querySelector('.popup-container') + 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.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.movePopup = this.movePopup.bind(this) } static get observedAttributes() { - return ['disabled', 'checked'] + return ['open']; } - get disabled() { - return this.isDisabled + get open() { + return this.isOpen } - set disabled(val) { - if (val) { - this.setAttribute('disabled', '') + resumeScrolling() { + const scrollY = document.body.style.top; + window.scrollTo(0, parseInt(scrollY || '0') * -1); + setTimeout(() => { + document.body.style.overflow = 'auto'; + document.body.style.top = 'initial' + }, 300); + } + + show(options = {}) { + const {pinned = false, popupStack = undefined} = options + if (popupStack) + this.popupStack = popupStack + if (this.popupStack && !this.hasAttribute('open')) { + this.popupStack.push({ + popup: this, + permission: pinned + }) + if (this.popupStack.items.length > 1) { + this.popupStack.items[this.popupStack.items.length - 2].popup.classList.add('stacked') + } + this.dispatchEvent( + new CustomEvent("popupopened", { + bubbles: true, + detail: { + popup: this, + popupStack: this.popupStack + } + }) + ) + this.setAttribute('open', '') + this.pinned = pinned + this.isOpen = true + } + this.popupContainer.classList.remove('hide') + this.popup.style.transform = 'none'; + document.body.style.overflow = 'hidden'; + document.body.style.top = `-${window.scrollY}px` + return this.popupStack + } + hide() { + if (window.innerWidth < 640) + this.popup.style.transform = 'translateY(100%)'; + else + this.popup.style.transform = 'translateY(3rem)'; + this.popupContainer.classList.add('hide') + this.removeAttribute('open') + if (typeof this.popupStack !== 'undefined') { + this.popupStack.pop() + if (this.popupStack.items.length) { + this.popupStack.items[this.popupStack.items.length - 1].popup.classList.remove('stacked') + } else { + this.resumeScrolling() + } } else { - this.removeAttribute('disabled') + this.resumeScrolling() + } + + if (this.forms.length) { + setTimeout(() => { + this.forms.forEach(form => form.reset()) + }, 300); + } + setTimeout(() => { + this.dispatchEvent( + new CustomEvent("popupclosed", { + bubbles: true, + detail: { + popup: this, + popupStack: this.popupStack + } + }) + ) + this.isOpen = false + }, 300); + } + + handleTouchStart(e) { + this.touchStartY = e.changedTouches[0].clientY + this.popup.style.transition = 'transform 0.1s' + this.touchStartTime = e.timeStamp + } + + handleTouchMove(e) { + if (this.touchStartY < e.changedTouches[0].clientY) { + this.offset = e.changedTouches[0].clientY - this.touchStartY; + this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup()) } } - get checked() { - return this.isChecked - } - - set checked(value) { - if (value) { - this.setAttribute('checked', '') - } - else { - this.removeAttribute('checked') - } - } - - set value(val) { - this.val = val - this.setAttribute('value', value) - } - - get value() { - return getAttribute('value') - } - - dispatch = () => { - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true - })) - } - handleKeyup = e => { - if ((e.code === "Enter" || e.code === "Space") && this.isDisabled == false) { - if (this.hasAttribute('checked')) { - this.input.checked = false - this.removeAttribute('checked') - } - else { - this.input.checked = true - this.setAttribute('checked', '') + handleTouchEnd(e) { + this.touchEndTime = e.timeStamp + cancelAnimationFrame(this.touchEndAnimataion) + this.touchEndY = e.changedTouches[0].clientY + this.popup.style.transition = 'transform 0.3s' + 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.show() + return + } else + this.hide() + } else { + this.show() } + } else { + if (this.touchEndY > this.touchStartY) + if (this.pinned) { + this.show() + return + } + else + this.hide() } } - handleChange = e => { - if (this.input.checked) { - this.setAttribute('checked', '') - } - else { - this.removeAttribute('checked') - } + + movePopup() { + this.popup.style.transform = `translateY(${this.offset}px)` } - + connectedCallback() { - this.val = '' - this.addEventListener('keyup', this.handleKeyup) - this.input.addEventListener('change', this.handleChange) - } - attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'disabled') { - if (newValue === 'true') { - this.isDisabled = true + this.popupBodySlot.addEventListener('slotchange', () => { + this.forms = this.querySelectorAll('sm-form') + }) + this.popupContainer.addEventListener('mousedown', e => { + if (e.target === this.popupContainer && !this.pinned) { + if (this.pinned) { + this.show() + } 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.isDisabled = false + this.threshold = entry.contentRect.height * 0.3 } } - else if (name === 'checked') { - if (this.hasAttribute('checked')) { - this.isChecked = true - this.input.checked = true - } - else { - this.input.checked = false - this.isChecked = false - } - this.dispatch() - } - } + }); + resizeObserver.observe(this) + + + this.popupHeader.addEventListener('touchstart', (e) => { this.handleTouchStart(e) }, { passive: true }) + this.popupHeader.addEventListener('touchmove', (e) => { this.handleTouchMove(e) }, { passive: true }) + this.popupHeader.addEventListener('touchend', (e) => { this.handleTouchEnd(e) }, { passive: true }) } disconnectedCallback() { - this.removeEventListener('keyup', this.handleKeyup) - this.removeEventListener('change', this.handleChange) + this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, { passive: true }) + this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, { passive: true }) + this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, { passive: true }) + resizeObserver.unobserve() + } + attributeChangedCallback(name, oldVal, newVal) { + if (name === 'open') { + if (this.hasAttribute('open')) { + this.show() + } + } } }) -//switch - const smSwitch = document.createElement('template') smSwitch.innerHTML = ` -
-
-
- - - -
-
- -
-
`; -customElements.define('sm-select', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smSelect.content.cloneNode(true)) +@keyframes load { + 50% { + stroke-dashoffset: 0; } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) + 100%{ + stroke-dashoffset: -180; } +} - collapse() { - this.chevron.classList.remove('rotate') - this.optionList.animate(this.slideUp, this.animationOptions) - .onfinish = () => { - this.optionList.classList.add('hide') - this.open = false - } - } - connectedCallback() { - this.availableOptions - this.optionList = this.shadowRoot.querySelector('.options') - this.chevron = this.shadowRoot.querySelector('.toggle') - let slot = this.shadowRoot.querySelector('.options slot'), - selection = this.shadowRoot.querySelector('.selection'), - previousOption - this.open = false; - this.slideDown = [{ - transform: `translateY(-0.5rem)`, - opacity: 0 - }, - { - transform: `translateY(0)`, - opacity: 1 - } - ] - this.slideUp = [{ - transform: `translateY(0)`, - opacity: 1 - }, - { - transform: `translateY(-0.5rem)`, - opacity: 0 - } - ] - this.animationOptions = { - duration: 300, - fill: "forwards", - easing: 'ease' - } - selection.addEventListener('click', e => { - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.animate(this.slideDown, this.animationOptions) - this.chevron.classList.add('rotate') - this.open = true - } else { - this.collapse() - } - }) - selection.addEventListener('keydown', e => { - if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { - e.preventDefault() - this.availableOptions[0].focus() - } - if (e.code === 'Enter' || e.code === 'Space') - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.animate(this.slideDown, this.animationOptions) - this.chevron.classList.add('rotate') - this.open = true - } else { - this.collapse() - } - }) - this.optionList.addEventListener('keydown', e => { - if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { - e.preventDefault() - if (document.activeElement.previousElementSibling) { - document.activeElement.previousElementSibling.focus() - } - } - if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { - e.preventDefault() - if (document.activeElement.nextElementSibling) - document.activeElement.nextElementSibling.focus() - } - }) - this.addEventListener('optionSelected', e => { - if (previousOption !== e.target) { - this.setAttribute('value', e.detail.value) - this.shadowRoot.querySelector('.option-text').textContent = e.detail.text; - this.dispatchEvent(new CustomEvent('change', { - bubbles: true, - composed: true, - detail: { - value: e.detail.value - } - })) - if (previousOption) { - previousOption.classList.remove('check-selected') - } - previousOption = e.target; - } - if (!e.detail.switching) - this.collapse() - - e.target.classList.add('check-selected') - }) - slot.addEventListener('slotchange', e => { - this.availableOptions = slot.assignedElements() - if (this.availableOptions[0]) { - let firstElement = this.availableOptions[0]; - previousOption = firstElement; - firstElement.classList.add('check-selected') - this.setAttribute('value', firstElement.getAttribute('value')) - this.shadowRoot.querySelector('.option-text').textContent = firstElement.textContent - this.availableOptions.forEach((element, index) => { - element.setAttribute('data-rank', index + 1); - element.setAttribute('tabindex', "0"); - }) - } - }); - document.addEventListener('mousedown', e => { - if (!this.contains(e.target) && this.open) { - this.collapse() - } - }) - } -}) - -// option -const smOption = document.createElement('template') -smOption.innerHTML = ` - -
- - - - -
`; -customElements.define('sm-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smOption.content.cloneNode(true)) - } - - sendDetails(switching) { - let optionSelected = new CustomEvent('optionSelected', { - bubbles: true, - composed: true, - detail: { - text: this.textContent, - value: this.getAttribute('value'), - switching: switching - } - }) - this.dispatchEvent(optionSelected) - } - - connectedCallback() { - let validKey = [ - 'ArrowUp', - 'ArrowDown', - 'ArrowLeft', - 'ArrowRight' - ] - this.addEventListener('click', e => { - this.sendDetails() - }) - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.sendDetails(false) - } - if (validKey.includes(e.code)) { - e.preventDefault() - this.sendDetails(true) - } - }) - if (this.hasAttribute('default')) { - setTimeout(() => { - this.sendDetails() - }, 0); - } - } -}) - -// strip select -const stripSelect = document.createElement('template') -stripSelect.innerHTML = ` - -
-
- -
- -
- -
-
+ ` -customElements.define('strip-select', class extends HTMLElement{ +class SquareLoader extends HTMLElement { constructor() { - super() + super(); this.attachShadow({ mode: 'open' - }).append(stripSelect.content.cloneNode(true)) - this.stripSelect = this.shadowRoot.querySelector('.strip-select') - this.slottedOptions - this._value - this.scrollDistance - } - 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() { - 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 (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) - } -}) - -const stripOption = document.createElement('template') -stripOption.innerHTML = ` - - -` - -//Strip option -customElements.define('strip-option', class extends HTMLElement{ - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(stripOption.content.cloneNode(true)) - this._value - this.radioButton = this.shadowRoot.querySelector('input') - } - 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._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) - } -}) - - -//popup -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 - } - - get open() { - return this.isOpen - } - - resumeScrolling = () => { - const scrollY = document.body.style.top; - window.scrollTo(0, parseInt(scrollY || '0') * -1); - setTimeout(() => { - document.body.style.overflow = 'auto'; - document.body.style.top= 'initial' - }, 300); - } - - show = (pinned, popupStack) => { - if (popupStack) - this.popupStack = popupStack - if (this.popupStack && !this.hasAttribute('open')) { - this.popupStack.push({ - popup: this, - permission: pinned - }) - if (this.popupStack.items.length > 1) { - this.popupStack.items[this.popupStack.items.length - 2].popup.classList.add('stacked') - } - this.dispatchEvent( - new CustomEvent("popupopened", { - bubbles: true, - detail: { - popup: this, - popupStack: this.popupStack - } - }) - ) - this.setAttribute('open', '') - this.pinned = pinned - this.isOpen = true - } - this.popupContainer.classList.remove('hide') - this.popup.style.transform = 'none'; - document.body.style.overflow = 'hidden'; - document.body.style.top= `-${window.scrollY}px` - return this.popupStack - } - hide = () => { - if (window.innerWidth < 640) - this.popup.style.transform = 'translateY(100%)'; - else - this.popup.style.transform = 'translateY(3rem)'; - this.popupContainer.classList.add('hide') - this.removeAttribute('open') - if (typeof this.popupStack !== 'undefined') { - this.popupStack.pop() - if (this.popupStack.items.length) { - this.popupStack.items[this.popupStack.items.length - 1].popup.classList.remove('stacked') - } else { - this.resumeScrolling() - } - } else { - this.resumeScrolling() - } - - if (this.inputFields.length) { - setTimeout(() => { - this.inputFields.forEach(field => { - if (field.type === 'radio' || field.tagName === 'SM-CHECKBOX') - field.checked = false - if (field.tagName === 'SM-INPUT' || field.tagName === 'TEXTAREA'|| field.tagName === 'SM-TEXTAREA') - field.value = '' - }) - }, 300); - } - setTimeout(() => { - this.dispatchEvent( - new CustomEvent("popupclosed", { - bubbles: true, - detail: { - popup: this, - popupStack: this.popupStack - } - }) - ) - this.isOpen = false - }, 300); - } - - handleTouchStart = (e) => { - this.touchStartY = e.changedTouches[0].clientY - this.popup.style.transition = 'transform 0.1s' - this.touchStartTime = e.timeStamp - } - - handleTouchMove = (e) => { - if (this.touchStartY < e.changedTouches[0].clientY) { - this.offset = e.changedTouches[0].clientY - this.touchStartY; - this.touchEndAnimataion = window.requestAnimationFrame(() => this.movePopup()) - } - /*else { - this.offset = this.touchStartY - e.changedTouches[0].clientY; - this.popup.style.transform = `translateY(-${this.offset}px)` - }*/ - } - - handleTouchEnd = (e) => { - this.touchEndTime = e.timeStamp - cancelAnimationFrame(this.touchEndAnimataion) - this.touchEndY = e.changedTouches[0].clientY - this.popup.style.transition = 'transform 0.3s' - 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.show() - return - } else - this.hide() - } else { - this.show() - } - } else { - if (this.touchEndY > this.touchStartY) - if (this.pinned) { - this.show() - return - } - else - this.hide() - } - } - - movePopup = () => { - this.popup.style.transform = `translateY(${this.offset}px)` - } - - connectedCallback() { - this.pinned = false - this.popupStack - this.popupContainer = this.shadowRoot.querySelector('.popup-container') - this.popup = this.shadowRoot.querySelector('.popup') - this.popupBodySlot = this.shadowRoot.querySelector('.popup-body slot') - this.offset - this.popupHeader = this.shadowRoot.querySelector('.popup-top') - this.touchStartY = 0 - this.touchEndY = 0 - this.touchStartTime = 0 - this.touchEndTime = 0 - this.touchEndAnimataion; - this.threshold = this.popup.getBoundingClientRect().height * 0.3 - - if (this.hasAttribute('open')) - this.show() - this.popupContainer.addEventListener('mousedown', e => { - if (e.target === this.popupContainer && !this.pinned) { - if (this.pinned) { - this.show() - return - } else - this.hide() - } - }) - - this.popupBodySlot.addEventListener('slotchange', () => { - setTimeout(() => { - this.threshold = this.popup.getBoundingClientRect().height * 0.3 - }, 200); - this.inputFields = this.querySelectorAll('sm-input', 'sm-checkbox', 'textarea', 'sm-textarea', 'radio') - }) - - this.popupHeader.addEventListener('touchstart', (e) => { this.handleTouchStart(e) }, {passive: true}) - this.popupHeader.addEventListener('touchmove', (e) => {this.handleTouchMove(e)}, {passive: true}) - this.popupHeader.addEventListener('touchend', (e) => {this.handleTouchEnd(e)}, {passive: true}) - } - disconnectedCallback() { - this.popupHeader.removeEventListener('touchstart', this.handleTouchStart, {passive: true}) - this.popupHeader.removeEventListener('touchmove', this.handleTouchMove, {passive: true}) - this.popupHeader.removeEventListener('touchend', this.handleTouchEnd, {passive: true}) - } -}) - -//carousel - -const smCarousel = document.createElement('template') -smCarousel.innerHTML = ` - - -`; - -customElements.define('sm-carousel', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smCarousel.content.cloneNode(true)) - - this.isAutoPlaying = false - this.autoPlayInterval = 5000 - this.autoPlayTimeout - this.initialTimeout - this.activeSlideNum = 0 - this.carouselItems - this.indicators - this.showIndicator = false - this.carousel = this.shadowRoot.querySelector('.carousel') - this.carouselContainer = this.shadowRoot.querySelector('.carousel-container') - this.carouselSlot = this.shadowRoot.querySelector('slot') - this.nextArrow = this.shadowRoot.querySelector('.carousel__button--right') - this.previousArrow = this.shadowRoot.querySelector('.carousel__button--left') - this.indicatorsContainer = this.shadowRoot.querySelector('.indicators') - } - - static get observedAttributes() { - return ['indicator', 'autoplay', 'interval'] - } - - scrollLeft = () => { - this.carousel.scrollBy({ - left: -this.scrollDistance, - behavior: 'smooth' - }) - } - - scrollRight = () => { - this.carousel.scrollBy({ - left: this.scrollDistance, - behavior: 'smooth' - }) - } - - handleIndicatorClick = (e) => { - if (e.target.closest('.dot')) { - const slideNum = parseInt(e.target.closest('.dot').dataset.rank) - if (this.activeSlideNum !== slideNum) { - this.showSlide(slideNum) - } - } - } - - showSlide = (slideNum) => { - this.carousel.scrollTo({ - left: (this.carouselItems[slideNum].getBoundingClientRect().left - this.carousel.getBoundingClientRect().left + this.carousel.scrollLeft), - behavior: 'smooth' - }) - } - - nextSlide = () => { - if (!this.carouselItems) return - let showSlideNo = (this.activeSlideNum + 1) < this.carouselItems.length ? this.activeSlideNum + 1 : 0 - this.showSlide(showSlideNo) - } - - autoPlay = () => { - this.nextSlide() - if (this.isAutoPlaying) { - this.autoPlayTimeout = setTimeout(() => { - this.autoPlay() - }, this.autoPlayInterval); - } - } - - startAutoPlay = () => { - this.setAttribute('autoplay', '') - } - - stopAutoPlay = () => { - this.removeAttribute('autoplay') - } - - connectedCallback() { - this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 - let frag = document.createDocumentFragment(); - if (this.hasAttribute('indicator')) - this.showIndicator = true - - - let firstVisible = false, - lastVisible = false - const allElementsObserver = new IntersectionObserver(entries => { - entries.forEach(entry => { - if (this.showIndicator) { - const activeRank = parseInt(entry.target.dataset.rank) - if (entry.isIntersecting) { - this.indicators[activeRank].classList.add('active') - this.activeSlideNum = activeRank - } - else - this.indicators[activeRank].classList.remove('active') - } - if (!entry.target.previousElementSibling) - if (entry.isIntersecting) { - this.previousArrow.classList.remove('expand') - firstVisible = true - } - else { - this.previousArrow.classList.add('expand') - firstVisible = false - } - if (!entry.target.nextElementSibling) - if (entry.isIntersecting) { - this.nextArrow.classList.remove('expand') - lastVisible = true - } - else { - this.nextArrow.classList.add('expand') - lastVisible = false - } - if (firstVisible && lastVisible) - this.indicatorsContainer.classList.add('hide') - else - this.indicatorsContainer.classList.remove('hide') - }) - }, { - root: this.carouselContainer, - threshold: 0.9 - }) - - const carouselObserver = new IntersectionObserver(entries => { - if (entries[0].isIntersecting) { - this.scrollDistance = this.carouselContainer.getBoundingClientRect().width / 3 - } - }) - - carouselObserver.observe(this.carouselContainer) - - this.carouselSlot.addEventListener('slotchange', e => { - this.carouselItems = this.carouselSlot.assignedElements() - this.carouselItems.forEach(item => allElementsObserver.observe(item)) - if (this.showIndicator) { - this.indicatorsContainer.innerHTML = `` - this.carouselItems.forEach((item, index) => { - let dot = document.createElement('div') - dot.classList.add('dot') - dot.dataset.rank = index - frag.append(dot) - item.dataset.rank = index - }) - this.indicatorsContainer.append(frag) - this.indicators = this.indicatorsContainer.children - } - }) - - this.addEventListener('keyup', e => { - if (e.code === 'ArrowLeft') - this.scrollRight() - else if (e.code === 'ArrowRight') - this.scrollRight() - }) - - this.nextArrow.addEventListener('click', this.scrollRight) - this.previousArrow.addEventListener('click', this.scrollLeft) - this.indicatorsContainer.addEventListener('click', this.handleIndicatorClick) - } - - async attributeChangedCallback(name, oldValue, newValue) { - if (oldValue !== newValue) { - if (name === 'indicator') { - if (this.hasAttribute('indicator')) - this.showIndicator = true - else - this.showIndicator = false - } - if (name === 'autoplay') { - if (this.hasAttribute('autoplay')) { - this.initialTimeout = setTimeout(() => { - this.isAutoPlaying = true - this.autoPlay() - }, this.autoPlayInterval); - } - else { - this.isAutoPlaying = false - clearTimeout(this.autoPlayTimeout) - clearTimeout(this.initialTimeout) - } - - } - if (name === 'interval') { - if (this.hasAttribute('interval') && this.getAttribute('interval').trim() !== '') { - this.autoPlayInterval = Math.abs(parseInt(this.getAttribute('interval').trim())) - } - else { - this.autoPlayInterval = 5000 - } - } - } - } - - disconnectedCallback() { - this.nextArrow.removeEventListener('click', this.scrollRight) - this.previousArrow.removeEventListener('click', this.scrollLeft) - this.indicatorsContainer.removeEventListener('click', this.handleIndicatorClick) - } -}) - -//notifications - -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)) - } - - handleTouchStart = (e) => { - this.notification = e.target.closest('.notification') - this.touchStartX = e.changedTouches[0].clientX - this.notification.style.transition = 'initial' - this.touchStartTime = e.timeStamp - } - - handleTouchMove = (e) => { - e.preventDefault() - if (this.touchStartX < e.changedTouches[0].clientX) { - this.offset = e.changedTouches[0].clientX - this.touchStartX; - this.touchEndAnimataion = requestAnimationFrame(this.movePopup) - } else { - this.offset = -(this.touchStartX - e.changedTouches[0].clientX); - this.touchEndAnimataion = requestAnimationFrame(this.movePopup) - } - } - - handleTouchEnd = (e) => { - this.notification.style.transition = 'transform 0.3s, opacity 0.3s' - this.touchEndTime = e.timeStamp - cancelAnimationFrame(this.touchEndAnimataion) - this.touchEndX = e.changedTouches[0].clientX - if (this.touchEndTime - this.touchStartTime > 200) { - if (this.touchEndX - this.touchStartX > this.threshold) { - this.removeNotification(this.notification) - } else if (this.touchStartX - this.touchEndX > this.threshold) { - this.removeNotification(this.notification, true) - } else { - this.resetPosition() - } - } else { - if (this.touchEndX > this.touchStartX) { - this.removeNotification(this.notification) - } else { - this.removeNotification(this.notification, true) - } - } - } - - movePopup = () => { - this.notification.style.transform = `translateX(${this.offset}px)` - } - - resetPosition = () => { - this.notification.style.transform = `translateX(0)` - } - - push = (messageBody, type, pinned) => { - let notification = document.createElement('div'), - composition = `` - notification.classList.add('notification') - if (pinned) - notification.classList.add('pinned') - if (type === 'error') { - composition += ` - - - - - ` - } else if (type === 'success') { - composition += ` - - - ` - } - composition += ` -

${messageBody}

- - Close - - - ` - notification.innerHTML = composition - this.notificationPanel.prepend(notification) - if (window.innerWidth > 640) { - notification.animate([{ - transform: `translateX(1rem)`, - opacity: '0' - }, - { - transform: 'translateX(0)', - opacity: '1' - } - ], this.animationOptions).onfinish = () => { - notification.setAttribute('style', `transform: none;`); - } - } else { - notification.setAttribute('style', `transform: translateY(0); opacity: 1`) - } - notification.addEventListener('touchstart', this.handleTouchStart) - notification.addEventListener('touchmove', this.handleTouchMove) - notification.addEventListener('touchend', this.handleTouchEnd) - } - - removeNotification = (notification, toLeft) => { - if (!this.offset) - this.offset = 0; - - if (toLeft) - notification.animate([{ - transform: `translateX(${this.offset}px)`, - opacity: '1' - }, - { - transform: `translateX(-100%)`, - opacity: '0' - } - ], this.animationOptions).onfinish = () => { - notification.remove() - } - else { - notification.animate([{ - transform: `translateX(${this.offset}px)`, - opacity: '1' - }, - { - transform: `translateX(100%)`, - opacity: '0' - } - ], this.animationOptions).onfinish = () => { - notification.remove() - } - } - } - - clearAll = () => { - Array.from(this.notificationPanel.children).forEach(child => { - this.removeNotification(child) - }) - } - - connectedCallback() { - this.notificationPanel = this.shadowRoot.querySelector('.notification-panel') - this.animationOptions = { - duration: 300, - fill: "forwards", - easing: "ease" - } - this.fontSize = Number(window.getComputedStyle(document.body).getPropertyValue('font-size').match(/\d+/)[0]) - this.notification - this.offset - this.touchStartX = 0 - this.touchEndX = 0 - this.touchStartTime = 0 - this.touchEndTime = 0 - this.threshold = this.notificationPanel.getBoundingClientRect().width * 0.3 - this.touchEndAnimataion; - - 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) { - if (!mutation.addedNodes[0].classList.contains('pinned')) - setTimeout(() => { - this.removeNotification(mutation.addedNodes[0]) - }, 5000); - if (window.innerWidth > 640) - this.notificationPanel.style.padding = '1.5rem 0 3rem 1.5rem'; - else - this.notificationPanel.style.padding = '1rem 1rem 2rem 1rem'; - } else if (mutation.removedNodes.length && !this.notificationPanel.children.length) { - this.notificationPanel.style.padding = 0; - } - } - }) - }) - observer.observe(this.notificationPanel, { - attributes: true, - childList: true, - subtree: true - }) - } -}) - - - -// sm-menu -const smMenu = document.createElement('template') -smMenu.innerHTML = ` - -
- -
- -
-
`; -customElements.define('sm-menu', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smMenu.content.cloneNode(true)) - } - static get observedAttributes() { - return ['value'] - } - get value() { - return this.getAttribute('value') - } - set value(val) { - this.setAttribute('value', val) - } - expand = () => { - if (!this.open) { - this.optionList.classList.remove('hide') - this.optionList.classList.add('no-transformations') - this.open = true - this.icon.classList.add('focused') - this.availableOptions.forEach(option => { - option.setAttribute('tabindex', '0') - }) - } - } - collapse() { - if (this.open) { - this.open = false - this.icon.classList.remove('focused') - this.optionList.classList.add('hide') - this.optionList.classList.remove('no-transformations') - this.availableOptions.forEach(option => { - option.removeAttribute('tabindex') - }) - } - } - connectedCallback() { - this.availableOptions - this.containerDimensions - this.optionList = this.shadowRoot.querySelector('.options') - let slot = this.shadowRoot.querySelector('.options slot'), - menu = this.shadowRoot.querySelector('.menu') - this.icon = this.shadowRoot.querySelector('.icon') - this.open = false; - menu.addEventListener('click', e => { - if (!this.open) { - this.expand() - } else { - this.collapse() - } - }) - menu.addEventListener('keydown', e => { - if (e.code === 'ArrowDown' || e.code === 'ArrowRight') { - e.preventDefault() - this.availableOptions[0].focus() - } - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - if (!this.open) { - this.expand() - } else { - this.collapse() - } - } - }) - this.optionList.addEventListener('keydown', e => { - if (e.code === 'ArrowUp' || e.code === 'ArrowRight') { - e.preventDefault() - if (document.activeElement.previousElementSibling) { - document.activeElement.previousElementSibling.focus() - } - } - if (e.code === 'ArrowDown' || e.code === 'ArrowLeft') { - e.preventDefault() - if (document.activeElement.nextElementSibling) - document.activeElement.nextElementSibling.focus() - } - }) - this.optionList.addEventListener('click', e => { - this.collapse() - }) - slot.addEventListener('slotchange', e => { - this.availableOptions = slot.assignedElements() - this.containerDimensions = this.optionList.getBoundingClientRect() - }); - window.addEventListener('mousedown', e => { - if (!this.contains(e.target) && e.button !== 2) { - this.collapse() - } - }) - } -}) - -// option -const smMenuOption = document.createElement('template') -smMenuOption.innerHTML = ` - -
- -
`; -customElements.define('sm-menu-option', class extends HTMLElement { - constructor() { - super() - this.attachShadow({ - mode: 'open' - }).append(smMenuOption.content.cloneNode(true)) - } - - connectedCallback() { - this.addEventListener('keyup', e => { - if (e.code === 'Enter' || e.code === 'Space') { - e.preventDefault() - this.click() - } - }) - } -}) - -// tab-header +window.customElements.define('sm-spinner', SquareLoader); const smTabHeader = document.createElement('template') smTabHeader.innerHTML = ` +
+ +
+`; + +customElements.define('sm-tab', class extends HTMLElement { + constructor() { + super() + this.shadow = this.attachShadow({ + mode: 'open' + }).append(smTab.content.cloneNode(true)) + } }) // tab-panels @@ -3505,21 +2274,27 @@ smTabPanels.innerHTML = ` display: flex; width: 100%; height: 100%; - overflow: hidden auto; + overflow: hidden; + scroll-snap-type: x mandatory; + content-visibility: auto; } -slot::slotted(.hide-completely){ - display: none; +::slotted(*){ + min-width: 100%; + scroll-snap-align: center; } -@media (hover: none){ - .tab-header::-webkit-scrollbar-track { - -webkit-box-shadow: none !important; - background-color: transparent !important; +@media (any-hover: none) { + .panel-container{ + overflow-x: auto; + scrollbar-width: none; } - .tab-header::-webkit-scrollbar { + .container { + overflow-y: scroll; + } + ::-webkit-scrollbar { + width: 0; height: 0; - background-color: transparent; } -} +}
Nothing to see here. @@ -3532,109 +2307,697 @@ customElements.define('sm-tab-panels', class extends HTMLElement { this.attachShadow({ mode: 'open' }).append(smTabPanels.content.cloneNode(true)) - this.panelSlot = this.shadowRoot.querySelector('slot'); + + this.isTransitioning = false + + this.panelContainer = this.shadowRoot.querySelector('.panel-container'); + this.handleTabChange = this.handleTabChange.bind(this) + } + handleTabChange(e) { + this.isTransitioning = true + this.panelContainer.scrollTo({ + left: this.allPanels[e.detail.index].getBoundingClientRect().left - this.panelContainer.getBoundingClientRect().left + this.panelContainer.scrollLeft, + behavior: 'smooth' + }) + setTimeout(() => { + this.isTransitioning = false + }, 300); + } + fireEvent(index) { + this.dispatchEvent( + new CustomEvent(`switchedpanel${this.id}`, { + bubbles: true, + detail: { + index: parseInt(index) + } + }) + ) } connectedCallback() { - - //animations - let flyInLeft = [{ - opacity: 0, - transform: 'translateX(-1rem)' - }, - { - opacity: 1, - transform: 'none' - } - ], - flyInRight = [{ - opacity: 0, - transform: 'translateX(1rem)' - }, - { - opacity: 1, - transform: 'none' - } - ], - flyOutLeft = [{ - opacity: 1, - transform: 'none' - }, - { - opacity: 0, - transform: 'translateX(-1rem)' - } - ], - flyOutRight = [{ - opacity: 1, - transform: 'none' - }, - { - opacity: 0, - transform: 'translateX(1rem)' - } - ], - animationOptions = { - duration: 300, - fill: 'forwards', - easing: 'ease' - } - this.prevPanel - this.allPanels - this.previousRank - - this.panelSlot.addEventListener('slotchange', () => { - this.panelSlot.assignedElements().forEach((panel) => { - panel.classList.add('hide-completely') + const slot = this.shadowRoot.querySelector('slot'); + slot.addEventListener('slotchange', (e) => { + this.allPanels = e.target.assignedElements() + this.allPanels.forEach((panel, index) => { + panel.dataset.index = index + intersectionObserver.observe(panel) }) }) - this.allPanels = this.panelSlot.assignedElements() - this._targetBodyFlyRight = (targetBody) => { - targetBody.classList.remove('hide-completely') - targetBody.animate(flyInRight, animationOptions) - } - this._targetBodyFlyLeft = (targetBody) => { - targetBody.classList.remove('hide-completely') - targetBody.animate(flyInLeft, animationOptions) - } - document.addEventListener('switchtab', e => { - if (e.detail.target !== this.id) - return + document.addEventListener(`switchedtab${this.id}`, this.handleTabChange) - if (this.prevPanel) { - let targetBody = this.allPanels[e.detail.rank], - currentBody = this.prevPanel; - if (this.previousRank < e.detail.rank) { - if (currentBody && !targetBody) - currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - } - else if (targetBody && !currentBody) { - this._targetBodyFlyRight(targetBody) - } else if (currentBody && targetBody) { - currentBody.animate(flyOutLeft, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - this._targetBodyFlyRight(targetBody) - } - } - } else { - if (currentBody && !targetBody) - currentBody.animate(flyOutRight, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - } - else if (targetBody && !currentBody) { - this._targetBodyFlyLeft(targetBody) - } else if (currentBody && targetBody) { - currentBody.animate(flyOutRight, animationOptions).onfinish = () => { - currentBody.classList.add('hide-completely') - this._targetBodyFlyLeft(targetBody) - } - } + const intersectionObserver = new IntersectionObserver(entries => { + + entries.forEach(entry => { + if (!this.isTransitioning && entry.isIntersecting) { + this.fireEvent(entry.target.dataset.index) } - } else { - this.allPanels[e.detail.rank].classList.remove('hide-completely') - } - this.previousRank = e.detail.rank - this.prevPanel = this.allPanels[e.detail.rank]; + }) + }, { + threshold: 0.6 }) } + disconnectedCallback() { + intersectionObserver.disconnect() + document.removeEventListener(`switchedtab${this.id}`, this.handleTabChange) + } }) + +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.code === 'Space') { + 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 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 !== '') { + this.placeholder.classList.add('hide') + } 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() + } + } + }) + 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('div') + 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, + }) + } +}) \ No newline at end of file diff --git a/css/main.css b/css/main.css index 8829112..b3999fc 100644 --- a/css/main.css +++ b/css/main.css @@ -9,145 +9,78 @@ font-size: clamp(1rem, 1.2vmax, 3rem); } -html, body { +html, +body { height: 100%; scroll-behavior: smooth; } body { - --accent-color: #1976D2; - --light-shade: rgba(var(--text-color), 0.06); - --text-color: 17, 17, 17; - --text-color-light: 100, 100, 100; - --foreground-color: 255, 255, 255; - --background-color: #F6f6f6; - --error-color: red; color: rgba(var(--text-color), 1); - background: var(--background-color); - display: flex; - flex-direction: column; + background: rgba(var(--background-color), 1); +} +body, +body * { + --accent-color: #5D54A4; + --text-color: 17, 17, 17; + --background-color: 246, 246, 246; + --foreground-color: white; + --danger-color: red; } -body[data-theme=dark] { - --accent-color: #42A5F5; +body[data-theme=dark], +body[data-theme=dark] * { + --accent-color: #9D65C9; --text-color: 240, 240, 240; --text-color-light: 170, 170, 170; - --foreground-color: 20, 20, 20; - --background-color: #0a0a0a; - --error-color: rgb(255, 106, 106); -} - -/* h1,h2,h3,h4,h5,h6{ - font-family: 'Montserrat', sans-serif; -} */ -.full-bleed { - grid-column: 1/4; -} - -.h1 { - font-size: 2.5rem; -} - -.h2 { - font-size: 2rem; -} - -.h3 { - font-size: 1.4rem; -} - -.h4 { - font-size: 1rem; -} - -.h5 { - font-size: 0.8rem; -} - -.uppercase { - text-transform: uppercase; -} - -.capitalize { - text-transform: capitalize; + --background-color: 10, 10, 10; + --foreground-color: rgb(20, 20, 20); + --danger-color: rgb(255, 106, 106); } p { - font-size: 0.8; - max-width: 60ch; + max-width: 65ch; line-height: 1.7; color: rgba(var(--text-color), 0.8); } p:not(:last-of-type) { - margin-bottom: 1rem; + margin-bottom: 1.5rem; } img { object-fit: cover; } -a { +a:where([class]) { color: inherit; text-decoration: none; } -a:focus-visible { +a:where([class]):focus-visible { box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset; } button { position: relative; display: inline-flex; - overflow: hidden; - align-items: center; - background: none; - cursor: pointer; - outline: none; - color: inherit; - font-size: 0.9rem; - font-weight: 500; - border-radius: 0.2rem; - padding: 0.5rem 0.6rem; - -webkit-tap-highlight-color: transparent; border: none; -} - -button:focus-visible { - outline: rgba(var(--text-color), 1) 0.1rem solid; -} - -a.button:any-link { - position: relative; - display: inline-flex; - align-items: center; - background: none; - cursor: pointer; - outline: none; - font-weight: 500; - font-size: 0.8rem; - border-radius: 0.3rem; - padding: 0.5rem 0.6rem; - align-self: flex-start; - text-decoration: none; - color: rgba(var(--text-color), 0.7); - -webkit-tap-highlight-color: transparent; - background-color: rgba(var(--text-color), 0.06); -} -a.button:any-link .icon { - margin-right: 0.3rem; - height: 1.2rem; + background-color: transparent; + overflow: hidden; + color: inherit; } a:any-link:focus-visible { outline: rgba(var(--text-color), 1) 0.1rem solid; } -.button { - background-color: rgba(var(--text-color), 0.06); -} - sm-button { --border-radius: 0.3rem; } +sm-button[variant=primary] .icon { + fill: rgba(var(--background-color), 1); +} +sm-button[disabled] .icon { + fill: rgba(var(--text-color), 0.6); +} ul { list-style: none; @@ -192,6 +125,38 @@ ul { hyphens: auto; } +.full-bleed { + grid-column: 1/4; +} + +.h1 { + font-size: 2.5rem; +} + +.h2 { + font-size: 2rem; +} + +.h3 { + font-size: 1.4rem; +} + +.h4 { + font-size: 1rem; +} + +.h5 { + font-size: 0.8rem; +} + +.uppercase { + text-transform: uppercase; +} + +.capitalize { + text-transform: capitalize; +} + .flex { display: flex; } @@ -200,6 +165,10 @@ ul { display: grid; } +.grid-3 { + grid-template-columns: 1fr auto auto; +} + .flow-column { grid-auto-flow: column; } @@ -264,6 +233,10 @@ ul { justify-self: start; } +.justify-self-end { + justify-self: end; +} + .direction-column { flex-direction: column; } @@ -276,6 +249,18 @@ ul { width: 100%; } +.color-0-8 { + color: rgba(var(--text-color), 0.8); +} + +.weight-400 { + font-weight: 400; +} + +.weight-500 { + font-weight: 500; +} + .ripple { position: absolute; border-radius: 50%; @@ -316,20 +301,6 @@ ul { margin-left: 0.5rem; } -.popup__header { - display: grid; - gap: 0.5rem; - width: 100%; - padding: 0 1.5rem 0 0.5rem; - align-items: center; - grid-template-columns: auto 1fr; -} - -.popup__header__close { - padding: 0.5rem; - cursor: pointer; -} - #confirmation_popup, #prompt_popup { flex-direction: column; @@ -354,129 +325,79 @@ ul { margin-left: auto; } -input[type=checkbox] { - display: none; -} - -.checkbox svg { - fill: none; - stroke: rgba(var(--text-color), 0.8); - stroke-width: 6; - overflow: visible; - height: 1.6rem; - width: 1.6rem; -} - -.checkbox svg .check { - stroke-dashoffset: 70; - stroke-dasharray: 70; - -webkit-transition: stroke-dashoffset 0.3s ease; - transition: stroke-dashoffset 0.3s ease; -} - -.checkbox input:checked + svg { - stroke: #00C853; -} - -.checkbox input:checked + svg .check { - stroke-dashoffset: 0; -} - -#settings_page { - padding: 1rem; -} - -#settings_page section { - width: 100%; - border-bottom: 1px solid rgba(var(--text-color), 0.1); - display: -ms-grid; +.popup__header { display: grid; - padding-bottom: 1rem; -} - -#settings_page section:last-of-type { - border: none; -} - -#settings_page h3, -#settings_page h4 { - display: flexbox; + gap: 0.5rem; width: 100%; - -ms-flex-item-align: center; - align-self: center; + padding: 0 1.5rem 0 0.5rem; + align-items: center; + grid-template-columns: auto 1fr auto; } -#settings_page h5 { - margin: 0; - -ms-flex-item-align: center; - -ms-grid-row-align: center; - align-self: center; - font-weight: normal; - opacity: 0.9; +.popup__header__close { + padding: 0.5rem; + cursor: pointer; } -#settings_page button { - background: transparent; - border: 1px solid var(--accent-color); - color: var(--accent-color); - margin: 1rem 0; - width: -webkit-min-content; - width: -moz-min-content; - width: min-content; - white-space: nowrap; -} -#settings_page button .icon { - fill: var(--accent-color); +#main_page { + height: 100%; + grid-template-rows: auto 1fr auto; + grid-template-areas: "main-header" "sub-pages" "main-nav"; } -#settings_page > div { - display: -webkit-box; - display: -ms-flexbox; +#main_header { + grid-area: main-header; display: flex; + gap: 1rem; + align-items: center; + position: sticky; + padding: 0.5rem 1.5rem; + background: rgba(var(--background-color), 1); + z-index: 1; +} + +#main_nav { + grid-area: main-nav; + position: relative; + display: flex; + align-items: center; +} + +.nav-list__item { + display: flex; + flex-direction: column; + align-items: center; width: 100%; - padding: 1rem 0; - -ms-flex-line-pack: center; - align-content: center; -} - -#settings_page .row { - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1; -} - -#settings_page .row span { font-size: 0.8rem; + font-weight: 500; + color: rgba(var(--text-color), 0.8); + cursor: pointer; } - -#settings_page .border-card { - color: inherit; - text-decoration: none; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - padding: 0.5rem 0; - width: auto; +.nav-list__item--active { + color: var(--accent-color); } - -#settings_page .border-card svg { +.nav-list__item--active .icon { fill: var(--accent-color); - display: flexbox; - height: 2rem; - -ms-flex-item-align: center; - align-self: center; - margin: 0.5rem; +} +.nav-list__item .icon { + margin-bottom: 0.3rem; +} + +#sub_page_container { + grid-area: sub-pages; + height: 100%; + overflow-y: auto; } .container-card { position: relative; - background: rgba(var(--foreground-color), 1); + background: var(--foreground-color); border-radius: 0.4rem; } .solid-background { transition: background-color 2s; - background: rgba(var(--foreground-color), 1); + background: var(--foreground-color); } a { @@ -497,44 +418,38 @@ a { left: 0; right: 0; place-content: center; - background-color: rgba(var(--foreground-color), 1); + background-color: var(--foreground-color); +} + +#sign_in_form { + width: 22rem; } .task { - display: -ms-grid; display: grid; - -ms-grid-columns: auto 1fr; grid-template-columns: auto 1fr; margin: 0 1rem; } .task:last-of-type .left .line { - -webkit-transform: scaleY(0); transform: scaleY(0); } .task .left { - display: -webkit-box; - display: -ms-flexbox; display: flex; position: relative; - -webkit-box-pack: center; - -ms-flex-pack: center; justify-content: center; padding-top: 0.5rem; } .task .left .circle { - display: -webkit-inline-box; - display: -ms-inline-flexbox; display: inline-flex; position: relative; - -ms-flex-item-align: start; align-self: flex-start; height: 1rem; width: 1rem; border-radius: 50%; - background: rgba(var(--foreground-color), 1); + background: var(--foreground-color); border: solid 2px rgba(var(--text-color), 0.4); z-index: 1; } @@ -544,31 +459,20 @@ a { left: 50%; height: 100%; width: 2px; - -webkit-transform: translateX(-50%) scaleY(1); transform: translateX(-50%) scaleY(1); background-color: rgba(var(--text-color), 0.4); } .task .right { margin-left: 1rem; - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; flex-direction: column; width: 100%; } .task .right .apply-cont { width: 100%; - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; flex-direction: row; } @@ -640,67 +544,9 @@ a { #dashboard { padding-bottom: 5rem; - -ms-grid-columns: auto; grid-template-columns: auto; } -.input { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: 100%; - margin: 1rem 0; - background: rgba(var(--text-color), 0.06); - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-radius: 0.2rem; - overflow: hidden; -} - -.input input, -.input textarea { - color: var(--light-text); - padding: 1rem 0.5rem; - width: 100%; - font-size: 1rem; - background: transparent; - margin-left: 0; -} - -.input input:focus, -.input textarea:focus { - outline: none; -} - -.input svg { - height: 1.2rem; - width: 1.2rem; - margin: 0 0.5rem 0 1rem; - fill: none; - stroke: rgba(var(--text-color), 0.8); - stroke-width: 6; - overflow: visible; -} - -.input:focus-within { - background: rgba(0, 0, 0, 0.1); -} - -input, -button, -textarea { - position: relative; - border: none; - font-size: 1rem; - border-radius: 0.2rem; -} - -button[disabled] { - opacity: 0.5 !important; - cursor: default; -} - .show { display: block; } @@ -727,73 +573,16 @@ button[disabled] { margin-top: 0.3rem; } -.chatInput { - overflow: hidden; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 0; -} - -.chatInput textarea { - resize: none; - line-height: 1.6; -} - -.chatInput button { - -webkit-transition: -webkit-transform 0.3s ease; - transition: -webkit-transform 0.3s ease; - transition: transform 0.3s ease; - transition: transform 0.3s ease, -webkit-transform 0.3s ease; - -webkit-transform: scale(0); - transform: scale(0); - -ms-flex-item-align: end; - align-self: flex-end; - padding: 1rem; -} - -.chatInput button svg { - margin: 0; - fill: rgba(var(--text-color), 1); -} - -#top_nav { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 0.5rem; - z-index: 4; -} - -#top_nav .spacer { +.spacer { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } -#top_nav .logo { - margin-right: 0.5rem; -} - .logo { - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; font-size: 1.2rem; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; width: 100%; } @@ -826,7 +615,10 @@ button[disabled] { } .project-card { + padding: 1rem; text-transform: capitalize; + font-weight: 500; + color: rgba(var(--text-color), 0.8); } .intern-card { @@ -889,10 +681,7 @@ button[disabled] { display: flex; position: relative; margin-bottom: 0.5rem; - -webkit-box-align: left; - -ms-flex-align: left; align-items: left; - -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 1rem; border-bottom: 1px solid rgba(var(--text-color), 0.1); @@ -931,8 +720,8 @@ button[disabled] { margin: 1rem; right: 2rem; min-width: 24rem; - background: rgba(var(--foreground-color), 1); - box-shadow: 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.24); + background: var(--foreground-color); + box-shadow: 0 1rem 1.5rem -0.5rem rgba(0, 0, 0, 0.3); border-radius: 0.5rem; } @@ -967,6 +756,7 @@ button[disabled] { max-height: 80vh; overflow-y: auto; flex-direction: column; + overscroll-behavior: contain; } #updates { @@ -974,16 +764,15 @@ button[disabled] { } .update { - display: flex; - flex-direction: column; + display: grid; + gap: 0.5rem; padding: 1rem; } -.update__project-name { - font-size: 1.2rem; +.update__topic { + font-weight: 500; + font-size: 1rem; max-width: 60ch; - margin: 0.3rem 0 0.5rem 0; - font-weight: bold; text-transform: capitalize; } @@ -993,6 +782,11 @@ button[disabled] { font-weight: 500; } +.update__time { + font-size: 0.85rem; + color: rgba(var(--text-color), 0.8); +} + .update__message { white-space: pre-line; } @@ -1115,9 +909,6 @@ button[disabled] { } #project_info { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; flex-direction: column; } @@ -1126,9 +917,6 @@ button[disabled] { padding: 0.5rem; border-radius: 0.2rem; margin: 0.5rem 0.5rem 0.5rem 0; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; } @@ -1138,34 +926,24 @@ button[disabled] { background: rgba(var(--text-color), 0.04); } -.active-project { - background: rgba(var(--text-color), 0.06); -} - .opac { opacity: 1 !important; } .task-list-item { - display: -ms-grid; display: grid; - -ms-grid-columns: auto auto 1fr auto; grid-template-columns: auto auto 1fr auto; grid-template-areas: "status . title options" "status . interns interns" "status . description description"; padding: 1rem; gap: 0.5rem; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; background: rgba(var(--text-color), 0.02); } -.task-list-item .checkbox { - -ms-grid-row-span: 3; +.task-list-item sm-checkbox { grid-area: status; + align-self: flex-start; padding: 0.5rem 0.5rem 0.5rem 0; - -ms-flex-item-align: start !important; - align-self: flex-start !important; } .task-list-item:first-of-type { @@ -1189,28 +967,17 @@ button[disabled] { } .task-list-item .assigned-interns { - -ms-grid-column-span: 2; grid-area: interns; } .task-list-item .task-option { grid-area: options; cursor: pointer; - opacity: 1; - -webkit-transition: opacity 0.3s ease; transition: opacity 0.3s ease; -} - -.task-list-item .task-option svg { - width: 2rem; - height: 2rem; padding: 0.5rem; - overflow: visible; - fill: rgba(var(--text-color), 0.8); } .task-list-item p { - -ms-grid-column-span: 2; grid-area: description; margin: 0; text-overflow: ellipsis; @@ -1219,28 +986,18 @@ button[disabled] { } .assigned-interns { - display: -webkit-box; - display: -ms-flexbox; display: flex; - -ms-flex-wrap: wrap; flex-wrap: wrap; } .assigned-interns .assigned-intern { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; - display: -webkit-box; - display: -ms-flexbox; display: flex; font-size: 0.8rem; margin: 0.2rem 0.5rem 0.2rem 0; padding: 0.2rem 0 0.2rem 0.4rem; border-radius: 0.2rem; border: 1px solid rgba(var(--text-color), 0.24); - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; white-space: nowrap; text-transform: capitalize; @@ -1263,156 +1020,35 @@ button[disabled] { } #task_context { - -webkit-transition: 0.3s opacity ease; transition: 0.3s opacity ease; top: 0; right: 0; margin: 0 2rem; list-style: none; padding: 0.5rem 0; - width: -webkit-max-content; - width: -moz-max-content; width: max-content; - border-radius: 0.2rem; + border-radius: 0.3rem; position: absolute; - background: rgba(var(--foreground-color), 1); - -webkit-box-shadow: 0.2rem 0.4rem 1rem rgba(0, 0, 0, 0.24), -0.1rem -0.2rem 0.4rem rgba(0, 0, 0, 0.16); - box-shadow: 0.2rem 0.4rem 1rem rgba(0, 0, 0, 0.24), -0.1rem -0.2rem 0.4rem rgba(0, 0, 0, 0.16); + background: var(--foreground-color); + box-shadow: 0 0.5rem 1rem -0.3rem rgba(0, 0, 0, 0.3); } - #task_context li { - padding: 0.8rem 1rem; - display: -webkit-box; - display: -ms-flexbox; + padding: 0.8rem 1.5rem; display: flex; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; + cursor: pointer; } - -#task_context li svg { - margin-right: 1rem; - width: 1.2rem; - height: 1.2rem; - fill: none; - stroke: rgba(var(--text-color), 0.8); - stroke-width: 6; - overflow: visible; -} - -.temp-task { - padding: 1rem; - background: rgba(var(--text-color), 0.02); - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.temp-task .input { - margin: 0.4rem 0; +#task_context li .icon { + margin-right: 0.5rem; } #branch_container { - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; flex-flow: row wrap; margin: 1rem 0; } -#notification { - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} - -#bottom_nav { - position: fixed; - bottom: 0; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - width: 100vw; - background: rgba(var(--foreground-color), 1); - z-index: 4; - border-top: 1px solid rgba(var(--text-color), 0.1); -} - -#bottom_nav button { - padding: 0.2rem; - width: 100%; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - font-size: 0.7rem; - font-weight: normal; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} - -#bottom_nav button svg { - margin: 0.4rem; -} - -#show_message { - -webkit-transform: translate(0, 0.4rem); - transform: translate(0, 0.4rem); - -webkit-transition: opacity 0.3s ease, -webkit-transform 0.3s ease; - transition: opacity 0.3s ease, -webkit-transform 0.3s ease; - transition: transform 0.3s ease, opacity 0.3s ease; - transition: transform 0.3s ease, opacity 0.3s ease, -webkit-transform 0.3s ease; - -webkit-box-shadow: 0.2rem 0.4rem 0.8rem rgba(0, 0, 0, 0.16); - box-shadow: 0.2rem 0.4rem 0.8rem rgba(0, 0, 0, 0.16); - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - color: white; - position: fixed; - bottom: 0; - right: 0; - width: 100%; - z-index: 11; -} - -#show_message span { - font-weight: 500; - padding: 1rem; - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1; -} - -#show_message button { - padding: 0.5rem 1rem; - margin: 0; -} - -#show_message button svg { - stroke: white; -} - #interns_list { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; flex-direction: column; min-width: 20rem; } @@ -1448,17 +1084,10 @@ button[disabled] { position: -webkit-sticky; position: sticky; top: 0; - background: rgba(var(--foreground-color), 1); - display: -webkit-box; - display: -ms-flexbox; + background: var(--foreground-color); display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row; flex-flow: row; border-bottom: 1px solid rgba(var(--text-color), 0.1); - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; z-index: 2; } @@ -1498,7 +1127,7 @@ button[disabled] { text-align: center; place-content: center; justify-items: center; - background-color: rgba(var(--foreground-color), 1); + background-color: var(--foreground-color); } .loading-message { @@ -1517,31 +1146,6 @@ button[disabled] { width: 4rem; } -.loader { - height: 2rem; - width: 2rem; - stroke-width: 8; - overflow: visible; - stroke: var(--accent-color); - fill: none; - stroke-dashoffset: 180; - stroke-dasharray: 180; - animation: load 3.6s linear infinite, spin 1s linear infinite; -} - -@keyframes load { - 50% { - stroke-dashoffset: 0; - } - 100% { - stroke-dashoffset: -180; - } -} -@keyframes spin { - 100% { - transform: rotate(360deg); - } -} #status_map_container { position: relative; overflow: hidden; @@ -1599,23 +1203,14 @@ button[disabled] { position: relative; padding-left: 1rem; padding-top: 1rem; - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; flex-direction: row; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; color: #000; z-index: 1; } .watching h4 { - -webkit-box-flex: 1; - -ms-flex: 1; flex: 1; font-weight: 500; } @@ -1638,8 +1233,6 @@ button[disabled] { } #right div:first-of-type h2 { - -webkit-box-flex: 1; - -ms-flex: 1; flex: 1; margin: 0.4rem 0; } @@ -1650,118 +1243,12 @@ button[disabled] { .center { position: relative; - display: -ms-grid; display: grid; place-content: center; height: 100%; text-align: center; } -.slide-left { - -webkit-animation: slide-left 0.4s ease; - animation: slide-left 0.4s ease; -} - -@-webkit-keyframes slide-left { - 100% { - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - opacity: 0; - } -} -@keyframes slide-left { - 100% { - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - opacity: 0; - } -} -.update-mi svg { - -webkit-animation: shake 0.6s ease; - animation: shake 0.6s ease; - -webkit-transform-origin: top; - transform-origin: top; -} - -@-webkit-keyframes shake { - 0% { - -webkit-transform: rotate(30deg); - transform: rotate(30deg); - } - 20% { - -webkit-transform: rotate(-30deg); - transform: rotate(-30deg); - } - 40% { - -webkit-transform: rotate(20deg); - transform: rotate(20deg); - } - 60% { - -webkit-transform: rotate(-20deg); - transform: rotate(-20deg); - } - 80% { - -webkit-transform: rotate(10deg); - transform: rotate(10deg); - } - 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } -} -@keyframes shake { - 0% { - -webkit-transform: rotate(30deg); - transform: rotate(30deg); - } - 20% { - -webkit-transform: rotate(-30deg); - transform: rotate(-30deg); - } - 40% { - -webkit-transform: rotate(20deg); - transform: rotate(20deg); - } - 60% { - -webkit-transform: rotate(-20deg); - transform: rotate(-20deg); - } - 80% { - -webkit-transform: rotate(10deg); - transform: rotate(10deg); - } - 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } -} -.settings-mi svg { - -webkit-animation: rot 0.6s ease; - animation: rot 0.6s ease; - -webkit-transform-origin: center; - transform-origin: center; -} - -@-webkit-keyframes rot { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - 100% { - -webkit-transform: rotate(60deg); - transform: rotate(60deg); - } -} -@keyframes rot { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - 100% { - -webkit-transform: rotate(60deg); - transform: rotate(60deg); - } -} .capitalise { text-transform: capitalize; } @@ -1771,13 +1258,13 @@ button[disabled] { margin: 0; } -#admin_panel { +#admin_page { padding: 0 1.5rem; display: grid; gap: 1.5rem; } -#admin_panel__header { +#admin_page__header { display: grid; gap: 0 1rem; padding: 0.5rem 0; @@ -1795,13 +1282,10 @@ button[disabled] { } .hide-on-mobile { - display: -webkit-box; - display: -ms-flexbox; display: flex; } .hide-page-on-mobile { - display: -ms-grid; display: grid; } @@ -1813,54 +1297,44 @@ button[disabled] { padding: 1.5rem 1.5rem 0 0.5rem; } - .page, -#show_all, -#project_explorer { - margin: 1rem 4vw; + #main_nav { + flex-direction: column; + align-items: flex-start; } - #top_nav { - padding: 1rem 2vw; + .nav-list__item { + flex-direction: row; + align-items: center; + padding: 0.5rem 0.8rem; + font-size: 1rem; + } + .nav-list__item--active { + background-color: rgba(var(--text-color), 0.06); + } + .nav-list__item .icon { + margin-right: 0.5rem; + margin-bottom: 0; + } + + .project-card--active { + background-color: rgba(var(--text-color), 0.1); } #settings_page { padding: 1rem 2rem; } - .logo { - -webkit-box-pack: left; - -ms-flex-pack: left; - justify-content: left; - width: auto; - } - - #show_message { - -webkit-transform: translate(0.4rem, 0); - transform: translate(0.4rem, 0); - margin: 1rem; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - border-radius: 0.2rem; - } - #sign_in { width: 24rem; height: auto; border-radius: 0.4rem; } - #floating_btn { - margin: 1rem; - } - #dashboard { - -ms-grid-columns: 3fr 1fr; grid-template-columns: 3fr 1fr; } #dashboard #status_map_container { - -ms-flex-item-align: start; align-self: flex-start; } @@ -1882,33 +1356,18 @@ button[disabled] { opacity: 1; } - #intern_info { - width: 24rem; - } - - .hover { - -webkit-transition: background 0.3s ease; - transition: background 0.3s ease; - cursor: pointer; - } - - .hover:hover { - background: rgba(var(--text-color), 0.06); - } - - #admin_panel { + #admin_page { grid-template-columns: 16rem 1fr; grid-template-rows: auto 1fr; grid-template-areas: "admin-header admin-header" ". ."; } - #admin_panel__header { + #admin_page__header { grid-area: admin-header; } #edit_data_fig { width: 16rem; - -ms-grid-column-align: center; justify-self: center; } @@ -1920,35 +1379,22 @@ button[disabled] { overflow-y: auto; } - .task-list-item .task-option { - opacity: 0; - } - - .task-list-item:hover .task-option { - opacity: 1; - } - #project_explorer { - display: -ms-grid; display: grid; align-items: flex-start; - -ms-grid-columns: 1fr 3fr; grid-template-columns: 1fr 3fr; grid-template-areas: "header header" "left right"; } #project_explorer .header { border-radius: 0.4rem 0.4rem 0 0; - -ms-grid-column-span: 2; grid-area: header; } #project_explorer #left { - position: -webkit-sticky; position: sticky; top: 4.8rem; grid-area: left; - -ms-flex-item-align: start; align-self: flex-start; border-right: 1px solid rgba(var(--text-color), 0.06); } @@ -1963,6 +1409,11 @@ button[disabled] { #project_explorer #right { grid-area: right; } + + #main_page { + grid-template-columns: 10rem minmax(0, 1fr); + grid-template-areas: "main-header main-header" "main-nav sub-pages"; + } } #update_of_project { color: rgba(var(--text-color), 0.8); @@ -2009,7 +1460,7 @@ ul { } .task__title { - font-size: 1.5rem; + font-size: 1.3rem; margin-bottom: 1rem !important; } @@ -2020,7 +1471,7 @@ ul { .send-update-button { grid-area: send-button; - border: solid 1px; + --padding: 0.6rem 0.8rem; color: var(--accent-color); } .send-update-button .icon { @@ -2029,13 +1480,6 @@ ul { fill: var(--accent-color); } -@media only screen and (min-width: 1280px) { - .page, -#show_all, -#project_explorer { - margin: 1rem 8vw; - } -} @media (any-hover: hover) { ::-webkit-scrollbar { width: 0.5rem; @@ -2050,6 +1494,10 @@ ul { background: rgba(var(--text-color), 0.5); } + .interact:hover { + background-color: rgba(var(--text-color), 0.06); + } + .send-update-button { opacity: 0; transition: opacity 0.3s; @@ -2058,6 +1506,15 @@ ul { .task-card:hover .send-update-button { opacity: 1; } + + .task-option { + opacity: 0; + } + + .task-list-item:hover .task-option, +.task-option:focus-within { + opacity: 1; + } } @media (any-hover: none) { .task-option, diff --git a/css/main.min.css b/css/main.min.css index 48329cb..003b9ce 100644 --- a/css/main.min.css +++ b/css/main.min.css @@ -1 +1 @@ -a,button{color:inherit}.input,.interact,.overflow-ellipsis,button{overflow:hidden}#textCopied,.hide,.ripple{pointer-events:none}.card,.request-card{margin-bottom:.5rem;padding:1rem}.popup__header,.task{grid-template-columns:auto 1fr}*{padding:0;margin:0;box-sizing:border-box;font-family:Roboto,sans-serif}:root{font-size:clamp(1rem,1.2vmax,3rem)}body,html{height:100%;scroll-behavior:smooth}body{--accent-color:#1976D2;--light-shade:rgba(var(--text-color), 0.06);--text-color:17,17,17;--text-color-light:100,100,100;--foreground-color:255,255,255;--background-color:#F6f6f6;--error-color:red;color:rgba(var(--text-color),1);background:var(--background-color);display:flex;flex-direction:column}a.button:any-link,button{display:inline-flex;padding:.5rem .6rem;-webkit-tap-highlight-color:transparent;background:0 0;font-weight:500;cursor:pointer}body[data-theme=dark]{--accent-color:#42A5F5;--text-color:240,240,240;--text-color-light:170,170,170;--foreground-color:20,20,20;--background-color:#0a0a0a;--error-color:rgb(255, 106, 106)}.full-bleed{grid-column:1/4}.h1{font-size:2.5rem}.h2{font-size:2rem}.h3{font-size:1.4rem}.h4{font-size:1rem}.h5{font-size:.8rem}.uppercase{text-transform:uppercase}#intern_info h3,#status_map_container #status_map h2,.assigned-interns .assigned-intern,.capitalise,.capitalize,.project-card,.update__project-name{text-transform:capitalize}p{font-size:.8;max-width:60ch;line-height:1.7;color:rgba(var(--text-color),.8)}p:not(:last-of-type){margin-bottom:1rem}img{object-fit:cover}a:focus-visible{box-shadow:0 0 0 .1rem rgba(var(--text-color),1) inset}button{align-items:center;outline:0}button:focus-visible{outline:solid rgba(var(--text-color),1)}a.button:any-link{position:relative;align-items:center;outline:0;font-size:.8rem;border-radius:.3rem;align-self:flex-start;text-decoration:none;color:rgba(var(--text-color),.7);background-color:rgba(var(--text-color),.06)}.button,.task__project-title{background-color:rgba(var(--text-color),.06)}a.button:any-link .icon{margin-right:.3rem;height:1.2rem}a:any-link:focus-visible{outline:solid rgba(var(--text-color),1)}sm-button{--border-radius:0.3rem}.hide{opacity:0}.hide-completely{display:none!important}.overflow-ellipsis{width:100%;white-space:nowrap;text-overflow:ellipsis}.breakable{overflow-wrap:break-word;word-wrap:break-word;-ms-word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.flex{display:flex}.grid{display:grid}.flow-column{grid-auto-flow:column}.gap-0-5{gap:.5rem}.gap-1,.page{gap:1rem}.gap-1-5{gap:1.5rem}.gap-2{gap:2rem}.gap-3{gap:3rem}.text-align-right{text-align:right}#loading_page,.center,.text-center{text-align:center}.align-start{align-items:flex-start}.align-center{align-items: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}.direction-column{flex-direction:column}.space-between{justify-content:space-between}.w-100{width:100%}.ripple{position:absolute;border-radius:50%;transform:scale(0);background:rgba(var(--text-color),.16)}#loading_page,#sign_in_page{right:0;background-color:rgba(var(--foreground-color),1);place-content:center}.interact{position:relative;cursor:pointer;-webkit-tap-highlight-color:transparent}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}.icon{width:1.5rem;height:1.5rem;fill:rgba(var(--text-color),.9)}.button__icon{height:1.2rem;width:1.2rem}.button__icon--left{margin-right:.5rem}.button__icon--right{margin-left:.5rem}.popup__header{display:grid;gap:.5rem;width:100%;padding:0 1.5rem 0 .5rem;align-items:center}.popup__header__close{padding:.5rem;cursor:pointer}#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}input[type=checkbox]{display:none}.checkbox svg{fill:none;stroke:rgba(var(--text-color),.8);stroke-width:6;overflow:visible;height:1.6rem;width:1.6rem}.checkbox svg .check{stroke-dashoffset:70;stroke-dasharray:70;-webkit-transition:stroke-dashoffset .3s ease;transition:stroke-dashoffset .3s ease}.checkbox input:checked+svg{stroke:#00C853}.checkbox input:checked+svg .check{stroke-dashoffset:0}#settings_page{padding:1rem}#settings_page section{width:100%;border-bottom:1px solid rgba(var(--text-color),.1);display:-ms-grid;display:grid;padding-bottom:1rem}#settings_page section:last-of-type{border:none}#settings_page h3,#settings_page h4{display:flexbox;width:100%;-ms-flex-item-align:center;align-self:center}#settings_page h5{margin:0;-ms-flex-item-align:center;-ms-grid-row-align:center;align-self:center;font-weight:400;opacity:.9}#settings_page button{background:0 0;border:1px solid var(--accent-color);color:var(--accent-color);margin:1rem 0;width:-webkit-min-content;width:-moz-min-content;width:min-content;white-space:nowrap}#settings_page button .icon{fill:var(--accent-color)}#settings_page>div{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%;padding:1rem 0;-ms-flex-line-pack:center;align-content:center}#settings_page .row{-webkit-box-flex:1;-ms-flex:1;flex:1}#settings_page .row span{font-size:.8rem}#settings_page .border-card{color:inherit;text-decoration:none;display:-webkit-box;display:-ms-flexbox;display:flex;padding:.5rem 0;width:auto}#settings_page .border-card svg{fill:var(--accent-color);display:flexbox;height:2rem;-ms-flex-item-align:center;align-self:center;margin:.5rem}.container-card{position:relative;background:rgba(var(--foreground-color),1);border-radius:.4rem}.solid-background{transition:background-color 2s;background:rgba(var(--foreground-color),1)}a{color:var(--accent-color);text-decoration:none}.medium-top-bottom-margin{margin:.5rem 0}#sign_in_page{display:grid;position:fixed;z-index:5;top:0;bottom:0;left:0}.task{display:-ms-grid;display:grid;-ms-grid-columns:auto 1fr;margin:0 1rem}.task:last-of-type .left .line{-webkit-transform:scaleY(0);transform:scaleY(0)}.task .left{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding-top:.5rem}.task .left .circle{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;position:relative;-ms-flex-item-align:start;align-self:flex-start;height:1rem;width:1rem;border-radius:50%;background:rgba(var(--foreground-color),1);border:2px solid;z-index:1}.task .left .line{position:absolute;left:50%;height:100%;width:2px;-webkit-transform:translateX(-50%) scaleY(1);transform:translateX(-50%) scaleY(1);background-color:rgba(var(--text-color),.4)}#top_nav,.card,.dropdown,.page,.request-card,button,input,textarea{position:relative}.task .right{margin-left:1rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;width:100%}#bottom_nav,#branch_container,#show_message,#top_nav,.task .right .apply-cont{-webkit-box-orient:horizontal}.task .right .apply-cont{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.task .right .apply-cont h4{-webkit-box-flex:1;-ms-flex:1;flex:1}.task h4{margin-top:.4rem;margin-bottom:1rem}.task p{white-space:pre-line;padding-bottom:2rem}.task .assigned-interns .assigned-intern{padding:.4rem}.completed-task .left .circle{border:2px solid #00C853!important;background:#00C853!important}.completed-task .left .line{background-color:#00C853!important}.page{display:grid;margin:1rem;animation:fadein .4s ease}#top_nav,.input{display:-ms-flexbox}.fade-in{-webkit-animation:fadein .4s ease;animation:fadein .4s ease}@-webkit-keyframes fadein{0%{opacity:0}100%{opacity:1}}@keyframes fadein{0%{opacity:0}100%{opacity:1}}.title{font-weight:500}.padding{padding:1rem}#dashboard{padding-bottom:5rem;-ms-grid-columns:auto;grid-template-columns:auto}.input{display:-webkit-box;display:flex;width:100%;margin:1rem 0;background:rgba(var(--text-color),.06);-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:.2rem}.input input,.input textarea{color:var(--light-text);padding:1rem .5rem;width:100%;font-size:1rem;background:0 0;margin-left:0}.input input:focus,.input textarea:focus{outline:0}.input svg{height:1.2rem;width:1.2rem;margin:0 .5rem 0 1rem;fill:none;stroke:rgba(var(--text-color),.8);stroke-width:6;overflow:visible}.input:focus-within{background:rgba(0,0,0,.1)}button,input,textarea{border:none;font-size:1rem;border-radius:.2rem}button[disabled]{opacity:.5!important;cursor:default}.show{display:block}.hide-on-mobile,.hide-page-on-mobile{display:none}.hide-on-desktop{display:initial}.no-transformations{-webkit-transform:none!important;transform:none!important}.no-bottom-margin{margin-bottom:0}.top-margin{margin-top:.3rem}.chatInput{overflow:hidden;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:0}.chatInput textarea{resize:none;line-height:1.6}.chatInput button{-webkit-transition:-webkit-transform .3s ease;transition:-webkit-transform .3s ease;transition:transform .3s ease;transition:transform .3s ease,-webkit-transform .3s ease;-webkit-transform:scale(0);transform:scale(0);-ms-flex-item-align:end;align-self:flex-end;padding:1rem}.chatInput button svg{margin:0;fill:rgba(var(--text-color),1)}#top_nav{display:-webkit-box;display:flex;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;padding:.5rem;z-index:4}#top_nav .spacer{-webkit-box-flex:1;-ms-flex:1;flex:1}#top_nav .logo{margin-right:.5rem}.logo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;font-size:1.2rem;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:100%}.logo .cls-2,.logo .cls-3{fill:rgba(var(--text-color),1);font-size:146.9px;font-family:ArialMT,Arial}.logo svg{height:2.5rem}.logo h4{margin:0}.active{opacity:1!important;color:var(--accent-color)}.active svg{fill:var(--accent-color)}.svg-margin-right svg{margin-right:.5rem}.intern-card{user-select:none}.intern-card span:first-of-type{display:flex;justify-content:center;align-items:center;flex-shrink:0;padding:.8rem;border-radius:50%;background:#673AB7;margin-right:1rem;color:#fff;font-weight:500;font-size:1.2rem;line-height:0}.intern-card span:first-of-type::after{content:"";display:block;padding-bottom:100%}.intern-card span:nth-of-type(2){flex:1;text-transform:capitalize;flex-shrink:0}.intern-card span:nth-of-type(3){display:inline-flex;align-items:center;align-content:center;font-weight:500;font-size:1.2rem;color:var(--light-text)}.intern-card span:nth-of-type(3) svg{fill:#FF5722!important;height:1rem!important;width:1rem!important;margin-right:.2rem}.card{display:flex;flex-direction:row;align-items:center}.request-card{display:flex;-webkit-box-align:left;-ms-flex-align:left;align-items:left;-ms-flex-wrap:wrap;flex-wrap:wrap;border-bottom:1px solid rgba(var(--text-color),.1)}.request-card p{margin-top:0;width:100%;font-size:1rem}.request-card b{font-weight:500}.request-card button{padding:.2rem .6rem .2rem 0}.request-card button:first-of-type{margin-left:auto}.request-card:last-of-type{border-bottom:none}.dropdown-content{overflow:hidden;position:absolute;z-index:2;margin:1rem;right:2rem;min-width:24rem;background:rgba(var(--foreground-color),1);box-shadow:0 .5rem 1rem -.5rem rgba(0,0,0,.24);border-radius:.5rem}#bottom_nav,#show_message,#textCopied{position:fixed;bottom:0}#intern_updates .container-header{padding-right:0;border-bottom:1px solid rgba(var(--text-color),.1)}#intern_updates .container-header button{padding:1rem 0;border-bottom:.2rem solid transparent;border-radius:0;opacity:.7}#intern_updates .container-header button:first-of-type{margin-right:1rem}#intern_updates .container-header button:last-of-type{margin-right:1rem}#intern_updates .container-header .active{color:rgba(var(--text-color),1);border-bottom:.2rem solid var(--accent-color)}.active-branch,.commit,.container-header span,.update__sender{color:var(--accent-color)}#requests_container,#update_container{display:flex;max-height:80vh;overflow-y:auto;flex-direction:column}#updates{transition:opacity .3s ease}.update{display:flex;flex-direction:column;padding:1rem}.update__project-name{font-size:1.2rem;max-width:60ch;margin:.3rem 0 .5rem;font-weight:700}.update__sender{font-size:.9rem;font-weight:500}.update__message{white-space:pre-line}.container-header{display:flex;align-items:center;flex-direction:row;width:100%;padding:0 1rem}.container-header h3{flex:1;font-weight:500}.container-header span{border-radius:.2rem;margin-right:.2rem;padding:.5rem 1rem;font-weight:500}.back-arrow{fill:none;stroke:rgba(var(--text-color),.8);stroke-width:6;overflow:visible;width:2rem;height:2rem;padding:.5rem .5rem .5rem 0;cursor:pointer}#task_context li svg,.close-svg,.tick-mark{stroke:rgba(var(--text-color),.8);overflow:visible}.close-svg,.tick-mark{fill:none;stroke-width:6;height:2rem;width:2rem}.close-svg{padding:.6rem}#textCopied{padding:1rem;border-radius:2rem;background:var(--sec-color);margin:2rem 0;left:50%;transform:translateX(-50%);transition:.3s opacity ease;z-index:10}#intern_info{flex-direction:column}#intern_info div{display:flex;flex-direction:row;align-items:center;width:100%;margin-bottom:1rem}#intern_info div span{flex:1;word-break:break-all;font-size:.9rem}#intern_info div svg{fill:rgba(var(--text-color),1);height:2.5rem;padding:.6rem;overflow:visible}#intern_info .gold-fill{fill:#FF5722}#intern_info #update_intern_score h4{margin:0;font-size:2rem}#intern_info #update_intern_score button{border:1px solid}#intern_info #update_intern_score button svg{stroke-width:10;fill:none;stroke:var(--accent-color)}#intern_info #update_intern_score rect{stroke:transparent}#intern_info h4,#intern_info h5{margin-top:.5rem}#project_info{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.branch-btn{padding:.5rem;border-radius:.2rem;margin:.5rem .5rem .5rem 0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.active-branch{opacity:1;background:rgba(var(--text-color),.04)}.active-project{background:rgba(var(--text-color),.06)}.opac{opacity:1!important}.task-list-item{display:-ms-grid;display:grid;-ms-grid-columns:auto auto 1fr auto;grid-template-columns:auto auto 1fr auto;grid-template-areas:"status . title options" "status . interns interns" "status . description description";padding:1rem;gap:.5rem;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:rgba(var(--text-color),.02)}.task-list-item .checkbox{-ms-grid-row-span:3;grid-area:status;padding:.5rem .5rem .5rem 0;-ms-flex-item-align:start!important;align-self:flex-start!important}.task-list-item:first-of-type{margin-top:1rem;border-radius:.2rem .2rem 0 0}.task-list-item:last-of-type{border-radius:0 0 .2rem .2rem;border-bottom:none;margin-bottom:1rem}.task-list-item h4{font-weight:500;margin:0}.task-list-item .title{grid-area:title}.task-list-item .assigned-interns{-ms-grid-column-span:2;grid-area:interns}.task-list-item .task-option{grid-area:options;cursor:pointer;opacity:1;-webkit-transition:opacity .3s ease;transition:opacity .3s ease}.task-list-item .task-option svg{width:2rem;height:2rem;padding:.5rem;overflow:visible;fill:rgba(var(--text-color),.8)}.task-list-item p{-ms-grid-column-span:2;grid-area:description;margin:0;text-overflow:ellipsis;overflow:hidden;max-width:100%}.assigned-interns{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}#task_context li,.temp-task{display:-webkit-box;display:-ms-flexbox}.assigned-interns .assigned-intern{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:-webkit-box;display:-ms-flexbox;display:flex;font-size:.8rem;margin:.2rem .5rem .2rem 0;padding:.2rem 0 .2rem .4rem;border-radius:.2rem;border:1px solid;-webkit-box-align:center;-ms-flex-align:center;align-items:center;white-space:nowrap}.assigned-interns .assigned-intern button{padding:.2rem}.assigned-interns .assigned-intern button svg{padding:.2rem;height:1rem;width:1rem}#bottom_nav button,#show_message{-webkit-box-direction:normal;width:100%}.commit{border:1px solid var(--accent-color);padding:.6rem}#task_context{-webkit-transition:.3s opacity ease;transition:.3s opacity ease;top:0;right:0;margin:0 2rem;list-style:none;padding:.5rem 0;width:-webkit-max-content;width:-moz-max-content;width:max-content;border-radius:.2rem;position:absolute;background:rgba(var(--foreground-color),1);-webkit-box-shadow:.2rem .4rem 1rem rgba(0,0,0,.24),-.1rem -.2rem .4rem rgba(0,0,0,.16);box-shadow:.2rem .4rem 1rem rgba(0,0,0,.24),-.1rem -.2rem .4rem rgba(0,0,0,.16)}#task_context li{padding:.8rem 1rem;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}#task_context li svg{margin-right:1rem;width:1.2rem;height:1.2rem;fill:none;stroke-width:6}.temp-task{padding:1rem;background:rgba(var(--text-color),.02);display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap}#bottom_nav,.header{background:rgba(var(--foreground-color),1)}#bottom_nav,#branch_container,#notification,#show_message{display:-webkit-box;display:-ms-flexbox}.temp-task .input{margin:.4rem 0}#branch_container{display:flex;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;margin:1rem 0}#notification{display:flex}#bottom_nav{display:flex;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;width:100vw;z-index:4;border-top:1px solid rgba(var(--text-color),.1)}#bottom_nav button{padding:.2rem;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;font-size:.7rem;font-weight:400;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column}#bottom_nav button svg{margin:.4rem}#show_message{-webkit-transform:translate(0,.4rem);transform:translate(0,.4rem);-webkit-transition:opacity .3s ease,-webkit-transform .3s ease;transition:opacity .3s ease,-webkit-transform .3s ease;transition:transform .3s ease,opacity .3s ease;transition:transform .3s ease,opacity .3s ease,-webkit-transform .3s ease;-webkit-box-shadow:.2rem .4rem .8rem rgba(0,0,0,.16);box-shadow:.2rem .4rem .8rem rgba(0,0,0,.16);-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-direction:row;flex-direction:row;display:flex;color:#fff;right:0;z-index:11}#show_message span,.watching h4{-webkit-box-flex:1;font-weight:500}#show_message span{padding:1rem;-ms-flex:1;flex:1}#show_message button{padding:.5rem 1rem;margin:0}#show_message button svg{stroke:#fff}#interns_list{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;min-width:20rem}.header,.watching{display:-webkit-box;-webkit-box-orient:horizontal;-webkit-box-direction:normal}#interns_list #interns_list_container{min-height:50vh;max-height:50vh;overflow-y:auto}#best_interns_container,#project_list_container{margin-bottom:1rem}#best_interns_container .container-header,#project_list_container .container-header{padding-right:0}#best_interns_container .container-header .icon,#project_list_container .container-header .icon{margin-right:.5rem}#edit_data_fig{fill:rgba(var(--text-color),.6);width:60vw;margin:2rem 0}.header svg,.loader{overflow:visible;fill:none}.header{position:-webkit-sticky;position:sticky;top:0;display:-ms-flexbox;display:flex;-ms-flex-flow:row;flex-flow:row;border-bottom:1px solid rgba(var(--text-color),.1);-webkit-box-align:center;-ms-flex-align:center;align-items:center;z-index:2}.header svg{stroke:rgba(var(--text-color),.8);stroke-width:6;height:2rem;width:2rem;cursor:pointer;padding:.4rem;margin-left:1rem}.header h3{padding:0 .5rem;display:inline-flexbox}.appear-on-scroll-up{position:fixed!important;top:0;width:100%;height:4rem!important}#loading_page{display:grid;position:fixed;top:0;bottom:0;left:0;z-index:5;justify-items:center}.loading-message{font-size:1.3rem;margin:1.5rem 0 .5rem}#loading_page__footer{position:absolute;bottom:0;width:100%;padding:1.5rem}#loading_page__footer .icon{height:4rem;width:4rem}.loader{height:2rem;width:2rem;stroke-width:8;stroke:var(--accent-color);stroke-dashoffset:180;stroke-dasharray:180;animation:load 3.6s linear infinite,spin 1s linear infinite}@keyframes load{50%{stroke-dashoffset:0}100%{stroke-dashoffset:-180}}@keyframes spin{100%{transform:rotate(360deg)}}#status_map_container{position:relative;overflow:hidden;background:#B9F6CA}#status_map_container .branch-btn{color:rgba(0,0,0,.8)}#status_map_container p{color:rgba(0,0,0,.9)}#status_map_container .active-branch{color:#fff;background:rgba(0,200,83,.6)}#status_map_container #status_map{position:relative;z-index:1;padding:1rem;color:#000}#status_map_container #status_map h2{margin:.4rem 0}#status_map_container #status_map .circle{background:#B9F6CA;border:2px solid rgba(0,0,0,.4)}#status_map_container #status_map .line{background:rgba(0,0,0,.4)}#status_map_container #status_map .assigned-intern{border:1px solid rgba(0,0,0,.4)}#status_map_container #status_map .apply-btn{color:#1B5E20;background:rgba(0,200,83,.2)}.apply-btn{padding:.3rem .6rem}#project_editing_panel,.watching button{padding:1rem}.watching{position:relative;padding-left:1rem;padding-top:1rem;display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;color:#000;z-index:1}.watching h4{-ms-flex:1;flex:1}.watching button svg{fill:none!important;fill:none;stroke-width:6;overflow:visible;stroke:#000}#right{padding:0 1rem}#right div:first-of-type h2{-webkit-box-flex:1;-ms-flex:1;flex:1;margin:.4rem 0}#right div:first-of-type button{border:1px solid}.center{position:relative;display:-ms-grid;display:grid;place-content:center;height:100%}.slide-left{-webkit-animation:slide-left .4s ease;animation:slide-left .4s ease}@-webkit-keyframes slide-left{100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}@keyframes slide-left{100%{-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}.update-mi svg{-webkit-animation:shake .6s ease;animation:shake .6s ease;-webkit-transform-origin:top;transform-origin:top}@-webkit-keyframes shake{0%{-webkit-transform:rotate(30deg);transform:rotate(30deg)}20%{-webkit-transform:rotate(-30deg);transform:rotate(-30deg)}40%{-webkit-transform:rotate(20deg);transform:rotate(20deg)}60%{-webkit-transform:rotate(-20deg);transform:rotate(-20deg)}80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}100%{-webkit-transform:rotate(0);transform:rotate(0)}}@keyframes shake{0%{-webkit-transform:rotate(30deg);transform:rotate(30deg)}20%{-webkit-transform:rotate(-30deg);transform:rotate(-30deg)}40%{-webkit-transform:rotate(20deg);transform:rotate(20deg)}60%{-webkit-transform:rotate(-20deg);transform:rotate(-20deg)}80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}100%{-webkit-transform:rotate(0);transform:rotate(0)}}.settings-mi svg{-webkit-animation:rot .6s ease;animation:rot .6s ease;-webkit-transform-origin:center;transform-origin:center}@-webkit-keyframes rot{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(60deg);transform:rotate(60deg)}}@keyframes rot{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(60deg);transform:rotate(60deg)}}#project_explorer,#show_all{margin:0}#admin_panel{padding:0 1.5rem;display:grid;gap:1.5rem}#admin_panel__header{display:grid;gap:0 1rem;padding:.5rem 0;grid-template-columns:1fr auto;align-items:center}@media only screen and (min-width:640px){.hide-on-desktop{display:none!important}.hide-on-mobile{display:-webkit-box;display:-ms-flexbox;display:flex}.hide-page-on-mobile{display:-ms-grid;display:grid}sm-popup{--width:24rem}.popup__header{padding:1.5rem 1.5rem 0 .5rem}#project_explorer,#show_all,.page{margin:1rem 4vw}#top_nav{padding:1rem 2vw}#settings_page{padding:1rem 2rem}.logo{-webkit-box-pack:left;-ms-flex-pack:left;justify-content:left;width:auto}#intern_info,#sign_in{width:24rem}#show_message{-webkit-transform:translate(.4rem,0);transform:translate(.4rem,0);margin:1rem;width:-webkit-max-content;width:-moz-max-content;width:max-content;border-radius:.2rem}#sign_in{height:auto;border-radius:.4rem}#floating_btn{margin:1rem}#dashboard{-ms-grid-columns:3fr 1fr;grid-template-columns:3fr 1fr}#dashboard #status_map_container{-ms-flex-item-align:start;align-self:flex-start}#dashboard #status_map_container .watching{padding-left:2rem}#dashboard #status_map_container #status_map{padding:1rem 2rem}.task .apply-btn{opacity:0;-webkit-transition:opacity .3s ease;transition:opacity .3s ease}.task:hover .apply-btn{opacity:1}.hover{-webkit-transition:background .3s ease;transition:background .3s ease;cursor:pointer}.hover:hover{background:rgba(var(--text-color),.06)}#admin_panel{grid-template-columns:16rem 1fr;grid-template-rows:auto 1fr;grid-template-areas:"admin-header admin-header" ". ."}#admin_panel__header{grid-area:admin-header}#edit_data_fig{width:16rem;-ms-grid-column-align:center;justify-self:center}#interns,#projects{display:flex;flex-direction:column;max-height:calc(100vh - 16rem);overflow-y:auto}.task-list-item .task-option{opacity:0}.task-list-item:hover .task-option{opacity:1}#project_explorer{display:-ms-grid;display:grid;align-items:flex-start;-ms-grid-columns:1fr 3fr;grid-template-columns:1fr 3fr;grid-template-areas:"header header" "left right"}#project_explorer .header{border-radius:.4rem .4rem 0 0;-ms-grid-column-span:2;grid-area:header}#project_explorer #left{position:-webkit-sticky;position:sticky;top:4.8rem;grid-area:left;-ms-flex-item-align:start;align-self:flex-start;border-right:1px solid rgba(var(--text-color),.06)}#project_explorer #left h4{margin-top:0;margin-bottom:.5rem;color:#29B6F6;font-size:.9rem}#project_explorer #right{grid-area:right}}#update_of_project,.task__description,.task__project-title{color:rgba(var(--text-color),.8)}#update_of_task{font-size:1.3rem;margin:.4rem 0 1.8rem}ul{padding:0;list-style:none}#assigned_task_list{display:grid;align-content:flex-start;gap:1.5rem}.task-card{display:grid;padding:1rem}.task__header{display:grid;gap:0 .5rem;align-items:flex-start;grid-template-columns:1fr auto;grid-template-areas:". send-button" ". send-button"}.task__project-title{font-size:.9rem;font-weight:500;border-radius:.3rem;padding:.3rem .5rem;justify-self:flex-start;margin-bottom:.5rem!important}.task__title{font-size:1.5rem;margin-bottom:1rem!important}.task__description{white-space:pre-line}.send-update-button{grid-area:send-button;border:1px solid;color:var(--accent-color)}.send-update-button .icon{height:1.2rem;width:1.2rem;fill:var(--accent-color)}@media only screen and (min-width:1280px){#project_explorer,#show_all,.page{margin:1rem 8vw}}@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)}.send-update-button{opacity:0;transition:opacity .3s}.task-card:hover .send-update-button{opacity:1}}@media (any-hover:none){.apply-btn,.task-option{opacity:1}} \ No newline at end of file +a:where([class]),button{color:inherit}#textCopied,.hide,.ripple{pointer-events:none}a,a:where([class]){text-decoration:none}*{padding:0;margin:0;box-sizing:border-box;font-family:Roboto,sans-serif}:root{font-size:clamp(1rem,1.2vmax,3rem)}body,html{height:100%;scroll-behavior:smooth}body{color:rgba(var(--text-color),1);background:rgba(var(--background-color),1)}body,body *{--accent-color:#5D54A4;--text-color:17,17,17;--background-color:246,246,246;--foreground-color:white;--danger-color:red}body[data-theme=dark],body[data-theme=dark] *{--accent-color:#9D65C9;--text-color:240,240,240;--text-color-light:170,170,170;--background-color:10,10,10;--foreground-color:rgb(20, 20, 20);--danger-color:rgb(255, 106, 106)}p{max-width:65ch;line-height:1.7;color:rgba(var(--text-color),.8)}p:not(:last-of-type){margin-bottom:1.5rem}img{object-fit:cover}a:where([class]):focus-visible{box-shadow:0 0 0 .1rem rgba(var(--text-color),1) inset}button{position:relative;display:inline-flex;border:none;background-color:transparent;overflow:hidden}.color-0-8,.nav-list__item{color:rgba(var(--text-color),.8)}a:any-link:focus-visible{outline:solid rgba(var(--text-color),1)}sm-button{--border-radius:0.3rem}sm-button[variant=primary] .icon{fill:rgba(var(--background-color),1)}#edit_data_fig,sm-button[disabled] .icon{fill:rgba(var(--text-color),.6)}.hide{opacity:0}.hide-completely{display:none!important}.overflow-ellipsis{width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.breakable{overflow-wrap:break-word;word-wrap:break-word;-ms-word-break:break-all;word-break:break-word;-ms-hyphens:auto;-moz-hyphens:auto;-webkit-hyphens:auto;hyphens:auto}.full-bleed{grid-column:1/4}.h1{font-size:2.5rem}.h2{font-size:2rem}.h3{font-size:1.4rem}.h4{font-size:1rem}.h5{font-size:.8rem}.uppercase{text-transform:uppercase}#intern_info h3,#status_map_container #status_map h2,.assigned-interns .assigned-intern,.capitalise,.capitalize,.project-card,.update__topic{text-transform:capitalize}.flex{display:flex}.grid{display:grid}.grid-3{grid-template-columns:1fr auto auto}.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}#loading_page,.center,.text-center{text-align:center}.align-start{align-items:flex-start}.align-center{align-items: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%}.weight-400{font-weight:400}.weight-500{font-weight:500}.ripple{position:absolute;border-radius:50%;transform:scale(0);background:rgba(var(--text-color),.16)}#loading_page,#sign_in_page{top:0;left:0;right:0;background-color:var(--foreground-color);bottom:0;place-content:center}.interact{position:relative;overflow:hidden;cursor:pointer;-webkit-tap-highlight-color:transparent}.observe-empty-state:empty{display:none}.observe-empty-state:not(:empty)~.empty-state{display:none}.icon{width:1.5rem;height:1.5rem;fill:rgba(var(--text-color),.9)}.button__icon{height:1.2rem;width:1.2rem}.button__icon--left{margin-right:.5rem}.button__icon--right{margin-left:.5rem}#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}.popup__header{display:grid;gap:.5rem;width:100%;padding:0 1.5rem 0 .5rem;align-items:center;grid-template-columns:auto 1fr auto}.popup__header__close{padding:.5rem;cursor:pointer}#main_page{height:100%;grid-template-rows:auto 1fr auto;grid-template-areas:"main-header" "sub-pages" "main-nav"}#main_header{grid-area:main-header;display:flex;gap:1rem;align-items:center;position:sticky;padding:.5rem 1.5rem;background:rgba(var(--background-color),1);z-index:1}#main_nav{grid-area:main-nav;position:relative;display:flex;align-items:center}.nav-list__item{display:flex;flex-direction:column;align-items:center;width:100%;font-size:.8rem;font-weight:500;cursor:pointer}.active,.nav-list__item--active,a{color:var(--accent-color)}.nav-list__item--active .icon{fill:var(--accent-color)}.nav-list__item .icon{margin-bottom:.3rem}#sub_page_container{grid-area:sub-pages;height:100%;overflow-y:auto}.container-card{position:relative;background:var(--foreground-color);border-radius:.4rem}.solid-background{transition:background-color 2s;background:var(--foreground-color)}.medium-top-bottom-margin{margin:.5rem 0}#sign_in_page{display:grid;position:fixed;z-index:5}#sign_in_form{width:22rem}.task{display:grid;grid-template-columns:auto 1fr;margin:0 1rem}.task:last-of-type .left .line{transform:scaleY(0)}.task .left{display:flex;position:relative;justify-content:center;padding-top:.5rem}.task .left .circle{display:inline-flex;position:relative;align-self:flex-start;height:1rem;width:1rem;border-radius:50%;background:var(--foreground-color);border:2px solid;z-index:1}.task .left .line{position:absolute;left:50%;height:100%;width:2px;transform:translateX(-50%) scaleY(1);background-color:rgba(var(--text-color),.4)}.task .right{margin-left:1rem;display:flex;flex-direction:column;width:100%}.task .right .apply-cont{width:100%;display:flex;flex-direction:row}.task .right .apply-cont h4{-webkit-box-flex:1;-ms-flex:1;flex:1}.task h4{margin-top:.4rem;margin-bottom:1rem}.task p{white-space:pre-line;padding-bottom:2rem}.task .assigned-interns .assigned-intern{padding:.4rem}.completed-task .left .circle{border:2px solid #00C853!important;background:#00C853!important}.completed-task .left .line{background-color:#00C853!important}.page{gap:1rem;display:grid;position:relative;margin:1rem;animation:fadein .4s ease}.fade-in{-webkit-animation:fadein .4s ease;animation:fadein .4s ease}@-webkit-keyframes fadein{0%{opacity:0}100%{opacity:1}}@keyframes fadein{0%{opacity:0}100%{opacity:1}}.title{font-weight:500}.padding{padding:1rem}#dashboard{padding-bottom:5rem;grid-template-columns:auto}.show{display:block}.hide-on-mobile,.hide-page-on-mobile{display:none}.hide-on-desktop{display:initial}.no-transformations{-webkit-transform:none!important;transform:none!important}.no-bottom-margin{margin-bottom:0}.top-margin{margin-top:.3rem}.spacer{-webkit-box-flex:1;-ms-flex:1;flex:1}.logo{display:flex;align-items:center;font-size:1.2rem;width:100%}.logo .cls-2,.logo .cls-3{fill:rgba(var(--text-color),1);font-size:146.9px;font-family:ArialMT,Arial}.logo svg{height:2.5rem}.logo h4{margin:0}.active{opacity:1!important}.active svg{fill:var(--accent-color)}.svg-margin-right svg{margin-right:.5rem}.project-card{padding:1rem;font-weight:500;color:rgba(var(--text-color),.8)}.intern-card{user-select:none}.intern-card span:first-of-type{display:flex;justify-content:center;align-items:center;flex-shrink:0;padding:.8rem;border-radius:50%;background:#673AB7;margin-right:1rem;color:#fff;font-weight:500;font-size:1.2rem;line-height:0}.intern-card span:first-of-type::after{content:"";display:block;padding-bottom:100%}.card,.request-card{margin-bottom:.5rem;padding:1rem;position:relative}.intern-card span:nth-of-type(2){flex:1;text-transform:capitalize;flex-shrink:0}.intern-card span:nth-of-type(3){display:inline-flex;align-items:center;align-content:center;font-weight:500;font-size:1.2rem;color:var(--light-text)}.intern-card span:nth-of-type(3) svg{fill:#FF5722!important;height:1rem!important;width:1rem!important;margin-right:.2rem}.card{display:flex;flex-direction:row;align-items:center}.request-card{display:flex;align-items:left;flex-wrap:wrap;border-bottom:1px solid rgba(var(--text-color),.1)}.request-card p{margin-top:0;width:100%;font-size:1rem}.request-card b{font-weight:500}.request-card button{padding:.2rem .6rem .2rem 0}.request-card button:first-of-type{margin-left:auto}.request-card:last-of-type{border-bottom:none}.dropdown{position:relative}.dropdown-content{overflow:hidden;position:absolute;z-index:2;margin:1rem;right:2rem;min-width:24rem;background:var(--foreground-color);box-shadow:0 1rem 1.5rem -.5rem rgba(0,0,0,.3);border-radius:.5rem}#intern_updates .container-header{padding-right:0;border-bottom:1px solid rgba(var(--text-color),.1)}#intern_updates .container-header button{padding:1rem 0;border-bottom:.2rem solid transparent;border-radius:0;opacity:.7}#intern_updates .container-header button:first-of-type{margin-right:1rem}#intern_updates .container-header button:last-of-type{margin-right:1rem}#intern_updates .container-header .active{color:rgba(var(--text-color),1);border-bottom:.2rem solid var(--accent-color)}#requests_container,#update_container{display:flex;max-height:80vh;overflow-y:auto;flex-direction:column;overscroll-behavior:contain}#updates{transition:opacity .3s ease}.update{display:grid;gap:.5rem;padding:1rem}.update__topic{font-weight:500;font-size:1rem;max-width:60ch}.update__sender{color:var(--accent-color);font-size:.9rem;font-weight:500}.update__time{font-size:.85rem;color:rgba(var(--text-color),.8)}.active-branch,.commit,.container-header span{color:var(--accent-color)}.update__message{white-space:pre-line}.container-header{display:flex;align-items:center;flex-direction:row;width:100%;padding:0 1rem}.container-header h3{flex:1;font-weight:500}.container-header span{border-radius:.2rem;margin-right:.2rem;padding:.5rem 1rem;font-weight:500}.back-arrow{fill:none;stroke:rgba(var(--text-color),.8);stroke-width:6;overflow:visible;width:2rem;height:2rem;padding:.5rem .5rem .5rem 0;cursor:pointer}.close-svg,.header svg,.tick-mark{stroke:rgba(var(--text-color),.8);overflow:visible}.close-svg,.tick-mark{fill:none;stroke-width:6;height:2rem;width:2rem}.close-svg{padding:.6rem}#textCopied{padding:1rem;border-radius:2rem;background:var(--sec-color);position:fixed;bottom:0;margin:2rem 0;left:50%;transform:translateX(-50%);transition:.3s opacity ease;z-index:10}#intern_info{flex-direction:column}#intern_info div{display:flex;flex-direction:row;align-items:center;width:100%;margin-bottom:1rem}#intern_info div span{flex:1;word-break:break-all;font-size:.9rem}#intern_info div svg{fill:rgba(var(--text-color),1);height:2.5rem;padding:.6rem;overflow:visible}#intern_info .gold-fill{fill:#FF5722}#intern_info #update_intern_score h4{margin:0;font-size:2rem}#intern_info #update_intern_score button{border:1px solid}#intern_info #update_intern_score button svg{stroke-width:10;fill:none;stroke:var(--accent-color)}#intern_info #update_intern_score rect{stroke:transparent}#intern_info h4,#intern_info h5{margin-top:.5rem}#project_info{flex-direction:column}.branch-btn{padding:.5rem;border-radius:.2rem;margin:.5rem .5rem .5rem 0;user-select:none}.active-branch{opacity:1;background:rgba(var(--text-color),.04)}.opac{opacity:1!important}.task-list-item{display:grid;grid-template-columns:auto auto 1fr auto;grid-template-areas:"status . title options" "status . interns interns" "status . description description";padding:1rem;gap:.5rem;align-items:center;background:rgba(var(--text-color),.02)}#task_context,.header{background:var(--foreground-color)}.task-list-item sm-checkbox{grid-area:status;align-self:flex-start;padding:.5rem .5rem .5rem 0}.task-list-item:first-of-type{margin-top:1rem;border-radius:.2rem .2rem 0 0}.task-list-item:last-of-type{border-radius:0 0 .2rem .2rem;border-bottom:none;margin-bottom:1rem}.task-list-item h4{font-weight:500;margin:0}.task-list-item .title{grid-area:title}.task-list-item .assigned-interns{grid-area:interns}.task-list-item .task-option{grid-area:options;cursor:pointer;transition:opacity .3s ease;padding:.5rem}.task-list-item p{grid-area:description;margin:0;text-overflow:ellipsis;overflow:hidden;max-width:100%}.assigned-interns{display:flex;flex-wrap:wrap}.assigned-interns .assigned-intern{user-select:none;display:flex;font-size:.8rem;margin:.2rem .5rem .2rem 0;padding:.2rem 0 .2rem .4rem;border-radius:.2rem;border:1px solid;align-items:center;white-space:nowrap}.assigned-interns .assigned-intern button{padding:.2rem}.assigned-interns .assigned-intern button svg{padding:.2rem;height:1rem;width:1rem}.commit{border:1px solid var(--accent-color);padding:.6rem}#task_context{transition:.3s opacity ease;top:0;right:0;margin:0 2rem;list-style:none;padding:.5rem 0;width:max-content;border-radius:.3rem;position:absolute;box-shadow:0 .5rem 1rem -.3rem rgba(0,0,0,.3)}#task_context li{padding:.8rem 1.5rem;display:flex;align-items:center;cursor:pointer}#task_context li .icon{margin-right:.5rem}#branch_container{display:flex;flex-flow:row wrap;margin:1rem 0}#interns_list{flex-direction:column;min-width:20rem}#interns_list #interns_list_container{min-height:50vh;max-height:50vh;overflow-y:auto}#best_interns_container,#project_list_container{margin-bottom:1rem}#best_interns_container .container-header,#project_list_container .container-header{padding-right:0}#best_interns_container .container-header .icon,#project_list_container .container-header .icon{margin-right:.5rem}#edit_data_fig{width:60vw;margin:2rem 0}.header{position:-webkit-sticky;position:sticky;top:0;display:flex;flex-flow:row;border-bottom:1px solid rgba(var(--text-color),.1);align-items:center;z-index:2}.header svg{fill:none;stroke-width:6;height:2rem;width:2rem;cursor:pointer;padding:.4rem;margin-left:1rem}.header h3{padding:0 .5rem;display:inline-flexbox}.appear-on-scroll-up{position:fixed!important;top:0;width:100%;height:4rem!important}#loading_page{display:grid;position:fixed;z-index:5;justify-items:center}.loading-message{font-size:1.3rem;margin:1.5rem 0 .5rem}#loading_page__footer{position:absolute;bottom:0;width:100%;padding:1.5rem}#loading_page__footer .icon{height:4rem;width:4rem}#status_map_container{position:relative;overflow:hidden;background:#B9F6CA}#status_map_container .branch-btn{color:rgba(0,0,0,.8)}#status_map_container p{color:rgba(0,0,0,.9)}#status_map_container .active-branch{color:#fff;background:rgba(0,200,83,.6)}#status_map_container #status_map{position:relative;z-index:1;padding:1rem;color:#000}#status_map_container #status_map h2{margin:.4rem 0}#status_map_container #status_map .circle{background:#B9F6CA;border:2px solid rgba(0,0,0,.4)}#status_map_container #status_map .line{background:rgba(0,0,0,.4)}#status_map_container #status_map .assigned-intern{border:1px solid rgba(0,0,0,.4)}#status_map_container #status_map .apply-btn{color:#1B5E20;background:rgba(0,200,83,.2)}.apply-btn{padding:.3rem .6rem}#project_editing_panel,.watching button{padding:1rem}.watching{position:relative;padding-left:1rem;padding-top:1rem;display:flex;flex-direction:row;align-items:center;color:#000;z-index:1}.watching h4{flex:1;font-weight:500}.watching button svg{fill:none!important;fill:none;stroke-width:6;overflow:visible;stroke:#000}#right{padding:0 1rem}#right div:first-of-type h2{flex:1;margin:.4rem 0}#right div:first-of-type button{border:1px solid}.center{position:relative;display:grid;place-content:center;height:100%}#project_explorer,#show_all{margin:0}#admin_page{padding:0 1.5rem;display:grid;gap:1.5rem}#admin_page__header{display:grid;gap:0 1rem;padding:.5rem 0;grid-template-columns:1fr auto;align-items:center}@media only screen and (min-width:640px){.hide-on-desktop{display:none!important}.hide-on-mobile{display:flex}.hide-page-on-mobile{display:grid}sm-popup{--width:24rem}.popup__header{padding:1.5rem 1.5rem 0 .5rem}#main_nav{flex-direction:column;align-items:flex-start}.nav-list__item{flex-direction:row;align-items:center;padding:.5rem .8rem;font-size:1rem}.nav-list__item--active{background-color:rgba(var(--text-color),.06)}.nav-list__item .icon{margin-right:.5rem;margin-bottom:0}.project-card--active{background-color:rgba(var(--text-color),.1)}#settings_page{padding:1rem 2rem}#sign_in{width:24rem;height:auto;border-radius:.4rem}#dashboard{grid-template-columns:3fr 1fr}#dashboard #status_map_container{align-self:flex-start}#dashboard #status_map_container .watching{padding-left:2rem}#dashboard #status_map_container #status_map{padding:1rem 2rem}.task .apply-btn{opacity:0;-webkit-transition:opacity .3s ease;transition:opacity .3s ease}.task:hover .apply-btn{opacity:1}#admin_page{grid-template-columns:16rem 1fr;grid-template-rows:auto 1fr;grid-template-areas:"admin-header admin-header" ". ."}#admin_page__header{grid-area:admin-header}#edit_data_fig{width:16rem;justify-self:center}#interns,#projects{display:flex;flex-direction:column;max-height:calc(100vh - 16rem);overflow-y:auto}#project_explorer{display:grid;align-items:flex-start;grid-template-columns:1fr 3fr;grid-template-areas:"header header" "left right"}#project_explorer .header{border-radius:.4rem .4rem 0 0;grid-area:header}#project_explorer #left{position:sticky;top:4.8rem;grid-area:left;align-self:flex-start;border-right:1px solid rgba(var(--text-color),.06)}#project_explorer #left h4{margin-top:0;margin-bottom:.5rem;color:#29B6F6;font-size:.9rem}#project_explorer #right{grid-area:right}#main_page{grid-template-columns:10rem minmax(0,1fr);grid-template-areas:"main-header main-header" "main-nav sub-pages"}}#update_of_project,.task__description,.task__project-title{color:rgba(var(--text-color),.8)}#update_of_task{font-size:1.3rem;margin:.4rem 0 1.8rem}ul{padding:0;list-style:none}#assigned_task_list{display:grid;align-content:flex-start;gap:1.5rem}.task-card{display:grid;padding:1rem}.task__header{display:grid;gap:0 .5rem;align-items:flex-start;grid-template-columns:1fr auto;grid-template-areas:". send-button" ". send-button"}.task__project-title{font-size:.9rem;font-weight:500;border-radius:.3rem;padding:.3rem .5rem;justify-self:flex-start;margin-bottom:.5rem!important;background-color:rgba(var(--text-color),.06)}.task__title{font-size:1.3rem;margin-bottom:1rem!important}.task__description{white-space:pre-line}.send-update-button{grid-area:send-button;--padding:0.6rem 0.8rem;color:var(--accent-color)}.send-update-button .icon{height:1.2rem;width:1.2rem;fill:var(--accent-color)}@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)}.interact:hover{background-color:rgba(var(--text-color),.06)}.send-update-button{opacity:0;transition:opacity .3s}.task-card:hover .send-update-button{opacity:1}.task-option{opacity:0}.task-list-item:hover .task-option,.task-option:focus-within{opacity:1}}@media (any-hover:none){.apply-btn,.task-option{opacity:1}} \ No newline at end of file diff --git a/css/main.scss b/css/main.scss index aab1cf3..bf1c7f6 100644 --- a/css/main.scss +++ b/css/main.scss @@ -1,161 +1,133 @@ -*{ +* { padding: 0; margin: 0; box-sizing: border-box; font-family: 'Roboto', sans-serif; } -:root{ + +:root { font-size: clamp(1rem, 1.2vmax, 3rem); } -html, body{ + +html, +body { height: 100%; scroll-behavior: smooth; } + body { - --accent-color: #1976D2; - --light-shade: rgba(var(--text-color), 0.06); - --text-color: 17, 17, 17; - --text-color-light: 100, 100, 100; - --foreground-color: 255, 255, 255; - --background-color: #F6f6f6; - --error-color: red; + + &, + * { + --accent-color: #5D54A4; + --text-color: 17, 17, 17; + --background-color: 246, 246, 246; + --foreground-color: white; + --danger-color: red; + } + color: rgba(var(--text-color), 1); - background: var(--background-color); - display: flex; - flex-direction: column; -} -body[data-theme='dark']{ - --accent-color: #42A5F5; - --text-color: 240, 240, 240; - --text-color-light: 170, 170, 170; - --foreground-color: 20, 20, 20; - --background-color: #0a0a0a; - --error-color: rgb(255, 106, 106); -} -/* h1,h2,h3,h4,h5,h6{ - font-family: 'Montserrat', sans-serif; -} */ -.full-bleed{ - grid-column: 1/4; -} -.h1{ - font-size: 2.5rem; -} -.h2{ - font-size: 2rem; -} -.h3{ - font-size: 1.4rem; -} -.h4{ - font-size: 1rem; -} -.h5{ - font-size: 0.8rem; + background: rgba(var(--background-color), 1); } -.uppercase{ - text-transform: uppercase; -} -.capitalize{ - text-transform: capitalize; +body[data-theme='dark'] { + + &, + * { + --accent-color: #9D65C9; + --text-color: 240, 240, 240; + --text-color-light: 170, 170, 170; + --background-color: 10, 10, 10; + --foreground-color: rgb(20, 20, 20); + --danger-color: rgb(255, 106, 106); + } } p { - font-size: 0.8; - max-width: 60ch; + max-width: 65ch; line-height: 1.7; color: rgba(var(--text-color), 0.8); - &:not(:last-of-type){ - margin-bottom: 1rem; + + &:not(:last-of-type) { + margin-bottom: 1.5rem; } } -img{ + +img { object-fit: cover; } -a{ +a:where([class]) { color: inherit; text-decoration: none; - &:focus-visible{ + + &:focus-visible { box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset; } } -button{ + +button { position: relative; display: inline-flex; - overflow: hidden; - align-items: center; - background: none; - cursor: pointer; - outline: none; - color: inherit; - font-size: 0.9rem; - font-weight: 500; - border-radius: 0.2rem; - padding: 0.5rem 0.6rem; - -webkit-tap-highlight-color: transparent; border: none; + background-color: transparent; + overflow: hidden; + color: inherit; } -button:focus-visible{ + +a:any-link:focus-visible { outline: rgba(var(--text-color), 1) 0.1rem solid; } -a.button:any-link{ - position: relative; - display: inline-flex; - align-items: center; - background: none; - cursor: pointer; - outline: none; - font-weight: 500; - font-size: 0.8rem; - border-radius: 0.3rem; - padding: 0.5rem 0.6rem; - align-self: flex-start; - text-decoration: none; - color: rgba(var(--text-color), 0.7); - -webkit-tap-highlight-color: transparent; - background-color: rgba(var(--text-color), 0.06); - .icon{ - margin-right: 0.3rem; - height: 1.2rem; + +sm-button { + --border-radius: 0.3rem; + + &[variant="primary"] { + .icon { + fill: rgba(var(--background-color), 1); + } + } + + &[disabled] { + .icon { + fill: rgba(var(--text-color), 0.6); + } } } -a:any-link:focus-visible{ - outline: rgba(var(--text-color), 1) 0.1rem solid; -} -.button{ - background-color: rgba(var(--text-color), 0.06); -} -sm-button{ - --border-radius: 0.3rem; -} -ul{ + +ul { list-style: none; } -.flex{ + +.flex { display: flex; } -.grid{ + +.grid { display: grid; } -.hide{ + +.hide { opacity: 0; pointer-events: none; } -.hide-completely{ + +.hide-completely { display: none !important; } -.no-transformations{ + +.no-transformations { transform: none !important; } -.overflow-ellipsis{ + +.overflow-ellipsis { width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } -.breakable{ + +.breakable { overflow-wrap: break-word; word-wrap: break-word; -ms-word-break: break-all; @@ -165,130 +137,202 @@ ul{ -webkit-hyphens: auto; hyphens: auto; } -.flex{ + +.full-bleed { + grid-column: 1/4; +} + +.h1 { + font-size: 2.5rem; +} + +.h2 { + font-size: 2rem; +} + +.h3 { + font-size: 1.4rem; +} + +.h4 { + font-size: 1rem; +} + +.h5 { + font-size: 0.8rem; +} + +.uppercase { + text-transform: uppercase; +} + +.capitalize { + text-transform: capitalize; +} + +.flex { display: flex; } -.grid{ + +.grid { display: grid; } -.flow-column{ + +.grid-3 { + grid-template-columns: 1fr auto auto; +} + +.flow-column { grid-auto-flow: column; } -.gap-0-5{ + +.gap-0-5 { gap: 0.5rem; } -.gap-1{ + +.gap-1 { gap: 1rem; } -.gap-1-5{ + +.gap-1-5 { gap: 1.5rem; } -.gap-2{ + +.gap-2 { gap: 2rem; } -.gap-3{ + +.gap-3 { gap: 3rem; } -.text-align-right{ + +.text-align-right { text-align: right; } -.align-start{ + +.align-start { align-items: flex-start; } -.align-center{ + +.align-center { align-items: center; } -.text-center{ + +.text-center { text-align: center; } -.justify-start{ + +.justify-start { justify-content: start; } -.justify-center{ + +.justify-center { justify-content: center; } -.justify-right{ + +.justify-right { margin-left: auto; } -.align-self-center{ + +.align-self-center { align-self: center; } -.justify-self-center{ + +.justify-self-center { justify-self: center; } -.justify-self-start{ + +.justify-self-start { justify-self: start; } -.direction-column{ + +.justify-self-end { + justify-self: end; +} + +.direction-column { flex-direction: column; } -.space-between{ + +.space-between { justify-content: space-between; } -.w-100{ + +.w-100 { width: 100%; } -.ripple{ + +.color-0-8 { + color: rgba(var(--text-color), 0.8); +} + +.weight-400 { + font-weight: 400; +} + +.weight-500 { + font-weight: 500; +} + +.ripple { position: absolute; border-radius: 50%; transform: scale(0); background: rgba(var(--text-color), 0.16); pointer-events: none; } -.interact{ + +.interact { position: relative; overflow: hidden; cursor: pointer; -webkit-tap-highlight-color: transparent; } -.observe-empty-state:empty{ - display: none; -} -.observe-empty-state:not(:empty) ~ .empty-state{ + +.observe-empty-state:empty { display: none; } +.observe-empty-state:not(:empty)~.empty-state { + display: none; +} -.icon{ +.icon { width: 1.5rem; height: 1.5rem; fill: rgba(var(--text-color), 0.9); } -.button__icon{ + +.button__icon { height: 1.2rem; width: 1.2rem; - &--left{ + + &--left { margin-right: 0.5rem; } - &--right{ + + &--right { margin-left: 0.5rem; } } -.popup__header{ - display: grid; - gap: 0.5rem; - width: 100%; - padding: 0 1.5rem 0 0.5rem; - align-items: center; - grid-template-columns: auto 1fr; -} -.popup__header__close{ - padding: 0.5rem; - cursor: pointer; -} + #confirmation_popup, #prompt_popup { flex-direction: column; + h4 { font-weight: 500; margin-bottom: 0.5rem; } - sm-button{ + + sm-button { margin: 0; } + .flex { padding: 0; margin-top: 1rem; + sm-button:first-of-type { margin-right: 0.6rem; margin-left: auto; @@ -296,127 +340,85 @@ ul{ } } -input[type="checkbox"] { - display: none; -} - -.checkbox svg { - fill: none; - stroke: rgba(var(--text-color), 0.8); - stroke-width: 6; - overflow: visible; - height: 1.6rem; - width: 1.6rem; -} - -.checkbox svg .check { - stroke-dashoffset: 70; - stroke-dasharray: 70; - -webkit-transition: stroke-dashoffset 0.3s ease; - transition: stroke-dashoffset 0.3s ease; -} - -.checkbox input:checked+svg { - stroke: #00C853; -} - -.checkbox input:checked+svg .check { - stroke-dashoffset: 0; -} -#settings_page { - padding: 1rem; -} - -#settings_page section { - width: 100%; - border-bottom: 1px solid rgba(var(--text-color), 0.1); - display: -ms-grid; +.popup__header { display: grid; - padding-bottom: 1rem; -} - -#settings_page section:last-of-type { - border: none; -} - -#settings_page h3, -#settings_page h4 { - display: flexbox; + gap: 0.5rem; width: 100%; - -ms-flex-item-align: center; - align-self: center; + padding: 0 1.5rem 0 0.5rem; + align-items: center; + grid-template-columns: auto 1fr auto; } -#settings_page h5 { - margin: 0; - -ms-flex-item-align: center; - -ms-grid-row-align: center; - align-self: center; - font-weight: normal; - opacity: 0.9; +.popup__header__close { + padding: 0.5rem; + cursor: pointer; } -#settings_page button { - background: transparent; - border: 1px solid var(--accent-color); - color: var(--accent-color); - margin: 1rem 0; - width: -webkit-min-content; - width: -moz-min-content; - width: min-content; - white-space: nowrap; - .icon{ - fill: var(--accent-color); +#main_page { + height: 100%; + grid-template-rows: auto 1fr auto; + grid-template-areas: 'main-header''sub-pages''main-nav'; +} + +#main_header { + grid-area: main-header; + display: flex; + gap: 1rem; + align-items: center; + position: sticky; + padding: 0.5rem 1.5rem; + background: rgba(var(--background-color), 1); + z-index: 1; +} + +#main_nav { + grid-area: main-nav; + position: relative; + display: flex; + align-items: center; +} + +.nav-list__item { + display: flex; + flex-direction: column; + align-items: center; + + width: 100%; + + font-size: 0.8rem; + font-weight: 500; + color: rgba(var(--text-color), 0.8); + + cursor: pointer; + + &--active { + color: var(--accent-color); + + .icon { + fill: var(--accent-color); + } + } + + .icon { + margin-bottom: 0.3rem; } } -#settings_page > div { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: 100%; - padding: 1rem 0; - -ms-flex-line-pack: center; - align-content: center; -} -#settings_page .row { - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1; -} - -#settings_page .row span { - font-size: 0.8rem; -} - -#settings_page .border-card { - color: inherit; - text-decoration: none; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - padding: 0.5rem 0; - width: auto; -} - -#settings_page .border-card svg { - fill: var(--accent-color); - display: flexbox; - height: 2rem; - -ms-flex-item-align: center; - align-self: center; - margin: 0.5rem; +#sub_page_container { + grid-area: sub-pages; + height: 100%; + overflow-y: auto; } .container-card { position: relative; - background: rgba(var(--foreground-color), 1); + background: var(--foreground-color); border-radius: 0.4rem; } .solid-background { transition: background-color 2s; - background: rgba(var(--foreground-color), 1); + background: var(--foreground-color); } a { @@ -428,7 +430,7 @@ a { margin: 0.5rem 0; } -#sign_in_page{ +#sign_in_page { display: grid; position: fixed; z-index: 5; @@ -437,45 +439,39 @@ a { left: 0; right: 0; place-content: center; - background-color: rgba(var(--foreground-color), 1); + background-color: var(--foreground-color); +} + +#sign_in_form { + width: 22rem; } .task { - display: -ms-grid; display: grid; - -ms-grid-columns: auto 1fr; grid-template-columns: auto 1fr; margin: 0 1rem; } .task:last-of-type .left .line { - -webkit-transform: scaleY(0); transform: scaleY(0); } .task .left { - display: -webkit-box; - display: -ms-flexbox; display: flex; position: relative; - -webkit-box-pack: center; - -ms-flex-pack: center; justify-content: center; padding-top: 0.5rem; } .task .left .circle { - display: -webkit-inline-box; - display: -ms-inline-flexbox; display: inline-flex; position: relative; - -ms-flex-item-align: start; align-self: flex-start; height: 1rem; width: 1rem; border-radius: 50%; - background: rgba(var(--foreground-color), 1); + background: var(--foreground-color); border: solid 2px rgba(var(--text-color), 0.4); z-index: 1; } @@ -485,31 +481,20 @@ a { left: 50%; height: 100%; width: 2px; - -webkit-transform: translateX(-50%) scaleY(1); transform: translateX(-50%) scaleY(1); background-color: rgba(var(--text-color), 0.4); } .task .right { margin-left: 1rem; - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; flex-direction: column; width: 100%; } .task .right .apply-cont { width: 100%; - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; flex-direction: row; } @@ -585,67 +570,9 @@ a { #dashboard { padding-bottom: 5rem; - -ms-grid-columns: auto; grid-template-columns: auto; } -.input { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - width: 100%; - margin: 1rem 0; - background: rgba(var(--text-color), 0.06); - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - border-radius: 0.2rem; - overflow: hidden; -} - -.input input, -.input textarea { - color: var(--light-text); - padding: 1rem 0.5rem; - width: 100%; - font-size: 1rem; - background: transparent; - margin-left: 0; -} - -.input input:focus, -.input textarea:focus { - outline: none; -} - -.input svg { - height: 1.2rem; - width: 1.2rem; - margin: 0 0.5rem 0 1rem; - fill: none; - stroke: rgba(var(--text-color), 0.8); - stroke-width: 6; - overflow: visible; -} - -.input:focus-within { - background: rgba(0, 0, 0, 0.1); -} - -input, -button, -textarea { - position: relative; - border: none; - font-size: 1rem; - border-radius: 0.2rem; -} - -button[disabled] { - opacity: 0.5 !important; - cursor: default; -} - .show { display: block; } @@ -672,73 +599,16 @@ button[disabled] { margin-top: 0.3rem; } -.chatInput { - overflow: hidden; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 0; -} - -.chatInput textarea { - resize: none; - line-height: 1.6; -} - -.chatInput button { - -webkit-transition: -webkit-transform 0.3s ease; - transition: -webkit-transform 0.3s ease; - transition: transform 0.3s ease; - transition: transform 0.3s ease, -webkit-transform 0.3s ease; - -webkit-transform: scale(0); - transform: scale(0); - -ms-flex-item-align: end; - align-self: flex-end; - padding: 1rem; -} - -.chatInput button svg { - margin: 0; - fill: rgba(var(--text-color), 1); -} - -#top_nav { - position: relative; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - padding: 0.5rem; - z-index: 4; -} - -#top_nav .spacer { +.spacer { -webkit-box-flex: 1; -ms-flex: 1; flex: 1; } -#top_nav .logo { - margin-right: 0.5rem; -} - .logo { - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; font-size: 1.2rem; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; width: 100%; } @@ -771,7 +641,10 @@ button[disabled] { } .project-card { + padding: 1rem; text-transform: capitalize; + font-weight: 500; + color: rgba(var(--text-color), 0.8); } .intern-card { @@ -834,10 +707,7 @@ button[disabled] { display: flex; position: relative; margin-bottom: 0.5rem; - -webkit-box-align: left; - -ms-flex-align: left; align-items: left; - -ms-flex-wrap: wrap; flex-wrap: wrap; padding: 1rem; border-bottom: 1px solid rgba(var(--text-color), 0.1); @@ -876,8 +746,8 @@ button[disabled] { margin: 1rem; right: 2rem; min-width: 24rem; - background: rgba(var(--foreground-color), 1); - box-shadow: 0 0.5rem 1rem -0.5rem rgba(0, 0, 0, 0.24); + background: var(--foreground-color); + box-shadow: 0 1rem 1.5rem -0.5rem rgba(0, 0, 0, 0.3); border-radius: 0.5rem; } @@ -912,6 +782,7 @@ button[disabled] { max-height: 80vh; overflow-y: auto; flex-direction: column; + overscroll-behavior: contain; } #updates { @@ -919,24 +790,30 @@ button[disabled] { } .update { - display: flex; - flex-direction: column; + display: grid; + gap: 0.5rem; padding: 1rem; } -.update__project-name{ - font-size: 1.2rem; + +.update__topic { + font-weight: 500; + font-size: 1rem; max-width: 60ch; - margin: 0.3rem 0 0.5rem 0; - font-weight: bold; text-transform: capitalize; } -.update__sender{ +.update__sender { color: var(--accent-color); font-size: 0.9rem; font-weight: 500; } -.update__message{ + +.update__time { + font-size: 0.85rem; + color: rgba(var(--text-color), 0.8); +} + +.update__message { white-space: pre-line; } @@ -1058,9 +935,6 @@ button[disabled] { } #project_info { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; flex-direction: column; } @@ -1069,9 +943,6 @@ button[disabled] { padding: 0.5rem; border-radius: 0.2rem; margin: 0.5rem 0.5rem 0.5rem 0; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; } @@ -1081,36 +952,26 @@ button[disabled] { background: rgba(var(--text-color), 0.04); } -.active-project { - background: rgba(var(--text-color), 0.06); -} - .opac { opacity: 1 !important; } .task-list-item { - display: -ms-grid; display: grid; - -ms-grid-columns: auto auto 1fr auto; grid-template-columns: auto auto 1fr auto; grid-template-areas: 'status . title options' 'status . interns interns' 'status . description description'; padding: 1rem; gap: 0.5rem; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; background: rgba(var(--text-color), 0.02); } -.task-list-item .checkbox { - -ms-grid-row-span: 3; +.task-list-item sm-checkbox { grid-area: status; + align-self: flex-start; padding: 0.5rem 0.5rem 0.5rem 0; - -ms-flex-item-align: start !important; - align-self: flex-start !important; } .task-list-item:first-of-type { @@ -1134,28 +995,17 @@ button[disabled] { } .task-list-item .assigned-interns { - -ms-grid-column-span: 2; grid-area: interns; } .task-list-item .task-option { grid-area: options; cursor: pointer; - opacity: 1; - -webkit-transition: opacity 0.3s ease; transition: opacity 0.3s ease; -} - -.task-list-item .task-option svg { - width: 2rem; - height: 2rem; padding: 0.5rem; - overflow: visible; - fill: rgba(var(--text-color), 0.8); } .task-list-item p { - -ms-grid-column-span: 2; grid-area: description; margin: 0; text-overflow: ellipsis; @@ -1164,28 +1014,18 @@ button[disabled] { } .assigned-interns { - display: -webkit-box; - display: -ms-flexbox; display: flex; - -ms-flex-wrap: wrap; flex-wrap: wrap; } .assigned-interns .assigned-intern { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; - display: -webkit-box; - display: -ms-flexbox; display: flex; font-size: 0.8rem; margin: 0.2rem 0.5rem 0.2rem 0; padding: 0.2rem 0 0.2rem 0.4rem; border-radius: 0.2rem; border: 1px solid rgba(var(--text-color), 0.24); - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; white-space: nowrap; text-transform: capitalize; @@ -1208,156 +1048,39 @@ button[disabled] { } #task_context { - -webkit-transition: 0.3s opacity ease; transition: 0.3s opacity ease; top: 0; right: 0; margin: 0 2rem; list-style: none; padding: 0.5rem 0; - width: -webkit-max-content; - width: -moz-max-content; width: max-content; - border-radius: 0.2rem; + border-radius: 0.3rem; position: absolute; - background: rgba(var(--foreground-color), 1); - -webkit-box-shadow: 0.2rem 0.4rem 1rem rgba(0, 0, 0, 0.24), -0.1rem -0.2rem 0.4rem rgba(0, 0, 0, 0.16); - box-shadow: 0.2rem 0.4rem 1rem rgba(0, 0, 0, 0.24), -0.1rem -0.2rem 0.4rem rgba(0, 0, 0, 0.16); + background: var(--foreground-color); + box-shadow: 0 0.5rem 1rem -0.3rem rgba(0, 0, 0, 0.3); + + li { + padding: 0.8rem 1.5rem; + display: flex; + align-items: center; + cursor: pointer; + + .icon { + margin-right: 0.5rem; + } + } } -#task_context li { - padding: 0.8rem 1rem; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -#task_context li svg { - margin-right: 1rem; - width: 1.2rem; - height: 1.2rem; - fill: none; - stroke: rgba(var(--text-color), 0.8); - stroke-width: 6; - overflow: visible; -} - -.temp-task { - padding: 1rem; - background: rgba(var(--text-color), 0.02); - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -ms-flex-wrap: wrap; - flex-wrap: wrap; -} - -.temp-task .input { - margin: 0.4rem 0; -} +.temp-task {} #branch_container { - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row wrap; flex-flow: row wrap; margin: 1rem 0; } -#notification { - display: -webkit-box; - display: -ms-flexbox; - display: flex; -} - -#bottom_nav { - position: fixed; - bottom: 0; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - width: 100vw; - background: rgba(var(--foreground-color), 1); - z-index: 4; - border-top: 1px solid rgba(var(--text-color), 0.1); -} - -#bottom_nav button { - padding: 0.2rem; - width: 100%; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - font-size: 0.7rem; - font-weight: normal; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; -} - -#bottom_nav button svg { - margin: 0.4rem; -} - -#show_message { - -webkit-transform: translate(0, 0.4rem); - transform: translate(0, 0.4rem); - -webkit-transition: opacity 0.3s ease, -webkit-transform 0.3s ease; - transition: opacity 0.3s ease, -webkit-transform 0.3s ease; - transition: transform 0.3s ease, opacity 0.3s ease; - transition: transform 0.3s ease, opacity 0.3s ease, -webkit-transform 0.3s ease; - -webkit-box-shadow: 0.2rem 0.4rem 0.8rem rgba(0, 0, 0, 0.16); - box-shadow: 0.2rem 0.4rem 0.8rem rgba(0, 0, 0, 0.16); - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - color: white; - position: fixed; - bottom: 0; - right: 0; - width: 100%; - z-index: 11; -} - -#show_message span { - font-weight: 500; - padding: 1rem; - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1; -} - -#show_message button { - padding: 0.5rem 1rem; - margin: 0; -} - -#show_message button svg { - stroke: white; -} - #interns_list { - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; flex-direction: column; min-width: 20rem; } @@ -1377,8 +1100,9 @@ button[disabled] { #project_list_container .container-header { padding-right: 0; } + #best_interns_container .container-header .icon, -#project_list_container .container-header .icon{ +#project_list_container .container-header .icon { margin-right: 0.5rem; } @@ -1392,17 +1116,10 @@ button[disabled] { position: -webkit-sticky; position: sticky; top: 0; - background: rgba(var(--foreground-color), 1); - display: -webkit-box; - display: -ms-flexbox; + background: var(--foreground-color); display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-flow: row; flex-flow: row; border-bottom: 1px solid rgba(var(--text-color), 0.1); - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; z-index: 2; } @@ -1431,7 +1148,7 @@ button[disabled] { height: 4rem !important; } -#loading_page{ +#loading_page { display: grid; position: fixed; top: 0; @@ -1442,49 +1159,26 @@ button[disabled] { text-align: center; place-content: center; justify-items: center; - background-color: rgba(var(--foreground-color), 1); + background-color: var(--foreground-color); } -.loading-message{ + +.loading-message { font-size: 1.3rem; margin: 1.5rem 0 0.5rem 0; } -#loading_page__footer{ + +#loading_page__footer { position: absolute; bottom: 0; width: 100%; padding: 1.5rem; - .icon{ + + .icon { height: 4rem; width: 4rem; } } -.loader { - height: 2rem; - width: 2rem; - stroke-width: 8; - overflow: visible; - stroke: var(--accent-color); - fill: none; - stroke-dashoffset: 180; - stroke-dasharray: 180; - animation: load 3.6s linear infinite, spin 1s linear infinite; -} -@keyframes load { - 50% { - stroke-dashoffset: 0; - } - 100%{ - stroke-dashoffset: -180; - } -} - -@keyframes spin { - 100% { - transform: rotate(360deg); - } -} - #status_map_container { position: relative; overflow: hidden; @@ -1537,27 +1231,19 @@ button[disabled] { .apply-btn { padding: 0.3rem 0.6rem; } + .watching { position: relative; padding-left: 1rem; padding-top: 1rem; - display: -webkit-box; - display: -ms-flexbox; display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; flex-direction: row; - -webkit-box-align: center; - -ms-flex-align: center; align-items: center; color: #000; z-index: 1; } .watching h4 { - -webkit-box-flex: 1; - -ms-flex: 1; flex: 1; font-weight: 500; } @@ -1580,8 +1266,6 @@ button[disabled] { } #right div:first-of-type h2 { - -webkit-box-flex: 1; - -ms-flex: 1; flex: 1; margin: 0.4rem 0; } @@ -1592,136 +1276,12 @@ button[disabled] { .center { position: relative; - display: -ms-grid; display: grid; place-content: center; height: 100%; text-align: center; } -.slide-left { - -webkit-animation: slide-left 0.4s ease; - animation: slide-left 0.4s ease; -} - -@-webkit-keyframes slide-left { - 100% { - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - opacity: 0; - } -} - -@keyframes slide-left { - 100% { - -webkit-transform: translateX(-100%); - transform: translateX(-100%); - opacity: 0; - } -} - -.update-mi svg { - -webkit-animation: shake 0.6s ease; - animation: shake 0.6s ease; - -webkit-transform-origin: top; - transform-origin: top; -} - -@-webkit-keyframes shake { - 0% { - -webkit-transform: rotate(30deg); - transform: rotate(30deg); - } - - 20% { - -webkit-transform: rotate(-30deg); - transform: rotate(-30deg); - } - - 40% { - -webkit-transform: rotate(20deg); - transform: rotate(20deg); - } - - 60% { - -webkit-transform: rotate(-20deg); - transform: rotate(-20deg); - } - - 80% { - -webkit-transform: rotate(10deg); - transform: rotate(10deg); - } - - 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } -} - -@keyframes shake { - 0% { - -webkit-transform: rotate(30deg); - transform: rotate(30deg); - } - - 20% { - -webkit-transform: rotate(-30deg); - transform: rotate(-30deg); - } - - 40% { - -webkit-transform: rotate(20deg); - transform: rotate(20deg); - } - - 60% { - -webkit-transform: rotate(-20deg); - transform: rotate(-20deg); - } - - 80% { - -webkit-transform: rotate(10deg); - transform: rotate(10deg); - } - - 100% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } -} - -.settings-mi svg { - -webkit-animation: rot 0.6s ease; - animation: rot 0.6s ease; - -webkit-transform-origin: center; - transform-origin: center; -} - -@-webkit-keyframes rot { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - - 100% { - -webkit-transform: rotate(60deg); - transform: rotate(60deg); - } -} - -@keyframes rot { - 0% { - -webkit-transform: rotate(0); - transform: rotate(0); - } - - 100% { - -webkit-transform: rotate(60deg); - transform: rotate(60deg); - } -} - .capitalise { text-transform: capitalize; } @@ -1731,19 +1291,21 @@ button[disabled] { margin: 0; } -#admin_panel { +#admin_page { padding: 0 1.5rem; display: grid; gap: 1.5rem; } -#admin_panel__header{ + +#admin_page__header { display: grid; gap: 0 1rem; padding: 0.5rem 0; grid-template-columns: 1fr auto; align-items: center; } -#project_editing_panel{ + +#project_editing_panel { padding: 1rem; } @@ -1753,70 +1315,64 @@ button[disabled] { } .hide-on-mobile { - display: -webkit-box; - display: -ms-flexbox; display: flex; } .hide-page-on-mobile { - display: -ms-grid; display: grid; } - sm-popup{ + + sm-popup { --width: 24rem; } - .popup__header{ + + .popup__header { padding: 1.5rem 1.5rem 0 0.5rem; } - .page, - #show_all, - #project_explorer { - margin: 1rem 4vw; + #main_nav { + flex-direction: column; + align-items: flex-start; } - #top_nav { - padding: 1rem 2vw; + .nav-list__item { + flex-direction: row; + align-items: center; + + padding: 0.5rem 0.8rem; + + font-size: 1rem; + + &--active { + background-color: rgba(var(--text-color), 0.06); + } + + .icon { + margin-right: 0.5rem; + margin-bottom: 0; + } } + .project-card { + &--active{ + background-color: rgba(var(--text-color), 0.1); + } + } + #settings_page { padding: 1rem 2rem; } - - .logo { - -webkit-box-pack: left; - -ms-flex-pack: left; - justify-content: left; - width: auto; - } - - #show_message { - -webkit-transform: translate(0.4rem, 0); - transform: translate(0.4rem, 0); - margin: 1rem; - width: -webkit-max-content; - width: -moz-max-content; - width: max-content; - border-radius: 0.2rem; - } - #sign_in { width: 24rem; height: auto; border-radius: 0.4rem; } - #floating_btn { - margin: 1rem; - } - #dashboard { - -ms-grid-columns: 3fr 1fr; grid-template-columns: 3fr 1fr; } #dashboard #status_map_container { - -ms-flex-item-align: start; align-self: flex-start; } @@ -1838,32 +1394,18 @@ button[disabled] { opacity: 1; } - #intern_info { - width: 24rem; - } - - .hover { - -webkit-transition: background 0.3s ease; - transition: background 0.3s ease; - cursor: pointer; - } - - .hover:hover { - background: rgba(var(--text-color), 0.06); - } - - #admin_panel { + #admin_page { grid-template-columns: 16rem 1fr; grid-template-rows: auto 1fr; - grid-template-areas: 'admin-header admin-header' '. .'; + grid-template-areas: 'admin-header admin-header''. .'; } - #admin_panel__header{ + + #admin_page__header { grid-area: admin-header; } #edit_data_fig { width: 16rem; - -ms-grid-column-align: center; justify-self: center; } @@ -1875,19 +1417,9 @@ button[disabled] { overflow-y: auto; } - .task-list-item .task-option { - opacity: 0; - } - - .task-list-item:hover .task-option { - opacity: 1; - } - #project_explorer { - display: -ms-grid; display: grid; align-items: flex-start; - -ms-grid-columns: 1fr 3fr; grid-template-columns: 1fr 3fr; grid-template-areas: 'header header' 'left right'; @@ -1895,16 +1427,13 @@ button[disabled] { #project_explorer .header { border-radius: 0.4rem 0.4rem 0 0; - -ms-grid-column-span: 2; grid-area: header; } #project_explorer #left { - position: -webkit-sticky; position: sticky; top: 4.8rem; grid-area: left; - -ms-flex-item-align: start; align-self: flex-start; border-right: 1px solid rgba(var(--text-color), 0.06); } @@ -1919,40 +1448,53 @@ button[disabled] { #project_explorer #right { grid-area: right; } + + + // Newer styles + + #main_page { + grid-template-columns: 10rem minmax(0, 1fr); + grid-template-areas: 'main-header main-header''main-nav sub-pages'; + } } // Newer styles -#update_of_project{ +#update_of_project { color: rgba(var(--text-color), 0.8); } -#update_of_task{ + +#update_of_task { font-size: 1.3rem; margin: 0.4rem 0 1.8rem 0; } -ul{ +ul { padding: 0; list-style: none; } -#assigned_task_list{ + +#assigned_task_list { display: grid; align-content: flex-start; gap: 1.5rem; } -.task-card{ + +.task-card { display: grid; padding: 1rem; } -.task__header{ + +.task__header { display: grid; gap: 0 0.5rem; align-items: flex-start; grid-template-columns: 1fr auto; - grid-template-areas: '. send-button' '. send-button'; + grid-template-areas: '. send-button''. send-button'; } -.task__project-title{ + +.task__project-title { font-size: 0.9rem; font-weight: 500; border-radius: 0.3rem; @@ -1962,19 +1504,23 @@ ul{ color: rgba(var(--text-color), 0.8); background-color: rgba(var(--text-color), 0.06); } -.task__title{ - font-size: 1.5rem; + +.task__title { + font-size: 1.3rem; margin-bottom: 1rem !important; } -.task__description{ + +.task__description { white-space: pre-line; color: rgba(var(--text-color), 0.8); } -.send-update-button{ + +.send-update-button { grid-area: send-button; - border: solid 1px; + --padding: 0.6rem 0.8rem; color: var(--accent-color); - .icon{ + + .icon { height: 1.2rem; width: 1.2rem; fill: var(--accent-color); @@ -1987,38 +1533,49 @@ ul{ -@media only screen and (min-width: 1280px) { +@media only screen and (min-width: 1280px) {} - .page, - #show_all, - #project_explorer { - margin: 1rem 8vw; - } -} -@media (any-hover: hover){ - ::-webkit-scrollbar{ +@media (any-hover: hover) { + ::-webkit-scrollbar { width: 0.5rem; height: 0.5rem; } - - ::-webkit-scrollbar-thumb{ + + ::-webkit-scrollbar-thumb { background: rgba(var(--text-color), 0.3); border-radius: 1rem; - &:hover{ + + &:hover { background: rgba(var(--text-color), 0.5); } } - .send-update-button{ + + .interact:hover { + background-color: rgba(var(--text-color), 0.06); + } + + .send-update-button { opacity: 0; transition: opacity 0.3s; } - .task-card:hover{ - .send-update-button{ + + .task-card:hover { + .send-update-button { opacity: 1; } } + .task-option { + opacity: 0; + } + + .task-list-item:hover .task-option, + .task-option:focus-within { + opacity: 1; + } } -@media (any-hover: none){ + +@media (any-hover: none) { + .task-option, .apply-btn { opacity: 1; diff --git a/new.html b/new.html index f743068..b8cf678 100644 --- a/new.html +++ b/new.html @@ -9,9 +9,8 @@ - - + -