feat(calendar): redesign app using plain HTML/CSS/TS#717
feat(calendar): redesign app using plain HTML/CSS/TS#717nicomiguelino wants to merge 19 commits intomasterfrom
Conversation
- Migrate from Vue 3 + Pinia to framework-free Web Components - Add reusable weekly-calendar-view custom element to edge-apps-library Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Explore these optional code suggestions:
|
- Fix missing error cause in events.ts - Extract CSS and utility functions into separate files to satisfy max-lines rules - Add e2e screenshots Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… file - Update `.this-week-title` to Inter Regular (weight 400), normal style, centered, with letter-spacing - Remove unused `weekly-calendar-view.css` (CSS lives in `weekly-calendar-view-styles.ts`)
- Increase day name font size to 0.98rem with line-height 1.333 - Increase day date font size to 1.469rem with line-height 1.556 - Add opacity 0.8 to today's day name - Increase day header height and time gutter padding-top to 5.225rem - Increase time gutter width to 6.5rem and padding-right to 1rem - Match time label font size to day name (0.98rem)
- Set day-body overflow to visible so the time indicator dot is not clipped - Adjust current time indicator dot left offset to -0.27rem - Remove horizontal margin from .header to fix app header alignment
- Force landscape orientation with letterbox bars and vertical centering - Fix app header margins and compact event display for short events - Fix timezone-aware day header date and locale-aware day names - Match Figma design tokens for event card and title styles
- Replace --calendar-accent-color with --theme-color-primary - Style app-header background and text color from theme - Make weekly-calendar-view background transparent
- Add `daily-calendar-view` Web Component with same styling as weekly view - Add `calendar-view-utils.ts` with shared `buildTimeGutter` and `buildEventElement` - Extract `filterEventsForWindow` into shared utils to eliminate duplication - Support `calendar_mode` setting to switch between weekly and daily views Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `schedule-calendar-view` Web Component showing today/tomorrow events - Move `calendar-view-utils.ts` to components root (shared by all views) - Fix `generateTimeSlots` to use configured timezone for time labels - Support `schedule` as default `calendar_mode` in calendar app Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add per-mode screenshot loops (schedule, weekly, daily)
- Rename files from `WxH.png` to `{mode}-WxH.png`
- Enrich ICS mock data with more events for schedule view
- Set screenly_color_accent to #2E8B57 in mock settings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move icon.svg from static/ to static/img/ - Update icon URL in manifest files to match new path - Remove unused bg.webp from static/images/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename calendar-new to calendar, replacing the old Vue 3/Pinia app - Add schedule, weekly, and daily calendar views as Web Components - Remove Vue, Vite, and blueprint dependencies - Update build tooling to use edge-apps-scripts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR migrates the Calendar edge app from a Vue 3 + Pinia implementation to framework-free Web Components, and introduces reusable calendar view components in edge-apps-library (daily/weekly/schedule) with shared event layout + rendering utilities.
Changes:
- Add
<weekly-calendar-view>,<daily-calendar-view>, and<schedule-calendar-view>Web Components (plus shared event layout + DOM builder utilities) toedge-apps-library. - Rewrite the Calendar app to render those components from plain HTML/CSS/TS, including new screenshot-test coverage and updated assets.
- Remove Vue/Vite/Vitest/Pinia scaffolding from the Calendar app and update manifests/docs accordingly.
Reviewed changes
Copilot reviewed 46 out of 87 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view.ts | New weekly view Web Component rendering a 7-day grid with event layout + current-time indicator. |
| edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view-utils.ts | Shared helpers for windowing, slot generation, event styling/clipping, and safe attribute setting. |
| edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view-styles.ts | Shadow-DOM CSS for the weekly view. |
| edge-apps/edge-apps-library/src/components/weekly-calendar-view/index.ts | Public exports for weekly view component + event type. |
| edge-apps/edge-apps-library/src/components/weekly-calendar-view/event-layout.ts | Event overlap clustering + column layout algorithm for time-grid views. |
| edge-apps/edge-apps-library/src/components/vite-env.d.ts | Add *.css?inline module typing for component CSS imports. |
| edge-apps/edge-apps-library/src/components/schedule-calendar-view/schedule-calendar-view.ts | New schedule list view Web Component (today + tomorrow, capped). |
| edge-apps/edge-apps-library/src/components/schedule-calendar-view/schedule-calendar-view-styles.ts | Shadow-DOM CSS for the schedule view. |
| edge-apps/edge-apps-library/src/components/schedule-calendar-view/index.ts | Public export for schedule view component. |
| edge-apps/edge-apps-library/src/components/daily-calendar-view/daily-calendar-view.ts | New daily view Web Component (12-hour window, event layout, current-time indicator). |
| edge-apps/edge-apps-library/src/components/daily-calendar-view/daily-calendar-view-styles.ts | Shadow-DOM CSS for the daily view. |
| edge-apps/edge-apps-library/src/components/daily-calendar-view/index.ts | Public export for daily view component. |
| edge-apps/edge-apps-library/src/components/calendar-view-utils.ts | Shared DOM builders for time gutter + event cards used by daily/weekly views. |
| edge-apps/edge-apps-library/src/components/register.ts | Register new calendar custom elements alongside existing components. |
| edge-apps/edge-apps-library/src/components/index.ts | Export new calendar view components (and CalendarEvent type) from the library entrypoint. |
| edge-apps/edge-apps-library/package.json | Add dayjs dependency needed by the new components/utilities. |
| edge-apps/edge-apps-library/bun.lock | Lockfile update for added dependency. |
| edge-apps/calendar/src/types.ts | New local types (CalendarEvent, ViewMode, VIEW_MODE) for the rewritten app. |
| edge-apps/calendar/src/main.ts | Rewrite app bootstrap to use Web Components, theme/error setup, and periodic ticking/refresh. |
| edge-apps/calendar/src/events.ts | Update iCal fetching/parsing to be framework-free and accept explicit timezone input. |
| edge-apps/calendar/src/css/style.css | New global app styles (layout + view switching via .active). |
| edge-apps/calendar/index.html | Replace Vue mount point with static layout using auto-scaler, app-header, and calendar view elements. |
| edge-apps/calendar/package.json | Switch scripts/tooling to edge-apps-scripts workflow; remove Vue/Pinia/Vitest plumbing. |
| edge-apps/calendar/README.md | Update deployment/dev/testing/screenshot instructions for the new architecture. |
| edge-apps/calendar/e2e/screenshots.spec.ts | Add Playwright-based screenshot generation test across modes and resolutions. |
| edge-apps/calendar/screenly.yml | Update manifest icon URL path. |
| edge-apps/calendar/screenly_qc.yml | Update QC manifest icon URL path. |
| edge-apps/calendar/.ignore | Add ignore file for deployment packaging (node_modules). |
| edge-apps/calendar/.gitignore | Add gitignore for build artifacts/logs/etc. |
| edge-apps/calendar/vitest.config.ts | Remove Vitest config (no longer using Vitest). |
| edge-apps/calendar/vite.config.ts | Remove Vite config (now handled by edge-apps-scripts). |
| edge-apps/calendar/tsconfig.vitest.json | Remove Vitest TS config. |
| edge-apps/calendar/tsconfig.node.json | Remove node/tooling TS config. |
| edge-apps/calendar/tsconfig.json | Remove TS project references for the prior Vue setup. |
| edge-apps/calendar/tsconfig.app.json | Remove Vue app TS config. |
| edge-apps/calendar/src/utils.ts | Remove re-export utilities tied to the old blueprint/Vue setup. |
| edge-apps/calendar/src/test-setup.ts | Remove prior Vitest setup. |
| edge-apps/calendar/src/stores/settings.ts | Remove Pinia settings store. |
| edge-apps/calendar/src/stores/calendar.ts | Remove Pinia calendar store. |
| edge-apps/calendar/src/constants.ts | Remove old constants re-export. |
| edge-apps/calendar/src/components/tests/App.spec.ts | Remove Vue unit test. |
| edge-apps/calendar/src/assets/main.scss | Remove old SCSS styling tied to Vue blueprint layout. |
| edge-apps/calendar/src/App.vue | Remove Vue root component. |
| edge-apps/calendar/playwright.config.ts | Remove old Playwright config (now using shared screenshot helpers). |
| edge-apps/calendar/eslint.config.ts | Remove Vue/Vitest/Playwright-specific ESLint config (now via edge-apps-scripts). |
| edge-apps/calendar/e2e/vue.spec.ts | Remove old Vue-focused Playwright test. |
| edge-apps/calendar/e2e/tsconfig.json | Remove old e2e TS config. |
| edge-apps/calendar/.vscode/extensions.json | Remove Vue/Vitest editor recommendations. |
| edge-apps/calendar/screenshots/weekly-800x480.webp | Add updated weekly-mode screenshot artifact. |
| edge-apps/calendar/screenshots/weekly-720x1280.webp | Add updated weekly-mode screenshot artifact. |
| edge-apps/calendar/screenshots/weekly-480x800.webp | Add updated weekly-mode screenshot artifact. |
| edge-apps/calendar/screenshots/schedule-800x480.webp | Add updated schedule-mode screenshot artifact. |
| edge-apps/calendar/screenshots/schedule-720x1280.webp | Add updated schedule-mode screenshot artifact. |
| edge-apps/calendar/screenshots/schedule-480x800.webp | Add updated schedule-mode screenshot artifact. |
| edge-apps/calendar/screenshots/daily-800x480.webp | Add updated daily-mode screenshot artifact. |
| edge-apps/calendar/screenshots/daily-720x1280.webp | Add updated daily-mode screenshot artifact. |
| edge-apps/calendar/screenshots/daily-480x800.webp | Add updated daily-mode screenshot artifact. |
| edge-apps/calendar/screenshots/daily-1280x720.webp | Add updated daily-mode screenshot artifact. |
| edge-apps/calendar/screenshots/daily-1080x1920.webp | Add updated daily-mode screenshot artifact. |
| edge-apps/calendar/static/images/enable-google-calendar-api.png | Include static documentation image asset for setup instructions. |
| edge-apps/calendar/static/images/authorization-code.png | Include static documentation image asset for setup instructions. |
| edge-apps/calendar/src/assets/font/Aeonik-Regular.woff2 | Include font asset (legacy/compat). |
| edge-apps/calendar/src/assets/font/Aeonik-Regular.woff | Include font asset (legacy/compat). |
| edge-apps/calendar/public/fonts/Aeonik-Regular.woff2 | Include font asset served from public/. |
| edge-apps/calendar/public/fonts/Aeonik-Regular.woff | Include font asset served from public/. |
| edge-apps/calendar/public/favicon.ico | Include app favicon asset. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const tick = () => { | ||
| activeEl.now = new Date() | ||
| } | ||
| tick() | ||
| setInterval(tick, 1000) | ||
|
|
| import './weekly-calendar-view/weekly-calendar-view.js' | ||
| import './daily-calendar-view/daily-calendar-view.js' | ||
| import './schedule-calendar-view/schedule-calendar-view.js' | ||
|
|
||
| import { WeeklyCalendarView } from './weekly-calendar-view/weekly-calendar-view.js' | ||
| import { DailyCalendarView } from './daily-calendar-view/daily-calendar-view.js' | ||
| import { ScheduleCalendarView } from './schedule-calendar-view/schedule-calendar-view.js' |
| // 'en-US' is intentional — we need locale-independent numeric output | ||
| // for parseInt() to work correctly regardless of the configured locale. | ||
| const currentHour = parseInt( | ||
| now.toLocaleString('en-US', { | ||
| hour: 'numeric', | ||
| hour12: false, | ||
| timeZone: tz, | ||
| }), | ||
| 10, | ||
| ) | ||
| const windowStartHour = getWindowStartHour(currentHour) | ||
| const timeSlots = generateTimeSlots(windowStartHour, now, locale, tz) | ||
| const weekStart = this._getWeekStart() | ||
| const eventLayouts = this._getEventLayouts() | ||
| const todayStr = dayjs(now).tz(tz).format('YYYY-MM-DD') | ||
|
|
||
| const currentMinute = parseInt( | ||
| now.toLocaleString('en-US', { minute: 'numeric', timeZone: tz }), | ||
| 10, | ||
| ) |
| get now(): Date { | ||
| return this._now | ||
| } | ||
|
|
||
| set now(value: Date) { | ||
| this._now = value | ||
| if (this._initialized) this._render() | ||
| } |
| export function setAttribute( | ||
| el: HTMLElement, | ||
| name: string, | ||
| value: string, | ||
| ): void { | ||
| const allowed = new Set([ | ||
| 'class', | ||
| 'style', | ||
| 'data-day-index', | ||
| 'data-hour', | ||
| 'title', | ||
| 'aria-label', | ||
| ]) | ||
| if (allowed.has(name) || name.startsWith('data-')) { |
| // 'en-US' is intentional — we need locale-independent numeric output | ||
| // for parseInt() to work correctly regardless of the configured locale. | ||
| const currentHour = parseInt( | ||
| now.toLocaleString('en-US', { | ||
| hour: 'numeric', | ||
| hour12: false, | ||
| timeZone: tz, | ||
| }), | ||
| 10, | ||
| ) | ||
| const windowStartHour = getWindowStartHour(currentHour) | ||
| const timeSlots = generateTimeSlots(windowStartHour, now, locale, tz) | ||
| const todayStr = dayjs(now).tz(tz).format('YYYY-MM-DD') | ||
| const todayEvents = filterEventsForWindow( | ||
| this._events, | ||
| todayStr, | ||
| windowStartHour, | ||
| tz, | ||
| ) | ||
| const eventLayouts = this._getEventLayouts(todayEvents) | ||
|
|
||
| const currentMinute = parseInt( | ||
| now.toLocaleString('en-US', { minute: 'numeric', timeZone: tz }), | ||
| 10, | ||
| ) |
| const { timezone } = settings | ||
| const screenlySettings = screenly.settings | ||
| const { ical_url: icalUrl } = screenlySettings | ||
| const corsProxy = screenly.cors_proxy_url | ||
| const bypassCors = Boolean( | ||
| JSON.parse(screenly.settings.bypass_cors as string), | ||
| JSON.parse(screenlySettings.bypass_cors as string), | ||
| ) |
Summary
<weekly-calendar-view>custom element toedge-apps-library