aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src
diff options
context:
space:
mode:
authorstanislavh <stanislav.honcharov@sonarsource.com>2024-11-28 17:13:02 +0100
committersonartech <sonartech@sonarsource.com>2024-11-29 20:03:06 +0000
commit7bfb85fef959d5f1cf12f08c88dc9d8025aba6f3 (patch)
tree7e8214860e449a6e9006a5d387cdadbd31943e15 /server/sonar-web/src
parent0e670b6152c075f8ada586e5202ce8b89d59a0ab (diff)
downloadsonarqube-7bfb85fef959d5f1cf12f08c88dc9d8025aba6f3.tar.gz
sonarqube-7bfb85fef959d5f1cf12f08c88dc9d8025aba6f3.zip
SONAR-22289 Fix a11y issues on project key page
Diffstat (limited to 'server/sonar-web/src')
-rw-r--r--server/sonar-web/src/main/js/apps/projectKey/ProjectKeyApp.tsx7
-rw-r--r--server/sonar-web/src/main/js/apps/projectKey/UpdateForm.tsx163
2 files changed, 90 insertions, 80 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectKey/ProjectKeyApp.tsx b/server/sonar-web/src/main/js/apps/projectKey/ProjectKeyApp.tsx
index 5e941b47821..3a790292b68 100644
--- a/server/sonar-web/src/main/js/apps/projectKey/ProjectKeyApp.tsx
+++ b/server/sonar-web/src/main/js/apps/projectKey/ProjectKeyApp.tsx
@@ -18,8 +18,9 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { Heading } from '@sonarsource/echoes-react';
import { Helmet } from 'react-helmet-async';
-import { LargeCenteredLayout, PageContentFontWrapper, Title } from '~design-system';
+import { LargeCenteredLayout, PageContentFontWrapper } from '~design-system';
import { withRouter } from '~sonar-aligned/components/hoc/withRouter';
import { Router } from '~sonar-aligned/types/router';
import { changeKey } from '../../api/components';
@@ -47,7 +48,9 @@ function ProjectKeyApp({ component, router }: Props) {
<Helmet defer={false} title={translate('update_key.page')} />
<PageContentFontWrapper className="sw-my-8 sw-typo-default">
<header className="sw-mt-8 sw-mb-4">
- <Title className="sw-mb-4">{translate('update_key.page')}</Title>
+ <Heading as="h1" className="sw-mb-4">
+ {translate('update_key.page')}
+ </Heading>
<div className="sw-mb-2">{translate('update_key.page.description')}</div>
</header>
<UpdateForm component={component} onKeyChange={handleChangeKey} />
diff --git a/server/sonar-web/src/main/js/apps/projectKey/UpdateForm.tsx b/server/sonar-web/src/main/js/apps/projectKey/UpdateForm.tsx
index a9337558cc5..7d82b428ff7 100644
--- a/server/sonar-web/src/main/js/apps/projectKey/UpdateForm.tsx
+++ b/server/sonar-web/src/main/js/apps/projectKey/UpdateForm.tsx
@@ -18,17 +18,11 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { Button, ButtonVariety, ModalAlert, Text } from '@sonarsource/echoes-react';
import * as React from 'react';
-import {
- ButtonPrimary,
- ButtonSecondary,
- FlagMessage,
- FormField,
- InputField,
- Note,
-} from '~design-system';
-import ConfirmButton from '../../components/controls/ConfirmButton';
-import { translate, translateWithParameters } from '../../helpers/l10n';
+import { useIntl } from 'react-intl';
+import { FlagMessage, FormField, InputField } from '~design-system';
+import { translate } from '../../helpers/l10n';
import { validateProjectKey } from '../../helpers/projects';
import { ProjectKeyValidationResult } from '../../types/component';
import { Component } from '../../types/types';
@@ -38,8 +32,8 @@ export interface UpdateFormProps {
onKeyChange: (newKey: string) => Promise<void>;
}
-export default function UpdateForm(props: UpdateFormProps) {
- const { component } = props;
+export default function UpdateForm({ component, onKeyChange }: Readonly<UpdateFormProps>) {
+ const intl = useIntl();
const [newKey, setNewKey] = React.useState(component.key);
const hasChanged = newKey !== component.key;
@@ -57,76 +51,89 @@ export default function UpdateForm(props: UpdateFormProps) {
);
return (
- <ConfirmButton
- confirmButtonText={translate('update_verb')}
- confirmData={newKey}
- modalBody={
- <>
- {translateWithParameters('update_key.are_you_sure_to_change_key', component.name)}
- <div className="sw-mt-2">
- {translate('update_key.old_key')}
- {': '}
- <strong className="sw-typo-lg-semibold">{component.key}</strong>
- </div>
- <div className="sw-mt-2">
- {translate('update_key.new_key')}
- {': '}
- <strong className="sw-typo-lg-semibold">{newKey}</strong>
- </div>
- </>
- }
- modalHeader={translate('update_key.page')}
- onConfirm={props.onKeyChange}
- >
- {({ onFormSubmit }) => (
- <form onSubmit={onFormSubmit}>
- <FormField label={translate('update_key.new_key')} required>
- <InputField
- id="project-key"
- name="update_key.new_key"
- required
- isInvalid={hasChanged && error !== undefined}
- isValid={hasChanged && error === undefined}
- autoFocus
- onChange={onInputChange}
- value={newKey}
- type="text"
- />
+ <form onSubmit={(e) => e.preventDefault()}>
+ <FormField htmlFor="project-key-input" label={translate('update_key.new_key')} required>
+ <InputField
+ id="project-key-input"
+ name="update_key.new_key"
+ required
+ aria-invalid={hasChanged && error !== undefined}
+ aria-describedby="project-key-input-error project-key-input-hint"
+ isInvalid={hasChanged && error !== undefined}
+ isValid={hasChanged && error === undefined}
+ autoFocus
+ onChange={onInputChange}
+ value={newKey}
+ type="text"
+ />
- {error && (
- <FlagMessage className="sw-mt-2 sw-w-abs-400" variant="error">
- {error}
- </FlagMessage>
- )}
+ <output>
+ {Boolean(error) && (
+ <FlagMessage
+ id="project-key-input-error"
+ className="sw-mt-2 sw-w-abs-400"
+ variant="error"
+ >
+ {error}
+ </FlagMessage>
+ )}
+ </output>
- <Note className="sw-mt-2 sw-max-w-1/2">
- {translate('onboarding.create_project.project_key.description')}
- </Note>
- </FormField>
+ <Text isSubdued className="sw-mt-2 sw-max-w-1/2">
+ <span id="project-key-input-hint">
+ {translate('onboarding.create_project.project_key.description')}
+ </span>
+ </Text>
+ </FormField>
- <div className="sw-mt-2">
- <ButtonPrimary
- disabled={!hasChanged || error !== undefined}
- id="update-key-submit"
- type="submit"
- >
+ <div className="sw-mt-2">
+ <ModalAlert
+ primaryButton={
+ <Button variety={ButtonVariety.Primary} onClick={() => onKeyChange(newKey)}>
{translate('update_verb')}
- </ButtonPrimary>
+ </Button>
+ }
+ title={translate('update_key.page')}
+ description={intl.formatMessage(
+ { id: 'update_key.are_you_sure_to_change_key' },
+ { '0': component.name },
+ )}
+ content={
+ <>
+ <span>
+ {translate('update_key.old_key')}:&nbsp;
+ <strong className="sw-typo-lg-semibold">{component.key}</strong>
+ </span>
+ <div className="sw-mt-2">
+ {translate('update_key.new_key')}:&nbsp;
+ <strong className="sw-typo-lg-semibold">{newKey}</strong>
+ </div>
+ </>
+ }
+ >
+ <Button
+ variety={ButtonVariety.Primary}
+ isDisabled={!hasChanged || error !== undefined}
+ id="update-key-submit"
+ type="submit"
+ >
+ {translate('update_verb')}
+ </Button>
+ </ModalAlert>
- <ButtonSecondary
- className="sw-ml-2"
- disabled={!hasChanged}
- id="update-key-reset"
- onClick={() => {
- setNewKey(component.key);
- }}
- type="reset"
- >
- {translate('reset_verb')}
- </ButtonSecondary>
- </div>
- </form>
- )}
- </ConfirmButton>
+ <Button
+ variety={ButtonVariety.Default}
+ className="sw-ml-2"
+ isDisabled={!hasChanged}
+ id="update-key-reset"
+ onClick={() => {
+ setNewKey(component.key);
+ }}
+ type="reset"
+ >
+ {translate('reset_verb')}
+ </Button>
+ </div>
+ </form>
);
}