From bc342c5b132da3a1e836e8a71e06d011c4fd7ca0 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Mon, 5 May 2025 11:30:52 +0200 Subject: [PATCH] chore(1-3679): use numeric input mode for numbers. (#9875) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds inputmode='decimal' to input fields with number input. As discussed on the [GOV.UK blog](https://technology.blog.gov.uk/2020/02/24/why-the-gov-uk-design-system-team-changed-the-input-type-for-numbers/), this finds a balance between giving numeric input options to mobile devices and improving validation / user experience. They mention this bit in their [design system guideline](https://design-system.service.gov.uk/components/text-input/#numbers) > Do not use `` unless your user research shows that there’s a need for it. With `` there’s a risk of users accidentally incrementing a number when they’re trying to do something else - for example, scroll up or down the page. And if the user tries to enter something that’s not a number, there’s no explicit feedback about what they’re doing wrong. I've purposefully not included the `pattern="[0-9]*"` attribute here, because the browser error messages conflict with our own and have several drawbacks in terms of accessibility according to Adrian Roselli's ["Avoid default field validation"](https://adrianroselli.com/2019/02/avoid-default-field-validation.html). Instead, the validation here will be part of the validation handling later. Also, I've opted for using `decimal` instead of `numeric`, because we allow you to store decimal values and that inputmode also adds the decimal separator to the keyboard. As always, however, there's complications: several languages (including Norwegian) use a comma as a decimal separator instead of a period, so the keyboard will likely contain numbers and a comma instead of a period. This is a problem because JS doesn't recognize "45,6" as a valid number. I've added a follow-up task to look into this. I thought at first it would just be expanding the validation, but because it's stored as a string on the back end and the SDKs presumably parse it, we can't just suddenly allow commas as decimal separators. --- .../AddSingleValueWidget.tsx | 12 ++++++++---- .../FeatureStrategyConstraints/AddValuesPopover.tsx | 13 ++++++++++++- .../EditableConstraint.tsx | 3 +++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyConstraints/AddSingleValueWidget.tsx b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyConstraints/AddSingleValueWidget.tsx index 545da27372..1ce574eabe 100644 --- a/frontend/src/component/feature/FeatureStrategy/FeatureStrategyConstraints/AddSingleValueWidget.tsx +++ b/frontend/src/component/feature/FeatureStrategy/FeatureStrategyConstraints/AddSingleValueWidget.tsx @@ -17,15 +17,16 @@ const StyledChip = styled(ValueChip, { }, })); -interface AddValuesProps { +type Props = { onAddValue: (newValue: string) => void; removeValue: () => void; currentValue?: string; helpText?: string; -} + inputType: 'text' | 'number'; +}; -export const AddSingleValueWidget = forwardRef( - ({ currentValue, onAddValue, removeValue, helpText }, ref) => { +export const AddSingleValueWidget = forwardRef( + ({ currentValue, onAddValue, removeValue, helpText, inputType }, ref) => { const [open, setOpen] = useState(false); const positioningRef = useRef(null); useImperativeHandle( @@ -55,6 +56,9 @@ export const AddSingleValueWidget = forwardRef( onDelete={currentValue ? removeValue : undefined} /> void; helpText?: string; + inputProps?: InputBaseComponentProps; }; const HelpText = styled('p')(({ theme }) => ({ @@ -52,6 +59,7 @@ export const AddValuesPopover: FC = ({ open, onClose, helpText, + inputProps, }) => { const [inputValue, setInputValue] = useState(initialValue || ''); const [error, setError] = useState(''); @@ -119,6 +127,9 @@ export const AddValuesPopover: FC = ({ error={!!error} helperText={error} aria-describedby={helpTextId} + inputProps={{ + ...inputProps, + }} /> = ({ ? 'Add a single number' : 'A semver value should be of the format X.Y.Z' } + inputType={ + inputType.type === 'number' ? 'number' : 'text' + } /> ); case 'multiple values':