Skip to content

Gray out disabled team and workspace members in Settings - #15258

Draft
warp-agent-staging[bot] wants to merge 3 commits into
masterfrom
factory/app-5480-disabled-members-client
Draft

Gray out disabled team and workspace members in Settings#15258
warp-agent-staging[bot] wants to merge 3 commits into
masterfrom
factory/app-5480-disabled-members-client

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

⚠️ Do not merge before warpdotdev/warp-server#15300 ships (or its successor) merges AND deploys to production

This PR selects a new field, isDisabled: Boolean!, on both TeamMember and WorkspaceMember. Selecting a field the server doesn't yet serve is a GraphQL document validation failure (FieldsOnCorrectType) — the server rejects the entire operation, not just the new field. A nullable field would fail identically; nothing defuses this except deploy order.

Blast radius covers more than the Teams page. crates/graphql/src/api/workspace.rs defines a single shared Workspace cynic struct that both GetWorkspacesMetadataForUser and the CreateTeam mutation embed. Both operations transitively select TeamMember.isDisabled and WorkspaceMember.isDisabled, so shipping this before the server deploys breaks workspace metadata loading and team creation, not just Settings > Teams.

Summary

Implements APP-5480: workspace/team members whose account is disabled (users.is_disabled) are grayed out with a "This user's account is disabled" tooltip everywhere the client renders a member row, instead of being hidden. Supersedes #15245, which covered team members only.

Changes

  • crates/warp_graphql_schema/api/schema.graphql: added isDisabled: Boolean! (with field description) to TeamMember and WorkspaceMember, hand-edited to match what the generator will emit once the server ships the field.
  • crates/graphql/src/api/workspace.rs: added is_disabled: bool to both cynic structs (TeamMember, WorkspaceMember).
  • app/src/workspaces/team.rs / app/src/workspaces/workspace.rs: added is_disabled: bool to the app-side TeamMember and WorkspaceMember models, wired through the Gql* -> * conversions in gql_convert.rs.
  • Not persisted to the local sqlite cache — it's a live-refreshed hint. Staleness is a false negative only (a disabled member renders as active, never the reverse); opening a page that refreshes workspace metadata corrects it.
  • Settings > Teams (app/src/settings_view/teams_page.rs): a disabled member's row — email text and role chip — renders dimmed, with a tooltip on hover. The trailing action icon/menu (remove, promote, etc.) stays at normal brightness and enabled; a disabled member remains removable. Tooltip uses overlay_tool_tip_on_element since the page renders inside a Clipped scroll viewport. Replaced the two parallel Vec<MouseStateHandle>s this list used with a single Vec<ItemMouseStates>; the render path asserts the item/mouse-state vectors stay the same length and indexes directly, rather than fabricating a fresh handle if they ever diverge. Fixed a pre-existing sizing bug where the vector was sized from members only at construction but from pending_email_invites + members on update.
  • Billing & usage per-member table (app/src/settings_view/billing_and_usage/billing_cycle_usage_rows.rs): this table also lists workspace members by email, so it gets the same dim + tooltip treatment on the member name, reusing the file's existing "former member" dimming pattern.
  • Surfaces deliberately left unchanged: the workspace/team usage_info and other read-only aggregates don't render individual member identity as a row; no other client surface builds a list from TeamMember/WorkspaceMember.

Validation

  • cargo nextest run -p warp teams_page_tests gql_convert_tests billing_cycle_usage user_workspaces_tests admin_tests — 104 tests passed, including: disabled_member_is_flagged_but_keeps_removal_action, active_member_is_not_flagged_disabled, disabled_row_renders_dimmed_and_tooltipped (both surfaces, pins the exact dimmed color and tooltip copy so deleting the dimming/tooltip branches fails the test), team_member_conversion_preserves_is_disabled, workspace_member_conversion_preserves_is_disabled, per_member_rows_flag_disabled_members_from_the_roster, per_member_rows_never_flag_departed_members_as_disabled.
  • ./script/format and cargo clippy -p warp --all-targets --tests -- -D warnings both clean.
  • cargo check -p warp --bin warp and a full cargo build --bin warp succeed.
  • A full pixel/element-tree-level rendering assertion (e.g. that the Text element's color or the overlay_tool_tip_on_element call actually fires) isn't expressible as a unit test — warpui's Element trait has no introspection API for a constructed color or attached tooltip, and this repo's own gui-integration-test guidance says not to reach for the (much heavier) integration harness for a purely-visual assertion like this. Extracted the branching decisions into small pure functions and pinned those instead, which is the closest available proxy and does fail if the dimming/tooltip logic is deleted or inverted.
  • Visual verification: screenshots below, captured against a synthetic team + workspace + billing data injected behind a temporary env-var-gated hook (removed before this commit) since the sandbox's WARP_API_KEY can't load real team/billing data. Covers both surfaces: Settings > Teams and Settings > Billing and Usage's per-member table. In both, the active member renders at full brightness and the disabled member renders dimmed with the tooltip "This user's account is disabled" on hover.
  • Not independently verified: real end-to-end flow against a server that actually serves isDisabled (blocked on the server PR merging/deploying first, per the warning above).

Settings > Teams page ("Debug Team") showing Team members list with alice@example.com (WORKSPACE ADMIN, normal brightness) and bob@example.com (dimmed), with tooltip "This user's account is disabled" shown on hover.

Settings > Billing and Usage page showing the Members table with alice@example.com (normal brightness) and bob@example.com (dimmed/grayed text), with a tooltip "This user's account is disabled" appearing while hovering over bob's row.

Plans: none

CHANGELOG-IMPROVEMENT: Disabled team/workspace members are now shown grayed out with an explanatory tooltip instead of appearing active.

Co-Authored-By: Warp agent@warp.dev

Adds isDisabled: Boolean! to the TeamMember and WorkspaceMember
GraphQL types (schema + cynic structs), threads is_disabled through
the app-side TeamMember/WorkspaceMember models, and dims disabled
members with an explanatory tooltip in every client surface that
renders a member row:

- Settings > Teams member list (email text + role chip dimmed, action
  icon/menu stays at normal brightness and enabled).
- The billing/usage per-member breakdown table, which also lists
  workspace members by email.

is_disabled is not persisted to the local sqlite cache; it's a
live-refreshed hint, so staleness only produces false negatives.

Refs APP-5480.

Co-Authored-By: Warp <agent@warp.dev>
warp-agent-staging Bot and others added 2 commits August 18, 2026 02:08
…sabled-members-client

# Conflicts:
#	app/src/workspaces/gql_convert_tests.rs
…ments

- Merge master to resolve the branch conflict.
- teams_page.rs: replace the unwrap_or_default() mouse-state fallback
  with a debug_assert on the item/mouse-state length invariant plus
  direct indexing, so a divergence fails loudly instead of fabricating
  a transient handle.
- Extract the dim-color and tooltip-text decisions in both
  teams_page.rs and billing_cycle_usage_rows.rs into small pure
  functions, and add unit tests pinning that a disabled row picks the
  dimmed color and the exact tooltip copy.
- Delete comments that only restated field names/structure.

Co-Authored-By: Warp <agent@warp.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants