Calendar panel: a picked mini-calendar day showed nowhere; no new-tab link on a phone

In Mail's side panel the agenda already lists the whole month and the mini
calendar never marked a selection, so clicking a day in the current month
changed nothing on screen. The day is now highlighted and the agenda scrolls to
it (TODAY scrolls back); a day in another month flips both to that month.

On a phone the panel drops the "Open calendar in new tab" footer: the host
passes newTabLink: false to the embedded calendar.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 21:23:10 +02:00
co-authored by Claude Opus 5.5
parent a5b0842e6a
commit 0ddfc8c658
2 changed files with 38 additions and 6 deletions
+9 -2
View File
@@ -12,6 +12,7 @@ import { useT } from "../../i18n";
import { api, apiFetch } from "../../lib/api";
import type { Address, AttachmentOut, MessageEnvelope, ThreadDetail } from "../../lib/types";
import { AvatarImage } from "../SenderAvatar";
import { useIsMobile } from "../../lib/useIsMobile";
import { loadBundle } from "../../plugins/bundleLoader";
import { usePluginContext } from "../../plugins/context";
import { isPreviewable } from "../thread/previewKind";
@@ -123,6 +124,8 @@ const CAL_BUNDLE = "/api/plugins/calendar/ui/page.js";
function PanelCalendar({ invite }: { invite: InviteSignal | null }) {
const ref = useRef<HTMLDivElement>(null);
const ctx = usePluginContext("calendar");
// A phone has no use for "Open calendar in new tab".
const mobile = useIsMobile();
// Remount when a new "Invite all" fires so the form opens with those guests.
const inviteN = invite?.n ?? 0;
useEffect(() => {
@@ -131,11 +134,15 @@ function PanelCalendar({ invite }: { invite: InviteSignal | null }) {
loadBundle(CAL_BUNDLE).then((mount) => {
if (!alive || !ref.current) return;
ref.current.innerHTML = "";
cleanup = mount(ref.current, ctx, { embed: "panel", newEventGuests: invite?.guests });
cleanup = mount(ref.current, ctx, {
embed: "panel",
newEventGuests: invite?.guests,
newTabLink: !mobile,
});
});
return () => { alive = false; if (typeof cleanup === "function") cleanup(); };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ctx, inviteN]);
}, [ctx, inviteN, mobile]);
return <div ref={ref} className="h-full" />;
}