diff --git a/frontend/src/components/calendar/EventDetailPanel.tsx b/frontend/src/components/calendar/EventDetailPanel.tsx
index 33adc6d..541c7ed 100644
--- a/frontend/src/components/calendar/EventDetailPanel.tsx
+++ b/frontend/src/components/calendar/EventDetailPanel.tsx
@@ -290,8 +290,10 @@ export default function EventDetailPanel({
useEffect(() => {
const el = descRef.current;
if (!el) return;
- el.style.height = 'auto';
- el.style.height = `${el.scrollHeight}px`;
+ requestAnimationFrame(() => {
+ el.style.height = 'auto';
+ el.style.height = `${el.scrollHeight}px`;
+ });
}, [editState.description, isEditing]);
// Poll lock status in view mode for shared events (Stream A: real-time lock awareness)
@@ -376,11 +378,11 @@ export default function EventDetailPanel({
end_datetime: endDt,
all_day: data.all_day,
location_id: data.location_id ? parseInt(data.location_id) : null,
- is_starred: data.is_starred,
- recurrence_rule: rule,
};
- // Invited editors cannot change calendars — omit calendar_id from payload
+ // Invited editors are restricted to the backend allowlist — omit fields they cannot modify
if (!canModifyAsInvitee) {
+ payload.is_starred = data.is_starred;
+ payload.recurrence_rule = rule;
payload.calendar_id = data.calendar_id ? parseInt(data.calendar_id) : null;
}
@@ -548,6 +550,7 @@ export default function EventDetailPanel({
: event?.title || '';
return (
+ // onWheel stopPropagation: defence-in-depth with CalendarPage's panelOpen guard to prevent month-scroll bleed
e.stopPropagation()}>
{/* Header */}
@@ -866,18 +869,6 @@ export default function EventDetailPanel({
)}
- {/* Star for invited editors (no recurrence row shown) */}
- {canModifyAsInvitee && (
-
- updateField('is_starred', (e.target as HTMLInputElement).checked)}
- />
-
-
- )}
-
{editState.recurrence_type === 'every_n_days' && (
@@ -955,7 +946,7 @@ export default function EventDetailPanel({
value={editState.description}
onChange={(e) => updateField('description', e.target.value)}
placeholder="Add a description..."
- className="text-sm resize-y flex-1 min-h-[80px]"
+ className="text-sm flex-1 min-h-[80px]"
/>
diff --git a/frontend/src/components/calendar/EventForm.tsx b/frontend/src/components/calendar/EventForm.tsx
index b24f770..2884b88 100644
--- a/frontend/src/components/calendar/EventForm.tsx
+++ b/frontend/src/components/calendar/EventForm.tsx
@@ -146,8 +146,10 @@ export default function EventForm({ event, templateData, templateName, initialSt
useEffect(() => {
const el = descRef.current;
if (!el) return;
- el.style.height = 'auto';
- el.style.height = `${el.scrollHeight}px`;
+ requestAnimationFrame(() => {
+ el.style.height = 'auto';
+ el.style.height = `${el.scrollHeight}px`;
+ });
}, [formData.description]);
const selectableCalendars = calendars.filter((c) => !c.is_system);
@@ -269,7 +271,7 @@ export default function EventForm({ event, templateData, templateName, initialSt
value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
placeholder="Add a description..."
- className="min-h-[80px] resize-y text-sm"
+ className="min-h-[80px] text-sm"
/>