From d6d9a9aedcd74821573673a6d8c89a2827e3959f Mon Sep 17 00:00:00 2001 From: David Nguyen Date: Fri, 19 Jun 2026 16:52:00 +1000 Subject: [PATCH] fix: improve team member removal ux --- .../dialogs/team-member-delete-dialog.tsx | 31 +++++- .../components/tables/team-members-table.tsx | 56 ++++++---- .../app-tests/e2e/teams/team-members.spec.ts | 105 ++++++++++++++++++ 3 files changed, 167 insertions(+), 25 deletions(-) create mode 100644 packages/app-tests/e2e/teams/team-members.spec.ts diff --git a/apps/remix/app/components/dialogs/team-member-delete-dialog.tsx b/apps/remix/app/components/dialogs/team-member-delete-dialog.tsx index 841268dfc..1dda81788 100644 --- a/apps/remix/app/components/dialogs/team-member-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/team-member-delete-dialog.tsx @@ -16,6 +16,17 @@ import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { useState } from 'react'; +import { match } from 'ts-pattern'; + +/** + * The reason a team member cannot be removed from the team. When set, the delete + * dialog explains the reason instead of offering a confirm button. + */ +export type TeamMemberDeleteDisableReason = + | 'TEAM_OWNER' + | 'HIGHER_ROLE' + | 'INHERIT_MEMBER_ENABLED' + | 'INHERITED_MEMBER'; export type TeamMemberDeleteDialogProps = { teamId: number; @@ -23,7 +34,7 @@ export type TeamMemberDeleteDialogProps = { memberId: string; memberName: string; memberEmail: string; - isInheritMemberEnabled: boolean | null; + disableReason?: TeamMemberDeleteDisableReason | null; trigger?: React.ReactNode; }; @@ -34,7 +45,7 @@ export const TeamMemberDeleteDialog = ({ memberId, memberName, memberEmail, - isInheritMemberEnabled, + disableReason, }: TeamMemberDeleteDialogProps) => { const [open, setOpen] = useState(false); @@ -86,10 +97,19 @@ export const TeamMemberDeleteDialog = ({ - {isInheritMemberEnabled ? ( + {disableReason ? ( - You cannot remove members from this team if the inherit member feature is enabled. + {match(disableReason) + .with('TEAM_OWNER', () => You cannot remove the organisation owner from the team.) + .with('HIGHER_ROLE', () => You cannot remove a member with a role higher than your own.) + .with('INHERIT_MEMBER_ENABLED', () => ( + You cannot remove members from this team while the inherit member feature is enabled. + )) + .with('INHERITED_MEMBER', () => ( + This member is inherited from a group and cannot be removed from the team directly. + )) + .exhaustive()} ) : ( @@ -109,11 +129,10 @@ export const TeamMemberDeleteDialog = ({ Close - {!isInheritMemberEnabled && ( + {!disableReason && (