diff --git a/status/css/dashboard.css b/status/css/dashboard.css index 379ca5d..788ac11 100644 --- a/status/css/dashboard.css +++ b/status/css/dashboard.css @@ -4247,3 +4247,113 @@ button:focus-visible { .top-row[data-logo-pos="left"] .calendar-widget-container { order: 3; } .top-row[data-logo-pos="center"] .calendar-widget-container { order: 3; } .top-row[data-logo-pos="right"] .calendar-widget-container { order: 3; margin-top: -80px; } + +/* ========== CALENDAR WIDGET — DC-168 (month grid + themed chip) ========== */ +/* Chip: weather-widget sized (same padding/font as before); all colors via + CSS variables so every theme + user theme renders correctly. */ + +/* Chip text states */ +.calendar-widget .cal-chip-muted { color: var(--muted); } +.calendar-widget .cal-chip-title { color: var(--fg); font-weight: 600; } +.calendar-widget .cal-chip-when { + color: var(--cal-chip-when, var(--accent)); + font-size: 0.78em; + font-weight: 600; + margin-left: 4px; +} + +/* Month navigation bar */ +.cal-monthbar { + display: flex; align-items: center; justify-content: center; gap: 10px; + margin-bottom: 8px; +} +.cal-month-label { font-weight: 600; color: var(--fg); min-width: 130px; text-align: center; } +.cal-nav-btn { + background: var(--base); color: var(--fg); + border: 1px solid var(--border); border-radius: 6px; + padding: 2px 10px; cursor: pointer; font-size: 0.95rem; line-height: 1.3; +} +.cal-nav-btn:hover { background: var(--hover); border-color: var(--accent); } + +/* Month grid */ +.cal-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 3px; + margin-bottom: 4px; +} +.cal-dow { + text-align: center; font-size: 0.68rem; font-weight: 700; + color: var(--muted); text-transform: uppercase; padding: 2px 0; +} +.cal-day { + position: relative; + min-height: 34px; + border: 1px solid var(--border); + border-radius: 6px; + padding: 2px 4px; + font-size: 0.72rem; + color: var(--fg); + background: transparent; + display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; +} +.cal-day.cal-pad { border-color: transparent; } +.cal-day.cal-today { + border-color: var(--accent); + box-shadow: inset 0 0 0 1px var(--accent); +} +.cal-day.cal-has-events { + background: color-mix(in srgb, var(--accent) 16%, transparent); + border-color: color-mix(in srgb, var(--accent) 55%, var(--border)); + font-weight: 600; +} +.cal-day.cal-has-events.cal-today { + background: color-mix(in srgb, var(--accent) 26%, transparent); +} +.cal-dots { display: flex; gap: 2px; } +.cal-dot { + width: 5px; height: 5px; border-radius: 50%; + background: var(--cal-dot, var(--accent-strong)); +} + +/* Upcoming list rows */ +.cal-list { display: flex; flex-direction: column; gap: 4px; max-height: 180px; overflow-y: auto; } +.cal-row { display: flex; gap: 8px; align-items: baseline; } +.cal-when { font-size: 0.78rem; color: var(--cal-when, var(--accent)); white-space: nowrap; font-weight: 600; } +.cal-evtitle { font-size: 0.85rem; color: var(--fg); } +.cal-loc { font-size: 0.75rem; color: var(--muted); } +.cal-empty { color: var(--muted); font-size: 0.85rem; } + +/* Sources rows */ +.cal-src-row { + border: 1px solid var(--border); border-radius: 6px; padding: 6px 10px; + align-items: center; +} +.cal-btn { + font-size: 0.75rem; padding: 2px 8px; + background: var(--base); color: var(--fg); + border: 1px solid var(--border); border-radius: 4px; cursor: pointer; +} +.cal-btn:hover { background: var(--hover); border-color: var(--accent); } +.cal-btn-danger { color: var(--error, var(--bad-fg)); } + + +/* ========== DC-168: per-theme calendar chip contrast ========== */ +/* Small text (0.78em) must stay readable: on dark themes with dark accents, + brighten the chip-when/when colors; light themes keep the accent. */ +:root.taxi .calendar-widget .cal-chip-when, +:root.taxi .cal-when { --cal-chip-when: #e8b26a; --cal-when: #e8b26a; --cal-dot: #e8b26a; } +:root.ocean .calendar-widget .cal-chip-when, +:root.ocean .cal-when { --cal-chip-when: #7fb8e8; --cal-when: #7fb8e8; --cal-dot: #7fb8e8; } +:root.solarized-dark .calendar-widget .cal-chip-when, +:root.solarized-dark .cal-when { --cal-chip-when: #6fb3e0; --cal-when: #6fb3e0; --cal-dot: #6fb3e0; } +:root.solarized-light .cal-when { --cal-when: #1f6bab; --cal-dot: #1f6bab; } +:root.black .calendar-widget .cal-chip-when, +:root.black .cal-when { --cal-chip-when: #ff6b76; --cal-dot: #ff6b76; } + +/* User/custom themes: derive from --accent automatically ( lighten on dark). */ +:root.mytheme .calendar-widget .cal-chip-when, +:root.mytheme .cal-when { + --cal-chip-when: color-mix(in srgb, var(--accent) 70%, white); + --cal-when: color-mix(in srgb, var(--accent) 70%, white); +} diff --git a/status/js/calendar-widget.js b/status/js/calendar-widget.js index b5f7e74..966daa8 100644 --- a/status/js/calendar-widget.js +++ b/status/js/calendar-widget.js @@ -1,17 +1,32 @@ -// ========== CALENDAR WIDGET (DC-161) ========== +// ========== CALENDAR WIDGET (DC-161 + DC-168) ========== // Zero-config for calendars deployed through DashCaddy (Radicale auto-wiring); // manual CalDAV/ICS sources via the ⚙️ settings modal. Weather-widget pattern: // compact top-bar display + weather-modal shell + server-backed settings. +// +// DC-168 (owner requirements): +// 1. Empty → chip says "No upcoming appointments" (calendar IS connected). +// 2. With events → chip shows the next appointment (title + day/time). +// 3. Modal → month GRID with appointment days highlighted (+ times in +// tooltip and the Upcoming list), not just a flat list. +// 4. Chip stays weather-widget size (CSS keeps padding/font identical). +// 5. Everything styled with CSS variables + [data-theme] overrides in +// dashboard.css — correct across all themes and user themes. (function() { const errorHandler = new ErrorHandler(); injectModal('calendar-modal', `