style(ui): standardise empty states and filter bars across committee tabs, mailing list members, and transactions#558
style(ui): standardise empty states and filter bars across committee tabs, mailing list members, and transactions#558nunoeufrasio wants to merge 3 commits into
Conversation
…tabs, mailing list members, and transactions - Replace custom card empty states in committee surveys, votes, and meetings with lfx-empty-state component - Fix committee-members emptymessage to use text-gray-400 icon, text-gray-500 text, and lfx-button CTA - Update committee-documents filter bar to match responsive flex-col/md:flex-row pattern - Refactor mailing-list-members filter bar layout, fix empty state icon (fa-eyes → fa-users), and remove manual loading spinner in favour of lfx-table [loading] binding - Move transactions tab bar inside card using lfx-card-tabs-bar; fix cell font size to text-sm (12px) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Nuno Eufrasio <nmeufrasio@gmail.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Standardises several UI surfaces (committee detail tabs, mailing list members, and transactions) to match the shared empty-state + filter-bar patterns established in #492, reducing bespoke markup and aligning spacing/typography.
Changes:
- Replaced multiple custom “no data” card states in committee tabs with the shared
lfx-empty-statecomponent. - Standardised filter-bar layouts (responsive flex patterns) for committee documents and mailing list members.
- Refactored Transactions to use
lfx-card-tabs-barinside the card and normalised table cell typography totext-sm.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/lfx-one/src/app/modules/transactions/transactions-dashboard/transactions-dashboard.component.ts | Swaps FilterPillsComponent for CardTabsBarComponent; adds computed activeTabLabel for dynamic empty copy. |
| apps/lfx-one/src/app/modules/transactions/transactions-dashboard/transactions-dashboard.component.html | Moves tab pills into a card header bar; adjusts padding and table text sizing; enhances empty message copy per active tab. |
| apps/lfx-one/src/app/modules/mailing-lists/components/mailing-list-members/mailing-list-members.component.html | Standardises filter bar layout and replaces manual spinner with lfx-table [loading]; updates empty icon. |
| apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.ts | Replaces CardComponent dependency for empty state with EmptyStateComponent. |
| apps/lfx-one/src/app/modules/committees/components/committee-votes/committee-votes.component.html | Replaces bespoke empty card with lfx-empty-state. |
| apps/lfx-one/src/app/modules/committees/components/committee-surveys/committee-surveys.component.ts | Replaces CardComponent dependency for empty state with EmptyStateComponent. |
| apps/lfx-one/src/app/modules/committees/components/committee-surveys/committee-surveys.component.html | Replaces bespoke empty card with lfx-empty-state. |
| apps/lfx-one/src/app/modules/committees/components/committee-members/committee-members.component.html | Improves emptymessage styling and swaps raw button for lfx-button CTA. |
| apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.ts | Adds EmptyStateComponent to standalone imports for standardised empty state rendering. |
| apps/lfx-one/src/app/modules/committees/components/committee-meetings/committee-meetings.component.html | Replaces bespoke empty card with lfx-empty-state and dynamic title/subtitle per time filter. |
| apps/lfx-one/src/app/modules/committees/components/committee-documents/committee-documents.component.html | Standardises filter bar to the responsive flex-col / md:flex-row pattern and adjusts input/select sizing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <lfx-empty-state | ||
| icon="fa-light fa-chart-simple" | ||
| title="No surveys yet" | ||
| subtitle="Surveys for this committee will appear here."> | ||
| </lfx-empty-state> |
There was a problem hiding this comment.
Switching to lfx-empty-state removes the previous aria-hidden="true" on the decorative icon. EmptyStateComponent currently renders its without aria-hidden, which can cause screen readers to announce the icon class/name. Consider updating lfx-empty-state to set aria-hidden="true" on the icon (or provide an input to control it) to avoid this accessibility regression.
| <lfx-empty-state | |
| icon="fa-light fa-chart-simple" | |
| title="No surveys yet" | |
| subtitle="Surveys for this committee will appear here."> | |
| </lfx-empty-state> | |
| <div class="flex flex-col items-center justify-center gap-3 py-8 text-center"> | |
| <i class="fa-light fa-chart-simple text-4xl" aria-hidden="true"></i> | |
| <div class="flex flex-col gap-1"> | |
| <div class="text-lg font-semibold">No surveys yet</div> | |
| <div class="text-sm">Surveys for this committee will appear here.</div> | |
| </div> | |
| </div> |
| <lfx-empty-state | ||
| icon="fa-light fa-calendar" | ||
| [title]="timeFilter() === 'upcoming' ? 'No upcoming meetings' : 'No past meetings'" | ||
| [subtitle]="timeFilter() === 'upcoming' ? 'Meetings for this group will appear here when scheduled.' : 'No past meetings found for this group.'"> | ||
| </lfx-empty-state> |
There was a problem hiding this comment.
Switching to lfx-empty-state removes the previous aria-hidden="true" on the decorative icon. EmptyStateComponent currently renders its without aria-hidden, which can cause screen readers to announce the icon class/name. Consider updating lfx-empty-state to set aria-hidden="true" on the icon (or provide an input to control it) to avoid this accessibility regression.
| <lfx-empty-state | |
| icon="fa-light fa-calendar" | |
| [title]="timeFilter() === 'upcoming' ? 'No upcoming meetings' : 'No past meetings'" | |
| [subtitle]="timeFilter() === 'upcoming' ? 'Meetings for this group will appear here when scheduled.' : 'No past meetings found for this group.'"> | |
| </lfx-empty-state> | |
| <div class="flex flex-col items-center justify-center py-12 text-center" data-testid="committee-meetings-empty-state"> | |
| <i class="fa-light fa-calendar text-4xl text-gray-300 mb-4" aria-hidden="true"></i> | |
| <h3 class="text-lg font-semibold text-gray-900"> | |
| {{ timeFilter() === 'upcoming' ? 'No upcoming meetings' : 'No past meetings' }} | |
| </h3> | |
| <p class="mt-1 text-sm text-gray-500"> | |
| {{ timeFilter() === 'upcoming' ? 'Meetings for this group will appear here when scheduled.' : 'No past meetings found for this group.' }} | |
| </p> | |
| </div> |
| <lfx-empty-state | ||
| icon="fa-light fa-check-to-slot" | ||
| title="No votes yet" | ||
| subtitle="Votes for this committee will appear here."> | ||
| </lfx-empty-state> |
There was a problem hiding this comment.
Switching to lfx-empty-state removes the previous aria-hidden="true" on the decorative icon. EmptyStateComponent currently renders its without aria-hidden, which can cause screen readers to announce the icon class/name. Consider updating lfx-empty-state to set aria-hidden="true" on the icon (or provide an input to control it) to avoid this accessibility regression.
| <lfx-empty-state | |
| icon="fa-light fa-check-to-slot" | |
| title="No votes yet" | |
| subtitle="Votes for this committee will appear here."> | |
| </lfx-empty-state> | |
| <div class="flex flex-col items-center justify-center gap-3 py-8 text-center"> | |
| <i class="fa-light fa-check-to-slot text-4xl" aria-hidden="true"></i> | |
| <div class="text-lg font-semibold">No votes yet</div> | |
| <div class="text-sm text-gray-600">Votes for this committee will appear here.</div> | |
| </div> |
…on truncation (#556) * fix(dashboards): constrain next meeting column width to fix description truncation Add min-w-0 to the right flex column in my-meetings so the nested truncate class on the description paragraph has a bounded width to clip against, showing an ellipsis instead of overflowing the card. Generated with [Claude Code](https://claude.ai/code) * fix(dashboards): apply min-w-0 to both meeting card columns Ensures the truncation fix covers the Last Meeting (past) card too, not just the Next Meeting card. Generated with [Claude Code](https://claude.ai/code)
A "maybe" RSVP is a valid response — the user has answered — so it should not appear as pending in either the dashboard Pending Actions panel or the /meetings Pending RSVP filter chip. Only a truly missing RSVP (null/no record) is pending. LFXV2-1569 - user.service.ts transformMissingRsvpsToActions: simplify to a Set of meeting_ids with any valid recorded response; update docstrings. - meetings-dashboard.component.ts filter: drop the maybe predicate. Signed-off-by: Manish Dixit <mdixit@linuxfoundation.org> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ba8b84d to
eabd772
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (pendingRsvpOnly) { | ||
| // Pending = no RSVP yet OR a non-committal "maybe". Matches the "needs response" semantics | ||
| // used by the pending-actions transformer. | ||
| filtered = filtered.filter((m) => !m.my_rsvp || m.my_rsvp.response_type === 'maybe'); | ||
| // Pending = no RSVP recorded. accepted, declined, and maybe are all valid responses. | ||
| filtered = filtered.filter((m) => !m.my_rsvp); | ||
| } |
There was a problem hiding this comment.
This change alters the meaning of the “Pending RSVP” filter: meetings with an RSVP of maybe are no longer considered pending (only missing my_rsvp). The PR description is focused on UI standardisation and doesn’t mention this behavior change; please either (a) update the PR description/release notes to call this out, or (b) split the RSVP semantics change into a separate PR so it can be reviewed/approved intentionally.
| @@ -1154,22 +1155,17 @@ export class UserService { | |||
|
|
|||
| const inWindowMeetingIds = new Set(meetings.map((m) => m.id).filter((id): id is string => !!id)); | |||
|
|
|||
| // Keep the strongest signal per meeting: accepted/declined beats maybe beats nothing. | |||
| const responseByMeeting = new Map<string, MeetingRsvp>(); | |||
| const respondedMeetingIds = new Set<string>(); | |||
| for (const rsvp of rsvps) { | |||
| if (!rsvp.meeting_id || !inWindowMeetingIds.has(rsvp.meeting_id)) continue; | |||
| if (!rsvp.registrant_id || !activeRegistrantIds.has(rsvp.registrant_id)) continue; | |||
| const existing = responseByMeeting.get(rsvp.meeting_id); | |||
| if (!existing || (existing.response_type === 'maybe' && rsvp.response_type !== 'maybe')) { | |||
| responseByMeeting.set(rsvp.meeting_id, rsvp); | |||
| } | |||
| respondedMeetingIds.add(rsvp.meeting_id); | |||
| } | |||
|
|
|||
| const actions: PendingActionItem[] = []; | |||
| for (const meeting of meetings) { | |||
| if (!meeting.id) continue; | |||
| const rsvp = responseByMeeting.get(meeting.id); | |||
| if (rsvp && rsvp.response_type !== 'maybe') continue; | |||
| if (respondedMeetingIds.has(meeting.id)) continue; | |||
| actions.push(this.createRsvpAction(meeting)); | |||
There was a problem hiding this comment.
This update changes pending-actions behavior for RSVPs: any RSVP (including maybe) now suppresses the “Set RSVP” pending action. Since this PR is described as UI standardisation work, please explicitly call out this behavioral change in the PR description (or move it to a dedicated PR) to avoid it being merged unintentionally.
What
Brings committee detail tabs, mailing list members, and the transactions page in line with the consistent UI patterns established in PR #492 (me-lens standardisation).
How
lfx-empty-statecomponent; remove non-standard PrimeNG color tokens (text-surface-*)lfx-empty-statewith dynamic title/subtitle based on time filtertext-gray-400icon,text-gray-500text,lfx-buttonCTA instead of raw<button>flex-col / md:flex-rowpattern withflex-1 min-w-0search andw-full sm:w-auto sm:shrink-0selectsfa-eyes→fa-users), remove manual spinner in favour of[loading]binding onlfx-tablelfx-card-tabs-bar; fix cell font size totext-sm(12px)Related
Checklist
🤖 Generated with Claude Code