[User Profile] Update page header design (#205250)

## Summary

This PR wraps each `right side item` of `EuiPageHeaderSection` in a
`EuiFlexItem` and assigns `grow` property based on what the field is.
This makes it so fields that are usually longer (e.g `email`) won't
truncate too early.

Closes: #204121

## Visuals
| Previous | New | Typical user |
|-----------------|-----------------|-----------------|

|![previous](https://github.com/user-attachments/assets/a7b2d4cc-5ec5-4b0c-883f-d1918a25942f)
|
![new](https://github.com/user-attachments/assets/4447da5d-a8bb-434d-a68c-b6deb3b933a6)
|
![typical_user](https://github.com/user-attachments/assets/f4cfd33f-74ce-4683-b391-8dc6c789c45e)
This commit is contained in:
Krzysztof Kowalczyk 2025-01-14 16:55:04 +01:00 committed by GitHub
parent 0d7f29c838
commit 8e9fea7677
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 88 additions and 188 deletions

View file

@ -34011,9 +34011,7 @@
"xpack.security.accountManagement.userProfile.detailsGroupDescription": "Fournissez quelques informations de base sur vous-même.",
"xpack.security.accountManagement.userProfile.detailsGroupTitle": "Détails",
"xpack.security.accountManagement.userProfile.discardChangesButton": "Abandonner",
"xpack.security.accountManagement.userProfile.emailHelpText": "Contactez un administrateur pour modifier votre adresse e-mail.",
"xpack.security.accountManagement.userProfile.emailLabel": "Adresse e-mail",
"xpack.security.accountManagement.userProfile.fullNameHelpText": "Contactez un administrateur pour modifier votre nom complet.",
"xpack.security.accountManagement.userProfile.fullNameLabel": "Nom complet",
"xpack.security.accountManagement.userProfile.imageAvatarTypeLabel": "Image",
"xpack.security.accountManagement.userProfile.imageUrlLabel": "Image",
@ -34024,7 +34022,6 @@
"xpack.security.accountManagement.userProfile.initialsMaxLengthError": "Entrez 2 caractères au maximum.",
"xpack.security.accountManagement.userProfile.initialsRequiredError": "Ajouter des initiales",
"xpack.security.accountManagement.userProfile.lightModeButton": "Claire",
"xpack.security.accountManagement.userProfile.noneProvided": "Aucune fournie",
"xpack.security.accountManagement.userProfile.overriddenMessage": "Ce paramètre est défini par le serveur Kibana et ne peut pas être modifié.",
"xpack.security.accountManagement.userProfile.passwordGroupDescription": "Protégez vos données avec un mot de passe fort.",
"xpack.security.accountManagement.userProfile.passwordGroupTitle": "Mot de passe",
@ -34032,14 +34029,11 @@
"xpack.security.accountManagement.userProfile.prepopulatedImageUrlPromptText": "Sélectionner ou glisser-déposer une image de remplacement",
"xpack.security.accountManagement.userProfile.randomizeButton": "Randomiser",
"xpack.security.accountManagement.userProfile.rolesCountLabel": "+{count} de plus",
"xpack.security.accountManagement.userProfile.rolesHelpText": "Les rôles contrôlent les accès et les autorisations dans la Suite Elastic.",
"xpack.security.accountManagement.userProfile.rolesLabel": "{roles, plural, one {Rôle} other {Rôles} }",
"xpack.security.accountManagement.userProfile.saveChangesButton": "{isSubmitting, select, true{Enregistrement des modifications…} other{Enregistrer les modifications}}",
"xpack.security.accountManagement.userProfile.submitErrorTitle": "Impossible de mettre à jour le profil",
"xpack.security.accountManagement.userProfile.themeFormGroupDescription": "Sélectionnez l'apparence de votre interface.",
"xpack.security.accountManagement.userProfile.title": "Profil",
"xpack.security.accountManagement.userProfile.unsavedChangesMessage": "{count, plural, one {# modification non enregistrée} other {# modifications non enregistrées}}",
"xpack.security.accountManagement.userProfile.usernameHelpText": "Le nom de l'utilisateur ne peut pas être modifié après la création du compte.",
"xpack.security.accountManagement.userProfile.usernameLabel": "Nom d'utilisateur",
"xpack.security.accountManagement.userProfile.userSettings.theme": "Mode",
"xpack.security.accountManagement.userProfile.userSettings.themeGroupDescription": "Thème Elastic",

View file

@ -33872,9 +33872,7 @@
"xpack.security.accountManagement.userProfile.detailsGroupDescription": "自分自身に関する基本情報を入力します。",
"xpack.security.accountManagement.userProfile.detailsGroupTitle": "詳細",
"xpack.security.accountManagement.userProfile.discardChangesButton": "破棄",
"xpack.security.accountManagement.userProfile.emailHelpText": "電子メールアドレスを変更するには、管理者に連絡してください。",
"xpack.security.accountManagement.userProfile.emailLabel": "メールアドレス",
"xpack.security.accountManagement.userProfile.fullNameHelpText": "氏名を変更するには、管理者に連絡してください。",
"xpack.security.accountManagement.userProfile.fullNameLabel": "フルネーム",
"xpack.security.accountManagement.userProfile.imageAvatarTypeLabel": "画像",
"xpack.security.accountManagement.userProfile.imageUrlLabel": "画像",
@ -33885,7 +33883,6 @@
"xpack.security.accountManagement.userProfile.initialsMaxLengthError": "2文字以下で入力してください。",
"xpack.security.accountManagement.userProfile.initialsRequiredError": "イニシャルを追加",
"xpack.security.accountManagement.userProfile.lightModeButton": "ライト",
"xpack.security.accountManagement.userProfile.noneProvided": "何も入力されていません",
"xpack.security.accountManagement.userProfile.overriddenMessage": "この設定は Kibana サーバーにより上書きされ、変更することはできません。",
"xpack.security.accountManagement.userProfile.passwordGroupDescription": "強力なパスワードでデータを保護します。",
"xpack.security.accountManagement.userProfile.passwordGroupTitle": "パスワード",
@ -33893,14 +33890,11 @@
"xpack.security.accountManagement.userProfile.prepopulatedImageUrlPromptText": "置換画像を選択するかドラッグアンドドロップします",
"xpack.security.accountManagement.userProfile.randomizeButton": "ランダム化",
"xpack.security.accountManagement.userProfile.rolesCountLabel": "他 {count} 件",
"xpack.security.accountManagement.userProfile.rolesHelpText": "ロールはElastic Stack全体のアクセスと権限を制御します。",
"xpack.security.accountManagement.userProfile.rolesLabel": "{roles, plural, other {ロール} }",
"xpack.security.accountManagement.userProfile.saveChangesButton": "{isSubmitting, select, true{変更を保存しています…} other{変更の保存}}",
"xpack.security.accountManagement.userProfile.submitErrorTitle": "プロファイルを更新できませんでした",
"xpack.security.accountManagement.userProfile.themeFormGroupDescription": "インターフェースの表示を選択します。",
"xpack.security.accountManagement.userProfile.title": "プロフィール",
"xpack.security.accountManagement.userProfile.unsavedChangesMessage": "{count, plural, other {# 保存されていない変更}}",
"xpack.security.accountManagement.userProfile.usernameHelpText": "アカウントの作成後は、ユーザー名を変更できません。",
"xpack.security.accountManagement.userProfile.usernameLabel": "ユーザー名",
"xpack.security.accountManagement.userProfile.userSettings.theme": "モード",
"xpack.security.accountManagement.userProfile.userSettings.themeGroupDescription": "Elasticテーマ",

View file

@ -33373,9 +33373,7 @@
"xpack.security.accountManagement.userProfile.detailsGroupDescription": "提供一些与您自己相关的基本信息。",
"xpack.security.accountManagement.userProfile.detailsGroupTitle": "详情",
"xpack.security.accountManagement.userProfile.discardChangesButton": "丢弃",
"xpack.security.accountManagement.userProfile.emailHelpText": "请联系管理员更改您的电子邮件地址。",
"xpack.security.accountManagement.userProfile.emailLabel": "电子邮件地址",
"xpack.security.accountManagement.userProfile.fullNameHelpText": "请联系管理员更改您的全名。",
"xpack.security.accountManagement.userProfile.fullNameLabel": "全名",
"xpack.security.accountManagement.userProfile.imageAvatarTypeLabel": "图像",
"xpack.security.accountManagement.userProfile.imageUrlLabel": "图像",
@ -33386,7 +33384,6 @@
"xpack.security.accountManagement.userProfile.initialsMaxLengthError": "最多输入 2 个字符。",
"xpack.security.accountManagement.userProfile.initialsRequiredError": "添加缩写",
"xpack.security.accountManagement.userProfile.lightModeButton": "浅色",
"xpack.security.accountManagement.userProfile.noneProvided": "未提供任何内容",
"xpack.security.accountManagement.userProfile.overriddenMessage": "此设置已由 Kibana 服务器覆盖,无法更改。",
"xpack.security.accountManagement.userProfile.passwordGroupDescription": "使用强密码保护您的数据。",
"xpack.security.accountManagement.userProfile.passwordGroupTitle": "密码",
@ -33394,14 +33391,11 @@
"xpack.security.accountManagement.userProfile.prepopulatedImageUrlPromptText": "选择或拖放替换图像",
"xpack.security.accountManagement.userProfile.randomizeButton": "随机化",
"xpack.security.accountManagement.userProfile.rolesCountLabel": "另外 {count} 个",
"xpack.security.accountManagement.userProfile.rolesHelpText": "角色将跨 Elastic Stack 控制访问权限和权限。",
"xpack.security.accountManagement.userProfile.rolesLabel": "{roles, plural, other {角色} }",
"xpack.security.accountManagement.userProfile.saveChangesButton": "{isSubmitting, select, true{正在保存更改……} other{保存更改}}",
"xpack.security.accountManagement.userProfile.submitErrorTitle": "无法更新配置文件",
"xpack.security.accountManagement.userProfile.themeFormGroupDescription": "选择您界面的外观。",
"xpack.security.accountManagement.userProfile.title": "配置文件",
"xpack.security.accountManagement.userProfile.unsavedChangesMessage": "{count, plural, other {# 个未保存的更改}}",
"xpack.security.accountManagement.userProfile.usernameHelpText": "创建帐户后无法更改用户名。",
"xpack.security.accountManagement.userProfile.usernameLabel": "用户名",
"xpack.security.accountManagement.userProfile.userSettings.theme": "模式",
"xpack.security.accountManagement.userProfile.userSettings.themeGroupDescription": "Elastic 主题",

View file

@ -70,7 +70,7 @@ describe('<AccountManagementPage>', () => {
expect(UserProfileMock).toHaveBeenCalledWith({ user, data }, expect.anything());
expect(coreStart.chrome.setBreadcrumbs).toHaveBeenLastCalledWith([
{ href: '/security/account', text: 'User settings' },
{ href: undefined, text: 'Profile' },
{ href: undefined, text: 'user' },
]);
});
});

View file

@ -408,9 +408,9 @@ describe('useUserProfileForm', () => {
<UserProfile user={nonCloudUser} data={data} />
</Providers>
);
expect(testWrapper.exists('span[data-test-subj="userRoles"]')).toBeTruthy();
expect(testWrapper.exists('dl[data-test-subj="userRoles"]')).toBeTruthy();
expect(testWrapper.exists('EuiButtonEmpty[data-test-subj="userRolesExpand"]')).toBeFalsy();
expect(testWrapper.exists('button[data-test-subj="userRolesExpand"]')).toBeFalsy();
expect(testWrapper.exists('EuiBadgeGroup[data-test-subj="remainingRoles"]')).toBeFalsy();
});
@ -438,12 +438,10 @@ describe('useUserProfileForm', () => {
const extraRoles = nonCloudUser.roles.splice(3);
const userRolesExpandButton = testWrapper.find(
'EuiButtonEmpty[data-test-subj="userRolesExpand"]'
);
const userRolesExpandButton = testWrapper.find('button[data-test-subj="userRolesExpand"]');
expect(userRolesExpandButton).toBeTruthy();
expect(userRolesExpandButton.text()).toEqual(`+${extraRoles.length} more`);
expect(userRolesExpandButton.text()).toEqual(`+${extraRoles.length}`);
});
});
});

