diff --git a/src/components/Button/index.scss b/src/components/Button/index.scss index 61d804ba..1d15d6c8 100644 --- a/src/components/Button/index.scss +++ b/src/components/Button/index.scss @@ -1,36 +1,36 @@ -@use '~styles/colors.scss' as colors; - -.button { - font-family: 'Noto Sans', sans-serif; - color: rgb(255, 255, 255); - font-size: 1.6rem; - font-weight: 500; - - padding: 1.6rem; - border: unset; - - background-color: colors.$primary200; - border-radius: 1.4rem; - - transition: 0.3s ease-in-out; - - cursor: pointer; - appearance: none; - - &--block { - width: 100%; - - display: block; - } - - &:hover:not(:disabled) { - background: colors.$primary600; - transform: scale(1.02); - } - - &:disabled { - background: colors.$gray600; - - cursor: not-allowed; - } -} +@use '~styles/colors.scss' as colors; + +.button { + font-family: 'Noto Sans', sans-serif; + color: colors.$secondary100; + font-size: 1.6rem; + font-weight: 500; + + padding: 1.6rem; + border: unset; + + background-color: colors.$primary200; + border-radius: 1.4rem; + + transition: 0.3s ease-in-out; + + cursor: pointer; + appearance: none; + + &--block { + width: 100%; + + display: block; + } + + &:hover:not(:disabled) { + background: colors.$primary600; + transform: scale(1.02); + } + + &:disabled { + background: colors.$gray600; + + cursor: not-allowed; + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/components/DateSelected/index.js b/src/components/Calendar/components/DateSelectorComposer/components/DateSelected/index.js new file mode 100644 index 00000000..3010d63e --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/DateSelected/index.js @@ -0,0 +1,32 @@ +import { Component } from 'pet-dex-utilities'; +import './index.scss'; + +const events = ['item:click']; + +const html = ` + +`; + +export default function DateSelected({ date = 1 }) { + Component.call(this, { html, events }); + + this.$dateSelected = this.selected.get('date-selected'); + this.setDate(date); + + this.$dateSelected.addEventListener('click', () => this.emit('item:click')); +} + +DateSelected.prototype = Object.assign( + DateSelected.prototype, + Component.prototype, + { + setDate(date) { + this.date = date; + this.$dateSelected.innerText = date; + }, + + getDate() { + return this.date; + }, + }, +); diff --git a/src/components/Calendar/components/DateSelectorComposer/components/DateSelected/index.scss b/src/components/Calendar/components/DateSelectorComposer/components/DateSelected/index.scss new file mode 100644 index 00000000..74871321 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/DateSelected/index.scss @@ -0,0 +1,16 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.date-selected { + font-family: fonts.$primaryFont; + color: colors.$gray800; + font-size: fonts.$lg; + font-weight: fonts.$regular; + + &:hover { + color: colors.$primary200; + font-weight: fonts.$semiBold; + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/components/MonthSelector/index.js b/src/components/Calendar/components/DateSelectorComposer/components/MonthSelector/index.js new file mode 100644 index 00000000..507438f4 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/MonthSelector/index.js @@ -0,0 +1,146 @@ +import { Component } from 'pet-dex-utilities'; +import { makeSwipable } from '~src/utils/swiper'; +import SelectorItem from '../SelectorItem'; +import { MONTHS } from '../../../../utils/months'; +import './index.scss'; + +const events = ['month:change', 'selector:click']; + +const html = ` +
+
+
+
    +
+
+
+
+`; + +export default function MonthSelector({ dateArray, nodePadding = 5 }) { + Component.call(this, { html, events }); + + this.dateArray = dateArray; + this.$monthSelector = this.selected.get('month-selector'); + this.$dateList = this.selected.get('month-list'); + this.$listContent = this.selected.get('list-content'); + + this.itemCount = this.dateArray.length; + const columnWidth = 150; + const activeColumnWidth = 176; + this.nodePadding = nodePadding; + this.scrollLeft = this.$monthSelector.scrollLeft; + + const swiper = makeSwipable(this.$monthSelector); + + const handleItemClick = (index) => { + const itemScroll = + index * columnWidth - (this.viewportWidth / 2 - columnWidth / 2); + this.$monthSelector.scrollLeft = itemScroll; + }; + + const emitMonthChangeEvent = (month) => { + const newMonth = MONTHS.indexOf(month); + this.emit('month:change', newMonth); + }; + + const calculateViewport = () => { + this.viewportWidth = this.$monthSelector.offsetWidth; + }; + + const renderWindow = () => { + this.totalContentWidth = + (this.itemCount - 1) * columnWidth + activeColumnWidth; + + this.startNode = + Math.floor(this.scrollLeft / columnWidth) - this.nodePadding; + this.startNode = Math.max(0, this.startNode); + + this.visibleNodesCount = + Math.ceil(this.viewportWidth / columnWidth) + 2 * this.nodePadding; + this.visibleNodesCount = Math.min( + this.itemCount - this.startNode, + this.visibleNodesCount, + ); + + this.offsetX = this.startNode * columnWidth; + + this.$dateList.style.width = `${this.totalContentWidth}px`; + this.$listContent.style.transform = `translateX(${this.offsetX}px)`; + + this.$listContent.innerHTML = ''; + this.visibleChildren = new Array(this.visibleNodesCount) + .fill(null) + .map( + (_, index) => + new SelectorItem({ item: this.dateArray[index + this.startNode] }), + ); + + this.visibleChildren.forEach((selectorItem, index) => { + selectorItem.mount(this.$listContent); + selectorItem.listen('item:click', () => + handleItemClick(index + this.startNode), + ); + selectorItem.listen('item:change', (item) => emitMonthChangeEvent(item)); + }); + + const middlePosition = this.scrollLeft + this.viewportWidth / 2; + const activeIndex = Math.round( + (middlePosition - this.offsetX) / columnWidth - 1, + ); + + if (activeIndex >= 0 && activeIndex < this.visibleChildren.length) { + this.visibleChildren[activeIndex].active(); + } + }; + + const scrollToMiddle = () => { + this.scrollLeft = this.totalContentWidth / 2 - this.viewportWidth / 2; + this.$monthSelector.scrollLeft = this.scrollLeft; + renderWindow(); + }; + + this.$monthSelector.addEventListener('scroll', (e) => { + if (this.animationFrame) { + cancelAnimationFrame(this.animationFrame); + } + this.animationFrame = requestAnimationFrame(() => { + this.scrollLeft = e.target.scrollLeft; + renderWindow(); + }); + }); + + swiper.left(() => { + this.scrollLeft = Math.max(this.scrollLeft - columnWidth, 0); + this.$monthSelector.scrollLeft = this.scrollLeft; + renderWindow(); + }); + + swiper.right(() => { + this.scrollLeft = Math.min( + this.scrollLeft + columnWidth, + this.totalContentWidth - this.viewportWidth, + ); + this.$monthSelector.scrollLeft = this.scrollLeft; + renderWindow(); + }); + + this.listen('mount', () => { + window.addEventListener('resize', () => { + calculateViewport(); + scrollToMiddle(); + }); + }); + + requestAnimationFrame(() => { + calculateViewport(); + renderWindow(); + scrollToMiddle(); + }); +} + +MonthSelector.prototype = Object.assign( + MonthSelector.prototype, + Component.prototype, + {}, +); diff --git a/src/components/Calendar/components/DateSelectorComposer/components/MonthSelector/index.scss b/src/components/Calendar/components/DateSelectorComposer/components/MonthSelector/index.scss new file mode 100644 index 00000000..4d5773d5 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/MonthSelector/index.scss @@ -0,0 +1,31 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.month-selector { + overflow: auto; + + display: flex; + flex-direction: row; + + margin-bottom: 2.4rem; + + padding-bottom: 2.4rem; + + border-bottom: 0.1rem solid colors.$gray150; + + box-sizing: border-box; + + scroll-snap-type: x proximity; + + scrollbar-width: none; + + &__list { + width: fit-content; + + display: flex; + + align-items: center; + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/components/SelectorItem/index.js b/src/components/Calendar/components/DateSelectorComposer/components/SelectorItem/index.js new file mode 100644 index 00000000..fd568bd4 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/SelectorItem/index.js @@ -0,0 +1,32 @@ +import { Component } from 'pet-dex-utilities'; +import './index.scss'; + +const events = ['item:change', 'item:click']; + +const html = ` +
  • +`; + +export default function SelectorItem({ item }) { + Component.call(this, { html, events }); + this.item = item; + this.$selectorItem = this.selected.get('selector-item'); + this.$selectorItem.innerText = this.item; + + if (typeof this.item === 'string') this.$selectorItem.style.width = '150px'; + + if (typeof this.item === 'number') this.$selectorItem.style.width = '70px'; + + this.$selectorItem.addEventListener('click', () => this.emit('item:click')); +} + +SelectorItem.prototype = Object.assign( + SelectorItem.prototype, + Component.prototype, + { + active() { + this.$selectorItem.classList.add('selector-item--active'); + this.emit('item:change', this.item); + }, + }, +); diff --git a/src/components/Calendar/components/DateSelectorComposer/components/SelectorItem/index.scss b/src/components/Calendar/components/DateSelectorComposer/components/SelectorItem/index.scss new file mode 100644 index 00000000..343921ac --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/SelectorItem/index.scss @@ -0,0 +1,27 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.selector-item { + font-family: fonts.$primaryFont; + color: colors.$gray700; + + text-align: center; + font-size: fonts.$xs; + font-weight: fonts.$medium; + + scroll-snap-align: center; + + &--active { + color: colors.$primary200; + font-size: fonts.$lg; + font-weight: fonts.$semiBold; + + padding: 0.6rem 1.2rem; + border: 1px solid colors.$blue100; + + background-color: rgba(209, 230, 255, 0.5); + border-radius: 1.4rem; + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/components/ModalItem/index.js b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/components/ModalItem/index.js new file mode 100644 index 00000000..6059f234 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/components/ModalItem/index.js @@ -0,0 +1,27 @@ +import { Component } from 'pet-dex-utilities'; +import './index.scss'; + +const events = ['item:change', 'item:click']; + +const html = ` +
  • +`; + +export default function ModalItem({ item }) { + Component.call(this, { html, events }); + + this.item = item; + this.$modalItem = this.selected.get('modal-item'); + this.$modalItem.innerText = this.item; + + this.$modalItem.addEventListener('click', () => + this.emit('item:click', this.item), + ); +} + +ModalItem.prototype = Object.assign(ModalItem.prototype, Component.prototype, { + active() { + this.$modalItem.classList.add('selector-modal__item--active'); + this.emit('item:change', this.item); + }, +}); diff --git a/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/components/ModalItem/index.scss b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/components/ModalItem/index.scss new file mode 100644 index 00000000..8a2d260f --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/components/ModalItem/index.scss @@ -0,0 +1,41 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.selector-modal__item { + font-family: fonts.$primaryFont; + color: colors.$gray500; + text-align: center; + font-size: fonts.$md; + font-weight: fonts.$medium; + line-height: 1.7; + + cursor: pointer; + + &--active { + color: colors.$gray800; + font-size: fonts.$lg; + font-weight: fonts.$bold; + + border-top: 1px solid colors.$gray150; + border-bottom: 1px solid colors.$gray150; + + position: relative; + + &::after { + width: 1.6rem; + height: 2.3rem; + + margin-left: 1rem; + + position: absolute; + + top: 0.9rem; + + background-image: url('../../../../../../images/arrows.svg'); + + content: ''; + } + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/index.js b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/index.js new file mode 100644 index 00000000..19733374 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/index.js @@ -0,0 +1,109 @@ +import { Component } from 'pet-dex-utilities'; +import ModalItem from './components/ModalItem'; + +import './index.scss'; + +const events = ['date:change']; + +const html = ` +
    +
    +
    +
      +
    +
    +
    +
    +`; + +export default function SelectorModal({ dateArray, nodePadding = 5 }) { + Component.call(this, { html, events }); + + this.dateArray = dateArray; + this.$selectorModal = this.selected.get('selector-modal'); + this.$modalList = this.selected.get('modal-list'); + this.$listContent = this.selected.get('list-content'); + + this.itemCount = this.dateArray.length; + const rowHeight = 34; + const activeRowHeight = 42.8; + this.nodePadding = nodePadding; + this.scrollTop = this.$selectorModal.scrollTop; + + setTimeout(() => { + this.viewportHeight = this.$selectorModal.offsetHeight; + + const renderWindow = () => { + this.totalContentHeight = + (this.itemCount - 1) * rowHeight + activeRowHeight; + + this.startNode = + Math.floor(this.scrollTop / rowHeight) - this.nodePadding; + this.startNode = Math.max(0, this.startNode); + + this.visibleNodesCount = + Math.ceil(this.viewportHeight / rowHeight) + 2 * this.nodePadding; + this.visibleNodesCount = Math.min( + this.itemCount - this.startNode, + this.visibleNodesCount, + ); + + this.offsetY = this.startNode * rowHeight; + + this.$modalList.style.height = `${this.totalContentHeight}px`; + this.$listContent.style.transform = `translateY(${this.offsetY}px)`; + + this.$listContent.innerHTML = ''; + this.visibleChildren = new Array(this.visibleNodesCount) + .fill(null) + .map( + (_, index) => + new ModalItem({ item: this.dateArray[index + this.startNode] }), + ); + + this.visibleChildren.forEach((modalItem, index) => { + modalItem.mount(this.$listContent); + modalItem.listen('item:change', (item) => + this.emit('date:change', item), + ); + + if (index === 8) { + modalItem.active(); + } + }); + }; + this.$selectorModal.addEventListener('scroll', (e) => { + if (this.animationFrame) { + cancelAnimationFrame(this.animationFrame); + } + this.animationFrame = requestAnimationFrame(() => { + this.scrollTop = e.target.scrollTop; + renderWindow(); + + const activeItem = this.$listContent.querySelector( + 'selector-item--active', + ); + if (activeItem) { + activeItem.scrollIntoView({ + block: 'center', + behavior: 'smooth', + }); + } + }); + }); + + const scrollToMiddle = () => { + this.scrollTop = this.totalContentHeight / 2 - this.viewportHeight / 2; + this.$selectorModal.scrollTop = this.scrollTop; + }; + + renderWindow(); + scrollToMiddle(); + }, 0); +} + +SelectorModal.prototype = Object.assign( + SelectorModal.prototype, + Component.prototype, + {}, +); diff --git a/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/index.scss b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/index.scss new file mode 100644 index 00000000..eac998b2 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/SelectorModal/index.scss @@ -0,0 +1,54 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.selector-modal { + width: 100%; + height: 18rem; + overflow: auto; + scroll-snap-type: y proximity; + + display: none; + flex-direction: column; + + box-sizing: border-box; + + position: absolute; + top: 4.6rem; + z-index: 2; + + background-color: colors.$secondary100; + + box-shadow: 0 4px 20px -2px rgba(50, 50, 71, 0.04); + + box-shadow: 0 0 5px 0 rgba(12, 26, 75, 0.08); + + border-radius: 1rem; + + animation: openModal 0.3s ease-out; + + scrollbar-width: none; + + &__list > * { + scroll-snap-align: center; + } +} + +@include breakpoints.from667 { + .selector-modal { + display: flex; + } +} + +@keyframes openModal { + from { + transform: translateY(-2.5rem); + opacity: 0; + } + + to { + transform: translateY(0); + opacity: 1; + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/components/YearSelector/index.js b/src/components/Calendar/components/DateSelectorComposer/components/YearSelector/index.js new file mode 100644 index 00000000..7214386f --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/YearSelector/index.js @@ -0,0 +1,142 @@ +import { Component } from 'pet-dex-utilities'; +import { makeSwipable } from '~src/utils/swiper'; +import SelectorItem from '../SelectorItem'; +import './index.scss'; + +const events = ['selector:click', 'year:change']; + +const html = ` +
    +
    +
    +
      +
    +
    +
    +
    +`; + +export default function YearSelector({ dateArray, nodePadding = 5 }) { + Component.call(this, { html, events }); + + this.dateArray = dateArray; + this.$yearSelector = this.selected.get('year-selector'); + this.$dateList = this.selected.get('date-list'); + this.$listContent = this.selected.get('list-content'); + + this.itemCount = this.dateArray.length; + const columnWidth = 70; + const activeColumnWidth = 96; + this.nodePadding = nodePadding; + this.scrollLeft = this.$yearSelector.scrollLeft; + + const swiper = makeSwipable(this.$yearSelector); + + const handleItemClick = (index) => { + const itemScroll = + index * columnWidth - (this.viewportWidth / 2 - columnWidth / 2); + this.$yearSelector.scrollLeft = itemScroll; + }; + + const calculateViewport = () => { + this.viewportWidth = this.$yearSelector.offsetWidth; + }; + + const renderWindow = () => { + this.totalContentWidth = + (this.itemCount - 1) * columnWidth + activeColumnWidth; + + this.startNode = + Math.floor(this.scrollLeft / columnWidth) - this.nodePadding; + this.startNode = Math.max(0, this.startNode); + + this.visibleNodesCount = + Math.ceil(this.viewportWidth / columnWidth) + 2 * this.nodePadding; + this.visibleNodesCount = Math.min( + this.itemCount - this.startNode, + this.visibleNodesCount, + ); + + this.offsetX = this.startNode * columnWidth; + + this.$dateList.style.width = `${this.totalContentWidth}px`; + this.$listContent.style.transform = `translateX(${this.offsetX}px)`; + + this.$listContent.innerHTML = ''; + this.visibleChildren = new Array(this.visibleNodesCount) + .fill(null) + .map( + (_, index) => + new SelectorItem({ item: this.dateArray[index + this.startNode] }), + ); + + this.visibleChildren.forEach((selectorItem, index) => { + selectorItem.mount(this.$listContent); + selectorItem.listen('item:click', () => + handleItemClick(index + this.startNode), + ); + selectorItem.listen('item:change', (item) => + this.emit('year:change', item), + ); + }); + + const middlePosition = this.scrollLeft + this.viewportWidth / 2; + const activeIndex = Math.round( + (middlePosition - this.offsetX) / columnWidth - 1, + ); + + if (activeIndex >= 0 && activeIndex < this.visibleChildren.length) { + this.visibleChildren[activeIndex].active(); + } + }; + + const scrollToMiddle = () => { + this.scrollLeft = this.totalContentWidth / 2 - this.viewportWidth / 2; + this.$yearSelector.scrollLeft = this.scrollLeft; + renderWindow(); + }; + + this.$yearSelector.addEventListener('scroll', (e) => { + if (this.animationFrame) { + cancelAnimationFrame(this.animationFrame); + } + this.animationFrame = requestAnimationFrame(() => { + this.scrollLeft = e.target.scrollLeft; + renderWindow(); + }); + }); + + swiper.left(() => { + this.scrollLeft = Math.max(this.scrollLeft - columnWidth, 0); + this.$yearSelector.scrollLeft = this.scrollLeft; + renderWindow(); + }); + + swiper.right(() => { + this.scrollLeft = Math.min( + this.scrollLeft + columnWidth, + this.totalContentWidth - this.viewportWidth, + ); + this.$yearSelector.scrollLeft = this.scrollLeft; + renderWindow(); + }); + + this.listen('mount', () => { + window.addEventListener('resize', () => { + calculateViewport(); + scrollToMiddle(); + }); + }); + + requestAnimationFrame(() => { + calculateViewport(); + renderWindow(); + scrollToMiddle(); + }); +} + +YearSelector.prototype = Object.assign( + YearSelector.prototype, + Component.prototype, + {}, +); diff --git a/src/components/Calendar/components/DateSelectorComposer/components/YearSelector/index.scss b/src/components/Calendar/components/DateSelectorComposer/components/YearSelector/index.scss new file mode 100644 index 00000000..e82a7097 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/components/YearSelector/index.scss @@ -0,0 +1,32 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.year-selector { + overflow: auto; + + display: flex; + flex-direction: row; + + margin-bottom: 2.4rem; + + padding-bottom: 2.4rem; + + border-bottom: 0.1rem solid colors.$gray150; + + box-sizing: border-box; + scrollbar-width: none; + + position: relative; + scroll-snap-type: x proximity; + + &__list { + width: max-content; + + display: flex; + + align-items: center; + justify-content: center; + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/index.js b/src/components/Calendar/components/DateSelectorComposer/index.js new file mode 100644 index 00000000..4996a0d8 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/index.js @@ -0,0 +1,114 @@ +import { Component } from 'pet-dex-utilities'; +import dayjs from 'dayjs'; +import { listenBreakpoint } from '../../../../utils/breakpoints/breakpoints'; +import { ModalController } from './utils/ModalController'; +import { + yearArrayGenerator, + monthArrayGenerator, +} from './utils/arraysGenerators'; +import YearSelector from './components/YearSelector'; +import DateSelected from './components/DateSelected'; +import { MONTHS } from '../../utils/months'; +import MonthSelector from './components/MonthSelector'; +import './index.scss'; + +const events = ['month:change', 'year:change']; + +const html = ` +
    +
    +
    +
    +`; + +export default function DateSelectorComposer({ + month = dayjs().date() + 1, + year = dayjs().year(), +}) { + Component.call(this, { html, events }); + + this.month = month; + this.year = year; + this.$dateSelector = this.selected.get('date-selector-composer'); + this.$monthSelector = this.selected.get('month-selector'); + this.$yearSelector = this.selected.get('year-selector'); + this.modalControl = new ModalController(this); + + const mountMobileSelectors = () => { + if (this.monthSelector) this.monthSelector.unmount(); + if (this.yearSelector) this.yearSelector.unmount(); + + this.monthArray = monthArrayGenerator(this.month); + this.yearArray = yearArrayGenerator(this.year); + + this.monthSelector = new MonthSelector({ dateArray: this.monthArray }); + this.monthSelector.mount(this.$monthSelector); + this.monthSelector.listen('month:change', (newMonth) => + this.setMonth(newMonth), + ); + + this.yearSelector = new YearSelector({ dateArray: this.yearArray }); + this.yearSelector.mount(this.$yearSelector); + this.yearSelector.listen('year:change', (newYear) => this.setYear(newYear)); + }; + + const mountDesktopSelectors = () => { + if (this.monthSelected) this.monthSelected.unmount(); + if (this.yearSelected) this.yearSelected.unmount(); + + this.monthSelected = new DateSelected({ date: MONTHS[this.month] }); + this.monthSelected.mount(this.$monthSelector); + this.monthSelected.listen('item:click', () => { + this.month = this.monthSelected.getDate(); + this.monthArray = monthArrayGenerator(MONTHS.indexOf(this.month)); + this.modalControl.onOpen(this.monthArray); + }); + + this.yearSelected = new DateSelected({ date: this.year }); + this.yearSelected.mount(this.$yearSelector); + this.yearSelected.listen('item:click', () => { + this.year = this.yearSelected.getDate(); + this.yearArray = yearArrayGenerator(this.year); + this.modalControl.onOpen(this.yearArray); + }); + }; + + listenBreakpoint('from667', (matches) => { + if (matches) { + if (this.monthSelector) this.monthSelector.unmount(); + if (this.yearSelector) this.yearSelector.unmount(); + + mountDesktopSelectors(); + } else { + if (this.monthSelected) this.monthSelected.unmount(); + if (this.yearSelected) this.yearSelected.unmount(); + this.modalControl.onClose(); + + mountMobileSelectors(); + } + }); + + window.addEventListener('click', (event) => + this.modalControl.CloseOnClickOutside(event), + ); +} + +DateSelectorComposer.prototype = Object.assign( + DateSelectorComposer.prototype, + Component.prototype, + { + setMonth(month) { + if (this.monthSelected) this.monthSelected.setDate(MONTHS[month]); + + this.month = month; + this.emit('month:change', month); + }, + + setYear(year) { + if (this.yearSelected) this.yearSelected.setDate(year); + + this.year = year; + this.emit('year:change', year); + }, + }, +); diff --git a/src/components/Calendar/components/DateSelectorComposer/index.scss b/src/components/Calendar/components/DateSelectorComposer/index.scss new file mode 100644 index 00000000..7033fd29 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/index.scss @@ -0,0 +1,35 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.date-selector-composer { + width: 100%; + + cursor: pointer; +} + +@include breakpoints.from667 { + .date-selector-composer { + width: max-content; + min-width: 23.1rem; + + display: flex; + flex-direction: row-reverse; + gap: 1rem; + + align-items: center; + justify-content: center; + + position: relative; + + &::before { + width: 1.6rem; + height: 2.3rem; + + background-image: url('../../images/arrows.svg'); + + content: ''; + } + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/utils/ModalController.js b/src/components/Calendar/components/DateSelectorComposer/utils/ModalController.js new file mode 100644 index 00000000..0cec0eb7 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/utils/ModalController.js @@ -0,0 +1,39 @@ +import { MONTHS } from '../../../utils/months'; +import SelectorModal from '../components/SelectorModal'; + +export class ModalController { + constructor(selector) { + this.selector = selector; + } + + onOpen(dateArray) { + if (this.modal) this.onClose(); + + this.modal = new SelectorModal({ dateArray }); + this.modal.mount(this.selector.$dateSelector); + this.modal.listen('date:change', (item) => this.changeDate(item)); + } + + changeDate(date) { + if (typeof date === 'string') { + this.selector.setMonth(MONTHS.indexOf(date)); + } + if (typeof date === 'number') this.selector.setYear(date); + } + + CloseOnClickOutside(event) { + const isOutside = !event + .composedPath() + .includes(this.selector.$dateSelector); + + if (!isOutside) return; + + this.onClose(); + } + + onClose() { + if (this.modal) { + this.modal.unmount(); + } + } +} diff --git a/src/components/Calendar/components/DateSelectorComposer/utils/arraysGenerators.js b/src/components/Calendar/components/DateSelectorComposer/utils/arraysGenerators.js new file mode 100644 index 00000000..cb47a1a4 --- /dev/null +++ b/src/components/Calendar/components/DateSelectorComposer/utils/arraysGenerators.js @@ -0,0 +1,18 @@ +import { MONTHS } from '../../../utils/months'; + +export function monthArrayGenerator(month) { + const monthArray = new Array(103); + for (let i = 0; i < monthArray.length; i += 1) { + const monthIndex = (month - (3 - i) + 12) % 12; + monthArray[i] = MONTHS[monthIndex]; + } + return monthArray; +} + +export function yearArrayGenerator(year) { + const yearArray = new Array(101); + for (let i = 0; i < yearArray.length; i += 1) { + yearArray[i] = year - (50 - i); + } + return yearArray; +} diff --git a/src/components/Calendar/components/DayComposer/components/DayButton/index.js b/src/components/Calendar/components/DayComposer/components/DayButton/index.js new file mode 100644 index 00000000..1d0595ba --- /dev/null +++ b/src/components/Calendar/components/DayComposer/components/DayButton/index.js @@ -0,0 +1,57 @@ +import { Component } from 'pet-dex-utilities'; +import './index.scss'; + +const events = ['day:active', 'day:previousMonth', 'day:nextMonth']; + +const html = ` +
  • + +
  • + +`; + +export default function DayButton(day, state) { + Component.call(this, { html, events }); + + this.day = day; + this.$day = this.selected.get('day'); + this.$dayButton = this.selected.get('day-button'); + this.setState(state); + + this.$dayButton.innerText = day; + this.$dayButton.setAttribute('aria-label', `Dia ${this.day}`); + + const emitClickevent = () => { + if (this.state === 'previousMonth') { + this.emit('day:previousMonth'); + } + + if (this.state === 'nextMonth') { + this.emit('day:nextMonth'); + } + + this.active(); + }; + + this.$day.addEventListener('click', () => emitClickevent()); +} + +DayButton.prototype = Object.assign(DayButton.prototype, Component.prototype, { + setState(state) { + this.state = state; + this.$dayButton.classList.add(`day__button--${state}`); + }, + + active() { + this.$dayButton.classList.add('day__button--active'); + this.emit('day:active', this.day); + }, + + desactive() { + this.$dayButton.classList.remove('day__button--active'); + }, + + currentDay() { + this.$dayButton.classList.add('day__button--actual'); + }, +}); diff --git a/src/components/Calendar/components/DayComposer/components/DayButton/index.scss b/src/components/Calendar/components/DayComposer/components/DayButton/index.scss new file mode 100644 index 00000000..8e4be64f --- /dev/null +++ b/src/components/Calendar/components/DayComposer/components/DayButton/index.scss @@ -0,0 +1,65 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.day { + width: 3.2rem; + height: 3.2rem; + + justify-self: center; + + &__button { + width: 100%; + height: 100%; + + font-family: fonts.$primaryFont; + color: colors.$gray500; + text-align: center; + font-size: fonts.$xxs; + font-weight: fonts.$medium; + + border: 0.1rem solid colors.$gray150; + + background-color: colors.$secondary100; + + border-radius: 10px; + + cursor: pointer; + + &:hover, + &--active { + color: colors.$primary200; + font-weight: fonts.$semiBold; + + border: 0.1rem solid colors.$blue100; + + background-color: colors.$blue150; + } + + &--actual { + color: colors.$primary200; + font-weight: fonts.$semiBold; + } + + &--previousMonth, + &--nextMonth { + color: rgba(160, 174, 192, 1); + + border: 0.1rem solid colors.$gray150; + + background-color: colors.$gray100; + } + } +} + +@include breakpoints.from667 { + .day { + width: 5.4rem; + height: 5.4rem; + + &__button { + font-size: fonts.$md; + } + } +} diff --git a/src/components/Calendar/components/DayComposer/index.js b/src/components/Calendar/components/DayComposer/index.js new file mode 100644 index 00000000..2788ee30 --- /dev/null +++ b/src/components/Calendar/components/DayComposer/index.js @@ -0,0 +1,90 @@ +import { Component } from 'pet-dex-utilities'; +import dayjs from 'dayjs'; +import DayButton from './components/DayButton'; +import './index.scss'; + +const events = ['day:change', 'day:nextMonth', 'day:previousMonth']; + +const html = ` +
    +`; + +export default function DayComposer({ + day = dayjs().date(), + month = dayjs().month() + 1, + year = dayjs().year(), +}) { + Component.call(this, { html, events }); + + this.day = day; + this.month = month; + this.year = year; + this.$dayComposer = this.selected.get('day-composer'); + this.activeDayButton = null; + + const currentDay = dayjs().date(); + const actualMonth = dayjs().month() + 1; + const actualYear = dayjs().year(); + + const totalDaysInCalendar = 42; + this.totalDaysInMonth = dayjs(`${this.year}-${this.month}-1`).daysInMonth(); + this.firstDayInWeek = dayjs(`${this.year}-${this.month}-1`).day(); + this.totalDaysInPreviousMonth = dayjs( + `${this.year}-${this.month - 1}-1`, + ).daysInMonth(); + this.nextMonthDay = 1; + this.actualMonthDay = 1; + + for (let i = 1; i <= totalDaysInCalendar; i += 1) { + if (i <= this.firstDayInWeek) { + const previousMonthDay = + this.totalDaysInPreviousMonth - this.firstDayInWeek + i; + this.mountDay(previousMonthDay, 'previousMonth'); + } else if (this.actualMonthDay > this.totalDaysInMonth) { + this.mountDay(this.nextMonthDay, 'nextMonth'); + this.nextMonthDay += 1; + } else { + this.mountDay( + this.actualMonthDay, + this.actualMonthDay === this.day && 'active', + ); + + if ( + this.actualMonthDay === currentDay && + this.month === actualMonth && + this.year === actualYear + ) + this.dayButton.currentDay(); + + this.actualMonthDay += 1; + } + } +} + +DayComposer.prototype = Object.assign( + DayComposer.prototype, + Component.prototype, + { + mountDay(day, state) { + this.dayButton = new DayButton(day, state); + + if (state === 'active') this.activeDayButton = this.dayButton; + + this.dayButton.mount(this.$dayComposer); + this.dayButton.listen('day:active', (activeDay) => + this.handleDayActive(this.dayButton, activeDay), + ); + this.dayButton.listen('day:previousMonth', () => + this.emit('day:previousMonth'), + ); + this.dayButton.listen('day:nextMonth', () => this.emit('day:nextMonth')); + }, + + handleDayActive(dayButton, activeDay) { + if (this.activeDayButton) this.activeDayButton.desactive(); + + this.activeDayButton = dayButton; + this.emit('day:change', activeDay); + }, + }, +); diff --git a/src/components/Calendar/components/DayComposer/index.scss b/src/components/Calendar/components/DayComposer/index.scss new file mode 100644 index 00000000..f6bab690 --- /dev/null +++ b/src/components/Calendar/components/DayComposer/index.scss @@ -0,0 +1,16 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.day-composer { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.2rem; + + list-style: none; + + @include breakpoints.from360 { + gap: 0.8rem; + } +} diff --git a/src/components/Calendar/components/NavigationButton/index.js b/src/components/Calendar/components/NavigationButton/index.js new file mode 100644 index 00000000..752eed91 --- /dev/null +++ b/src/components/Calendar/components/NavigationButton/index.js @@ -0,0 +1,41 @@ +import { Component } from 'pet-dex-utilities'; +import arrow from '../../images/nav-button.svg'; + +import './index.scss'; + +const events = ['button:click']; + +const html = ` + +`; + +export default function NavigationButton(state) { + Component.call(this, { html, events }); + + this.state = state; + this.$navigationButton = this.selected.get('navigation-button'); + this.$buttonIcon = this.selected.get('button-icon'); + + this.$buttonIcon.classList.toggle( + 'navigation-button__icon--next', + this.state === 'next', + ); + this.$navigationButton.setAttribute( + 'aria-label', + this.state === 'next' ? 'Ir para o próximo mês' : 'Ir para o mês anterior', + ); + + this.emitEvent = () => { + this.emit('button:click'); + }; + + this.$navigationButton.addEventListener('click', this.emitEvent); +} + +NavigationButton.prototype = Object.assign( + NavigationButton.prototype, + Component.prototype, + {}, +); diff --git a/src/components/Calendar/components/NavigationButton/index.scss b/src/components/Calendar/components/NavigationButton/index.scss new file mode 100644 index 00000000..854e2e80 --- /dev/null +++ b/src/components/Calendar/components/NavigationButton/index.scss @@ -0,0 +1,36 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.navigation-button { + width: 4.6rem; + height: 4.6rem; + + display: none; + + align-items: center; + justify-content: center; + + border: 0.1rem solid rgb(160, 174, 192); + + background-color: colors.$secondary100; + + border-radius: 14px; + + cursor: pointer; + + &__icon { + color: rgb(160, 174, 192); + + &--next { + transform: rotate(180deg); + } + } +} + +@include breakpoints.from667 { + .navigation-button { + display: flex; + } +} diff --git a/src/components/Calendar/components/WeekDayComposer/components/WeekDay/index.js b/src/components/Calendar/components/WeekDayComposer/components/WeekDay/index.js new file mode 100644 index 00000000..fe9879f8 --- /dev/null +++ b/src/components/Calendar/components/WeekDayComposer/components/WeekDay/index.js @@ -0,0 +1,19 @@ +import { Component } from 'pet-dex-utilities'; +import './index.scss'; + +const events = []; + +const html = ` + +`; + +export default function WeekDay(weekDay) { + Component.call(this, { events, html }); + + this.weekDay = weekDay; + this.$weekDay = this.selected.get('week-day'); + this.$weekDay.innerText = weekDay.abbreviation; + this.$weekDay.setAttribute('aria-label', `${weekDay.name}`); +} + +WeekDay.prototype = Object.assign(WeekDay.prototype, Component.prototype, {}); diff --git a/src/components/Calendar/components/WeekDayComposer/components/WeekDay/index.scss b/src/components/Calendar/components/WeekDayComposer/components/WeekDay/index.scss new file mode 100644 index 00000000..85a5b178 --- /dev/null +++ b/src/components/Calendar/components/WeekDayComposer/components/WeekDay/index.scss @@ -0,0 +1,23 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.week-days__day { + font-family: fonts.$fourthFont; + color: rgb(160, 174, 192); + text-align: center; + font-size: 1rem; + font-weight: fonts.$regular; + + &--active { + color: colors.$primary200; + font-weight: fonts.$semiBold; + } +} + +@include breakpoints.from667 { + .week-days__day { + font-size: fonts.$xs; + } +} diff --git a/src/components/Calendar/components/WeekDayComposer/index.js b/src/components/Calendar/components/WeekDayComposer/index.js new file mode 100644 index 00000000..b782347a --- /dev/null +++ b/src/components/Calendar/components/WeekDayComposer/index.js @@ -0,0 +1,38 @@ +import { Component } from 'pet-dex-utilities'; +import WeekDay from './components/WeekDay'; +import { WEEK_DAYS } from './utils/weekDays'; + +import './index.scss'; + +const events = []; + +const html = ` +
    +`; + +export default function WeekDayComposer() { + Component.call(this, { html, events }); + + this.$weekDays = this.selected.get('week-days'); + this.totalWeekDays = 7; + + for (let i = 0; i < this.totalWeekDays; i += 1) { + const weekDay = new WeekDay(WEEK_DAYS[i]); + weekDay.mount(this.$weekDays); + } +} + +WeekDayComposer.prototype = Object.assign( + WeekDayComposer.prototype, + Component.prototype, + { + activeWeekDay(currentWeekDay) { + Array.from(this.$weekDays.children).forEach((weekDay, index) => { + weekDay.classList.toggle( + 'week-days__day--active', + index === currentWeekDay, + ); + }); + }, + }, +); diff --git a/src/components/Calendar/components/WeekDayComposer/index.scss b/src/components/Calendar/components/WeekDayComposer/index.scss new file mode 100644 index 00000000..25986ce9 --- /dev/null +++ b/src/components/Calendar/components/WeekDayComposer/index.scss @@ -0,0 +1,7 @@ +.week-days { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.8rem; + + margin-bottom: 1.6rem; +} diff --git a/src/components/Calendar/components/WeekDayComposer/utils/weekDays.js b/src/components/Calendar/components/WeekDayComposer/utils/weekDays.js new file mode 100644 index 00000000..9c3f7ab0 --- /dev/null +++ b/src/components/Calendar/components/WeekDayComposer/utils/weekDays.js @@ -0,0 +1,36 @@ +export const WEEK_DAYS = [ + { + name: 'Domingo', + abbreviation: 'Dom', + }, + + { + name: 'Segunda-Feira', + abbreviation: 'Seg', + }, + + { + name: 'Terça-Feira', + abbreviation: 'Ter', + }, + + { + name: 'Quarta-Feira', + abbreviation: 'Qua', + }, + + { + name: 'Quinta-Feira', + abbreviation: 'Qui', + }, + + { + name: 'Sexta-Feira', + abbreviation: 'Sex', + }, + + { + name: 'Sábado', + abbreviation: 'Sáb', + }, +]; diff --git a/src/components/Calendar/images/arrows.svg b/src/components/Calendar/images/arrows.svg new file mode 100644 index 00000000..1ebda089 --- /dev/null +++ b/src/components/Calendar/images/arrows.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/Calendar/images/nav-button.svg b/src/components/Calendar/images/nav-button.svg new file mode 100644 index 00000000..ea74a960 --- /dev/null +++ b/src/components/Calendar/images/nav-button.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/Calendar/index.js b/src/components/Calendar/index.js new file mode 100644 index 00000000..00be72e6 --- /dev/null +++ b/src/components/Calendar/index.js @@ -0,0 +1,174 @@ +import { Component } from 'pet-dex-utilities'; +import dayjs from 'dayjs'; +import WeekDayComposer from './components/WeekDayComposer'; +import NavigationButton from './components/NavigationButton'; +import DateSelectorComposer from './components/DateSelectorComposer'; +import DayComposer from './components/DayComposer'; + +import './index.scss'; + +const events = [ + 'date:change', + 'day:change', + 'month:change', + 'year:change', + 'month:next', + 'month:previous', +]; + +const html = ` +
    +
    +
    +
    +`; + +export default function Calendar({ + day = dayjs().date(), + month = dayjs().month() + 1, + year = dayjs().year(), +}) { + Component.call(this, { html, events }); + + this.day = day; + this.month = month; + this.year = year; + + this.$calendar = this.selected.get('calendar'); + this.$calendarControls = this.selected.get('calendar-controls'); + this.$calendarContent = this.selected.get('calendar-content'); + + this.previousButton = new NavigationButton('previous'); + this.previousButton.mount(this.$calendarControls); + this.previousButton.listen('button:click', () => this.previousMonth()); + + this.dateSelector = new DateSelectorComposer({ + month: this.month - 1, + year: this.year, + }); + this.dateSelector.mount(this.$calendarControls); + this.dateSelector.listen('month:change', (newMonth) => { + this.setMonth(newMonth + 1); + }); + this.dateSelector.listen('year:change', (newYear) => this.setYear(newYear)); + + this.nextButton = new NavigationButton('next'); + this.nextButton.mount(this.$calendarControls); + this.nextButton.listen('button:click', () => this.nextMonth()); + + this.weekDayComposer = new WeekDayComposer(); + this.weekDayComposer.mount(this.$calendarContent); + + this.mountDayComposer = () => { + if (this.dayComposer) this.dayComposer.unmount(); + + this.dayComposer = new DayComposer(this.getDate()); + this.dayComposer.mount(this.$calendarContent); + this.dayComposer.listen('day:change', (newDay) => this.setDay(newDay)); + this.dayComposer.listen('day:previousMonth', () => this.previousMonth()); + this.dayComposer.listen('day:nextMonth', () => this.nextMonth()); + }; + + this.setDate(this.day, this.month, this.year); +} + +Calendar.prototype = Object.assign(Calendar.prototype, Component.prototype, { + setDate(day, month, year) { + this.day = day; + this.month = month; + this.year = year; + + this.mountDayComposer(); + this.firstDayInWeek = dayjs(`${this.year}-${this.month}-${this.day}`).day(); + this.weekDayComposer.activeWeekDay(this.firstDayInWeek); + + this.emit('date:change', { + day: this.day, + month: this.month, + year: this.year, + }); + }, + + setDay(day) { + this.day = day; + this.setDate(this.day, this.month, this.year); + + this.emit('day:change', this.day); + }, + + setMonth(month) { + this.month = month; + this.setDate(this.day, this.month, this.year); + + this.emit('month:change', this.month); + }, + + setYear(year) { + this.year = year; + this.setDate(this.day, this.month, this.year); + + this.emit('year:change', this.year); + }, + + getDate() { + return { + day: this.day, + month: this.month, + year: this.year, + }; + }, + + getDay() { + return this.day; + }, + + getMonth() { + return this.month; + }, + + getYear() { + return this.year; + }, + + nextMonth(day) { + this.day = day || this.day; + this.month += 1; + + if (this.month > 12) { + this.month = 1; + this.year += 1; + this.dateSelector.setYear(this.year); + } + + const totalDaysInMonth = dayjs( + `${this.year}-${this.month}-1`, + ).daysInMonth(); + if (this.day > totalDaysInMonth) this.day = totalDaysInMonth; + + this.dateSelector.setMonth(this.month - 1); + this.setDate(this.day, this.month, this.year); + + this.emit('month:next', this.month); + }, + + previousMonth(day) { + this.day = day || this.day; + this.month -= 1; + + if (this.month < 1) { + this.month = 12; + this.year -= 1; + this.dateSelector.setYear(this.year); + } + + const totalDaysInMonth = dayjs( + `${this.year}-${this.month}-1`, + ).daysInMonth(); + if (this.day > totalDaysInMonth) this.day = totalDaysInMonth; + + this.dateSelector.setMonth(this.month - 1); + this.setDate(this.day, this.month, this.year); + + this.emit('month:previous', this.year); + }, +}); diff --git a/src/components/Calendar/index.scss b/src/components/Calendar/index.scss new file mode 100644 index 00000000..979e2c8b --- /dev/null +++ b/src/components/Calendar/index.scss @@ -0,0 +1,16 @@ +@use '~styles/base.scss'; +@use '~styles/colors.scss' as colors; +@use '~styles/fonts.scss' as fonts; +@use '~styles/breakpoints.scss' as breakpoints; + +.calendar { + &__controls { + display: flex; + + align-items: center; + + justify-content: space-between; + + margin-bottom: 2.4rem; + } +} diff --git a/src/components/Calendar/utils/months.js b/src/components/Calendar/utils/months.js new file mode 100644 index 00000000..956f6c9a --- /dev/null +++ b/src/components/Calendar/utils/months.js @@ -0,0 +1,14 @@ +export const MONTHS = [ + 'Janeiro', + 'Fevereiro', + 'Março', + 'Abril', + 'Maio', + 'Junho', + 'Julho', + 'Agosto', + 'Setembro', + 'Outubro', + 'Novembro', + 'Dezembro', +]; diff --git a/src/layouts/components/SideMenu/index.scss b/src/layouts/components/SideMenu/index.scss index 3ea4b4d3..959ae2de 100644 --- a/src/layouts/components/SideMenu/index.scss +++ b/src/layouts/components/SideMenu/index.scss @@ -84,31 +84,6 @@ font-style: fonts.$normal; } - &__avatars-yourpet { - max-height: calc(8.5rem * 2 + 2rem); - overflow-y: auto; - - display: grid; - grid-template-columns: repeat(3, 6rem); - gap: 2rem; - - margin-top: 2rem; - padding: 0.4rem 0.2rem; - - &::-webkit-scrollbar { - width: 0.4rem; - } - - &::-webkit-scrollbar-track { - background: colors.$primary600; - } - - &::-webkit-scrollbar-thumb { - background-color: colors.$primary700; - border-radius: 1rem; - } - } - &__itens { font-family: fonts.$primaryFont; color: colors.$secondary100; diff --git a/src/stories/Calendar.stories.js b/src/stories/Calendar.stories.js new file mode 100644 index 00000000..55c03cc2 --- /dev/null +++ b/src/stories/Calendar.stories.js @@ -0,0 +1,20 @@ +import Calendar from '../components/Calendar'; + +export default { + title: 'Components/Calendar', + render: (args) => { + const calendar = new Calendar(args); + const $container = document.createElement('div'); + calendar.mount($container); + + return $container; + }, +}; + +export const Default = { + args: { + day: 1, + month: 1, + year: 2024, + }, +}; diff --git a/src/styles/colors.scss b/src/styles/colors.scss index a2bddb97..b522f0ea 100644 --- a/src/styles/colors.scss +++ b/src/styles/colors.scss @@ -25,8 +25,8 @@ $error100: rgb(179, 38, 30); $white: rgb(255, 255, 255); -// neutrals (Gray) -$gray100: rgb(236, 239, 242); +// neutrals (Grey) +$gray100: rgb(247, 250, 252); $gray150: rgb(236, 239, 242); $gray200: rgb(224, 224, 224); $gray250: rgb(172, 172, 181); @@ -34,7 +34,7 @@ $gray300: rgb(179, 190, 205); $gray400: rgb(141, 141, 141); $gray500: rgb(96, 104, 115); $gray600: rgb(102, 116, 121); -$gray700: rgb(6, 8, 9); +$gray700: rgb(128, 139, 154); $gray800: rgb(57, 67, 79); $gray900: rgb(32, 35, 38); @@ -49,4 +49,6 @@ $shade100: rgb(0, 0, 0); // custom +$blue100: rgb(209, 230, 255); +$blue150: rgba(209, 230, 255, 0.5); $blue600: rgb(18, 104, 204);