Skip to content

feat(FR-26): show error state on ProjectSelect when no accessible projects#7455

Open
ironAiken2 wants to merge 1 commit into
05-18-chore_remove_unused_alert_import_in_vfoldernodes.tsxfrom
05-18-feat_fr-26_show_error_state_on_projectselect_when_no_accessible_projects
Open

feat(FR-26): show error state on ProjectSelect when no accessible projects#7455
ironAiken2 wants to merge 1 commit into
05-18-chore_remove_unused_alert_import_in_vfoldernodes.tsxfrom
05-18-feat_fr-26_show_error_state_on_projectselect_when_no_accessible_projects

Conversation

@ironAiken2
Copy link
Copy Markdown
Contributor

@ironAiken2 ironAiken2 commented May 18, 2026

Stacked on #7469 (chore: remove unused Alert import in VFolderNodes.tsx) — merge that first.

Resolves #2933(FR-26)

Summary

When the current user has no accessible projects in the current domain, ProjectSelect now visually and accessibly communicates the empty state:

  • The select border switches to the error color via status="error".
  • The suffix arrow is replaced with an InfoCircleOutlined icon (visual cue).
  • The explanation "No accessible projects available." (ko: "선택 가능한 프로젝트가 없습니다.") is attached to the focusable select control itself — via BAISelect's tooltip (hover over the whole control) and a persistent aria-label — so keyboard and screen-reader users can discover why it is in an error state, not just that it is.

The error treatment is suppressed while the select is disabled or loading, so existing UX is preserved:

  • WebUIHeader.tsx — during project switching (isProjectChanging), the select is disabled+loading, so the error never flashes mid-switch.
  • UpdateUsersModal.tsx — when no domain is picked yet, the field is disabled and the form-item already shows a "Please select a domain" warning; we don't compete with that.

Why

ProjectSelect previously rendered as an empty dropdown with no indication of why it was empty. Users with no project membership (a real case after onboarding, after losing a project, or in a fresh domain) saw a normal-looking selector with nothing inside it. This change makes the empty state legible at a glance without a heavy error boundary fallback.

Ghost-mode border fix (BAISelect)

The header ProjectSelect is rendered with ghost. BAISelect's ghostSelect style hard-overrides border-color with !important, which swallowed antd's status="error" red border — so in the header (the primary use case) only the info icon appeared and the border stayed the ghost color. Added a higher-specificity &.ant-select.ant-select-status-error rule inside ghostSelect that restores the error border + suffix color. Normal (non-error) ghost selects are unaffected; no other ghost select uses status="error" today.

Accessibility (Copilot review feedback)

The first revision exposed the reason only through a tooltip on the non-focusable suffix icon, so keyboard / screen-reader users got the error state without the reason. The message is now attached to the focusable control: tooltip (antd Tooltip over the whole select) for pointer users and a persistent aria-label (independent of tooltip open state) for assistive tech. The icon stays as a pure visual affordance.

Changes

  • react/src/components/ProjectSelect.tsx — derive showNoProjectError = !accessibleProjects?.length && !disabled && !loading; in the empty state forward status="error", the InfoCircleOutlined suffix, and the explanation via BAISelect tooltip + aria-label. Preserves caller-supplied status / suffixIcon / tooltip / aria-label when not in the empty state.
  • packages/backend.ai-ui/src/components/BAISelect.tsx — add an error-status override to the ghostSelect style so a ghost select can still surface a red error border (root cause of the header border not turning red).
  • resources/i18n/en.json, resources/i18n/ko.json — add projectSelect.NoAccessibleProjects key. Other languages will be filled in by /fw:i18n.

Test plan

  • Header ProjectSelect in a domain with no accessible projects → red error border + info icon; hovering anywhere on the select shows the tooltip; the control exposes the reason as its accessible name.
  • Tab to the header ProjectSelect with a screen reader in the no-project state → the reason is announced (not just "invalid").
  • Header ProjectSelect during project switching (loading) → no error styling.
  • UpdateUsersModal with no domain selected → field disabled, existing "Please select a domain" warning, no project-select error styling.
  • UpdateUsersModal with a domain that has projects → normal selector, no error styling.
  • UserSettingModal admin-edit flow with no accessible projects → error border + accessible reason.

🤖 Generated with Claude Code

@github-actions github-actions Bot added area:ux UI / UX issue. area:i18n Localization size:S 10~30 LoC labels May 18, 2026
Copy link
Copy Markdown
Contributor Author

ironAiken2 commented May 18, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • flow:merge-queue - adds this PR to the back of the merge queue
  • flow:hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has required the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Coverage Report for react-coverage (./react)

