diff --git a/src/components/calendar/CalendarWidget.tsx b/src/components/calendar/CalendarWidget.tsx index 97d3984..d1cb23e 100644 --- a/src/components/calendar/CalendarWidget.tsx +++ b/src/components/calendar/CalendarWidget.tsx @@ -2,10 +2,15 @@ import { useState, useMemo, useCallback, useEffect } from 'react'; import { format, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, isSameMonth, isSameDay, isToday } from 'date-fns'; import { useCalendar, CalendarEvent, formatEventTime } from '@/hooks/useCalendar'; import { VirtualKeyboard } from '@/components/keyboard'; +import { getEventColor } from './eventColors'; function EventItem({ event }: { event: CalendarEvent }) { + const color = getEventColor(event.summary); return ( -
+
{formatEventTime(event)} {event.summary}
); @@ -74,21 +79,28 @@ function EventDetails({ date, events, onAddEvent }: { date: Date; events: Calend

No events

) : (
- {events.map((event) => ( -
-
- - {formatEventTime(event)} - - {event.summary} -
- {event.location && ( -
- {event.location} + {events.map((event) => { + const color = getEventColor(event.summary); + return ( +
+
+ + + {formatEventTime(event)} + + {event.summary}
- )} -
- ))} + {event.location && ( +
+ {event.location} +
+ )} +
+ ); + })}
)}
diff --git a/src/components/calendar/eventColors.ts b/src/components/calendar/eventColors.ts new file mode 100644 index 0000000..f750344 --- /dev/null +++ b/src/components/calendar/eventColors.ts @@ -0,0 +1,32 @@ +// Google Calendar's 11 event colors, values lifted from the web client +// color picker. Colors are assigned deterministically by hashing the event +// summary so each recurring event always renders in the same color. +const GOOGLE_EVENT_COLORS = [ + { name: 'Tomato', bg: '#d50000', text: '#ffffff' }, + { name: 'Flamingo', bg: '#e67c73', text: '#ffffff' }, + { name: 'Tangerine', bg: '#f4511e', text: '#ffffff' }, + { name: 'Banana', bg: '#f6bf26', text: '#202124' }, + { name: 'Sage', bg: '#33b679', text: '#ffffff' }, + { name: 'Basil', bg: '#0b8043', text: '#ffffff' }, + { name: 'Peacock', bg: '#039be5', text: '#ffffff' }, + { name: 'Blueberry', bg: '#3f51b5', text: '#ffffff' }, + { name: 'Lavender', bg: '#7986cb', text: '#ffffff' }, + { name: 'Grape', bg: '#8e24aa', text: '#ffffff' }, + { name: 'Graphite', bg: '#616161', text: '#ffffff' }, +] as const; + +export type EventColor = (typeof GOOGLE_EVENT_COLORS)[number]; + +function hash(str: string): number { + let h = 2166136261; + for (let i = 0; i < str.length; i++) { + h ^= str.charCodeAt(i); + h = Math.imul(h, 16777619); + } + return h >>> 0; +} + +export function getEventColor(key: string): EventColor { + const idx = hash(key.toLowerCase().trim()) % GOOGLE_EVENT_COLORS.length; + return GOOGLE_EVENT_COLORS[idx]; +} diff --git a/src/components/photoframe/PhotoFrame.tsx b/src/components/photoframe/PhotoFrame.tsx index 589aac0..29be558 100644 --- a/src/components/photoframe/PhotoFrame.tsx +++ b/src/components/photoframe/PhotoFrame.tsx @@ -137,7 +137,7 @@ export function PhotoFrame({ intervalMs = 15_000, transitionMs = 1_200 }: PhotoF key={`prev-${prevSrc}`} src={prevSrc} alt="" - className="absolute inset-0 w-full h-full object-cover animate-ken-burns" + className="absolute inset-0 w-full h-full object-contain animate-ken-burns" style={{ opacity: 1 }} /> )} @@ -146,20 +146,18 @@ export function PhotoFrame({ intervalMs = 15_000, transitionMs = 1_200 }: PhotoF key={`cur-${index}`} src={currentSrc} alt="" - className="absolute inset-0 w-full h-full object-cover animate-ken-burns" + className="absolute inset-0 w-full h-full object-contain animate-ken-burns" style={{ opacity: 0, animation: `photo-fade-in ${transitionMs}ms ease-out forwards, ken-burns 20s ease-in-out infinite alternate`, }} /> )} - {/* Gradient + centered clock/date overlay (Skylight style) */} -
-
-
-
{timeStr}
-
{dateStr}
-
+ {/* Lower-right clock + date overlay */} +
+
{timeStr}
+
{dateStr}