Wizard: Add tooltip explaining password visibility in edit mode

When editing a blueprint, password fields show an eye icon that appears
clickable but is actually disabled for security reasons (passwords cannot
be retrieved from the backend). This creates confusing UX where users
expect the icon to work but it doesn't respond.

This change adds a tooltip that appears when hovering over the disabled
eye button, explaining that "Passwords cannot be viewed when editing a
blueprint for security reasons."

The fix wraps the disabled button in a span element to ensure the tooltip
triggers properly, as disabled buttons don't receive mouse events.

Also adds unit test to verify the tooltip functionality

Fixes #3303

🤖 Generated with AI
This commit is contained in:
Michal Gold 2025-07-31 17:14:14 +03:00 committed by Klara Simickova
parent 4f250ee637
commit 88dd0880c8
3 changed files with 52 additions and 9 deletions

View file

@ -10,6 +10,7 @@ import {
InputGroupItem,
TextInput,
TextInputProps,
Tooltip,
} from '@patternfly/react-core';
import { EyeIcon, EyeSlashIcon } from '@patternfly/react-icons';
@ -46,6 +47,21 @@ export const PasswordValidatedInput = ({
setIsPasswordVisible(!isPasswordVisible);
};
const isEditingWithoutValue = hasPassword && !value;
const PasswordToggleButton = () => {
return (
<Button
variant="control"
onClick={togglePasswordVisibility}
aria-label={isPasswordVisible ? 'Hide password' : 'Show password'}
isDisabled={isEditingWithoutValue}
>
{isPasswordVisible ? <EyeSlashIcon /> : <EyeIcon />}
</Button>
);
};
return (
<FormGroup label="Password" className="pf-v6-u-pb-md">
<>
@ -61,14 +77,15 @@ export const PasswordValidatedInput = ({
/>
</InputGroupItem>
<InputGroupItem>
<Button
variant="control"
onClick={togglePasswordVisibility}
aria-label={isPasswordVisible ? 'Hide password' : 'Show password'}
isDisabled={hasPassword && !value}
>
{isPasswordVisible ? <EyeSlashIcon /> : <EyeIcon />}
</Button>
{isEditingWithoutValue ? (
<Tooltip content="Passwords cannot be viewed when editing a blueprint for security reasons">
<span>
<PasswordToggleButton/>
</span>
</Tooltip>
) : (
<PasswordToggleButton/>
)}
</InputGroupItem>
</InputGroup>
</>

View file

@ -506,4 +506,30 @@ describe('Users edit mode', () => {
const expectedRequest = usersCreateBlueprintRequest;
expect(receivedRequest).toEqual(expectedRequest);
});
test('shows tooltip on disabled password eye icon when editing blueprint with existing password', async () => {
const user = userEvent.setup();
const id = mockBlueprintIds['users'];
await renderEditMode(id);
const usersNavButtons = await screen.findAllByRole('button', { name: /Users/ });
await waitFor(() => user.click(usersNavButtons[0]));
const passwordToggleButton = await screen.findByRole('button', {
name: 'Show password'
});
expect(passwordToggleButton).toBeDisabled();
await waitFor(() => user.hover(passwordToggleButton));
const tooltip = await screen.findByText('Passwords cannot be viewed when editing a blueprint for security reasons');
expect(tooltip).toBeInTheDocument();
await waitFor(() => user.unhover(passwordToggleButton));
await waitFor(() => {
expect(screen.queryByText('Passwords cannot be viewed when editing a blueprint for security reasons')).not.toBeInTheDocument();
});
});
});

View file

@ -502,7 +502,7 @@ export const usersCreateBlueprintRequest: CreateBlueprintRequest = {
name: 'best',
ssh_key: 'ssh-rsa d',
groups: ['wheel'],
hasPassword: false,
hasPassword: true,
},
],
},