Files
Ely-GPUI-Components/examples/gallery/pages/calendar/mod.rs
T
ZacharyZhang-NYandClaude Opus 5.5 f316ab56ba Calendar · Months: a month view, a year view, event chips and cards
CalendarMonthView lays a month in week rows. An event across days lies
over them as a bar in the first free lane, cut at the week's edge;
the rest sit by the hour as chips, and a crowded day keeps the rest
behind "N more". Arrows move a day, Page keys turn the month, and
Enter or a double press opens the day; the cursor holds through the
owner's echo of a turn. Days sit at sevenths of their row, as the bars
do, so text never widens a column.

YearView shows twelve small months; a day with something on it wears a
dot in its first event's hue. EventChip is an event in a line and
EventCard a block with its hours and place. MiniCalendar points to
forms::Calendar. Palette::hue is now the one home for a chart color by
index, for mail labels and events alike.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 02:49:37 -04:00

90 lines
3.2 KiB
Rust

use ely_gpui_component::{
calendar::Event,
theme::{ActiveTheme, TextSize},
};
use gpui::{AnyElement, App, IntoElement, ParentElement, SharedString, Styled, Window, div};
use jiff::{Timestamp, ToSpan, civil::Date, tz::TimeZone};
mod months;
use super::Page;
use crate::script::Step;
pub const PAGE: Page = Page {
number: 30,
slug: "calendar",
title: "Calendar",
summary: "Days, weeks, months and years, and what happens in them.",
render,
script: SCRIPT,
};
const SCRIPT: &[Step] = &[
Step::DownAt("calendar-month", 285.0, 230.0),
Step::UpAt("calendar-month", 285.0, 230.0),
Step::Key("right"),
Step::Key("down"),
Step::Wait(150),
Step::Shot("month-cursor"),
Step::Key("pagedown"),
Step::Wait(200),
Step::Shot("month-next"),
Step::Key("pageup"),
Step::DownAt("calendar-year", 150.0, 150.0),
Step::UpAt("calendar-year", 150.0, 150.0),
Step::Key("right"),
Step::Wait(150),
Step::Shot("year-cursor"),
];
/// What a demo says it did, under it.
fn quiet(text: SharedString, cx: &App) -> impl IntoElement + use<> {
let theme = cx.theme();
div()
.text_size(theme.text_size(TextSize::Sm))
.text_color(theme.colors.fg_muted)
.child(text)
}
/// The gallery's zone and today in it.
fn here() -> (TimeZone, Date) {
let zone = TimeZone::try_system().expect("the gallery reads the system time zone");
let today = Timestamp::now().to_zoned(zone.clone()).date();
(zone, today)
}
/// A studio's weeks around today: meetings, a crowded day, an offsite, a trip past a weekend, a night shoot past midnight.
fn events(today: Date, zone: &TimeZone) -> Vec<Event> {
let day = |offset: i64| today.checked_add(offset.days()).expect("a day nearby");
let at = |offset: i64, hour: i8, minute: i8| {
day(offset)
.at(hour, minute, 0, 0)
.to_zoned(zone.clone())
.expect("the zone holds the hour")
.timestamp()
};
vec![
Event::timed("standup", "Studio stand-up", at(0, 9, 30), at(0, 9, 45), 0),
Event::timed("review", "Design review", at(0, 11, 0), at(0, 12, 0), 3).place("Model room"),
Event::timed("lunch", "Lunch with Ana", at(0, 12, 30), at(0, 13, 30), 5),
Event::timed("samples", "Plaster samples", at(0, 15, 0), at(0, 16, 0), 2),
Event::timed("client", "Client call", at(0, 17, 0), at(0, 17, 30), 1),
Event::timed("crit", "Crit", at(-3, 14, 0), at(-3, 15, 30), 3).place("Studio 2"),
Event::timed("print", "Print run", at(-9, 10, 0), at(-9, 11, 0), 2),
Event::all_day("offsite", "Studio offsite", day(2), day(4), 4),
Event::timed("night", "Night shoot", at(5, 21, 0), at(6, 2, 0), 6).place("Atrium"),
Event::all_day("trip", "Site visit · Lisbon", day(9), day(13), 7),
Event::timed("models", "Model photos", at(11, 10, 0), at(11, 12, 0), 0),
Event::all_day("launch", "Launch", day(18), day(18), 1),
]
}
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
div()
.child(months::month(window, cx))
.child(months::mini(window, cx))
.child(months::year(window, cx))
.child(months::marks(cx))
.into_any_element()
}