Status Category Percentage Covered / Total
🔵 Lines 6.51% 1785 / 27381
🔵 Statements 5.36% 1980 / 36912
🔵 Functions 5.25% 296 / 5634
🔵 Branches 3.73% 1293 / 34580
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
react/src/components/ProjectSelect.tsx 0% 0% 0% 0% 34-168
Generated in workflow #832 for commit 591a307 by the Vitest Coverage Report Action

@ironAiken2 ironAiken2 force-pushed the 05-18-feat_fr-26_show_error_state_on_projectselect_when_no_accessible_projects branch from b262481 to faf382e Compare May 18, 2026 03:50
@github-actions github-actions Bot added migration size:M 30~100 LoC and removed size:S 10~30 LoC labels May 18, 2026
@ironAiken2 ironAiken2 force-pushed the 05-18-feat_fr-26_show_error_state_on_projectselect_when_no_accessible_projects branch from faf382e to ee4458c Compare May 18, 2026 03:55
@ironAiken2 ironAiken2 marked this pull request as ready for review May 18, 2026 09:38
@ironAiken2 ironAiken2 requested review from agatha197, Copilot, nowgnuesLee and yomybaby and removed request for Copilot May 18, 2026 09:38
@ironAiken2 ironAiken2 force-pushed the 05-18-feat_fr-26_show_error_state_on_projectselect_when_no_accessible_projects branch from ee4458c to 4c80f67 Compare May 18, 2026 09:39
Copilot AI review requested due to automatic review settings May 18, 2026 09:39
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

This PR updates ProjectSelect to surface an empty/error state when the current user has no accessible projects, aligning the selector UX with the onboarding/no-membership scenario described in FR-26.

Changes:

  • Adds status="error" and an info suffix tooltip when ProjectSelect has no accessible projects and is not disabled/loading.
  • Adds the projectSelect.NoAccessibleProjects translation key across all supported locale files.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
react/src/components/ProjectSelect.tsx Adds no-project error state and tooltip icon behavior.
resources/i18n/en.json Adds English no-accessible-projects text.
resources/i18n/ko.json Adds Korean no-accessible-projects text.
resources/i18n/de.json Adds German translation.
resources/i18n/el.json Adds Greek translation.
resources/i18n/es.json Adds Spanish translation.
resources/i18n/fi.json Adds Finnish translation.
resources/i18n/fr.json Adds French translation.
resources/i18n/id.json Adds Indonesian translation.
resources/i18n/it.json Adds Italian translation.
resources/i18n/ja.json Adds Japanese translation.
resources/i18n/mn.json Adds Mongolian translation.
resources/i18n/ms.json Adds Malay translation.
resources/i18n/pl.json Adds Polish translation.
resources/i18n/pt-BR.json Adds Brazilian Portuguese translation.
resources/i18n/pt.json Adds Portuguese translation.
resources/i18n/ru.json Adds Russian translation.
resources/i18n/th.json Adds Thai translation.
resources/i18n/tr.json Adds Turkish translation.
resources/i18n/vi.json Adds Vietnamese translation.
resources/i18n/zh-CN.json Adds Simplified Chinese translation.
resources/i18n/zh-TW.json Adds Traditional Chinese translation.

Comment thread react/src/components/ProjectSelect.tsx Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

Coverage Report for backend-ai-ui-coverage (./packages/backend.ai-ui)

Status Category Percentage Covered / Total
🔵 Lines 8.03% 362 / 4506
🔵 Statements 7.17% 411 / 5728
🔵 Functions 8.93% 94 / 1052
🔵 Branches 6.36% 362 / 5688
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/backend.ai-ui/src/components/BAISelect.tsx 0% 0% 0% 0% 17-263
Generated in workflow #831 for commit 591a307 by the Vitest Coverage Report Action

…jects

When the current user has no accessible projects in the current domain, the project selector now indicates this with an error-colored border and an InfoCircleOutlined suffix icon. Hovering the icon shows a tooltip explaining the state.

The guard suppresses the error look while the underlying select is `disabled` or `loading`, so the existing 'please select a domain first' warning in UpdateUsersModal and the project-switching spinner in the header keep their original UX.
@ironAiken2 ironAiken2 changed the base branch from main to graphite-base/7455 May 18, 2026 10:08
@ironAiken2 ironAiken2 force-pushed the 05-18-feat_fr-26_show_error_state_on_projectselect_when_no_accessible_projects branch from 4c80f67 to 591a307 Compare May 18, 2026 10:08
@ironAiken2 ironAiken2 changed the base branch from graphite-base/7455 to 05-18-chore_remove_unused_alert_import_in_vfoldernodes.tsx May 18, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:i18n Localization area:ux UI / UX issue. migration size:M 30~100 LoC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Need to handle errors if the user doesn't belong to a project

2 participants