From 81fd7dec587612409f988299af59d6a5535bd898 Mon Sep 17 00:00:00 2001 From: Guillermo Pages Date: Wed, 16 Jul 2025 16:54:55 +0200 Subject: [PATCH] feat: active date --- src/App.tsx | 2 + src/components/calendar/DateRange/index.tsx | 19 ++++- src/components/calendar/Day/Day.module.scss | 83 ++++++++++++++++++++- src/components/calendar/Day/index.tsx | 1 + src/components/calendar/DayNumber/index.tsx | 1 + src/types/calendar.ts | 3 +- 6 files changed, 105 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index ab6a755..8991663 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,6 +3,7 @@ import { DateRangePicker } from './examples/DateRangePicker'; import { SingleMonth } from './examples/SingleMonth'; import { WeekView } from './examples/WeekView'; import { DateRangeView } from './examples/DateRangeView'; +import { InteractiveDateRange } from './examples/InteractiveDateRange'; import { CompactYear } from './examples/CompactYear'; import styles from './App.module.scss'; @@ -13,6 +14,7 @@ const App: React.FC = () => { + ); diff --git a/src/components/calendar/DateRange/index.tsx b/src/components/calendar/DateRange/index.tsx index 68844d9..022c5d7 100644 --- a/src/components/calendar/DateRange/index.tsx +++ b/src/components/calendar/DateRange/index.tsx @@ -16,6 +16,8 @@ interface DateRangeProps { size?: DaySize; fontProportion?: number; magnify?: boolean; + onDateClick?: (date: Date) => void; + activeDates?: Date[]; } export const DateRange: React.FC = ({ @@ -27,7 +29,9 @@ export const DateRange: React.FC = ({ weekendDays = [6, 0], size = 'l', fontProportion = 100, - magnify = false + magnify = false, + onDateClick, + activeDates = [] }) => { const startDate = startOfDay(from); const endDate = startOfDay(to); @@ -53,6 +57,16 @@ export const DateRange: React.FC = ({ const dayOfWeek = date.getDay(); const variations = getDateVariations(date, dateRange, weekendDays, dayOfWeek); + // Check if this date is active + const isActive = activeDates.some(activeDate => + startOfDay(activeDate).getTime() === startOfDay(date).getTime() + ); + + // Add 'active' to variations if the date is active + const variationsWithActive = isActive + ? [...variations, 'active' as DayVariation] + : variations; + const wrapperClasses = classNames( styles.DateRange__DayWrapper, { @@ -67,7 +81,8 @@ export const DateRange: React.FC = ({ onDateClick(date) : undefined} size={size} fontProportion={fontProportion} magnify={magnify} diff --git a/src/components/calendar/Day/Day.module.scss b/src/components/calendar/Day/Day.module.scss index f981ada..938ca2f 100644 --- a/src/components/calendar/Day/Day.module.scss +++ b/src/components/calendar/Day/Day.module.scss @@ -190,6 +190,69 @@ } // end implicit (midrange) { + // active state - inverted colors + &.Day__Container--active { + background: colors.$day-header-defaultmode-defaultstate-background-color; + color: colors.$day-header-defaultmode-defaultstate-color; + + .Day__Header { + background: colors.$day-content-defaultmode-defaultstate-background-color; + color: colors.$day-content-defaultmode-defaultstate-color; + } + + .Day__Number { + color: colors.$day-header-defaultmode-defaultstate-color; + + // Ensure number stays inverted on hover + .Day__Container--interactive:hover & { + color: colors.$day-header-defaultmode-defaultstate-color; + } + } + + // Maintain dark background on hover + &.Day__Container--interactive:hover { + background: colors.$day-header-defaultmode-defaultstate-background-color; + } + + &.Day__Container--greyed { + background: colors.$day-header-greyedmode-defaultstate-background-color; + color: colors.$day-header-greyedmode-defaultstate-color; + + .Day__Header { + background: colors.$day-content-greyedmode-defaultstate-background-color; + color: colors.$day-content-greyedmode-defaultstate-color; + } + + .Day__Number { + color: colors.$day-header-greyedmode-defaultstate-color; + + // Ensure number stays inverted on hover for greyed days + .Day__Container--interactive:hover & { + color: colors.$day-header-greyedmode-defaultstate-color; + } + } + + // Maintain grey background on hover + &.Day__Container--interactive:hover { + background: colors.$day-header-greyedmode-defaultstate-background-color; + } + } + + // Active state takes precedence over selected/selecting for visual clarity + &.Day__Container--selected, + &.Day__Container--selecting { + background: colors.$day-header-defaultmode-defaultstate-background-color; + + .Day__Header { + background: colors.$day-content-defaultmode-defaultstate-background-color; + } + + .Day__Number { + color: colors.$day-header-defaultmode-defaultstate-color; + } + } + } + // rangestart (selected|selecting)(greyed|defaultMode) &.Day__Container--rangeStart:not(.Day__Container--rangeEnd) { // implicit .Day__Container--selected { @@ -488,7 +551,7 @@ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; font-feature-settings: 'tnum' on, 'lnum' on; - .Day__Container--interactive:hover &:not(&--selected) { + .Day__Container--interactive:hover &:not(&--selected):not(&--active) { fill: colors.$day-color-interactive-text-hover; } @@ -497,6 +560,24 @@ fill: colors.$day-content-greyedmode-defaultstate-color; } + // Active state - inverted colors (high priority) + &--active { + fill: colors.$day-header-defaultmode-defaultstate-color; + + // Ensure active state is maintained on hover + .Day__Container--interactive:hover & { + fill: colors.$day-header-defaultmode-defaultstate-color; + } + + &.DayNumber__Text--greyed { + fill: colors.$day-header-greyedmode-defaultstate-color; + + .Day__Container--interactive:hover & { + fill: colors.$day-header-greyedmode-defaultstate-color; + } + } + } + // Selected states &--selected { fill: colors.$day-content-defaultmode-selectedstate-midrange-color; diff --git a/src/components/calendar/Day/index.tsx b/src/components/calendar/Day/index.tsx index 6457268..97f8621 100644 --- a/src/components/calendar/Day/index.tsx +++ b/src/components/calendar/Day/index.tsx @@ -40,6 +40,7 @@ export const Day: React.FC = ({ [styles['Day__Container--greyed']]: variations.includes('greyed'), [styles['Day__Container--rowStart']]: variations.includes('rowStart'), [styles['Day__Container--rowEnd']]: variations.includes('rowEnd'), + [styles['Day__Container--active']]: variations.includes('active'), [styles['magnify']]: magnify && (variations.includes('selected') || variations.includes('selecting')) }, styles[`Day--${headerStyle}`], diff --git a/src/components/calendar/DayNumber/index.tsx b/src/components/calendar/DayNumber/index.tsx index e105546..be6923e 100644 --- a/src/components/calendar/DayNumber/index.tsx +++ b/src/components/calendar/DayNumber/index.tsx @@ -54,6 +54,7 @@ export const DayNumber: React.FC = ({ [styles['DayNumber__Text--selecting']]: variations.includes('selecting'), [styles['DayNumber__Text--rangeStart']]: variations.includes('rangeStart'), [styles['DayNumber__Text--rangeEnd']]: variations.includes('rangeEnd'), + [styles['DayNumber__Text--active']]: variations.includes('active'), } ); diff --git a/src/types/calendar.ts b/src/types/calendar.ts index b7124e0..a5a347b 100644 --- a/src/types/calendar.ts +++ b/src/types/calendar.ts @@ -16,7 +16,8 @@ export type DayVariation = | 'rangeEnd' | 'selecting' | 'rowStart' - | 'rowEnd'; + | 'rowEnd' + | 'active'; export type DaySize = 'xl' | 'l' | 'm' | 's' | 'xs' | 'xxs'; export interface YearProps {