Add mini-calendar sidebar to Calendar TUI

- Add MonthCalendar widget as a collapsible sidebar (toggle with 's')
- Sidebar syncs with main week grid (week highlight, selected date)
- Click dates in sidebar to navigate week grid to that date
- Click month navigation arrows to change displayed month
- Add goto_date() method to WeekGrid for date navigation
This commit is contained in:
Bendt
2025-12-19 10:40:33 -05:00
parent 48d2455b9c
commit a82f001918
3 changed files with 116 additions and 1 deletions

View File

@@ -18,6 +18,7 @@ from textual.reactive import reactive
from src.calendar.backend import CalendarBackend, Event
from src.calendar.widgets.WeekGrid import WeekGrid
from src.calendar.widgets.MonthCalendar import MonthCalendar
from src.calendar.widgets.AddEventForm import EventFormData
from src.utils.shared_config import get_theme_name
@@ -51,6 +52,26 @@ class CalendarApp(App):
Screen {
layout: vertical;
}
#main-content {
layout: horizontal;
height: 1fr;
}
#sidebar {
width: 26;
border-right: solid $surface-darken-1;
background: $surface;
padding: 1 0;
}
#sidebar.hidden {
display: none;
}
#sidebar-calendar {
height: auto;
}
#week-grid {
height: 1fr;
@@ -98,6 +119,7 @@ class CalendarApp(App):
Binding("L", "next_week", "Next Week", show=True),
Binding("g", "goto_today", "Today", show=True),
Binding("w", "toggle_weekends", "Weekends", show=True),
Binding("s", "toggle_sidebar", "Sidebar", show=True),
Binding("r", "refresh", "Refresh", show=True),
Binding("enter", "view_event", "View", show=True),
Binding("a", "add_event", "Add", show=True),
@@ -106,6 +128,7 @@ class CalendarApp(App):
# Reactive attributes
include_weekends: reactive[bool] = reactive(True)
show_sidebar: reactive[bool] = reactive(True)
# Instance attributes
backend: Optional[CalendarBackend]
@@ -124,7 +147,10 @@ class CalendarApp(App):
def compose(self) -> ComposeResult:
"""Create the app layout."""
yield Header()
yield WeekGrid(id="week-grid")
with Horizontal(id="main-content"):
with Vertical(id="sidebar"):
yield MonthCalendar(id="sidebar-calendar")
yield WeekGrid(id="week-grid")
yield Static(id="event-detail", classes="hidden")
yield CalendarStatusBar(id="status-bar")
yield Footer()
@@ -136,10 +162,23 @@ class CalendarApp(App):
# Load events for current week
self.load_events()
# Sync sidebar calendar with current week
self._sync_sidebar_calendar()
# Update status bar and title
self._update_status()
self._update_title()
def _sync_sidebar_calendar(self) -> None:
"""Sync the sidebar calendar with the main week grid."""
try:
grid = self.query_one("#week-grid", WeekGrid)
calendar = self.query_one("#sidebar-calendar", MonthCalendar)
calendar.update_week(grid.week_start)
calendar.update_selected(grid.get_cursor_date())
except Exception:
pass # Sidebar might not exist yet
def load_events(self) -> None:
"""Load events from backend for the current week."""
if not self.backend:
@@ -255,11 +294,22 @@ class CalendarApp(App):
def on_week_grid_week_changed(self, message: WeekGrid.WeekChanged) -> None:
"""Handle week change - reload events."""
self.load_events()
self._sync_sidebar_calendar()
def on_week_grid_event_selected(self, message: WeekGrid.EventSelected) -> None:
"""Handle event selection."""
self._update_event_detail(message.event)
# Handle MonthCalendar messages
def on_month_calendar_date_selected(
self, message: MonthCalendar.DateSelected
) -> None:
"""Handle date selection from sidebar calendar."""
grid = self.query_one("#week-grid", WeekGrid)
grid.goto_date(message.date)
self.load_events()
self._sync_sidebar_calendar()
# Navigation actions (forwarded to grid)
def action_cursor_down(self) -> None:
"""Move cursor down."""
@@ -311,6 +361,15 @@ class CalendarApp(App):
mode = "7 days" if self.include_weekends else "5 days (weekdays)"
self.notify(f"Showing {mode}")
def action_toggle_sidebar(self) -> None:
"""Toggle sidebar visibility."""
self.show_sidebar = not self.show_sidebar
sidebar = self.query_one("#sidebar", Vertical)
if self.show_sidebar:
sidebar.remove_class("hidden")
else:
sidebar.add_class("hidden")
def action_refresh(self) -> None:
"""Refresh events from backend."""
self.load_events()
@@ -383,6 +442,7 @@ Keybindings:
H/L - Previous/Next week
g - Go to today
w - Toggle weekends (5/7 days)
s - Toggle sidebar
Enter - View event details
a - Add new event
r - Refresh