kithkin/resources/css/lib/calendar.css

591 lines
15 KiB
CSS

/**
* month view
**/
.calendar.month {
@apply grid col-span-3 pb-6 2xl:pb-8 pt-2;
/*grid-template-rows: 2rem 1fr; */
/* force month container to fit window */
grid-template-rows: 2rem calc(100% - 2rem);
overflow-y: hidden;
hgroup {
@apply grid grid-cols-7 w-full gap-1;
> span {
@apply uppercase text-right pr-4 font-bold;
}
}
ol {
@apply grid grid-cols-7 w-full gap-1;
contain: paint;
grid-auto-rows: 1fr;
/*max-height: var(--month-calendar-height); */
/* day element */
li {
@apply bg-white relative px-1 pt-8 border-t-md border-gray-900 overflow-y-auto;
transition: scale 150ms ease-in-out;
/* day number */
&::before {
@apply sticky top-0 -mt-8 -translate-y-8 right-0 w-auto h-8 z-1;
@apply flex items-center justify-end pr-3 text-sm font-medium bg-inherit;
content: attr(data-day-number);
}
&.day--outside {
@apply bg-gray-50 text-gray-700;
}
&.day--today {
@apply bg-cyan-100;
}
/* need to handle this for various 4, 5, and 7 day configs */
&:nth-child(-n+7) { /* first 7 items */
@apply border-t-2;
}
&:nth-last-child(-n+7) { /* last 7 items */
@apply border-b-md;
}
/*&:last-child {
@apply rounded-br-lg;
}*/
/* progressive "show more" button */
div.more-events {
@apply absolute bottom-0 h-6 bg-inherit z-2 flex items-center;
width: calc(100% - 0.5rem);
}
button.day-more {
@apply text-xs px-1 h-4;
}
&[data-event-visible="0"] {
.event:nth-child(n+1) { @apply hidden; }
}
&[data-event-visible="1"] {
.event:nth-child(n+2) { @apply hidden; }
}
&[data-event-visible="2"] {
.event:nth-child(n+3) { @apply hidden; }
}
&[data-event-visible="3"] {
.event:nth-child(n+4) { @apply hidden; }
}
&[data-event-visible="4"] {
.event:nth-child(n+5) { @apply hidden; }
}
&[data-event-visible="5"] {
.event:nth-child(n+6) { @apply hidden; }
}
&[data-event-visible="6"] {
.event:nth-child(n+7) { @apply hidden; }
}
&[data-event-visible="7"] {
.event:nth-child(n+8) { @apply hidden; }
}
&[data-event-visible="8"] {
.event:nth-child(n+9) { @apply hidden; }
}
&[data-event-visible="9"] {
.event:nth-child(n+10) { @apply hidden; }
}
/* events */
.event {
@apply flex items-center text-xs gap-1 px-1 py-px font-medium truncate rounded-sm bg-transparent;
transition: background-color 125ms ease-in-out;
animation: event-slide 350ms ease-in-out both;
.indicator {
--indicator-bg: var(--event-color);
}
.title {
@apply grow truncate;
}
time {
@apply text-2xs shrink-0 mt-px;
}
&:hover {
background-color: color-mix(in srgb, var(--event-color) 25%, #fff 100%);
}
&.hidden {
@apply hidden;
}
}
/* expanded days with truncated events */
&.is-expanded {
position: relative;
height: min-content;
padding-bottom: 1px;
z-index: 3;
border: 1.5px solid black;
border-radius: 0.5rem;
scale: 1.05;
width: 120%;
margin-left: -10%;
margin-bottom: -100%; /* needed to break out of row in webkit */
div.more-events {
@apply relative h-8;
}
.event {
animation: none;
}
}
}
}
}
/**
* time-based views
*/
.calendar.time {
@apply grid;
grid-template-columns: 6rem auto;
grid-template-rows: 5rem auto 5rem;
--row-height: 2.5rem;
--now-row: 1;
--now-col-start: 1;
--now-col-end: 2;
/* if we have an all day event, change the grid */
&.allday {
grid-template-columns: 6rem auto;
grid-template-rows: 5rem min-content auto 5rem;
}
/* top day bar */
hgroup {
@apply bg-white col-span-2 border-b-2 border-primary pl-24 sticky z-10;
@apply top-20;
span.name {
@apply font-semibold uppercase text-sm;
}
a.number {
@apply flex items-center justify-center text-xl h-10 w-10 rounded-full bg-gray-100 font-semibold;
aspect-ratio: 1 / 1;
&:hover {
@apply bg-gray-200;
}
}
div.day-header {
@apply relative flex flex-col gap-1 justify-end items-start pb-2 h-full;
animation: header-slide 250ms ease-in;
&:not(:last-of-type)::after {
@apply block w-px bg-gray-200 absolute -right-2 top-20;
content: '';
height: calc(100dvh - 16rem);
}
&.active {
a.number {
@apply bg-teal-500 text-white;
&:hover {
@apply bg-teal-600;
}
}
}
}
}
/* all day bar */
ol.day {
@apply sticky top-42 grid col-span-2 bg-white py-2 border-b border-primary col-span-2 pl-24 z-2 overflow-x-hidden;
box-shadow: 0 0.25rem 0.5rem -0.25rem var(--color-gray-200);
&::before {
@apply absolute left-0 top-1/2 -translate-y-1/2 w-24 pr-4 text-right;
@apply uppercase text-xs font-mono text-secondary font-medium;
content: 'All day';
}
li.events {
@apply flex flex-col gap-1 relative overflow-x-hidden;
grid-row-start: var(--event-row);
grid-row-end: var(--event-end);
grid-column-start: var(--event-col);
grid-column-end: calc(var(--event-col) + 1);
a.event {
@apply flex items-center text-xs gap-1 px-1 py-px font-medium rounded-sm w-full;
background-color: var(--event-bg);
color: var(--event-fg);
> span {
@apply truncate;
}
&:hover {
background-color: color-mix(in srgb, var(--event-bg) 100%, #000 10%);
}
}
}
}
/* time column */
ol.time {
@apply grid z-0 pt-4;
grid-template-rows: repeat(var(--grid-rows, 96), var(--row-height));
time {
@apply relative flex items-center justify-end items-start pr-4;
@apply text-xs text-secondary font-mono;
&::after {
@apply block absolute h-px bg-gray-200;
width: calc(100cqw - 6rem);
content: '';
top: 0.6rem;
left: 6rem;
}
}
}
/* event positioning */
ol.events {
@apply grid py-4;
grid-template-rows: repeat(var(--grid-rows, 96), var(--row-height));
--event-col: 0;
--event-row: 0;
--event-end: 4;
--event-bg: var(--color-gray-100);
--event-fg: var(--color-primary);
li.event {
@apply flex rounded-md relative border border-white overflow-hidden;
background-color: var(--event-bg);
color: var(--event-fg);
grid-row-start: var(--event-row);
grid-row-end: var(--event-end);
grid-column-start: var(--event-col);
grid-column-end: calc(var(--event-col) + 1);
width: calc(100% - var(--event-overlap-offset, 100%));
margin-left: var(--event-overlap-offset, 0%);
z-index: var(--event-z, 1);
top: 0.6rem;
a.event {
@apply flex flex-col grow px-3 py-2 gap-2px text-sm;
> span {
@apply font-semibold leading-none break-all;
}
> time {
@apply text-2xs font-medium whitespace-nowrap;
}
}
&:hover {
/*animation: event-hover 125ms ease forwards;*/
transform: translateY(-2px);
transition:
transform 125ms ease-in;
/*width: 100%;*/
/*z-index: 20; /* enough to make sure it's always on top of other events */
}
}
}
/* bottom controls */
footer {
@apply bg-white flex items-center justify-between col-span-2 border-t-md border-primary;
@apply sticky bottom-0 pt-2 pb-6 z-10;
a.timezone {
@apply text-xs bg-gray-100 rounded px-2 py-1;
}
div.right {
@apply flex items-center gap-4 justify-end;
}
}
/* now indicator */
.now-indicator {
@apply relative pointer-events-none z-10 border-t-3 border-red-600 opacity-90 -ml-2;
grid-row: var(--now-row);
grid-column: var(--now-col-start) / var(--now-col-end);
width: calc(100% + 1rem);
top: calc(0.6rem + (var(--row-height) * var(--now-offset, 0)));
&::before {
@apply block w-3 h-3 rounded-full bg-red-600 -translate-y-1/2 -mt-[1.5px];
content: "";
}
}
}
/* step handling */
.calendar.time[data-density="30"] { /* half-hourly */
--row-height: 2rem;
ol.time li:nth-child(2n) {
visibility: hidden; /* preserves space + row alignment */
}
}
.calendar.time[data-density="60"] { /* hourly */
--row-height: 1.25rem;
ol.time li:not(:nth-child(4n + 1)) {
visibility: hidden; /* preserves space + row alignment */
}
&.week {
ol.events {
a.event {
@apply p-2;
}
li.event[data-span="1"] {
a.event > span,
a.event > time {
@apply text-xs;
}
}
li.event[data-span="1"],
li.event[data-span="2"] {
a.event {
@apply flex-col gap-0 py-1;
> span {
@apply min-h-4 line-clamp-1;
}
}
}
}
}
}
/**
* day view
*/
.calendar.day {
container: day / inline-size;
hgroup {
@apply flex items-start justify-start;
}
}
/**
* week view
*/
.calendar.week {
container: week / inline-size;
--days: 7;
hgroup {
@apply grid gap-x-2;
grid-template-columns: repeat(var(--days), 1fr);
}
ol.day {
@apply gap-x-2;
grid-template-columns: repeat(var(--days), 1fr);
}
ol.events {
@apply gap-x-2;
grid-template-columns: repeat(var(--days), 1fr);
--col: calc(100% / var(--days));
/* draw a 1px line at the start of each column repeat + highlight weekends */
/* need to factor in weekends on/off */
background-image:
linear-gradient(
to right,
var(--color-gray-10) var(--col),
transparent var(--col),
transparent calc((var(--col) * 6) + 5px),
var(--color-gray-10) calc((var(--col) * 6) + 5px)
);
background-position: 0;
background-size: 100%;
background-repeat: no-repeat;
}
&[data-weekstart="1"] {
ol.events {
background-image:
linear-gradient(
to right,
transparent,
transparent calc((var(--col) * 5) + 5px),
var(--color-gray-10) calc((var(--col) * 5) + 5px)
);
}
}
}
/**
* four-day view
*/
.calendar.four {
container: four / inline-size;
--days: 4;
hgroup {
@apply grid gap-x-2;
grid-template-columns: repeat(var(--days), 1fr);
}
ol.day {
@apply gap-x-2;
grid-template-columns: repeat(var(--days), 1fr);
}
ol.events {
@apply gap-x-2;
grid-template-columns: repeat(var(--days), 1fr);
--col: calc(100% / var(--days));
background-image:
repeating-linear-gradient(
to right,
transparent,
transparent var(--col),
var(--color-gray-200) var(--col),
var(--color-gray-200) calc(var(--col) + 1px)
);
background-position: 0;
background-size: 100%;
background-repeat: no-repeat;
}
}
/**
* calendar list in the left bar
*/
#calendar-toggles {
@apply pb-6;
summary {
@apply flex items-center gap-1 justify-start;
span {
@apply capitalize;
}
a {
@apply hidden -mt-2px;
}
&:hover {
a {
@apply flex;
}
}
}
li.calendar-toggle {
@apply relative;
/* hide the edit link by default */
.edit-link {
@apply hidden absolute pl-4 right-1 top-1/2 -translate-y-1/2 underline text-sm;
background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 33%);
}
/* show menu on hover */
&:hover {
.edit-link {
@apply block;
}
}
/* limit calendar titles to 1 line */
.checkbox-label span {
@apply line-clamp-1;
}
}
}
/**
* media queries
*/
@media (width >= theme(--breakpoint-2xl)) /* 96rem */
{
.calendar.time {
hgroup {
@apply top-22;
}
}
}
@media (height <= 50rem)
{
.calendar.time {
grid-template-rows: 4rem auto 5rem;
&.allday {
grid-template-rows: 4rem min-content auto 5rem;
}
ol.day {
@apply top-38;
}
hgroup {
div.day-header {
@apply flex-row items-center justify-start gap-2;
.name {
order: 2;
}
&:not(:last-of-type)::after {
@apply top-16;
}
}
}
}
}
/**
* animations
*/
@keyframes event-slide {
from {
opacity: 0;
transform: translateX(-1rem);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes event-hover {
from {
transform: translateY(0);
z-index: 1;
}
to {
transform: translateY(-2px);
z-index: 10;
}
}
@keyframes header-slide {
from {
opacity: 0;
transform: translateX(-0.25rem);
}
to {
opacity: 1;
transform: translateX(0);
}
}