Skip to content

Frontend: upstreamable: Add placeholder buttons to prevent layout shift during project loading#393

Draft
tejhan wants to merge 1 commit intoAzure:headlamp-downstreamfrom
tejhan:project-delete-button-placeholder
Draft

Frontend: upstreamable: Add placeholder buttons to prevent layout shift during project loading#393
tejhan wants to merge 1 commit intoAzure:headlamp-downstreamfrom
tejhan:project-delete-button-placeholder

Conversation

@tejhan
Copy link
Collaborator

@tejhan tejhan commented Mar 10, 2026

Description

Currently, the project delete button pops in only after async operations resolve (namespace loading, RBAC checks, project type detection), causing a visible layout shift on the project details page.

For custom project types (AKS projects for ex.), there's an additional visual glitch where the default delete button renders first, disappears, then the custom one appears, resulting in a flash/additional layout shift.

These issues typically occur within the first second, but are noticeable at longer load times and are visually inconsistent with most of the statically loaded components on the page.

This PR adds placeholder buttons so the delete button area is standardized from the initial render, which visually aligns with the behavior of most other static components on the project details page.

Note: This PR is related but not exclusive to #392. Additional fixes for the AKSProjectDeleteButton reside there

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Code refactoring
  • CI/CD changes
  • Other: **___**

Changes Made

  • Added authResolved state that is utilized to shows a placeholder button while namespaces load and RBAC permissions resolve.
  • Changed DeleteButton state to initialize as null when a custom delete button is being resolved.

Testing

  • Unit tests pass
  • Integration tests pass
  • Manual testing completed
  • Performance tested (if applicable)
  • Accessibility tested (if applicable)

Test Cases

Steps to reproduce

  1. Open a standard AKS project
  2. Delete button should be visible on initial page render.
  3. Open a AKS managed project.
  4. Delete button should be visible on initial page render, & shouldn't disappear or flicker afterwards.

Copilot AI review requested due to automatic review settings March 10, 2026 11:31
Copy link

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 fixes visible layout shifts and button flickering on the project details page that occur while async operations (namespace loading, RBAC checks, custom delete button resolution) resolve. It adds placeholder buttons that maintain the layout area from the initial render, matching the visual behavior of static components on the page.

Changes:

  • Added authResolved state to ProjectDeleteButton to show a placeholder button while RBAC permissions are pending, replacing it seamlessly with the real button once auth resolves.
  • Updated ProjectDetails.tsx to initialize DeleteButton as null when a custom delete button is being resolved, rendering a placeholder ActionButton in its place.
  • Fixed a pre-existing bug where isEnabled returning false never showed the fallback ProjectDeleteButton.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
frontend/src/components/project/ProjectDeleteButton.tsx Adds namespace-loading and RBAC-pending placeholders to prevent layout shift; introduces authResolved state wired to AuthVisible's onAuthResult/onError callbacks
frontend/src/components/project/ProjectDetails.tsx Initializes DeleteButton as null during async custom-button resolution, renders a placeholder ActionButton; also fixes the isEnabled = false fallback to correctly display ProjectDeleteButton

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

@illume illume left a comment

Choose a reason for hiding this comment

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

Please check the open review comments?

For the commit it could have projects: added.

It's not upstreamable? (I'm not sure... but looks like it could be?) if so please add the upstreamable to the commit/PR title?

@illume illume marked this pull request as draft March 11, 2026 18:34
Copy link

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 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +58 to +88
{!authResolved && (
<ActionButton
description={t('Delete project')}
buttonStyle={buttonStyle}
onClick={() => {}}
icon="mdi:delete"
/>
)}
<AuthVisible
item={projectNamespaces[0]}
authVerb="update"
onAuthResult={() => setAuthResolved(true)}
onError={() => setAuthResolved(true)}
>
{authResolved && (
<>
<ActionButton
description={t('Delete project')}
buttonStyle={buttonStyle}
onClick={() => setOpenDialog(true)}
icon="mdi:delete"
/>
<ProjectDeleteDialog
open={openDialog}
project={project}
onClose={() => setOpenDialog(false)}
namespaces={projectNamespaces}
/>
</>
)}
</AuthVisible>
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

With the current authResolved gating, users who are not authorized will briefly see the placeholder button and then it will disappear once onAuthResult fires with allowed: false, causing a layout shift (and a short-lived “Delete” affordance). If the goal is to avoid layout shifts in all cases, consider reserving the space even after auth resolves but is denied (e.g., keep a disabled button with visibility: hidden/aria-hidden, or a fixed-size container) rather than removing it entirely.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

@tejhan tejhan Mar 12, 2026

Choose a reason for hiding this comment

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

The placeholder button exists to prevent layout shift for authorized users (the common case). Making it disabled would cause a visible white -> grey -> white flicker as it transitions to the real button.

For unauthorized users, there would be a brief flash of the placeholder before it disappears, but this comment suggests an empty placeholder for that case - which means these 2 goals are contradictory. Since we check auth first before making the decision of 'showing' it or not, we can't know which placeholder type to use before the auth is done.

Current approach leans toward the most common case so we see zero layout shift.

But this is something that might be a design decision to discuss. (delete button is right aligned)

@tejhan tejhan force-pushed the project-delete-button-placeholder branch from 514c808 to 82dbdc5 Compare March 12, 2026 08:43
@tejhan tejhan changed the title Frontend: Add placeholder buttons to prevent layout shift during async loading headlamp: upstreamable: frontend: Add placeholder buttons to prevent layout shift during async loading Mar 12, 2026
@tejhan tejhan changed the title headlamp: upstreamable: frontend: Add placeholder buttons to prevent layout shift during async loading Headlamp: upstreamable: frontend: Add placeholder buttons to prevent layout shift during async loading Mar 12, 2026
@tejhan tejhan changed the title Headlamp: upstreamable: frontend: Add placeholder buttons to prevent layout shift during async loading Frontend: upstreamable: Add placeholder buttons to prevent layout shift during async loading Mar 12, 2026
@tejhan tejhan changed the title Frontend: upstreamable: Add placeholder buttons to prevent layout shift during async loading Frontend: upstreamable: Add placeholder buttons to prevent layout shift during project loading Mar 12, 2026
@illume illume added p-none No priority was assigned bug Something isn't working labels Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working p-none No priority was assigned

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants