aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2024-03-13 09:44:29 +0100
committersonartech <sonartech@sonarsource.com>2024-03-16 20:02:47 +0000
commitf4896ace30bcad83d4df1bcf4a768e6ff68facb0 (patch)
treef01b625d06a1fe68fa41b0807c238e60616131d0 /server
parent4592d635902de23b402a28787a8468ba1ac3a3a4 (diff)
downloadsonarqube-f4896ace30bcad83d4df1bcf4a768e6ff68facb0.tar.gz
sonarqube-f4896ace30bcad83d4df1bcf4a768e6ff68facb0.zip
SONAR-21639 Start using new RadioButtonGroup and deprecate legacy RadioButton component
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/design-system/src/components/DropdownMenu.tsx30
-rw-r--r--server/sonar-web/design-system/src/components/__tests__/DropdownMenu-test.tsx4
-rw-r--r--server/sonar-web/design-system/src/components/input/RadioButton.tsx10
-rw-r--r--server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx27
-rw-r--r--server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx31
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/ChangeDefaultVisibilityForm.tsx32
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx24
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx27
-rw-r--r--server/sonar-web/src/main/js/components/common/VisibilitySelector.tsx27
9 files changed, 81 insertions, 131 deletions
diff --git a/server/sonar-web/design-system/src/components/DropdownMenu.tsx b/server/sonar-web/design-system/src/components/DropdownMenu.tsx
index 9072d93ae65..d5ba01e2485 100644
--- a/server/sonar-web/design-system/src/components/DropdownMenu.tsx
+++ b/server/sonar-web/design-system/src/components/DropdownMenu.tsx
@@ -30,7 +30,6 @@ import NavLink from './NavLink';
import { Tooltip } from './Tooltip';
import { ClipboardBase } from './clipboard';
import { Checkbox } from './input/Checkbox';
-import { RadioButton } from './input/RadioButton';
interface Props extends React.HtmlHTMLAttributes<HTMLMenuElement> {
children?: React.ReactNode;
@@ -198,30 +197,6 @@ export function ItemCheckbox(props: ItemCheckboxProps) {
);
}
-interface ItemRadioButtonProps extends ListItemProps {
- checked: boolean;
- disabled?: boolean;
- onCheck: (value: string) => void;
- value: string;
-}
-
-export function ItemRadioButton(props: ItemRadioButtonProps) {
- const { checked, children, className, disabled, innerRef, onCheck, value, ...liProps } = props;
- return (
- <li ref={innerRef} role="none" {...liProps}>
- <ItemRadioButtonStyled
- checked={checked}
- className={classNames(className, { disabled })}
- disabled={disabled}
- onCheck={onCheck}
- value={value}
- >
- {children}
- </ItemRadioButtonStyled>
- </li>
- );
-}
-
interface ItemCopyProps {
children?: React.ReactNode;
className?: string;
@@ -398,8 +373,3 @@ const ItemCheckboxStyled = styled(Checkbox)`
--color: ${themeContrast('dropdownMenu')};
${itemStyle}
`;
-
-const ItemRadioButtonStyled = styled(RadioButton)`
- --color: ${themeContrast('dropdownMenu')};
- ${itemStyle}
-`;
diff --git a/server/sonar-web/design-system/src/components/__tests__/DropdownMenu-test.tsx b/server/sonar-web/design-system/src/components/__tests__/DropdownMenu-test.tsx
index 087a89bcdb3..5e2aebceb65 100644
--- a/server/sonar-web/design-system/src/components/__tests__/DropdownMenu-test.tsx
+++ b/server/sonar-web/design-system/src/components/__tests__/DropdownMenu-test.tsx
@@ -30,7 +30,6 @@ import {
ItemHeader,
ItemLink,
ItemNavLink,
- ItemRadioButton,
} from '../DropdownMenu';
import { Tooltip } from '../Tooltip';
import { MenuIcon } from '../icons/MenuIcon';
@@ -74,9 +73,6 @@ function renderDropdownMenu() {
<ItemCheckbox checked onCheck={noop}>
Checkbox item
</ItemCheckbox>
- <ItemRadioButton checked={false} onCheck={noop} value="radios">
- Radio item
- </ItemRadioButton>
</DropdownMenu>,
);
}
diff --git a/server/sonar-web/design-system/src/components/input/RadioButton.tsx b/server/sonar-web/design-system/src/components/input/RadioButton.tsx
index 7ee29e59f89..f36d7ec762f 100644
--- a/server/sonar-web/design-system/src/components/input/RadioButton.tsx
+++ b/server/sonar-web/design-system/src/components/input/RadioButton.tsx
@@ -39,6 +39,11 @@ type Props =
| ({ onCheck: (value: string) => void; value: string } & PropsBase)
| ({ onCheck: () => void; value: never } & PropsBase);
+/** @deprecated Use RadioButtonGroup from Echoes instead.
+ *
+ * Individual Radio Buttons can't be used anymore.
+ * Instead, build the list of options and pass it to the RadioButtonGroup component.
+ */
export function RadioButton({
checked,
children,
@@ -88,6 +93,11 @@ const LabelStyled = styled.label<{ disabled?: boolean }>`
}
`;
+/** @deprecated Use RadioButtonGroup from Echoes instead.
+ *
+ * Individual Radio Buttons can't be used anymore.
+ * Instead, build the list of options and pass it to the RadioButtonGroup component.
+ */
export const RadioButtonStyled = styled.input`
appearance: none; //disables native style
border: ${themeBorder('default', 'radioBorder')};
diff --git a/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx b/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx
index 7242e023fd0..98b3de92e9c 100644
--- a/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx
+++ b/server/sonar-web/src/main/js/apps/audit-logs/components/AuditAppRenderer.tsx
@@ -18,14 +18,13 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { Link, RadioButtonGroup } from '@sonarsource/echoes-react';
import { subDays } from 'date-fns';
import {
DateRangePicker,
LargeCenteredLayout,
- Link,
PageContentFontWrapper,
PopupZLevel,
- RadioButton,
Title,
} from 'design-system';
import * as React from 'react';
@@ -75,7 +74,7 @@ const getRangeOptions = (housekeepingPolicy: HousekeepingPolicy) => {
return rangeOptions;
};
-export default function AuditAppRenderer(props: AuditAppRendererProps) {
+export default function AuditAppRenderer(props: Readonly<AuditAppRendererProps>) {
const { dateRange, downloadStarted, housekeepingPolicy, selection } = props;
return (
@@ -112,19 +111,15 @@ export default function AuditAppRenderer(props: AuditAppRendererProps) {
<div className="sw-mb-6">
<h3 className="sw-mb-4">{translate('audit_logs.download')}</h3>
- <ul>
- {getRangeOptions(housekeepingPolicy).map((option) => (
- <li key={option} className="sw-mb-2">
- <RadioButton
- checked={selection === option}
- onCheck={props.handleOptionSelection}
- value={option}
- >
- {translate('audit_logs.range_option', option)}
- </RadioButton>
- </li>
- ))}
- </ul>
+ <RadioButtonGroup
+ id="audit-logs-housekeeping-radio"
+ options={getRangeOptions(housekeepingPolicy).map((option) => ({
+ label: translate('audit_logs.range_option', option),
+ value: option,
+ }))}
+ value={selection}
+ onChange={props.handleOptionSelection}
+ />
<DateRangePicker
className="sw-w-abs-350 sw-mt-4"
diff --git a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
index e0cd92c98df..4102f8cf9cc 100644
--- a/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
+++ b/server/sonar-web/src/main/js/apps/issues/components/BulkChangeModal.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { Checkbox, Spinner } from '@sonarsource/echoes-react';
+import { Checkbox, RadioButtonGroup, Spinner } from '@sonarsource/echoes-react';
import {
ButtonPrimary,
FlagMessage,
@@ -28,7 +28,6 @@ import {
LabelValueSelectOption,
LightLabel,
Modal,
- RadioButton,
} from 'design-system';
import { countBy, flattenDeep, pickBy, sortBy } from 'lodash';
import * as React from 'react';
@@ -297,23 +296,16 @@ export class BulkChangeModal extends React.PureComponent<Props, State> {
<Highlight as="legend" className="sw-mb-2">
{translate('issue.change_status')}
</Highlight>
- {transitions.map((transition) => (
- <div
- className="sw-mb-1 sw-flex sw-items-center sw-justify-between"
- key={transition.transition}
- >
- <RadioButton
- checked={this.state.transition === transition.transition}
- onCheck={this.handleRadioTransitionChange}
- value={transition.transition}
- >
- {translate('issue.transition', transition.transition)}
- </RadioButton>
- <LightLabel>
- ({translateWithParameters('issue_bulk_change.x_issues', transition.count)})
- </LightLabel>
- </div>
- ))}
+
+ <RadioButtonGroup
+ id="bulk-change-transition"
+ options={transitions.map(({ transition, count }) => ({
+ label: translate('issue.transition', transition),
+ value: transition,
+ helpText: translateWithParameters('issue_bulk_change.x_issues', count),
+ }))}
+ onChange={this.handleRadioTransitionChange}
+ />
</fieldset>
</div>
);
@@ -333,7 +325,6 @@ export class BulkChangeModal extends React.PureComponent<Props, State> {
return (
<FormField label={translate('issue_bulk_change.resolution_comment')}>
<InputTextArea
- autoFocus
aria-label={translate('issue_bulk_change.resolution_comment')}
onChange={this.handleCommentChange}
placeholder={translate(
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/ChangeDefaultVisibilityForm.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/ChangeDefaultVisibilityForm.tsx
index 31d075ba7a1..6f2eca87f86 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/ChangeDefaultVisibilityForm.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/ChangeDefaultVisibilityForm.tsx
@@ -17,7 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { ButtonPrimary, FlagMessage, Modal, RadioButton, TextSubdued } from 'design-system';
+import { RadioButtonGroup } from '@sonarsource/echoes-react';
+import { ButtonPrimary, FlagMessage, Modal } from 'design-system';
import React, { useState } from 'react';
import { translate } from '../../helpers/l10n';
import { useGithubProvisioningEnabledQuery } from '../../queries/identity-provider/github';
@@ -31,7 +32,7 @@ export interface Props {
const FORM_ID = 'change-default-visibility-form';
-export default function ChangeDefaultVisibilityForm(props: Props) {
+export default function ChangeDefaultVisibilityForm(props: Readonly<Props>) {
const [visibility, setVisibility] = useState(props.defaultVisibility);
const { data: githubProbivisioningEnabled } = useGithubProvisioningEnabledQuery();
@@ -49,22 +50,17 @@ export default function ChangeDefaultVisibilityForm(props: Props) {
const body = (
<form id={FORM_ID} onSubmit={handleConfirmClick}>
- {Object.values(Visibility).map((visibilityValue) => (
- <div className="sw-mb-4" key={visibilityValue}>
- <RadioButton
- value={visibilityValue}
- checked={visibility === visibilityValue}
- onCheck={handleVisibilityChange}
- >
- <div>
- {translate('visibility', visibilityValue)}
- <TextSubdued as="p" className="sw-mt-2">
- {translate('visibility', visibilityValue, 'description.short')}
- </TextSubdued>
- </div>
- </RadioButton>
- </div>
- ))}
+ <RadioButtonGroup
+ id="settings-projects-visibility-radio"
+ options={Object.values(Visibility).map((visibilityValue) => ({
+ label: translate('visibility', visibilityValue),
+ helpText: translate('visibility', visibilityValue, 'description.short'),
+ value: visibilityValue,
+ }))}
+ value={visibility}
+ onChange={handleVisibilityChange}
+ />
+
<FlagMessage variant="warning">
{translate(
`settings.projects.change_visibility_form.warning${
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx
index 61f7ae71dfc..06b60e44600 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionModal.tsx
@@ -17,7 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { ButtonPrimary, FormField, Modal, RadioButton } from 'design-system';
+import { RadioButtonGroup } from '@sonarsource/echoes-react';
+import { ButtonPrimary, FormField, Modal } from 'design-system';
import * as React from 'react';
import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
import { isDiffMetric } from '../../../helpers/measures';
@@ -93,18 +94,15 @@ export default function AddConditionModal({ metrics, onClose, qualityGate }: Rea
return (
<form onSubmit={handleFormSubmit} id={ADD_CONDITION_MODAL_ID}>
<FormField label={translate('quality_gates.conditions.where')}>
- <div className="sw-flex sw-gap-4">
- <RadioButton checked={scope === 'new'} onCheck={handleScopeChange} value="new">
- <span data-test="quality-gates__condition-scope-new">
- {translate('quality_gates.conditions.new_code')}
- </span>
- </RadioButton>
- <RadioButton checked={scope === 'overall'} onCheck={handleScopeChange} value="overall">
- <span data-test="quality-gates__condition-scope-overall">
- {translate('quality_gates.conditions.overall_code')}
- </span>
- </RadioButton>
- </div>
+ <RadioButtonGroup
+ id="quality_gates-add-condition-scope-radio"
+ options={[
+ { label: translate('quality_gates.conditions.new_code'), value: 'new' },
+ { label: translate('quality_gates.conditions.overall_code'), value: 'overall' },
+ ]}
+ value={scope}
+ onChange={handleScopeChange}
+ />
</FormField>
<FormField
diff --git a/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx b/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx
index cf638be0286..87e64ff1bed 100644
--- a/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx
+++ b/server/sonar-web/src/main/js/apps/system/components/ChangeLogLevelForm.tsx
@@ -17,7 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { ButtonPrimary, FlagMessage, Modal, RadioButton } from 'design-system';
+import { RadioButtonGroup } from '@sonarsource/echoes-react';
+import { ButtonPrimary, FlagMessage, Modal } from 'design-system';
import * as React from 'react';
import { setLogLevel } from '../../../api/system';
import { translate } from '../../../helpers/l10n';
@@ -65,21 +66,15 @@ export default class ChangeLogLevelForm extends React.PureComponent<Props, State
onClose={this.props.onClose}
body={
<form id={FORM_ID} onSubmit={this.handleFormSubmit}>
- {LOGS_LEVELS.map((level) => (
- <RadioButton
- key={level}
- checked={level === newLevel}
- className="sw-mb-2"
- id={`loglevel-${level}`}
- name="system.log_levels"
- onCheck={this.handleLevelChange}
- value={level}
- >
- <label className="text-middle" htmlFor={`loglevel-${level}`}>
- {level}
- </label>
- </RadioButton>
- ))}
+ <div className="sw-mt-1">
+ <RadioButtonGroup
+ id="system-loglevel-radio"
+ options={LOGS_LEVELS.map((level) => ({ label: level, value: level }))}
+ value={newLevel}
+ onChange={this.handleLevelChange}
+ />
+ </div>
+
<FlagMessage className="sw-mt-2" variant="info">
{this.props.infoMsg}
</FlagMessage>
diff --git a/server/sonar-web/src/main/js/components/common/VisibilitySelector.tsx b/server/sonar-web/src/main/js/components/common/VisibilitySelector.tsx
index 51f3effe069..e3cfc540ab7 100644
--- a/server/sonar-web/src/main/js/components/common/VisibilitySelector.tsx
+++ b/server/sonar-web/src/main/js/components/common/VisibilitySelector.tsx
@@ -17,8 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { RadioButtonGroup } from '@sonarsource/echoes-react';
import classNames from 'classnames';
-import { RadioButton } from 'design-system';
import * as React from 'react';
import { translate } from '../../helpers/l10n';
import { Visibility } from '../../types/component';
@@ -32,22 +32,21 @@ export interface VisibilitySelectorProps {
loading?: boolean;
}
-export default function VisibilitySelector(props: VisibilitySelectorProps) {
+export default function VisibilitySelector(props: Readonly<VisibilitySelectorProps>) {
const { className, canTurnToPrivate, visibility, disabled, loading = false } = props;
return (
<div className={classNames(className)}>
- {Object.values(Visibility).map((v) => (
- <RadioButton
- className={`sw-mr-10 it__visibility-${v}`}
- key={v}
- value={v}
- checked={v === visibility}
- onCheck={props.onChange}
- disabled={disabled || (v === Visibility.Private && !canTurnToPrivate) || loading}
- >
- <div>{translate('visibility', v)}</div>
- </RadioButton>
- ))}
+ <RadioButtonGroup
+ id="project-visiblity-radio"
+ isDisabled={disabled}
+ options={Object.values(Visibility).map((v) => ({
+ label: translate('visibility', v),
+ value: v,
+ isDisabled: (v === Visibility.Private && !canTurnToPrivate) || loading,
+ }))}
+ value={visibility}
+ onChange={props.onChange}
+ />
</div>
);
}