Files
2026-07-13 12:12:04 +08:00

274 lines
6.6 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =============================================================================
* Calendar Component Styles
*
* A compound component for date selection.
* Uses BEM naming convention: calendar, calendar__element, calendar--modifier
* ============================================================================= */
/* -----------------------------------------------------------------------------
* Base Calendar Styles
* -------------------------------------------------------------------------- */
.calendar {
@apply w-63 max-w-63;
container-type: inline-size;
}
/* Week view visibleDuration={{ weeks: n }} */
.calendar--week-view {
.calendar__cell {
/* Keep cells circular on the 7-column grid; only filled cells take space. */
@apply aspect-square size-auto w-full place-self-center;
}
}
/* Day view visibleDuration={{ days: n }} */
.calendar--day-view {
.calendar__cell {
@apply aspect-square size-auto w-full place-self-center;
}
/*
* Isolate header and body into separate 7-column grids. With display:contents
* on the root grid, fewer than 7 weekday headers flow into the same row as dates.
*/
.calendar__grid {
display: flex;
flex-direction: column;
}
.calendar__grid-header {
display: grid;
grid-template-columns: repeat(7, 1fr);
@apply w-full;
& > tr {
display: contents;
}
}
.calendar__grid-body {
display: grid;
grid-template-columns: repeat(7, 1fr);
@apply mt-1 w-full;
& > tr {
display: contents;
}
& > tr:first-child > td {
@apply mt-0;
}
}
}
/* -----------------------------------------------------------------------------
* Calendar Header
* -------------------------------------------------------------------------- */
.calendar__header {
@apply flex items-center justify-between px-0.5 pb-4;
&:has(.calendar-year-picker__trigger[data-open="true"]) {
.calendar__nav-button {
@apply pointer-events-none opacity-0;
}
}
}
.calendar__heading {
@apply flex-1 text-sm font-medium;
}
.calendar__nav-button {
@apply flex size-6 items-center justify-center rounded-2xl text-accent-soft-foreground;
will-change: scale;
/**
* Transitions
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
*/
transition:
transform 250ms var(--ease-out),
background-color 100ms var(--ease-out),
box-shadow 100ms var(--ease-out),
opacity 150ms var(--ease-out);
@apply transform-gpu motion-reduce:transition-none;
cursor: var(--cursor-interactive);
/* Hover state only on devices that support hover (avoids false triggers on touch) */
@media (hover: hover) {
&:hover,
&[data-hovered="true"] {
@apply bg-default text-accent-soft-foreground;
}
}
/* Pressed state */
&:active,
&[data-pressed="true"] {
transform: scale(0.95);
}
/* Focus state */
&:focus-visible,
&[data-focus-visible="true"] {
@apply status-focused;
}
/* Disabled state */
&:disabled,
&[data-disabled="true"] {
@apply status-disabled;
}
}
.calendar__nav-button-icon {
@apply size-4;
}
/* -----------------------------------------------------------------------------
* Calendar Grid
* -------------------------------------------------------------------------- */
.calendar__grid {
/* Override table display with CSS Grid for easier customization */
display: grid;
grid-template-columns: repeat(7, 1fr);
@apply w-full;
&[aria-readonly="true"] {
.calendar__cell {
@apply pointer-events-none;
}
}
}
.calendar__grid-header {
/* Grid header (thead) styles */
display: contents;
& > tr {
display: contents;
}
}
.calendar__grid-body {
/* Grid body (tbody) styles */
display: contents;
& > tr {
display: contents;
}
/* Add top spacing between header and first body row */
& > tr:first-child > td {
@apply mt-1;
}
}
.calendar__grid-row {
/* Use 'contents' so cells participate directly in grid */
/* Note: This class can be used for custom row styling if needed */
display: contents;
}
.calendar__header-cell {
/* Header cell (th - weekday names) styles */
@apply flex items-center justify-center pb-2 text-xs font-medium text-muted;
}
/* -----------------------------------------------------------------------------
* Calendar Cells
* -------------------------------------------------------------------------- */
.calendar__cell {
/* Cell (td) wrapper styles - margins now work with grid layout */
@apply relative flex aspect-square size-full items-center justify-center rounded-3xl text-center text-sm font-medium outline-none no-highlight;
will-change: scale;
/**
* Transitions
* CRITICAL: motion-reduce must be AFTER transition for correct override specificity
*/
transition:
transform 250ms var(--ease-out),
box-shadow 100ms var(--ease-out);
@apply transform-gpu motion-reduce:transition-none;
cursor: var(--cursor-interactive);
/* Focus state */
&:focus-visible:not(:focus),
&[data-focus-visible="true"] {
@apply status-focused;
}
/* Today indicator */
&[data-today="true"] {
@apply bg-accent-soft text-accent-soft-foreground;
@media (hover: hover) {
&:hover:not([data-selected="true"]),
&[data-hovered="true"]:not([data-selected="true"]) {
@apply bg-accent-soft-hover;
}
}
}
/* Selected state */
&[data-selected="true"] {
@apply bg-accent text-accent-foreground;
}
/* Pressed state */
&:active,
&[data-pressed="true"] {
@apply bg-default;
transform: scale(0.95);
&[data-selected="true"] {
@apply bg-accent-hover;
}
}
/* Hover state only on devices that support hover (avoids false triggers on touch) */
@media (hover: hover) {
&:hover:not([data-selected="true"]),
&[data-hovered="true"]:not([data-selected="true"]) {
@apply bg-default;
}
}
/* Outside month (previous/next month days) */
&[data-outside-month="true"] {
@apply text-muted opacity-50;
}
&[data-selected="true"][data-outside-month="true"] {
@apply bg-default;
}
/* Unavailable dates */
&[data-unavailable="true"] {
@apply status-disabled;
}
/* Disabled state */
&:disabled:not([data-outside-month="true"]),
&[data-disabled="true"]:not([data-outside-month="true"]) {
@apply status-disabled;
text-decoration: line-through;
}
}
/* Cell indicator - small dot at bottom center of cell */
.calendar__cell-indicator {
@apply absolute bottom-1 left-1/2 size-[3px] -translate-x-1/2 rounded-xs bg-muted;
/* Indicator color changes when cell is selected */
[data-selected="true"] > & {
@apply bg-accent-foreground;
}
}