[pending-judge] feat(DC-168): calendar widget UX + theming — "No upcoming appointments" state, month grid with highlighted appointment days, theme-correct styling
Owner requests (2026-10-10/11): 1. "Instead of showing no calendar like it does now It should just show no upcoming appointments but if there are appointments it should show a calendar with the days and times highlighted for each appointment" 2. "We should properly stylize the calendar to fit with each theme correctly" 3. "Should also be a relatively small widget basically about the size of the weather widget" Changes (status/ only — frontend): - Chip: empty state now says "No upcoming appointments" (the calendar IS connected — the old "No calendar" string was wrong); with events it shows title + day/time with .cal-chip-when accent highlight. Chip CSS keeps the existing weather-widget proportions (padding 4px 10px, 0.85rem, pill). - Modal: month GRID (cal-grid, 7 columns, prev/next month nav) with: appointment days highlighted (accent-tinted background + border), today ring, per-event dots with time tooltips; Upcoming list kept below with day/time emphasis. Sources manager unchanged functionally, restyled via CSS vars. - Theming: every color via CSS variables (--fg/--muted/--accent/--border/ --base/--hover/--error). Per-theme overrides for dark-accent themes where small accent text fails contrast on dark surfaces (taxi/ocean/ solarized-dark get brightened chip-when/dots; black gets its red accent; solarized-light dark-on-light). User/custom themes derive automatically via color-mix(--accent, white). No hardcoded hex in the shared rules. Bug fixed en route: escapeHtml was previously expected as a global (never defined in this file — latent XSS/ReferenceError if another bundle didn't provide it). Now defined locally. Verification: node --check clean; DC-168 smoke harness (DOM shim) proves empty chip → "No upcoming appointments", events chip → title + highlighted when-span, modal grid renders correct day-cell counts with cal-day/cal-dow structure; eslint 0 errors (parser-options run).
This commit is contained in:
2 files changed
+219
-23
No files matched your search
@@ -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);
|
||||
}
|
||||
Reference in new issue
Block a user