Cleanup, layout fixes, better event colors.
This commit is contained in:
parent
c0d76109a1
commit
93c23c594c
6
calendar-main.css
Normal file
6
calendar-main.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* Calendar CSS - Main file with imports */
|
||||||
|
@import url('colors.css');
|
||||||
|
@import url('layout.css');
|
||||||
|
@import url('cells.css');
|
||||||
|
@import url('events.css');
|
||||||
|
@import url('utilities.css');
|
42
calendar.js
42
calendar.js
@ -113,7 +113,7 @@ class InfiniteCalendar {
|
|||||||
const handleWheel = e => {
|
const handleWheel = e => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
const currentYear = parseInt(this.weekLabel.textContent)
|
const currentYear = parseInt(this.yearLabel.textContent)
|
||||||
const topDisplayIndex = Math.floor(this.viewport.scrollTop / this.rowHeight)
|
const topDisplayIndex = Math.floor(this.viewport.scrollTop / this.rowHeight)
|
||||||
const currentWeekIndex = topDisplayIndex + this.minVirtualWeek
|
const currentWeekIndex = topDisplayIndex + this.minVirtualWeek
|
||||||
const sensitivity = 1/3
|
const sensitivity = 1/3
|
||||||
@ -125,7 +125,7 @@ class InfiniteCalendar {
|
|||||||
this.navigateToYear(newYear, currentWeekIndex)
|
this.navigateToYear(newYear, currentWeekIndex)
|
||||||
setTimeout(() => throttled = false, 100)
|
setTimeout(() => throttled = false, 100)
|
||||||
}
|
}
|
||||||
this.weekLabel.addEventListener('wheel', handleWheel, { passive: false })
|
this.yearLabel.addEventListener('wheel', handleWheel, { passive: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
navigateTo(date) {
|
navigateTo(date) {
|
||||||
@ -206,15 +206,15 @@ class InfiniteCalendar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createHeader() {
|
createHeader() {
|
||||||
this.weekLabel = document.createElement('div')
|
this.yearLabel = document.createElement('div')
|
||||||
this.weekLabel.className = 'dow-label'
|
this.yearLabel.className = 'year-label'
|
||||||
this.weekLabel.textContent = isoWeekInfo(new Date()).year
|
this.yearLabel.textContent = isoWeekInfo(new Date()).year
|
||||||
this.header.appendChild(this.weekLabel)
|
this.header.appendChild(this.yearLabel)
|
||||||
|
|
||||||
const names = this.getLocalizedWeekdayNames()
|
const names = this.getLocalizedWeekdayNames()
|
||||||
names.forEach((name, i) => {
|
names.forEach((name, i) => {
|
||||||
const c = document.createElement('div')
|
const c = document.createElement('div')
|
||||||
c.className = 'cell dow'
|
c.classList.add('dow')
|
||||||
const dayIdx = (i + 1) % 7
|
const dayIdx = (i + 1) % 7
|
||||||
if (this.weekend[dayIdx]) c.classList.add('weekend')
|
if (this.weekend[dayIdx]) c.classList.add('weekend')
|
||||||
c.textContent = name
|
c.textContent = name
|
||||||
@ -294,7 +294,7 @@ class InfiniteCalendar {
|
|||||||
const topVW = topDisplayIndex + this.minVirtualWeek
|
const topVW = topDisplayIndex + this.minVirtualWeek
|
||||||
const monday = this.getMondayForVirtualWeek(topVW)
|
const monday = this.getMondayForVirtualWeek(topVW)
|
||||||
const { year } = isoWeekInfo(monday)
|
const { year } = isoWeekInfo(monday)
|
||||||
if (this.weekLabel.textContent !== String(year)) this.weekLabel.textContent = year
|
if (this.yearLabel.textContent !== String(year)) this.yearLabel.textContent = year
|
||||||
}
|
}
|
||||||
|
|
||||||
createWeekElement(virtualWeek) {
|
createWeekElement(virtualWeek) {
|
||||||
@ -626,7 +626,7 @@ class InfiniteCalendar {
|
|||||||
title: eventData.title,
|
title: eventData.title,
|
||||||
startDate: eventData.startDate,
|
startDate: eventData.startDate,
|
||||||
endDate: eventData.endDate,
|
endDate: eventData.endDate,
|
||||||
color: this.generateEventColor()
|
colorId: this.generateEventColorId()
|
||||||
}
|
}
|
||||||
|
|
||||||
const startDate = new Date(fromLocalString(event.startDate))
|
const startDate = new Date(fromLocalString(event.startDate))
|
||||||
@ -641,12 +641,9 @@ class InfiniteCalendar {
|
|||||||
this.refreshEvents()
|
this.refreshEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
generateEventColor() {
|
generateEventColorId() {
|
||||||
const colors = [
|
// Return a color ID from 0-11 for 12 evenly spaced hues
|
||||||
'#ff6b6b', '#4ecdc4', '#45b7d1', '#96ceb4', '#feca57',
|
return Math.floor(Math.random() * 12)
|
||||||
'#ff9ff3', '#54a0ff', '#5f27cd', '#00d2d3', '#ff9f43'
|
|
||||||
]
|
|
||||||
return colors[Math.floor(Math.random() * colors.length)]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshEvents() {
|
refreshEvents() {
|
||||||
@ -705,22 +702,9 @@ class InfiniteCalendar {
|
|||||||
|
|
||||||
createOverlaySpan(overlay, w) {
|
createOverlaySpan(overlay, w) {
|
||||||
const span = document.createElement('div')
|
const span = document.createElement('div')
|
||||||
span.className = 'event-span'
|
span.className = `event-span event-color-${w.colorId}`
|
||||||
span.style.gridColumn = `${w.startIdx + 1} / ${w.endIdx + 2}`
|
span.style.gridColumn = `${w.startIdx + 1} / ${w.endIdx + 2}`
|
||||||
span.style.gridRow = `${w._row}`
|
span.style.gridRow = `${w._row}`
|
||||||
span.style.height = '1.2em'
|
|
||||||
span.style.borderRadius = '.4em'
|
|
||||||
span.style.fontSize = '.75em'
|
|
||||||
span.style.lineHeight = '1.2'
|
|
||||||
span.style.padding = '0 .5em'
|
|
||||||
span.style.whiteSpace = 'nowrap'
|
|
||||||
span.style.overflow = 'hidden'
|
|
||||||
span.style.textOverflow = 'ellipsis'
|
|
||||||
span.style.background = w.color
|
|
||||||
span.style.color = 'white'
|
|
||||||
span.style.fontWeight = '600'
|
|
||||||
span.style.pointerEvents = 'auto'
|
|
||||||
span.style.zIndex = '1'
|
|
||||||
span.textContent = w.title
|
span.textContent = w.title
|
||||||
span.title = `${w.title} (${w.startDate === w.endDate ? w.startDate : w.startDate + ' - ' + w.endDate})`
|
span.title = `${w.title} (${w.startDate === w.endDate ? w.startDate : w.startDate + ' - ' + w.endDate})`
|
||||||
overlay.appendChild(span)
|
overlay.appendChild(span)
|
||||||
|
39
colors.css
39
colors.css
@ -1,10 +1,9 @@
|
|||||||
/* Color tokens */
|
/* Color tokens */
|
||||||
:root {
|
:root {
|
||||||
--bg: #f6f7fb;
|
|
||||||
--panel: #fff;
|
--panel: #fff;
|
||||||
--today: #f83;
|
--today: #f83;
|
||||||
--ink: #111;
|
--ink: #222;
|
||||||
--ink-rgb: 17, 17, 17;
|
--inkstrong: #000;
|
||||||
--muted: #888;
|
--muted: #888;
|
||||||
--weekend: #888;
|
--weekend: #888;
|
||||||
--firstday: #000;
|
--firstday: #000;
|
||||||
@ -27,14 +26,26 @@
|
|||||||
.oct { background: hsl(18 78% 95%) }
|
.oct { background: hsl(18 78% 95%) }
|
||||||
.nov { background: hsl(18 78% 88%) }
|
.nov { background: hsl(18 78% 88%) }
|
||||||
|
|
||||||
|
.event-color-0 { background: hsl(0, 40%, 80%); }
|
||||||
|
.event-color-1 { background: hsl(30, 40%, 80%); }
|
||||||
|
.event-color-2 { background: hsl(60, 40%, 80%); }
|
||||||
|
.event-color-3 { background: hsl(90, 40%, 80%); }
|
||||||
|
.event-color-4 { background: hsl(120, 40%, 80%); }
|
||||||
|
.event-color-5 { background: hsl(150, 40%, 80%); }
|
||||||
|
.event-color-6 { background: hsl(180, 40%, 80%); }
|
||||||
|
.event-color-7 { background: hsl(210, 40%, 80%); }
|
||||||
|
.event-color-8 { background: hsl(240, 40%, 80%); }
|
||||||
|
.event-color-9 { background: hsl(270, 40%, 80%); }
|
||||||
|
.event-color-10 { background: hsl(300, 40%, 80%); }
|
||||||
|
.event-color-11 { background: hsl(330, 40%, 80%); }
|
||||||
|
|
||||||
/* Color tokens (dark) */
|
/* Color tokens (dark) */
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
--bg: radial-gradient(1200px 800px at 20% -10%, #1c2130 0%, #0c0f16 35%, #0a0b11 100%);
|
|
||||||
--panel: #111318;
|
--panel: #111318;
|
||||||
--today: #f83;
|
--today: #f83;
|
||||||
--ink: #ddd;
|
--ink: #ddd;
|
||||||
--ink-rgb: 221, 221, 221;
|
--inkstrong: #fff;
|
||||||
--muted: #888;
|
--muted: #888;
|
||||||
--weekend: #999;
|
--weekend: #999;
|
||||||
--firstday: #fff;
|
--firstday: #fff;
|
||||||
@ -56,15 +67,29 @@
|
|||||||
.sep { background: hsl(18 70% 18%) }
|
.sep { background: hsl(18 70% 18%) }
|
||||||
.oct { background: hsl(18 70% 26%) }
|
.oct { background: hsl(18 70% 26%) }
|
||||||
.nov { background: hsl(18 70% 18%) }
|
.nov { background: hsl(18 70% 18%) }
|
||||||
|
|
||||||
|
.event-color-0 { background: hsl(0, 40%, 50%); }
|
||||||
|
.event-color-1 { background: hsl(30, 40%, 50%); }
|
||||||
|
.event-color-2 { background: hsl(60, 40%, 50%); }
|
||||||
|
.event-color-3 { background: hsl(90, 40%, 50%); }
|
||||||
|
.event-color-4 { background: hsl(120, 40%, 50%); }
|
||||||
|
.event-color-5 { background: hsl(150, 40%, 50%); }
|
||||||
|
.event-color-6 { background: hsl(180, 40%, 50%); }
|
||||||
|
.event-color-7 { background: hsl(210, 40%, 50%); }
|
||||||
|
.event-color-8 { background: hsl(240, 40%, 50%); }
|
||||||
|
.event-color-9 { background: hsl(270, 40%, 50%); }
|
||||||
|
.event-color-10 { background: hsl(300, 40%, 50%); }
|
||||||
|
.event-color-11 { background: hsl(330, 40%, 50%); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Selection styles */
|
/* Selection styles */
|
||||||
.weekend { color: var(--weekend) }
|
.weekend { color: var(--weekend) }
|
||||||
.firstday { color: var(--firstday); text-shadow: 0 0 .1em rgba(var(--ink-rgb), .5) }
|
.firstday { color: var(--firstday); text-shadow: 0 0 .1em; }
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
background: var(--select);
|
background: var(--select);
|
||||||
border: 2px solid rgba(var(--ink-rgb), .3);
|
border: 2px solid var(--ink);
|
||||||
box-shadow: inset 0 0 0 1px rgba(255,255,255,.3);
|
box-shadow: inset 0 0 0 1px rgba(255,255,255,.3);
|
||||||
}
|
}
|
||||||
.selected .event { opacity: .7 }
|
.selected .event { opacity: .7 }
|
||||||
|
@ -4,9 +4,8 @@
|
|||||||
padding: .1em .3em;
|
padding: .1em .3em;
|
||||||
margin: .1em 0;
|
margin: .1em 0;
|
||||||
border-radius: .2em;
|
border-radius: .2em;
|
||||||
color: white;
|
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
white-space: nowrap;
|
white-space: normal;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -15,14 +14,13 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
.event:hover { opacity: .8 }
|
|
||||||
|
|
||||||
/* Spanning events in the overlay (grid-positioned, not absolutely measured) */
|
/* Spanning events in the overlay (grid-positioned, not absolutely measured) */
|
||||||
.event-span {
|
.event-span {
|
||||||
font-size: .75em;
|
font-size: .75em;
|
||||||
padding: 0 .5em;
|
padding: 0 .5em;
|
||||||
border-radius: .4em;
|
border-radius: .4em;
|
||||||
color: white;
|
color: var(--inkstrong);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
10
layout.css
10
layout.css
@ -51,13 +51,11 @@ header {
|
|||||||
.calendar-header, #calendar-header {
|
.calendar-header, #calendar-header {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: var(--label-w) repeat(7, var(--cell-w)) var(--overlay-w);
|
grid-template-columns: var(--label-w) repeat(7, var(--cell-w)) var(--overlay-w);
|
||||||
border-bottom: .1em solid var(--muted);
|
border-bottom: .2em solid var(--muted);
|
||||||
align-items: last baseline;
|
align-items: last baseline;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.calendar-header .dow-label { display:grid; place-items:center; height: var(--cell-h); color: var(--muted) }
|
|
||||||
.overlay-header-spacer { grid-column: -2 / -1 }
|
|
||||||
|
|
||||||
/* Main container */
|
/* Main container */
|
||||||
.calendar-container, #calendar-container {
|
.calendar-container, #calendar-container {
|
||||||
@ -108,16 +106,18 @@ header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Label cells */
|
/* Label cells */
|
||||||
.dow-label, .week-label {
|
.year-label, .week-label {
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: var(--cell-h);
|
|
||||||
color: var(--muted);
|
color: var(--muted);
|
||||||
cursor: ns-resize;
|
cursor: ns-resize;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.week-label {
|
||||||
|
height: var(--cell-h);
|
||||||
|
}
|
||||||
/* 7-day grid inside each week row */
|
/* 7-day grid inside each week row */
|
||||||
.week-row > .days-grid {
|
.week-row > .days-grid {
|
||||||
grid-column: 2 / span 7;
|
grid-column: 2 / span 7;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user