/* ============================================================================= * RangeCalendar Component Styles * * A compound component for contiguous date range selection. * Uses BEM naming convention: range-calendar, range-calendar__element, range-calendar--modifier * ============================================================================= */ /* ----------------------------------------------------------------------------- * Base RangeCalendar Styles * -------------------------------------------------------------------------- */ .range-calendar { @apply w-63 max-w-63; container-type: inline-size; } /* Week view – visibleDuration={{ weeks: n }} */ .range-calendar--week-view { .range-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 }} */ .range-calendar--day-view { .range-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. */ .range-calendar__grid { display: flex; flex-direction: column; } .range-calendar__grid-header { display: grid; grid-template-columns: repeat(7, 1fr); @apply w-full; & > tr { display: contents; } } .range-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; } } } /* ----------------------------------------------------------------------------- * RangeCalendar Header * -------------------------------------------------------------------------- */ .range-calendar__header { @apply flex items-center justify-between px-0.5 pb-4; &:has(.calendar-year-picker__trigger[data-open="true"]) { .range-calendar__nav-button { @apply pointer-events-none opacity-0; } } } .range-calendar__heading { @apply flex-1 text-sm font-medium; } .range-calendar__nav-button { @apply flex size-6 items-center justify-center rounded-xl 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; } } .range-calendar__nav-button-icon { @apply size-4; } /* ----------------------------------------------------------------------------- * RangeCalendar Grid * -------------------------------------------------------------------------- */ .range-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"] { .range-calendar__cell { @apply pointer-events-none; } } } .range-calendar__grid-header { /* Grid header (thead) styles */ display: contents; & > tr { display: contents; } } .range-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; } } .range-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; } .range-calendar__header-cell { /* Header cell (th - weekday names) styles */ @apply flex items-center justify-center pb-2 text-xs font-medium text-muted; } /* ----------------------------------------------------------------------------- * RangeCalendar Cells * -------------------------------------------------------------------------- */ .range-calendar__cell { @apply relative z-1 mx-0 my-[2px] rounded-3xl p-0 outline-none; cursor: var(--cursor-interactive); will-change: background-color, border-color; /** * Transitions * CRITICAL: motion-reduce must be AFTER transition for correct override specificity */ transition: box-shadow 100ms var(--ease-out), border-color 100ms var(--ease-out); @apply transform-gpu motion-reduce:transition-none; /* Inner interactive circle/capsule (equivalent to React Aria "button-base") */ .range-calendar__cell-button { @apply flex aspect-square w-full items-center justify-center rounded-3xl text-sm font-medium text-foreground no-highlight; will-change: scale; transition: scale 200ms var(--ease-out); @apply transform-gpu motion-reduce:transition-none; } /* Focus state */ &:focus-visible:not(:focus), &[data-focus-visible="true"] { @apply z-2; .range-calendar__cell-button { @apply status-focused; } } /* Today indicator */ &[data-today="true"] { .range-calendar__cell-button { @apply bg-accent-soft text-accent-soft-foreground; } @media (hover: hover) { &:hover:not([data-selected="true"]), &[data-hovered="true"]:not([data-selected="true"]) { .range-calendar__cell-button { @apply bg-accent-soft-hover; } } } } /* Range selected track (middle segment) */ &[data-selected="true"]:not([data-outside-month="true"]) { @apply rounded-none bg-accent-soft; } /* Round row boundaries so the range track looks continuous across weeks */ &[data-selected="true"]:is(td:first-child > *, [aria-disabled] + td > *) { @apply rounded-ss-lg rounded-es-lg; &[data-selection-start="true"] { @apply rounded-ss-3xl rounded-es-3xl; } } &[data-selected="true"]:is(td:last-child > *, td:has(+ [aria-disabled]) > *) { @apply rounded-se-lg rounded-ee-lg; &[data-selection-end="true"] { @apply rounded-se-3xl rounded-ee-3xl; } } /* Range caps (start/end) */ &[data-selection-start="true"]:not([data-outside-month="true"]), &[data-selection-end="true"]:not([data-outside-month="true"]) { @apply z-2; .range-calendar__cell-button { @apply bg-accent text-accent-foreground; } } /* &[data-selection-start="true"]:has(+ [data-selection-end="true"]) { @apply rounded-full; } */ &[data-selection-start="true"]:not([data-outside-month="true"]) { @apply rounded-tl-3xl rounded-bl-3xl; } &[data-selection-end="true"]:not([data-outside-month="true"]) { @apply rounded-tr-3xl rounded-br-3xl; } /* Pressed state */ &:active, &[data-pressed="true"] { .range-calendar__cell-button { scale: 0.9; } &[data-selection-start="true"], &[data-selection-end="true"] { .range-calendar__cell-button { @apply bg-accent-hover; } } } /* Hover state for non-selected days */ @media (hover: hover) { &:hover:not([data-selected="true"]), &[data-hovered="true"]:not([data-selected="true"]) { .range-calendar__cell-button { @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"]:not( [data-selection-start="true"], [data-selection-end="true"] ) { @apply bg-default/20; } /* 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; } } /* Outside-month cell followed by selected cell across adjacent table cells */ .range-calendar__grid-body td:has(> .range-calendar__cell[data-outside-month="true"]) + td > .range-calendar__cell[data-selected="true"] { @apply rounded-ss-lg rounded-es-lg; &[data-outside-month="true"], &[data-selection-start="true"] { @apply rounded-ss-3xl rounded-es-3xl; } } /* Selected cell followed by outside-month cell across adjacent table cells */ .range-calendar__grid-body td:has(> .range-calendar__cell[data-selected="true"]):has( + td > .range-calendar__cell[data-outside-month="true"] ) > .range-calendar__cell[data-selected="true"] { @apply rounded-se-lg rounded-ee-lg; &[data-outside-month="true"], &[data-selection-end="true"] { @apply rounded-se-3xl rounded-ee-3xl; } } /* Cell indicator - small dot at bottom center of cell */ .range-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; } }