From ea026ec12244fa40097ede9cf3bc68fcf34eb321 Mon Sep 17 00:00:00 2001 From: sgendre <31214611+sgendre@users.noreply.github.com> Date: Tue, 28 Nov 2023 10:26:08 +0100 Subject: [PATCH] feat(forms): migrate to DS Tabs + CollapsibleFieldset (#4928) --- .changeset/beige-terms-yell.md | 5 + .changeset/few-months-tickle.md | 5 + .../Tabs/Primitive/TabStyles.module.scss | 20 +++ .../src/components/Tabs/Primitive/Tabs.tsx | 6 +- .../src/components/Tabs/variants/Tabs.tsx | 9 +- .../src/stories/navigation/Tabs.stories.tsx | 22 +++ .../UIForm/fieldsets/Array/Array.component.js | 1 + .../CollapsibleFieldset.component.js | 51 ++++-- .../CollapsibleFieldset.component.test.js | 26 +-- ...CollapsibleFieldset.component.test.js.snap | 157 +++++++----------- .../UIForm/fieldsets/Tabs/Tabs.component.js | 39 ++--- .../__snapshots__/Tabs.component.test.js.snap | 92 ++++------ packages/forms/src/UIForm/utils/array.js | 1 + .../forms/stories/SchemaFieldsets.stories.tsx | 10 ++ .../forms/stories/SchemaState.stories.tsx | 4 +- .../UIFormStoriesSchemas/errors.schema.js | 47 ++++++ .../fieldsets/core-arrays-collapsible.json | 89 ++++++++++ .../forms/stories/json/fieldsets/index.ts | 1 + 18 files changed, 372 insertions(+), 213 deletions(-) create mode 100644 .changeset/beige-terms-yell.md create mode 100644 .changeset/few-months-tickle.md create mode 100644 packages/forms/stories/json/fieldsets/core-arrays-collapsible.json diff --git a/.changeset/beige-terms-yell.md b/.changeset/beige-terms-yell.md new file mode 100644 index 00000000000..44df4b4bf36 --- /dev/null +++ b/.changeset/beige-terms-yell.md @@ -0,0 +1,5 @@ +--- +'@talend/react-forms': minor +--- + +Use DS tabs in UIForm diff --git a/.changeset/few-months-tickle.md b/.changeset/few-months-tickle.md new file mode 100644 index 00000000000..e7c8d0af7ed --- /dev/null +++ b/.changeset/few-months-tickle.md @@ -0,0 +1,5 @@ +--- +'@talend/design-system': minor +--- + +Error state for tabs diff --git a/packages/design-system/src/components/Tabs/Primitive/TabStyles.module.scss b/packages/design-system/src/components/Tabs/Primitive/TabStyles.module.scss index d0224816457..76737107486 100644 --- a/packages/design-system/src/components/Tabs/Primitive/TabStyles.module.scss +++ b/packages/design-system/src/components/Tabs/Primitive/TabStyles.module.scss @@ -102,4 +102,24 @@ margin-right: tokens.$coral-spacing-s; } } + + &_error { + color: tokens.$coral-color-danger-text; + + &[aria-selected='true'] { + color: tokens.$coral-color-danger-text; + } + } + + &_error::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + border-top: tokens.$coral-border-m-solid tokens.$coral-color-danger-text; + opacity: 0; + transition: tokens.$coral-transition-fast; + transform: translateY(100%); + } } diff --git a/packages/design-system/src/components/Tabs/Primitive/Tabs.tsx b/packages/design-system/src/components/Tabs/Primitive/Tabs.tsx index 2efcab63ffe..4e221050612 100644 --- a/packages/design-system/src/components/Tabs/Primitive/Tabs.tsx +++ b/packages/design-system/src/components/Tabs/Primitive/Tabs.tsx @@ -28,6 +28,7 @@ export type TabPropTypes = { icon?: IconNameWithSize<'S'>; tag?: string | number; tooltip?: string; + error?: boolean; }; export function Tab(props: TabPropTypes) { @@ -36,7 +37,10 @@ export function Tab(props: TabPropTypes) { - + + - + + Jimmy, Somsanith + +
-
- -

- - This is description - -

-
-

- Widget not found - string -

+ + +

- Widget not found - string + + This is description +

+

+ Widget not found + string +

+

+ Widget not found + string +

diff --git a/packages/forms/src/UIForm/fieldsets/Tabs/Tabs.component.js b/packages/forms/src/UIForm/fieldsets/Tabs/Tabs.component.js index 86c65244bdd..3b54f097f7b 100644 --- a/packages/forms/src/UIForm/fieldsets/Tabs/Tabs.component.js +++ b/packages/forms/src/UIForm/fieldsets/Tabs/Tabs.component.js @@ -1,29 +1,22 @@ import PropTypes from 'prop-types'; -import { useState } from 'react'; -import TabBar from '@talend/react-components/lib/TabBar'; -import classNames from 'classnames'; -import { useTranslation } from 'react-i18next'; +import { Tabs } from '@talend/design-system'; import Widget from '../../Widget'; import { isValid } from '../../utils/validation'; -import theme from './Tabs.module.scss'; -import { I18N_DOMAIN_FORMS } from '../../../constants'; - -function Tabs(props) { - const [selectedKey, setSelectedKey] = useState(0); - const { t } = useTranslation(I18N_DOMAIN_FORMS); +function TabsAdapter(props) { const { schema, ...restProps } = props; + const tabs = schema.items.map((item, index) => { const tabIsValid = isValid(item, restProps.errors); return { key: index, - label: item.title, - className: classNames({ [theme['has-error']]: !tabIsValid }), - 'aria-label': tabIsValid - ? undefined - : `${item.title} (${t('TF_TABS_HAS_ERRORS', { defaultValue: 'has errors' })})`, - children: ( + tabTitle: { + title: item.title, + id: `${restProps.id}-tabs-${index}`, + error: !tabIsValid, + }, + tabContent: ( setSelectedKey(item.key)} - selectedKey={selectedKey} - /> - ); + return ; } if (process.env.NODE_ENV !== 'production') { - Tabs.propTypes = { + TabsAdapter.propTypes = { errors: PropTypes.object, schema: PropTypes.shape({ items: PropTypes.arrayOf( @@ -57,4 +42,4 @@ if (process.env.NODE_ENV !== 'production') { }; } -export default Tabs; +export default TabsAdapter; diff --git a/packages/forms/src/UIForm/fieldsets/Tabs/__snapshots__/Tabs.component.test.js.snap b/packages/forms/src/UIForm/fieldsets/Tabs/__snapshots__/Tabs.component.test.js.snap index 816fb2e547e..f05c1ee2664 100644 --- a/packages/forms/src/UIForm/fieldsets/Tabs/__snapshots__/Tabs.component.test.js.snap +++ b/packages/forms/src/UIForm/fieldsets/Tabs/__snapshots__/Tabs.component.test.js.snap @@ -1,77 +1,54 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Tabs widget should render tabs 1`] = ` -
- -
-
+
+ +
- + `; diff --git a/packages/forms/src/UIForm/utils/array.js b/packages/forms/src/UIForm/utils/array.js index cd0a78e6e03..bc8c3eb4f63 100644 --- a/packages/forms/src/UIForm/utils/array.js +++ b/packages/forms/src/UIForm/utils/array.js @@ -131,5 +131,6 @@ export function getArrayElementSchema(arraySchema, elementIndex) { items: getArrayElementItems(arraySchema, elementIndex), widget: arraySchema.itemWidget || 'fieldset', title: arraySchema.itemTitle, + managed: arraySchema.itemManaged, }; } diff --git a/packages/forms/stories/SchemaFieldsets.stories.tsx b/packages/forms/stories/SchemaFieldsets.stories.tsx index 0eb5518003f..a5210c59db4 100644 --- a/packages/forms/stories/SchemaFieldsets.stories.tsx +++ b/packages/forms/stories/SchemaFieldsets.stories.tsx @@ -54,6 +54,16 @@ export const CoreCollapsibleFieldset = { data: fieldsets.coreCollapsibleFieldset, }, }; +export const CoreArraysCollapsibleFieldset = { + parameters: { + formStoryDisplayMode: { + doc: 'ArraysCollapsibleFieldset/README.md', + }, + }, + args: { + data: fieldsets.coreArraysCollapsibleFieldset, + }, +}; export const CoreColumns = { parameters: { formStoryDisplayMode: { diff --git a/packages/forms/stories/SchemaState.stories.tsx b/packages/forms/stories/SchemaState.stories.tsx index d8fe62fec2a..cfbc81dfd73 100644 --- a/packages/forms/stories/SchemaState.stories.tsx +++ b/packages/forms/stories/SchemaState.stories.tsx @@ -85,7 +85,9 @@ const errorsProps = errorsSchema.uiSchema.reduce( ...acc, [current.key.split('.').join(',')]: 'There is an error', }), - {}, + { + tabConfiguration: 'There is an error', + }, ); export const Errors: Story = { diff --git a/packages/forms/stories/UIFormStoriesSchemas/errors.schema.js b/packages/forms/stories/UIFormStoriesSchemas/errors.schema.js index ef86ec63d6f..4f0454aa8f9 100644 --- a/packages/forms/stories/UIFormStoriesSchemas/errors.schema.js +++ b/packages/forms/stories/UIFormStoriesSchemas/errors.schema.js @@ -2,7 +2,25 @@ export const errorsSchema = { jsonSchema: { type: 'object', title: 'Comment', + required: ['fieldname'], properties: { + tabConfiguration: { + type: 'object', + properties: { + fieldname: { + type: 'string', + }, + }, + }, + fieldname: { + type: 'string', + }, + description: { + type: 'string', + }, + tabs: { + type: 'tabs', + }, arrayOfObjects: { type: 'array', items: { @@ -84,6 +102,35 @@ export const errorsSchema = { }, }, uiSchema: [ + { + key: 'tabs', + title: '2 Tabs', + widget: 'tabs', + items: [ + { + key: 'tabConfiguration', + title: 'Configuration', + widget: 'fieldset', + items: [ + { + key: 'fieldname', + title: 'Field Name', + }, + ], + }, + { + key: 'tabInfo', + title: 'Info', + widget: 'fieldset', + items: [ + { + key: 'description', + title: 'Description', + }, + ], + }, + ], + }, { key: 'arrayOfObjects', title: 'Array of objects', diff --git a/packages/forms/stories/json/fieldsets/core-arrays-collapsible.json b/packages/forms/stories/json/fieldsets/core-arrays-collapsible.json new file mode 100644 index 00000000000..143aaa96341 --- /dev/null +++ b/packages/forms/stories/json/fieldsets/core-arrays-collapsible.json @@ -0,0 +1,89 @@ +{ + "jsonSchema": { + "type": "object", + "title": "Comment", + "required": ["comments"], + "properties": { + "groupBy": { + "type": "array", + "minItems": 1, + "maxItems": 5, + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string", + "enum": ["First Field", "Second Field", "Third Field"] + } + } + } + }, + "operations": { + "type": "array", + "minItems": 1, + "maxItems": 5, + "items": { + "type": "object", + "properties": { + "fieldName": { + "type": "string", + "enum": ["First Field", "Second Field", "Third Field"] + }, + "operation": { + "type": "string", + "enum": ["First Operation", "Second Operation", "Third Operation"] + } + } + } + } + } + }, + "uiSchema": [ + { + "key": "operations", + "title": "Operations", + "itemWidget": "collapsibleFieldset", + "itemManaged": false, + "items": [ + { + "key": "operations[].fieldName", + "title": "Field" + }, + { + "key": "operations[].operation", + "title": "Operation" + } + ] + }, + { + "key": "groupBy", + "title": "Group by", + "items": [ + { + "key": "groupBy[].fieldName", + "title": "Field" + } + ] + } + ], + "properties": { + "groupBy": [ + { + "fieldName": "First Field" + }, + { + "fieldName": "Second Field" + } + ], + "operations": [ + { + "fieldName": "First Field", + "operation": "First Operation" + }, + { + "fieldName": "Second Field", + "operation": "First Operation" + } + ] + } +} diff --git a/packages/forms/stories/json/fieldsets/index.ts b/packages/forms/stories/json/fieldsets/index.ts index fec5e66d191..74927719732 100644 --- a/packages/forms/stories/json/fieldsets/index.ts +++ b/packages/forms/stories/json/fieldsets/index.ts @@ -2,6 +2,7 @@ export { default as coreArraysComplex } from './core-arrays-complex.json'; export { default as coreArraysWithCustomOptions } from './core-arrays-with-custom-options.json'; export { default as coreArrays } from './core-arrays.json'; export { default as coreCollapsibleFieldset } from './core-collapsibleFieldset.json'; +export { default as coreArraysCollapsibleFieldset } from './core-arrays-collapsible.json'; export { default as coreColumns } from './core-columns.json'; export { default as coreFieldset } from './core-fieldset.json'; export { default as coreTabs } from './core-tabs.json';