Skip to content

style(ui): standardise empty states and filter bars across committee tabs, mailing list members, and transactions#558

Closed
nunoeufrasio wants to merge 3 commits into
mainfrom
feat/table-list-consistency
Closed

style(ui): standardise empty states and filter bars across committee tabs, mailing list members, and transactions#558
nunoeufrasio wants to merge 3 commits into
mainfrom
feat/table-list-consistency

Conversation

@nunoeufrasio
Copy link
Copy Markdown
Contributor

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

  • Committee surveys & votes: Replace custom card empty states with lfx-empty-state component; remove non-standard PrimeNG color tokens (text-surface-*)
  • Committee meetings: Replace custom card empty state with lfx-empty-state with dynamic title/subtitle based on time filter
  • Committee members: Fix emptymessage — text-gray-400 icon, text-gray-500 text, lfx-button CTA instead of raw <button>
  • Committee documents: Update filter bar to responsive flex-col / md:flex-row pattern with flex-1 min-w-0 search and w-full sm:w-auto sm:shrink-0 selects
  • Mailing list members: Fix filter bar layout, empty state icon (fa-eyesfa-users), remove manual spinner in favour of [loading] binding on lfx-table
  • Transactions: Move tab bar inside card using lfx-card-tabs-bar; fix cell font size to text-sm (12px)

Related

Checklist

  • Tests added/updated
  • License headers on new files
  • Docs updated if needed
  • Under 1000 lines of diff

🤖 Generated with Claude Code

…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>
Copilot AI review requested due to automatic review settings April 23, 2026 13:48
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3023c07b-bb28-40da-bb98-7ed82844ea06

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/table-list-consistency

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-state component.
  • Standardised filter-bar layouts (responsive flex patterns) for committee documents and mailing list members.
  • Refactored Transactions to use lfx-card-tabs-bar inside the card and normalised table cell typography to text-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.

Comment on lines +37 to +41
<lfx-empty-state
icon="fa-light fa-chart-simple"
title="No surveys yet"
subtitle="Surveys for this committee will appear here.">
</lfx-empty-state>
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
<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>

Copilot uses AI. Check for mistakes.
Comment on lines +163 to +167
<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>
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
<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>

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +42
<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>
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
<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>

Copilot uses AI. Check for mistakes.
nunoeufrasio and others added 2 commits April 23, 2026 16:00
…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>
Copilot AI review requested due to automatic review settings April 23, 2026 15:04
@nunoeufrasio nunoeufrasio force-pushed the feat/table-list-consistency branch from ba8b84d to eabd772 Compare April 23, 2026 15:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines 525 to 528
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);
}
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 1144 to 1169
@@ -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));
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
@nunoeufrasio nunoeufrasio deleted the feat/table-list-consistency branch April 24, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants