Files
webmail/app/boot-skeleton.css
T

209 lines
7.4 KiB
CSS

/*
* Page skeletons (components/boot-skeleton).
*
* The server draws every variant of a skeleton; these variants show the one
* that matches the attributes the boot script set on <html> before the first
* paint (lib/boot-skeleton/boot-script.ts). Part of the first stylesheet, so
* nothing here arrives late.
*/
/* Mountain View shell. Its geometry only applies on desktop, so pair it with
lg: in markup (lg:mv:hidden), except the phone bottom bar, which follows
the layout at every width. */
@custom-variant mv (&:where([data-interface-layout="mountain-view"] *));
/* Mail layout (effectiveMailLayout: Mountain View and simple mode are focus). */
@custom-variant boot-split (&:where([data-boot-mail-layout="split"] *));
@custom-variant boot-horizontal (&:where([data-boot-mail-layout="horizontal"] *));
@custom-variant boot-focus (&:where([data-boot-mail-layout="focus"] *));
/* A message, thread, contact, settings page or admin page is open. */
@custom-variant boot-open (&:where([data-boot-pane] *));
@custom-variant boot-thread (&:where([data-boot-pane="thread"] *));
/* The Pro interface takes this page over on a desktop. */
@custom-variant boot-pro (&:where([data-boot-pro="on"] *));
/* Nothing stored that checkAuth could restore: draw the login card. */
@custom-variant boot-out (&:where([data-boot-auth="out"] *));
/* Calendar view. */
@custom-variant boot-cal-month (&:where([data-boot-calendar-view="month"] *));
@custom-variant boot-cal-week (&:where([data-boot-calendar-view="week"] *));
@custom-variant boot-cal-day (&:where([data-boot-calendar-view="day"] *));
@custom-variant boot-cal-agenda (&:where([data-boot-calendar-view="agenda"] *));
@custom-variant boot-cal-tasks (&:where([data-boot-calendar-view="tasks"] *));
@custom-variant boot-cal-collapsed (&:where([data-boot-collapsed~="calendar"] *));
/* Files. */
@custom-variant boot-files-grid (&:where([data-boot-files-view="grid"] *));
@custom-variant boot-files-details (&:where([data-boot-files-details="on"] *));
/* What the rail showed last time (bulwark-boot-hints). Without hints every
app is drawn: the rail of a server with all of them. */
@custom-variant boot-no-calendar (&:where([data-boot-rail]:not([data-boot-rail~="calendar"]) *));
@custom-variant boot-no-contacts (&:where([data-boot-rail]:not([data-boot-rail~="contacts"]) *));
@custom-variant boot-no-files (&:where([data-boot-rail]:not([data-boot-rail~="files"]) *));
@custom-variant boot-rail-add-app (&:where([data-boot-rail~="add-app"] *));
@custom-variant boot-rail-admin (&:where([data-boot-rail~="admin"] *));
@custom-variant boot-rail-a11y (&:where([data-boot-rail~="a11y"] *));
@custom-variant boot-rail-quota (&:where([data-boot-rail~="quota"] *));
/* A placeholder shape. A slow opacity pulse rather than a moving shimmer:
opacity runs on the compositor, so the skeleton costs the main thread
nothing while the app's JS is still starting up. */
.sk-shape {
background-color: var(--color-muted);
animation: sk-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes sk-pulse {
50% {
opacity: 0.55;
}
}
/* Reduced motion: no pulse at all (the global rule only shortens it). */
@media (prefers-reduced-motion: reduce) {
:root:not([data-motion="full"]) .sk-shape {
animation: none;
}
}
:root[data-motion="reduce"] .sk-shape {
animation: none;
}
/* More contrast: shapes that stand out from the panels they sit on. */
@media (prefers-contrast: more) {
:root:not([data-contrast="normal"]) .sk-shape {
background-color: color-mix(in oklab, var(--color-foreground) 28%, transparent);
}
}
:root[data-contrast="more"] .sk-shape {
background-color: color-mix(in oklab, var(--color-foreground) 28%, transparent);
}
/* Forced colours drop backgrounds; keep the shapes as system grey. */
@media (forced-colors: active) {
.sk-shape {
forced-color-adjust: none;
background-color: GrayText;
animation: none;
}
}
/* calendar */
/* Week numbers beside the sidebar's mini month (showWeekNumbers). */
@custom-variant boot-cal-weeknums (&:where([data-boot-cal-weeknums="on"] *));
/* Calendar tasks are on (enableCalendarTasks): a view pill and a sidebar row. */
@custom-variant boot-cal-tasks-on (&:where([data-boot-cal-tasks="on"] *));
/* The views measure their pane to size their rows; the skeleton does the
same with the pane as a size container. --sk-head is the header's
offsetHeight (whole pixels, as the views read it). */
.sk-cal-view {
container-type: size;
}
.sk-cal-week,
.sk-cal-day {
/* pt-2 + weekday line + gap-0.5 + date circle + pb-1.5 + border */
--sk-head: round(nearest, 3.5rem + 1.03125rem + 1px, 1px);
--sk-hour-min: 60px;
/* fillHourHeight takes the fitted height from ceil(min * 0.9) up. */
--sk-hour-floor: 54px;
--sk-hour: var(--sk-hour-min);
--sk-shift: 0px;
}
.sk-cal-day {
--sk-hour-min: 64px;
--sk-hour-floor: 58px;
}
.sk-cal-month {
/* py-2 + text-xs line + border */
--sk-head: calc(2rem + 1px);
--sk-week-min: 146px;
--sk-week: var(--sk-week-min);
}
@media (width < 48rem) {
.sk-cal-week {
--sk-head: round(nearest, 3rem + 1.03125rem + 1px, 1px);
}
.sk-cal-month {
--sk-head: round(nearest, 0.75rem + 1.03125rem + 1px, 1px);
--sk-week-min: 52px;
}
}
@supports (height: round(down, 1.5px, 1px)) and (height: 1cqh) {
.sk-cal-week,
.sk-cal-day {
--sk-fit: round(down, (100cqh - var(--sk-head)) / var(--boot-cal-hours, 12), 1px);
--sk-hour: max(var(--sk-fit), clamp(0px, (var(--sk-hour-floor) - var(--sk-fit)) * 1000, var(--sk-hour-min)));
/* The scroll the grid opens at: an hour before now, at most to the end. */
--sk-shift: clamp(
0px,
var(--boot-cal-scroll, -1) * var(--sk-hour-min) - 8px,
var(--boot-cal-hours, 12) * var(--sk-hour) - (100cqh - var(--sk-head))
);
}
.sk-cal-month {
--sk-week: max(var(--sk-week-min), round(down, (100cqh - var(--sk-head)) / 6, 1px));
}
}
.sk-cal-hours {
height: calc(var(--boot-cal-hours, 12) * var(--sk-hour));
}
.sk-cal-hours > * {
top: calc(-1 * var(--sk-shift));
}
.sk-cal-hour {
height: var(--sk-hour);
}
/* The slots' border-b border-border/50, one per hour, as a background. */
.sk-cal-slots {
background-image: linear-gradient(
to bottom,
transparent calc(var(--sk-hour) - 1px),
color-mix(in oklab, var(--color-border) 50%, transparent) calc(var(--sk-hour) - 1px)
);
background-size: 100% var(--sk-hour);
}
/* A range that starts at midnight leaves its first hour unlabelled. */
.sk-cal-first-label {
opacity: min(1, var(--boot-cal-start, 8));
}
/* The all-hours toggle shows while the hours are limited. */
.sk-cal-hours-toggle {
opacity: min(1, 24 - var(--boot-cal-hours, 12));
}
.sk-cal-month-week {
height: var(--sk-week);
}
.sk-cal-mini-days {
height: calc(var(--boot-cal-mini-rows, 6) * 1.75rem);
}
@media (pointer: coarse) {
.sk-cal-mini-days {
height: calc(var(--boot-cal-mini-rows, 6) * 2.75rem);
}
}
/* Week columns: floor((pane - gutter) / columns), at least 80px; 120px on
phones (calendar-week-view.tsx, measureColWidth). Columns past the pane
are the next days of the strip, cut off. */
.sk-cal-cols {
--sk-col: calc((100cqw - 3.5rem) / var(--boot-cal-cols, 7));
grid-auto-flow: column;
grid-auto-columns: var(--sk-col);
}
@supports (width: round(down, 1.5px, 1px)) and (width: 1cqw) {
.sk-cal-cols {
--sk-col: max(80px, round(down, (100cqw - 3.5rem) / var(--boot-cal-cols, 7), 1px));
}
}
@media (width < 48rem) {
.sk-cal-cols {
--sk-col: 120px;
}
}