View file

@ -20,15 +20,11 @@ import {
EuiFlexItem,
EuiFormRow,
EuiIcon,
EuiIconTip,
EuiKeyPadMenu,
EuiKeyPadMenuItem,
EuiPageHeaderSection,
EuiPopover,
EuiSpacer,
EuiText,
EuiTextTruncate,
EuiTitle,
EuiToolTip,
useEuiTheme,
useGeneratedHtmlId,
@ -82,22 +78,6 @@ const pageHeaderCSS = css`
border-bottom: none;
`;
const pageTitleCSS = css`
min-width: 120px;
`;
const rightSideItemsCSS = css`
justify-content: flex-start;
@include euiBreakpoint('m') {
justify-content: flex-end;
}
`;
const rightSideItemCSS = css`
min-width: 160px;
`;
export interface UserProfileProps {
user: AuthenticatedUser;
data?: UserProfileData;
@ -682,13 +662,22 @@ const UserRoles: FunctionComponent<UserRoleProps> = ({ user }) => {
const renderMoreRoles = () => {
const button = (
<EuiButtonEmpty size="xs" onClick={onButtonClick} data-test-subj="userRolesExpand">
<EuiBadge
onClick={onButtonClick}
data-test-subj="userRolesExpand"
onClickAriaLabel={i18n.translate(
'xpack.security.accountManagement.userProfile.showMoreRolesHelpText',
{
defaultMessage: 'Show more roles',
}
)}
>
<FormattedMessage
id="xpack.security.accountManagement.userProfile.rolesCountLabel"
defaultMessage="+{count} more"
defaultMessage="+{count}"
values={{ count: remainingRoles.length }}
/>
</EuiButtonEmpty>
</EuiBadge>
);
return (
<EuiPopover
@ -723,22 +712,19 @@ const UserRoles: FunctionComponent<UserRoleProps> = ({ user }) => {
{role}
</EuiBadge>
))}
{remainingRoles.length ? renderMoreRoles() : null}
</EuiBadgeGroup>
{remainingRoles.length ? renderMoreRoles() : null}
</>
);
};
export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data }) => {
const { euiTheme } = useEuiTheme();
const { services } = useKibana<CoreStart>();
const formik = useUserProfileForm({ user, data });
const formChanges = useFormChanges();
const titleId = useGeneratedHtmlId();
const [showChangePasswordForm, setShowChangePasswordForm] = useState(false);
const canChangeDetails = canUserChangeDetails(user, services.application.capabilities);
const isCloudUser = user.elastic_cloud_user;
const { isThemeOverridden, isOverriddenThemeDarkMode } = determineIfThemeOverridden(
@ -746,93 +732,11 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
services.theme
);
const rightSideItems = [
{
title: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.usernameLabel"
defaultMessage="Username"
/>
),
description:
user.username &&
((<EuiTextTruncate text={user.username} />) as string | undefined | JSX.Element),
helpText: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.usernameHelpText"
defaultMessage="User name cannot be changed after account creation."
/>
),
testSubj: 'username',
},
];
if (!canChangeDetails) {
rightSideItems.push({
title: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.fullNameLabel"
defaultMessage="Full name"
/>
),
description: user.full_name && <EuiTextTruncate text={user.full_name} />,
helpText: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.fullNameHelpText"
defaultMessage="Please contact an administrator to change your full name."
/>
),
testSubj: 'full_name',
});
rightSideItems.push({
title: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.emailLabel"
defaultMessage="Email address"
/>
),
description: user.email && <EuiTextTruncate text={user.email} />,
helpText: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.emailHelpText"
defaultMessage="Please contact an administrator to change your email address."
/>
),
testSubj: 'email',
});
}
rightSideItems.push({
title: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.rolesLabel"
defaultMessage="{roles, plural,
one {Role}
other {Roles}
}"
values={{ roles: user.roles.length }}
/>
),
description: <UserRoles user={user} />,
helpText: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.rolesHelpText"
defaultMessage="Roles control access and permissions across the Elastic Stack."
/>
),
testSubj: 'userRoles',
});
return (
<>
<FormikProvider value={formik}>
<FormChangesProvider value={formChanges}>
<Breadcrumb
text={i18n.translate('xpack.security.accountManagement.userProfile.title', {
defaultMessage: 'Profile',
})}
>
<Breadcrumb text={user.username}>
{showChangePasswordForm ? (
<ChangePasswordModal
username={user.username}
@ -842,60 +746,76 @@ export const UserProfile: FunctionComponent<UserProfileProps> = ({ user, data })
) : null}
<KibanaPageTemplate className="eui-fullHeight" restrictWidth={true}>
<KibanaPageTemplate.Header id={titleId} css={pageHeaderCSS}>
<EuiPageHeaderSection>
<EuiTitle size="l" css={pageTitleCSS}>
<h1>
<FormattedMessage
id="xpack.security.accountManagement.userProfile.title"
defaultMessage="Profile"
/>
</h1>
</EuiTitle>
</EuiPageHeaderSection>
<EuiPageHeaderSection>
<EuiFlexGroup alignItems="flexStart" css={rightSideItemsCSS}>
{rightSideItems.map((item) => (
<EuiDescriptionList
key={item.testSubj}
textStyle="reverse"
css={rightSideItemCSS}
listItems={[
<KibanaPageTemplate.Header
id={titleId}
css={pageHeaderCSS}
pageTitle={user.username}
alignItems="bottom"
pageTitleProps={{
'data-test-subj': 'username',
'aria-label': i18n.translate(
'xpack.security.accountManagement.userProfile.usernameLabel',
{
defaultMessage: 'Username',
}
),
}}
description={
<EuiText component="span">
{user.full_name && (
<EuiText
data-test-subj="full_name"
component="span"
aria-label={i18n.translate(
'xpack.security.accountManagement.userProfile.fullNameLabel',
{
title: (
<EuiText color={euiTheme.colors.darkestShade} size="s">
<EuiFlexGroup
responsive={false}
alignItems="center"
gutterSize="none"
>
<EuiFlexItem grow={false}>{item.title}</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiIconTip type="questionInCircle" content={item.helpText} />
</EuiFlexItem>
</EuiFlexGroup>
</EuiText>
),
description: (
<span data-test-subj={item.testSubj}>
{item.description || (
<EuiText color={euiTheme.colors.textDisabled} size="s">
<FormattedMessage
id="xpack.security.accountManagement.userProfile.noneProvided"
defaultMessage="None provided"
/>
</EuiText>
)}
</span>
),
},
]}
compressed
/>
))}
</EuiFlexGroup>
</EuiPageHeaderSection>
</KibanaPageTemplate.Header>
defaultMessage: 'Full name',
}
)}
>
{user.full_name}
</EuiText>
)}
{user.full_name && user.email && <EuiText component="span">, </EuiText>}
{user.email && (
<EuiText
data-test-subj="email"
component="span"
aria-label={i18n.translate(
'xpack.security.accountManagement.userProfile.emailLabel',
{
defaultMessage: 'Email address',
}
)}
>
{user.email}
</EuiText>
)}
</EuiText>
}
rightSideItems={[
<EuiDescriptionList
type="column"
data-test-subj="userRoles"
listItems={[
{
title: (
<FormattedMessage
id="xpack.security.accountManagement.userProfile.rolesLabel"
defaultMessage="{roles, plural,
one {Role}
other {Roles}
}"
values={{ roles: user.roles.length }}
/>
),
description: <UserRoles user={user} />,
},
]}
compressed
/>,
]}
/>
<KibanaPageTemplate.Section>
<Form aria-labelledby={titleId}>
<UserDetailsEditor user={user} />