From 659f7c064ceef5ba3d63d9bc5cd165a63c7da1b8 Mon Sep 17 00:00:00 2001 From: JF-Cozy Date: Wed, 1 Apr 2026 15:46:02 +0200 Subject: [PATCH 1/6] feat(cozy-ui-plus): Add prop on Contacts modal to remove field --- .../Contacts/AddModal/ContactForm/helpers.js | 13 +++- .../AddModal/ContactForm/helpers.spec.js | 62 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.js b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.js index fd2cedfad0..e6d225f409 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.js +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.js @@ -460,17 +460,26 @@ export const makeFields = (customFields, defaultFields) => { return defaultFields } - const fields = [...defaultFields] + let fields = [...defaultFields] customFields.forEach(customField => { const defaultField = fields.find(field => field.name === customField.name) + + // If isRemoved is true, remove the field from the result + if (customField.isRemoved) { + if (defaultField) { + fields = fields.filter(field => field.name !== customField.name) + } + return + } + const _field = defaultField || customField if (defaultField) { Object.assign(_field, customField) } - if (_field.position) { + if (_field.position !== undefined) { if (defaultField) { const fieldIndex = fields.indexOf(defaultField) fields.splice(fieldIndex, 1) diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.spec.js b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.spec.js index 4f67590e54..970a98f925 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.spec.js +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/helpers.spec.js @@ -441,6 +441,68 @@ describe('makeFields', () => { } ]) }) + + it('should remove default field when custom field has isRemoved set to true', () => { + const defaultFields = [ + { name: 'firstname' }, + { name: 'lastname' }, + { name: 'email' } + ] + const customFields = [{ name: 'lastname', isRemoved: true }] + + const res = makeFields(customFields, defaultFields) + + expect(res).toStrictEqual([{ name: 'firstname' }, { name: 'email' }]) + }) + + it('should remove multiple default fields when multiple custom fields have isRemoved set to true', () => { + const defaultFields = [ + { name: 'firstname' }, + { name: 'lastname' }, + { name: 'email' }, + { name: 'phone' } + ] + const customFields = [ + { name: 'lastname', isRemoved: true }, + { name: 'phone', isRemoved: true } + ] + + const res = makeFields(customFields, defaultFields) + + expect(res).toStrictEqual([{ name: 'firstname' }, { name: 'email' }]) + }) + + it('should ignore custom fields with isRemoved but no matching default field', () => { + const defaultFields = [{ name: 'firstname' }, { name: 'lastname' }] + const customFields = [{ name: 'nonexistent', isRemoved: true }] + + const res = makeFields(customFields, defaultFields) + + expect(res).toStrictEqual(defaultFields) + }) + + it('should handle mixed custom fields with isRemoved, position, and property overrides', () => { + const defaultFields = [ + { name: 'firstname', type: 'text' }, + { name: 'lastname', type: 'text' }, + { name: 'email', type: 'email' }, + { name: 'phone', type: 'tel' } + ] + const customFields = [ + { name: 'lastname', isRemoved: true }, + { name: 'email', isSecondary: true, position: 0 }, + { name: 'middlename', position: 1 } + ] + + const res = makeFields(customFields, defaultFields) + + expect(res).toStrictEqual([ + { name: 'email', type: 'email', isSecondary: true, position: 0 }, + { name: 'middlename', position: 1 }, + { name: 'firstname', type: 'text' }, + { name: 'phone', type: 'tel' } + ]) + }) }) describe('hasNoValues', () => { From 13a500603b6bffa494ae120cb0bcf32bfb50f6bb Mon Sep 17 00:00:00 2001 From: JF-Cozy Date: Wed, 1 Apr 2026 15:46:32 +0200 Subject: [PATCH 2/6] feat(cozy-ui-plus): Change size of contacts modal fields --- .../src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx index 9be55489cf..240f9927a1 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx @@ -37,6 +37,7 @@ const FieldInputWrapper = ({ {...props} variant={variant} fullWidth={fullWidth} + size="small" minRows="2" /> ) From 65ad3a1c8a631e9a3b9a63163f40d0a25f4f5405 Mon Sep 17 00:00:00 2001 From: JF-Cozy Date: Wed, 1 Apr 2026 15:47:12 +0200 Subject: [PATCH 3/6] fix(cozy-ui-plus): Remove icon wrapper on contact modal if no icon --- .../Contacts/AddModal/ContactForm/FieldInputLayout.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx index d60b68add4..5e8d52f79c 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx @@ -35,9 +35,11 @@ const FieldInputLayout = ({ 'u-dn': isSecondary && !showSecondaryFields })} > -
- {icon && } -
+ {icon && ( +
+ +
+ )}
{layout === 'array' ? ( Date: Thu, 2 Apr 2026 09:40:43 +0200 Subject: [PATCH 4/6] feat(cozy-ui-plus): Move field remove button next to the input --- .../AddModal/ContactForm/FieldInput.jsx | 38 ++++++++++++++----- .../AddModal/ContactForm/FieldInputArray.jsx | 17 ++------- .../AddModal/ContactForm/RemoveButton.jsx | 18 +++++++++ .../Contacts/AddModal/ContactForm/styles.styl | 2 - 4 files changed, 50 insertions(+), 25 deletions(-) create mode 100644 packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/RemoveButton.jsx delete mode 100644 packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/styles.styl diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInput.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInput.jsx index 091dc7bc94..3ca8d0746f 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInput.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInput.jsx @@ -4,16 +4,32 @@ import PropTypes from 'prop-types' import React, { useState } from 'react' import { Field } from 'react-final-form' +import { useBreakpoints } from 'cozy-ui/transpiled/react/providers/Breakpoints' import { useI18n, useExtendI18n } from 'twake-i18n' import FieldInputWrapper from './FieldInputWrapper' import HasValueCondition from './HasValueCondition' import { RelatedContactList } from './RelatedContactList' +import RemoveButton from './RemoveButton' import { locales } from './locales' -import styles from './styles.styl' import ContactAddressDialog from '../ContactAddressDialog' import { fieldInputAttributesTypes, labelPropTypes } from '../types' +const FieldAndRemove = ({ showRemove, onRemove, ...props }) => { + const { isMobile } = useBreakpoints() + + if (isMobile) { + return ( +
+ + {showRemove && } +
+ ) + } + + return +} + const FieldInput = ({ name, labelProps, @@ -22,6 +38,8 @@ const FieldInput = ({ contacts, contact, error, + onRemove, + showRemove, helperText, label, isInvisible @@ -33,6 +51,7 @@ const FieldInput = ({ useState(false) useExtendI18n(locales) const { t } = useI18n() + const { isMobile } = useBreakpoints() const handleClick = () => { if (name.includes('address')) { @@ -50,14 +69,12 @@ const FieldInput = ({ return (
- @@ -85,7 +104,7 @@ const FieldInput = ({ )} {labelProps && ( -
+
)} + {showRemove && !isMobile && }
) } diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx index 4eb2228307..847c3ee793 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx @@ -4,10 +4,7 @@ import { FieldArray } from 'react-final-form-arrays' import Button from 'cozy-ui/transpiled/react/Buttons' import Icon from 'cozy-ui/transpiled/react/Icon' -import IconButton from 'cozy-ui/transpiled/react/IconButton' -import CrossCircleIcon from 'cozy-ui/transpiled/react/Icons/CrossCircle' import PlusIcon from 'cozy-ui/transpiled/react/Icons/Plus' -import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon' import { useI18n, useExtendI18n } from 'twake-i18n' import FieldInput from './FieldInput' @@ -53,22 +50,14 @@ const FieldInputArray = ({ contacts={contacts} contact={contact} error={isError} + index={index} + showRemove={showRemove} helperText={isError ? errors[inputName] : null} name={inputName} label={t(`Contacts.AddModal.ContactForm.fields.${name}`)} labelProps={label} + onRemove={() => removeField(fields, index)} /> - {showRemove && ( - - removeField(fields, index)} - > - - - - )}
) })} diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/RemoveButton.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/RemoveButton.jsx new file mode 100644 index 0000000000..4985a952e8 --- /dev/null +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/RemoveButton.jsx @@ -0,0 +1,18 @@ +import React from 'react' + +import Icon from 'cozy-ui/transpiled/react/Icon' +import IconButton from 'cozy-ui/transpiled/react/IconButton' +import CrossCircleIcon from 'cozy-ui/transpiled/react/Icons/CrossCircle' +import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon' + +const RemoveButton = ({ onRemove }) => { + return ( + + + + + + ) +} + +export default RemoveButton diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/styles.styl b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/styles.styl deleted file mode 100644 index a604e3e9b5..0000000000 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/styles.styl +++ /dev/null @@ -1,2 +0,0 @@ -.contact-form-field__wrapper - width calc(100% - 3rem) From f04795db203a2b4f4917fa2b008a142463663435 Mon Sep 17 00:00:00 2001 From: JF-Cozy Date: Thu, 2 Apr 2026 10:52:38 +0200 Subject: [PATCH 5/6] feat(cozy-ui-plus): Add `isHalfWidth` prop on fields to show 2 fields on the same row --- .../ContactForm/FieldInputWrapper.jsx | 3 +- .../AddModal/ContactForm/fieldsConfig.jsx | 4 +- .../Contacts/AddModal/ContactForm/index.jsx | 41 ++++++++++++------- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx index 240f9927a1..ab08d6091b 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx @@ -13,11 +13,12 @@ const FieldInputWrapper = ({ attributes: { component, layout, + isHalfWidth, icon, isSecondary, validate, ...restAttributes - }, // ⚠️ `layout` `icon` `isSecondary` `validate` are removed from attributes to avoid DOM propagration, only used for business rules + }, // ⚠️ `layout` `isHalfWidth` `icon` `isSecondary` `validate` are removed from attributes to avoid DOM propagration, only used for business rules variant, fullWidth, ...props diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/fieldsConfig.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/fieldsConfig.jsx index f2f98be142..ac516f68ee 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/fieldsConfig.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/fieldsConfig.jsx @@ -40,6 +40,7 @@ export const fields = [ icon: null, type: 'text', layout: 'accordion', + isHalfWidth: true, subFields: [ { name: 'additionalName', @@ -56,7 +57,8 @@ export const fields = [ { name: 'familyName', icon: null, - type: 'text' + type: 'text', + isHalfWidth: true }, { name: 'company', diff --git a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/index.jsx b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/index.jsx index 344859b72d..a3b5ab1742 100644 --- a/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/index.jsx +++ b/packages/cozy-ui-plus/src/Contacts/AddModal/ContactForm/index.jsx @@ -3,7 +3,9 @@ import React, { useState } from 'react' import { Form } from 'react-final-form' import { getHasManyItems } from 'cozy-client/dist/associations/HasMany' +import Box from 'cozy-ui/transpiled/react/Box' import Button from 'cozy-ui/transpiled/react/Buttons' +import { useBreakpoints } from 'cozy-ui/transpiled/react/providers/Breakpoints' import { useI18n, useExtendI18n } from 'twake-i18n' import FieldInputLayout from './FieldInputLayout' @@ -49,6 +51,7 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => { const { t } = useI18n() const { fields, makeCustomFieldsFormValues, makeCustomContactValues } = customFieldsProps + const { isMobile } = useBreakpoints() const _fields = makeFields(fields, defaultFields) const hasSecondaryFields = _fields.some(el => el.isSecondary) @@ -90,20 +93,30 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => { onSubmit={handleSubmit} className="u-flex u-flex-column" > - {_fields.map((attributes, index) => ( - - ))} +
+ {_fields.map((attributes, index) => ( + + + + ))} +
{hasSecondaryFields && !showSecondaryFields && (