mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Add input help text (#9883)
Adds help text to the popover input for free text values, single numeric and semver values. The help text is in addition to the error text (so you can get both). Also makes the add button a little narrower to better match sketches. ## Rendered Multiple values (free text): <img width="953" alt="image" src="https://github.com/user-attachments/assets/1d9bf7da-af8c-46b6-8eae-ae4f8a687363" /> With error <img width="936" alt="image" src="https://github.com/user-attachments/assets/aa9dc2da-ad9f-43da-9e44-c36fd8344df1" /> Numeric operators: <img width="927" alt="image" src="https://github.com/user-attachments/assets/f1e8afd8-7051-4691-bdd2-810929ccd4fa" /> SemVer operators: <img width="944" alt="image" src="https://github.com/user-attachments/assets/655a7a7b-a4a4-468c-8a5d-23e5d38375b8" />
This commit is contained in:
		
							parent
							
								
									3d84001273
								
							
						
					
					
						commit
						832e3f2e79
					
				| @ -21,10 +21,11 @@ interface AddValuesProps { | ||||
|     onAddValue: (newValue: string) => void; | ||||
|     removeValue: () => void; | ||||
|     currentValue?: string; | ||||
|     helpText?: string; | ||||
| } | ||||
| 
 | ||||
| export const AddSingleValueWidget = forwardRef<HTMLDivElement, AddValuesProps>( | ||||
|     ({ currentValue, onAddValue, removeValue }, ref) => { | ||||
|     ({ currentValue, onAddValue, removeValue, helpText }, ref) => { | ||||
|         const [open, setOpen] = useState(false); | ||||
|         const positioningRef = useRef<HTMLDivElement>(null); | ||||
|         useImperativeHandle( | ||||
| @ -56,6 +57,7 @@ export const AddSingleValueWidget = forwardRef<HTMLDivElement, AddValuesProps>( | ||||
|                 <AddValuesPopover | ||||
|                     initialValue={currentValue} | ||||
|                     onAdd={handleAdd} | ||||
|                     helpText={helpText} | ||||
|                     open={open} | ||||
|                     anchorEl={positioningRef.current} | ||||
|                     onClose={() => setOpen(false)} | ||||
|  | ||||
| @ -33,19 +33,31 @@ type AddValuesProps = { | ||||
|     open: boolean; | ||||
|     anchorEl: HTMLElement | null; | ||||
|     onClose: () => void; | ||||
|     helpText?: string; | ||||
| }; | ||||
| 
 | ||||
| const HelpText = styled('p')(({ theme }) => ({ | ||||
|     color: theme.palette.text.secondary, | ||||
|     fontSize: theme.typography.caption.fontSize, | ||||
| })); | ||||
| 
 | ||||
| const AddButton = styled(Button)(({ theme }) => ({ | ||||
|     minWidth: theme.spacing(4), | ||||
| })); | ||||
| 
 | ||||
| export const AddValuesPopover: FC<AddValuesProps> = ({ | ||||
|     initialValue, | ||||
|     onAdd, | ||||
|     anchorEl, | ||||
|     open, | ||||
|     onClose, | ||||
|     helpText, | ||||
| }) => { | ||||
|     const [inputValue, setInputValue] = useState(initialValue || ''); | ||||
|     const [error, setError] = useState(''); | ||||
|     const inputRef = useRef<HTMLInputElement>(null); | ||||
|     const inputId = useId(); | ||||
|     const helpTextId = useId(); | ||||
| 
 | ||||
|     return ( | ||||
|         <StyledPopover | ||||
| @ -106,16 +118,19 @@ export const AddValuesPopover: FC<AddValuesProps> = ({ | ||||
|                         autoFocus | ||||
|                         error={!!error} | ||||
|                         helperText={error} | ||||
|                         aria-describedby={helpTextId} | ||||
|                     /> | ||||
|                     <Button | ||||
|                     <AddButton | ||||
|                         variant='text' | ||||
|                         type='submit' | ||||
|                         size='small' | ||||
|                         color='primary' | ||||
|                         disabled={!inputValue?.trim()} | ||||
|                     > | ||||
|                         Add | ||||
|                     </Button> | ||||
|                     </AddButton> | ||||
|                 </InputRow> | ||||
|                 <HelpText id={helpTextId}>{helpText}</HelpText> | ||||
|             </form> | ||||
|         </StyledPopover> | ||||
|     ); | ||||
|  | ||||
| @ -28,10 +28,11 @@ const AddValuesButton = styled('button')(({ theme }) => ({ | ||||
| 
 | ||||
| interface AddValuesProps { | ||||
|     onAddValues: (newValues: string[]) => void; | ||||
|     helpText?: string; | ||||
| } | ||||
| 
 | ||||
| export const AddValuesWidget = forwardRef<HTMLButtonElement, AddValuesProps>( | ||||
|     ({ onAddValues }, ref) => { | ||||
|     ({ onAddValues, helpText }, ref) => { | ||||
|         const [open, setOpen] = useState(false); | ||||
|         const positioningRef = useRef<HTMLButtonElement>(null); | ||||
|         useImperativeHandle( | ||||
| @ -73,6 +74,7 @@ export const AddValuesWidget = forwardRef<HTMLButtonElement, AddValuesProps>( | ||||
| 
 | ||||
|                 <AddValuesPopover | ||||
|                     onAdd={handleAdd} | ||||
|                     helpText={helpText} | ||||
|                     open={open} | ||||
|                     anchorEl={positioningRef.current} | ||||
|                     onClose={() => setOpen(false)} | ||||
|  | ||||
| @ -146,21 +146,28 @@ const StyledCaseSensitiveIcon = styled(CaseSensitiveIcon)(({ theme }) => ({ | ||||
|     fill: 'currentcolor', | ||||
| })); | ||||
| 
 | ||||
| const getInputType = (input: Input) => { | ||||
| type InputType = | ||||
|     | { input: 'legal values' } | ||||
|     | { input: 'date' } | ||||
|     | { input: 'single value'; type: 'number' | 'semver' } | ||||
|     | { input: 'multiple values' }; | ||||
| 
 | ||||
| const getInputType = (input: Input): InputType => { | ||||
|     switch (input) { | ||||
|         case 'IN_OPERATORS_LEGAL_VALUES': | ||||
|         case 'STRING_OPERATORS_LEGAL_VALUES': | ||||
|         case 'NUM_OPERATORS_LEGAL_VALUES': | ||||
|         case 'SEMVER_OPERATORS_LEGAL_VALUES': | ||||
|             return 'legal values'; | ||||
|             return { input: 'legal values' }; | ||||
|         case 'DATE_OPERATORS_SINGLE_VALUE': | ||||
|             return 'date input'; | ||||
|             return { input: 'date' }; | ||||
|         case 'NUM_OPERATORS_SINGLE_VALUE': | ||||
|             return { input: 'single value', type: 'number' }; | ||||
|         case 'SEMVER_OPERATORS_SINGLE_VALUE': | ||||
|             return 'single text value'; | ||||
|             return { input: 'single value', type: 'semver' }; | ||||
|         case 'IN_OPERATORS_FREETEXT': | ||||
|         case 'STRING_OPERATORS_FREETEXT': | ||||
|             return 'free text'; | ||||
|             return { input: 'multiple values' }; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| @ -273,8 +280,8 @@ export const EditableConstraint: FC<Props> = ({ | ||||
|     }; | ||||
| 
 | ||||
|     const TopRowInput = () => { | ||||
|         switch (inputType) { | ||||
|             case 'date input': | ||||
|         switch (inputType.input) { | ||||
|             case 'date': | ||||
|                 return ( | ||||
|                     <ConstraintDateInput | ||||
|                         setValue={setValue} | ||||
| @ -283,7 +290,7 @@ export const EditableConstraint: FC<Props> = ({ | ||||
|                         setError={setError} | ||||
|                     /> | ||||
|                 ); | ||||
|             case 'single text value': | ||||
|             case 'single value': | ||||
|                 return ( | ||||
|                     <AddSingleValueWidget | ||||
|                         onAddValue={(newValue) => { | ||||
| @ -291,11 +298,17 @@ export const EditableConstraint: FC<Props> = ({ | ||||
|                         }} | ||||
|                         removeValue={() => setValue('')} | ||||
|                         currentValue={localConstraint.value} | ||||
|                         helpText={ | ||||
|                             inputType.type === 'number' | ||||
|                                 ? 'Add a single number' | ||||
|                                 : 'A semver value should be of the format X.Y.Z' | ||||
|                         } | ||||
|                     /> | ||||
|                 ); | ||||
|             case 'free text': | ||||
|             case 'multiple values': | ||||
|                 return ( | ||||
|                     <AddValuesWidget | ||||
|                         helpText='Maximum 100 char length per value' | ||||
|                         ref={addValuesButtonRef} | ||||
|                         onAddValues={(newValues) => { | ||||
|                             // todo (`addEditStrategy`): move deduplication logic higher up in the context handling
 | ||||
| @ -400,7 +413,7 @@ export const EditableConstraint: FC<Props> = ({ | ||||
|                     </StyledIconButton> | ||||
|                 </HtmlTooltip> | ||||
|             </TopRow> | ||||
|             {inputType === 'legal values' ? ( | ||||
|             {inputType.input === 'legal values' ? ( | ||||
|                 <LegalValuesContainer> | ||||
|                     <LegalValuesSelector | ||||
|                         data={resolveLegalValues( | ||||
| @ -411,7 +424,7 @@ export const EditableConstraint: FC<Props> = ({ | ||||
|                         values={localConstraint.values || []} | ||||
|                         setValuesWithRecord={setValuesWithRecord} | ||||
|                         setValues={setValues} | ||||
|                     />{' '} | ||||
|                     /> | ||||
|                 </LegalValuesContainer> | ||||
|             ) : null} | ||||
|         </Container> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user