#641 Schedule cell polish: alignment + external text colour

- Attendees column no longer centres its content. AttendeeFlow's <ul>
  switched from justify-center to justify-start; AttendeeGroup header
  and subheading rows (both committed and pending) switched from
  text-center to text-start. Restores cell-start alignment (right in
  AR, left in EN) the user expected on fresh inline-add and on
  existing rows.
- External meetings now render the meeting title cell text and the
  attendee names in red (#b91c1c), matching the row tint family, in
  addition to the existing red background. Implemented by:
  * Conditional text-[#b91c1c] / text-[#0B1E3F] on the meeting <td>
    based on meeting.isExternal.
  * New optional `externalText` prop on AttendeeFlowSharedProps,
    threaded from AttendeesCell (derived from meeting.isExternal) and
    applied as a colour class on the AttendeeFlow root <ul> so all
    attendee names inherit red. Group headers and subheadings keep
    their neutral navy palette per scope.
- Non-external rows and the cancelled/highlighted white-on-red # cell
  are untouched. Print/PDF path reuses the same renderer so the red
  carries through automatically.
- No schema/API/migration changes. TS clean.

Files: artifacts/tx-os/src/pages/executive-meetings.tsx
This commit is contained in:
riyadhafraa
2026-05-25 12:51:46 +00:00
parent a131b2dc75
commit 32cac678bf
@@ -4559,7 +4559,7 @@ function MeetingRow({
return (
<td
key="meeting"
className="border border-gray-300 px-3 py-3 align-middle text-[#0B1E3F] relative group"
className={`border border-gray-300 px-3 py-3 align-middle ${meeting.isExternal ? "text-[#b91c1c]" : "text-[#0B1E3F]"} relative group`}
style={tintedCellStyle(col, true)}
>
<EditableCell
@@ -5558,6 +5558,7 @@ function AttendeesCell({
"executiveMeetings.schedule.newSubheadingAria",
),
meetingId: meeting.id,
externalText: Boolean(meeting.isExternal),
};
if (hasSplit) {
@@ -5760,6 +5761,11 @@ type AttendeeFlowSharedProps = {
editSubheadingAriaLabel: string;
newSubheadingAriaLabel: string;
meetingId: number;
// #641: When true, attendee names render in red so the user gets the
// same visual cue inside the cell that the row tint already gives at
// the row level (external meeting). Group headers and subheadings
// keep their own neutral colour — only the names list flips.
externalText?: boolean;
// When true, the trailing "+ عنوان فرعي" <li> at the very end of the
// flow is NOT rendered. Used by split-mode cells (≥2 attendance
// groups visible) so the cell shows ONE cell-level "+ عنوان فرعي"
@@ -5783,7 +5789,7 @@ function AttendeeGroup({
than a stray line of text. */}
<div
data-testid="em-attendee-group-header"
className="text-sm font-bold text-[#0B1E3F] mt-0.5 mb-1 pb-0.5 text-center pointer-events-none select-none border-b border-[#0B1E3F]/15 print:border-b print:border-gray-400"
className="text-sm font-bold text-[#0B1E3F] mt-0.5 mb-1 pb-0.5 text-start pointer-events-none select-none border-b border-[#0B1E3F]/15 print:border-b print:border-gray-400"
>
{label}
</div>
@@ -5811,6 +5817,7 @@ function AttendeeFlow({
newAriaLabel,
editSubheadingAriaLabel,
newSubheadingAriaLabel,
externalText = false,
suppressTrailingSubheadingChip = false,
}: { items: AttendeeWithIndex[] } & AttendeeFlowSharedProps) {
const editable = canMutate && !!onSaveAttendeeName;
@@ -5923,7 +5930,7 @@ function AttendeeFlow({
return (
<li
key={key}
className="basis-full text-center font-semibold text-[#0B1E3F]/90 mt-1.5 mb-0.5"
className="basis-full text-start font-semibold text-[#0B1E3F]/90 mt-1.5 mb-0.5"
data-testid={`em-add-subheading-pending-${addType}`}
>
<EditableCell
@@ -6038,7 +6045,7 @@ function AttendeeFlow({
};
return (
<ul className="flex flex-wrap justify-center items-baseline gap-x-4 gap-y-0.5 text-[#0B1E3F] leading-snug">
<ul className={`flex flex-wrap justify-start items-baseline gap-x-4 gap-y-0.5 ${externalText ? "text-[#b91c1c]" : "text-[#0B1E3F]"} leading-snug`}>
{items.flatMap(({ a, i }, listIdx) => {
const isSub = (a.kind ?? "person") === "subheading";
const nodes: ReactNode[] = [];
@@ -6064,7 +6071,7 @@ function AttendeeFlow({
key={a.id ?? `sub-${i}`}
data-testid={`em-attendee-subheading-${i}`}
data-attendee-kind="subheading"
className="basis-full text-center font-semibold text-[#0B1E3F]/90 mt-1.5 mb-0.5 leading-snug"
className="basis-full text-start font-semibold text-[#0B1E3F]/90 mt-1.5 mb-0.5 leading-snug"
>
{editable ? (
<EditableCell