@/application-components
Generic components for building Merchant Center applications.
Installation
yarn add @commercetools-frontend/application-components# ornpm --save install @commercetools-frontend/application-components
Additionally install the peer dependencies (if not present)
yarn add react react-dom react-intl# ornpm --save install react react-dom react-intl
Page components
Custom Applications typically consist of a variety of pages with different hierarchical levels. For example, a page to show a list of products, followed by a detail page to see the product's details.
Moreover, pages with similar hierarchical levels might need to fulfill different requirements. For example a detail page with or without a form, or a page with tabs.
We provide several components that cover the most common use cases. We recommend using them wherever possible to ensure visual consistency and reduce development efforts.
We identified 3 groups of components:
Info
Form
/CustomForm
Tabular
Additionally, we identified 4 hierarchical levels:
Main
Detail
Modal
Dialog
Components for main pages
The following page components should be used in the landing pages of the Custom Application that don't have a parent page in the hierarchy. For example, for a Custom Application for products, the main page can show a list of products.
InfoMainPage
Info Main pages are controlled components used to render a page to show more information about a particular feature. Similar to <InfoModalPage>
but not rendered as a modal.
Usage
import { InfoMainPage } from '@commercetools-frontend/application-components';import Text from '@commercetools-uikit/text';const MainPage = () => {return (<InfoMainPagetitle="Main page"><Text.Body>{'Lorem ipsum ...'}</Text.Body></InfoMainPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
Static properties
Page Header title
Pre-configured page header title component to use as part of a custom title row.
InfoMainPage.PageHeaderTitle = PageHeaderTitle;
FormMainPage
Form Main pages are controlled components used to render a page with a form or something that requires user input. Similar to <FormModalPage>
but not rendered as a modal. The header includes buttons to control the submission or cancellation of the form.
If you need to customize these buttons, you will need to use the <CustomFormMainPage>
component instead.
Usage
import { useFormik } from 'formik';import TextField from '@commercetools-uikit/text-field';import TextInput from '@commercetools-uikit/text-input';import { FormMainPage } from '@commercetools-frontend/application-components';const MainPage = () => {const formik = useFormik({initialValues: {email: "",},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<FormMainPagetitle="Manage your account"isPrimaryButtonDisabled={formik.isSubmitting}onSecondaryButtonClick={formik.handleReset}onPrimaryButtonClick={formik.handleSubmit}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></FormMainPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
labelSecondaryButton | string or Intl message | Cancel | The label for the secondary button as a string, or as an Intl message ({ id, defaultMessage } ). | |
iconLeftSecondaryButton | node | The icon for the secondary button label. | ||
labelPrimaryButton | string or Intl message | Save | The label for the primary button as a string, or as an Intl message ({ id, defaultMessage } ). | |
onPrimaryButtonClick | function | ✅ | - | Called when the primary button is clicked. |
onSecondaryButtonClick | function | ✅ | - | Called when the secondary button is clicked. |
isPrimaryButtonDisabled | boolean | - | false | Indicates whether the primary button is deactivated or not. |
isSecondaryButtonDisabled | boolean | - | false | Indicates whether the secondary button is deactivated or not. |
dataAttributesSecondaryButton | object | - | - | Use this prop to pass data- attributes to the secondary button. |
dataAttributesPrimaryButton | object | - | - | Use this prop to pass data- attributes to the primary button. |
hideControls | boolean | - | false | Hides the form controls. |
Static properties
Page Header title
Pre-configured page header title component to use as part of a custom title row.
FormMainPage.PageHeaderTitle = PageHeaderTitle;FormMainPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can, for instance, be used for button labels.
CustomFormMainPage
Custom Form Main page is a variation of the <FormMainPage>
that allows passing custom control elements via formControls. This is useful in case the main page needs different control elements than the default ones (primary and secondary buttons).
Usage
import { useFormik } from 'formik';import TextField from '@commercetools-uikit/text-field';import TextInput from '@commercetools-uikit/text-input';import { CustomFormMainPage } from '@commercetools-frontend/application-components';const AccountPage = () => {const formik = useFormik({initialValues: {email: "",},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<CustomFormMainPagetitle="Manage your account"formControls={<><CustomFormMainPage.FormSecondaryButton onClick={formik.handleReset} /><CustomFormMainPage.FormPrimaryButton onClick={formik.handleSubmit} /><CustomFormMainPage.FormDeleteButton onClick={handleDelete} /></>}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></CustomFormMainPage>);};
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
formControls | node | - | - | Pass a React.node with form controls. You can use the pre-made form buttons exposed by this component or you can use your own. |
hideControls | boolean | - | false | Hides the form controls. |
Static properties
Form Control Buttons
Pre-configured form control buttons to reuse in custom controls.
CustomFormMainPage.FormPrimaryButton = FormPrimaryButton;CustomFormMainPage.FormSecondaryButton = FormSecondaryButton;CustomFormMainPage.FormDeleteButton = FormDeleteButton;Page Header title
Pre-configured page header title component to use as part of a custom title row.
CustomFormMainPage.PageHeaderTitle = PageHeaderTitle;CustomFormMainPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can for instance be used for button labels.
TabularMainPage
Tabular Main pages are controlled components used to render a page with navigational controls and route-driven content using Tabs. The layout is similar to TabularModalPage
but is not rendered as a modal.
Tabs must be rendered using the <TabHeader>
component via the tabControls
prop. A <TabHeader>
is rendered as a link and it assumes the "tab content" is controlled and rendered using <Route>
components.
The <TabularMainPage>
is supposed to be used in one of the main application landing pages, as the top-level component page. The page should have no parent pages in the hierarchy.
The layout of this page can be recognized by the white background header and the gray content background.
Usage
import { Switch, Route, useRouteMatch } from 'react-router-dom'import { TabularMainPage, TabHeader } from '@commercetools-frontend/application-components';const MainPage = () => {const match = useRouteMatch()return (<TabularMainPagetitle="Main page"tabControls={<><TabHeader to={`${match.url}/tab-one`} label="Tab One" /><TabHeader to={`${match.url}/tab-two`} label="Tab Two" /></>}><Switch><Route path={`${match.path}/tab-one`}><Tab1 /></Route><Route path={`${match.path}/tab-two`}><Tab2 /></Route></Switch></TabularMainPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
tabControls | node | ✅ | - | Pass a React.node to be used as the Tabs component for controlling the navigation between the Tab contents within the page. |
formControls | node | - | - | Pass a React.node with form controls. You can use the pre-made form buttons exposed by this component or you can use your own. |
hideControls | bool | - | false | Hides the form controls. |
Static properties
Form Control Buttons
Pre-configured form control buttons to easily re-use them in the custom controls.
TabularMainPage.FormPrimaryButton = FormPrimaryButton;TabularMainPage.FormSecondaryButton = FormSecondaryButton;TabularMainPage.FormDeleteButton = FormDeleteButton;Page Header title
Pre-configured page header title component to use as part of a custom title row.
TabularMainPage.PageHeaderTitle = PageHeaderTitle;TabularMainPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can, for instance, be used for button labels.
Components for detail pages
The following page components should be used in the pages of the Custom Application that show data of a specific resource. Hierarchically, the parent page should be the main page. For example, for a Custom Application for products, the detail page shows the product's data.
InfoDetailPage
Info Detail pages are controlled components used to render a page to show more information about a particular feature. Similar to <InfoModalPage>
but not rendered as a modal.
The <InfoDetailPage>
may be used as a direct child of one of the main pages. A back link in the header section is also required.
The layout of this page can be recognized by the gray background header and the white content background.
Usage
import { useHistory } from 'react-router-dom'import { InfoDetailPage } from '@commercetools-frontend/application-components';import Text from '@commercetools-uikit/text';const DetailPage = () => {const history = useHistory();return (<InfoDetailPagetitle="Detail page"onPreviousPathClick={() => history.push('/starting-page')}previousPathLabel="Go back"><Text.Body>{'Lorem ipsum ...'}</Text.Body></InfoDetailPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
previousPathLabel | string or Intl message | - | "Go back" (translated) | Label to appear as the previous path of the top bar of the page. |
onPreviousPathClick | function | ✅ | - | Called when the back button is clicked. |
Static properties
Page Header title
Pre-configured page header title component to use as part of a custom title row.
InfoDetailPage.PageHeaderTitle = PageHeaderTitle;
FormDetailPage
Form Detail pages are controlled components used to render a page with a form or something that requires user input. Similar to <FormModalPage>
but not rendered as a modal.
The header includes buttons to control the submission or cancellation of the form. These buttons can be overwritten with custom controls by using the <CustomFormDetailPage>
component.
The <FormDetailPage>
may be used as a direct child of one of the main pages. A back link in the header section is also required.
The layout of this page can be recognized by the gray background header and the white content background.
Usage
import { useHistory } from 'react-router-dom'import { useFormik } from "formik";import TextField from "@commercetools-uikit/text-field";import TextInput from "@commercetools-uikit/text-input";import { FormDetailPage } from "@commercetools-frontend/application-components";const AccountPage = () => {const history = useHistory();const formik = useFormik({initialValues: {email: "",},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<FormDetailPagetitle="Manage your account"onPreviousPathClick={() => history.push('/starting-page')}isPrimaryButtonDisabled={formik.isSubmitting}onSecondaryButtonClick={formik.handleReset}onPrimaryButtonClick={formik.handleSubmit}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></FormDetailPage>);};
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
previousPathLabel | string or Intl message | - | "Go back" (translated) | Label to appear as the previous path of the top bar of the page. |
onPreviousPathClick | function | ✅ | - | Called when the back button is clicked. |
labelSecondaryButton | string or Intl message | Cancel | The label for the secondary button as a string, or as an Intl message ({ id, defaultMessage } ). | |
labelPrimaryButton | string or Intl message | Save | The label for the primary button as a string, or as an Intl message ({ id, defaultMessage } ). | |
onPrimaryButtonClick | function | ✅ | - | Called when the primary button is clicked. |
onSecondaryButtonClick | function | ✅ | - | Called when the secondary button is clicked. |
iconLeftSecondaryButton | node | - | - | The icon for the secondary button label. |
isPrimaryButtonDisabled | boolean | - | false | Indicates whether the primary button is deactivated or not. |
isSecondaryButtonDisabled | boolean | - | false | Indicates whether the secondary button is deactivated or not. |
dataAttributesSecondaryButton | object | - | - | Use this prop to pass data- attributes to the secondary button. |
dataAttributesPrimaryButton | object | - | - | Use this prop to pass data- attributes to the primary button. |
hideControls | boolean | - | false | Hides the form controls. |
Static properties
Page Header title
Pre-configured page header title component to use as part of a custom title row.
FormDetailPage.PageHeaderTitle = PageHeaderTitle;FormDetailPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<FormDetailPage// other props...labelSecondaryButton={FormDetailPage.Intl.revert}/>
CustomFormDetailPage
Custom Form Detail pages are a variation of the <FormDetailPage>
that allow passing custom control elements via formControls
.
This is useful in case the detail page needs different control elements than the default ones (primary and secondary button).
The <CustomFormDetailPage>
may be used as a direct child of one of the main pages. A back link in the header section is also required.
The layout of this page can be recognized by the gray background header and the white content background.
Usage
import { useHistory } from 'react-router-dom'import { useFormik } from "formik";import TextField from "@commercetools-uikit/text-field";import TextInput from "@commercetools-uikit/text-input";import {CustomFormDetailPage} from "@commercetools-frontend/application-components";const AccountPage = () => {const history = useHistory();const formik = useFormik({initialValues: {email: "",},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<CustomFormDetailPagetitle="Manage your account"onPreviousPathClick={() => history.push('/starting-page')}formControls={<><CustomFormDetailPage.FormSecondaryButton onClick={formik.handleReset} /><CustomFormDetailPage.FormPrimaryButton onClick={formik.handleSubmit} /><CustomFormDetailPage.FormDeleteButton onClick={handleDelete} /></>}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></CustomFormDetailPage>);};
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
previousPathLabel | string or Intl message | - | "Go back" (translated) | Label to appear as the previous path of the top bar of the page. |
onPreviousPathClick | function | ✅ | - | Called when the back button is clicked. |
formControls | node | - | - | Pass a React.node with form controls. You can use the pre-made form buttons exposed by this component or you can use your own. |
hideControls | boolean | - | false | Hides the form controls. |
Static properties
Form Control Buttons
Pre-configured form control buttons to easily re-use them in the custom controls.
CustomFormDetailPage.FormPrimaryButton = FormPrimaryButton;CustomFormDetailPage.FormSecondaryButton = FormSecondaryButton;CustomFormDetailPage.FormDeleteButton = FormDeleteButton;Page Header title
Pre-configured page header title component to use as part of a custom title row.
CustomFormDetailPage.PageHeaderTitle = PageHeaderTitle;CustomFormModalPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<CustomFormDetailPage// other props...formControls={<CustomFormDetailPage.FormSecondaryButton// other props...label={CustomFormDetailPage.Intl.revert}/>}/>
TabularDetailPage
Tabular Detail pages are controlled components used to render a page with navigational controls and route-driven content using Tabs. The layout is similar to TabularModalPage
but is not rendered as a modal.
Tabs must be rendered using the <TabHeader>
component via the tabControls
prop. A <TabHeader>
is rendered as a link and it assumes the "tab content" is controlled and rendered using <Route>
components.
The <TabularDetailPage>
should be used as a direct child of one of the main pages. Typically it's used as a detail page with multiple sub-pages (tabs).
The layout of this page can be recognized by the gray background header and the white content background. A backlink in the header section is also required.
Usage
import { Switch, Route, useRouteMatch, useHistory } from 'react-router-dom'import { TabularDetailPage, TabHeader } from '@commercetools-frontend/application-components';const DetailPage = () => {const match = useRouteMatch()const history = useHistory();return (<TabularDetailPagetitle="Detail page"onPreviousPathClick={() => history.push('/starting-page')}previousPathLabel="Go back"tabControls={<><TabHeader to={`${match.url}/tab-one`} label="Tab One" /><TabHeader to={`${match.url}/tab-two`} label="Tab Two" /></>}><Switch><Route path={`${match.path}/tab-one`}><Tab1 /></Route><Route path={`${match.path}/tab-two`}><Tab2 /></Route></Switch></TabularDetailPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
title | string | - | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
children | node | ✅ | - | Content rendered within the page. It's expected to have its style fully customized. |
tabControls | node | ✅ | - | Pass a React.node to be used as the Tabs component for controlling the navigation between the Tab contents within the page. |
formControls | node | - | - | Pass a React.node with form controls. You can use the pre-made form buttons exposed by this component or you can use your own. |
hideControls | bool | - | false | Hides the form controls. |
previousPathLabel | string or Intl message | - | "Go back" (translated) | Label to appear as the previous path of the top bar of the page. |
onPreviousPathClick | function | ✅ | - | Called when the back button is clicked. |
Static properties
Form Control Buttons
Pre-configured form control buttons to easily re-use them in the custom controls.
TabularDetailPage.FormPrimaryButton = FormPrimaryButton;TabularDetailPage.FormSecondaryButton = FormSecondaryButton;TabularDetailPage.FormDeleteButton = FormDeleteButton;Page Header title
Pre-configured page header title component to use as part of a custom title row.
TabularDetailPage.PageHeaderTitle = PageHeaderTitle;TabularDetailPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can for instance be used for button labels.
Components for modal pages
The following page components should be used in nested pages of the Custom Application. Hierarchically, the parent page should be the detail page. For example, for a Custom Application for products, the modal page shows the product's variants data.
InfoModalPage
Info Modal pages are controlled components used to render a page using a modal container, which makes it appear on top of the normal page. This is useful to render detailed data that typically requires some space.
Usage
import { InfoModalPage, useModalState } from '@commercetools-frontend/application-components';const Example = () => {const pageModalState = useModalState()return (<InfoModalPagetitle="Lorem ipsum"isOpen={pageModalState.isModalOpen}onClose={pageModalState.closeModal}subtitle={<Text.Body>{'Lorem ipsum ...'}</Text.Body>}topBarCurrentPathLabel="Lorem ipsum"topBarPreviousPathLabel="Back"><Text.Body>{'Lorem ipsum ...'}</Text.Body></InfoModalPage>)}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
isOpen | boolean | ✅ | - | Indicates whether the page is open or closed. The parent component needs to manage this state. |
title | string | ✅ | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
onClose | function | - | - | Called when the page closes: click in overlay, click in close button, press ESC . If the function is not provided, the page cannot be closed by any of the listed options. |
zIndex | number | - | - | - |
topBarCurrentPathLabel | string | The title prop | Label to appear as the current path of the top bar of the modal. | |
topBarPreviousPathLabel | string | "Go Back" (translated) | Label to appear as the previous path of the top bar of the modal. | |
children | node | ✅ | - | Content rendered within the page. If the content is long in height (depending on the screen size) a scrollbar will appear. |
getParentSelector | function | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
shouldDelayOnClose | bool | - | true | Sets whether the ModalPage should delay calling its onClose function to allow the closing animation time to finish. This can be turned off if the developer is controlling the ModalPage only through the isOpen prop, and not abruptly mounting/unmounting it or one of its parent elements. You might also want to turn this off if you need to display a prompt (for example to save changes) on the ModalPage before navigating out of it, as this option makes the Modal close itself before onClose is called. |
afterOpenStyles | string or object | - | - | Overwrite the default styles of afterOpen . You can pass a "class name" or a CSS-in-JS style object. This should be used only in cases the default styles are causing some layout issues. |
FormModalPage
Form Modal pages are controlled components used to render a page with a form or something that requires user input. It is similar to InfoModalPage
but has a semantically different role. The header includes buttons to control the submission or cancellation of the form. These buttons can be overwritten with custom controls by using the <CustomFormModalPage>
component.
Usage
import { useFormik } from 'formik';import TextField from '@commercetools-uikit/text-field';import TextInput from '@commercetools-uikit/text-input';import { FormModalPage, useModalState } from '@commercetools-frontend/application-components';const AccountPage = () => {const formModalState = useModalState()const formik = useFormik({initialValues: {email: '',},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<FormModalPagetitle="Manage your account"isOpen={formModalState.isModalOpen}onClose={formModalState.closeModal}isPrimaryButtonDisabled={formik.isSubmitting}onSecondaryButtonClick={formik.handleReset}onPrimaryButtonClick={formik.handleSubmit}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></FormModalPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
isOpen | boolean | ✅ | - | Indicates whether the page is open or closed. The parent component needs to manage this state. |
title | string | ✅ | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
onClose | function | - | - | Called when the page closes click in overlay, click in close button, press ESC . If the function is not provided, the page cannot be closed by any of the listed options. |
zIndex | number | - | - | - |
topBarCurrentPathLabel | string | The title prop | Label to appear as the current path of the top bar of the modal. | |
topBarPreviousPathLabel | string | "Go Back" (translated) | Label to appear as the previous path of the top bar of the modal. | |
children | node | ✅ | - | Content rendered within the page. If the content is long in height (depending on the screen size) a scrollbar will appear. |
hideControls | boolean | - | false | Hides the form controls. |
labelSecondaryButton | string | Intl message | - | Cancel | |
labelPrimaryButton | string | Intl message | - | Save | |
onSecondaryButtonClick | function | ✅ | - | Called when the secondary button is clicked. |
onPrimaryButtonClick | function | ✅ | - | Called when the primary button is clicked. |
iconLeftSecondaryButton | node | - | - | The icon for the secondary button label. |
isPrimaryButtonDisabled | boolean | - | false | Indicates whether the primary button is deactivated or not. |
isSecondaryButtonDisabled | boolean | - | false | Indicates whether the secondary button is deactivated or not. |
dataAttributesSecondaryButton | object | - | - | Use this prop to pass data- attributes to the secondary button. |
dataAttributesPrimaryButton | object | - | - | Use this prop to pass data- attributes to the primary button. |
getParentSelector | function | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
shouldDelayOnClose | bool | - | true | Sets whether the ModalPage should delay calling its onClose function to allow the closing animation time to finish. This can be turned off if the developer is controlling the ModalPage only through the isOpen prop, and not abruptly mounting/unmounting it or one of its parent elements. You might also want to turn this off if you need to display a Prompt (for example to save changes) on the ModalPage before navigating out of it, as this option makes the Modal close itself before onClose is called. |
afterOpenStyles | string or object | - | - | Overwrite the default styles of afterOpen . You can pass a "class name" or a CSS-in-JS style object. This should be used only in cases the default styles are causing some layout issues. |
Static properties
FormModalPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<FormModalPage// other props...labelSecondaryButton={FormModalPage.Intl.revert}/>
CustomFormModalPage
Custom Form Modal pages are a variation of the <FormModalPage>
that allow passing custom control elements via formControls
.
This is useful in case the modal page needs different control elements than the default ones (primary and secondary buttons).
Usage
import { useFormik } from 'formik';import TextField from '@commercetools-uikit/text-field';import TextInput from '@commercetools-uikit/text-input';import { CustomFormModalPage, useModalState } from '@commercetools-frontend/application-components';const AccountPage = () => {const formModalState = useModalState()const formik = useFormik({initialValues: {email: '',},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<CustomFormModalPagetitle="Manage your account"isOpen={formModalState.isModalOpen}onClose={formModalState.closeModal}formControls={<><CustomFormModalPage.FormSecondaryButton onClick={formik.handleReset} /><CustomFormModalPage.FormPrimaryButton onClick={formik.handleSubmit} /><CustomFormModalPage.FormDeleteButton onClick={handleDelete} /></>}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></CustomFormModalPage>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
isOpen | boolean | ✅ | - | Indicates whether the page is open or closed. The parent component needs to manage this state. |
title | string | ✅ | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
onClose | function | - | - | Called when the page closes: click in overlay, click in close button, press ESC . If the function is not provided, the page cannot be closed by any of the listed options. |
zIndex | number | - | - | - |
topBarCurrentPathLabel | string | The title prop | Label to appear as the current path of the top bar of the modal | |
topBarPreviousPathLabel | string | "Go Back" (translated) | Label to appear as the previous path of the top bar of the modal | |
children | node | ✅ | - | Content rendered within the page. If the content is long in height (depending on the screen size) a scrollbar will appear. |
formControls | node | - | - | Pass a React.node with form controls. You can use the pre-made form buttons exposed by this component or you can use your own. |
getParentSelector | function | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
hideControls | bool | - | false | Hides the form controls. |
shouldDelayOnClose | bool | - | true | Sets whether the ModalPage should delay calling its onClose function to allow the closing animation time to finish. This can be turned off if the developer is controlling the ModalPage only through the isOpen prop, and not abruptly mounting/unmounting it or one of its parent elements. You might also want to turn this off if you need to display a Prompt (for example to save changes) on the ModalPage before navigating out of it, as this option makes the Modal close itself before onClose is called. |
afterOpenStyles | string or object | - | - | Overwrite the default styles of afterOpen . You can pass a "class name" or a CSS-in-JS style object. This should be used only in cases the default styles are causing some layout issues. |
Static properties
Form Control Buttons
Pre-configured form control buttons to easily re-use them in the custom controls.
CustomFormModalPage.FormPrimaryButton = FormPrimaryButton;CustomFormModalPage.FormSecondaryButton = FormSecondaryButton;CustomFormModalPage.FormDeleteButton = FormDeleteButton;CustomFormModalPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<CustomFormModalPage// other props...formControls={<CustomFormModalPage.FormSecondaryButton// other props...label={CustomFormModalPage.Intl.revert}/>}/>
TabularModalPage
Tabular Modal pages are controlled components used to render a page with navigational controls and route-driven content using Tabs.
Tabs must be rendered using the <TabHeader>
component via the tabControls
prop. A <TabHeader>
is rendered as a link and it assumes the "tab content" is controlled and rendered using <Route>
components.
Usage
import { BrowserRouter as Router, Switch, Route, useRouteMatch } from 'react-router-dom'import { TabularModalPage, useModalState, TabHeader } from '@commercetools-frontend/application-components';const AccountPage = () => {const match = useRouteMatch()const tabsModalState = useModalState()return (<Router><TabularModalPagetitle="Manage your account"isOpen={tabsModalState.isModalOpen}onClose={tabsModalState.closeModal}tabControls={<><TabHeader to={`${match.url}/tab-one`} label="Tab One" /><TabHeader to={`${match.url}/tab-two`} label="Tab Two" /></>}><Switch><Route path={`${match.path}/tab-one`}><Tab1 /></Route><Route path={`${match.path}/tab-two`}><Tab2 /></Route></Switch></TabularModalPage></Router>);}
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
isOpen | boolean | ✅ | - | Indicates whether the page is open or closed. The parent component needs to manage this state. |
title | string | ✅ | - | The title of the page. |
subtitle | node or string | - | - | The subtitle of the page, usually a React component. If a string is passed, it's rendered as a paragraph. |
onClose | function | - | - | Called when the page closes: click in overlay, click in close button, press ESC . If the function is not provided, the page cannot be closed by any of the listed options. |
zIndex | number | - | - | - |
topBarCurrentPathLabel | string | The title prop | Label to appear as the current path of the top bar of the modal. | |
topBarPreviousPathLabel | string | "Go Back" (translated) | Label to appear as the previous path of the top bar of the modal. | |
children | node | ✅ | - | Content rendered within the page. It isn't wrapped by anything except the Modal Container itself, so it's expected to have its style fully customized. |
formControls | node | - | - | Pass a React.node with form controls. You can use the pre-made form buttons exposed by this component or you can use your own. |
customTitleRow | node | - | - | Pass a React.node to be used in place of the title and subtitle . |
tabControls | node | ✅ | - | Pass a React.node to be used as the Tabs component for controlling the navigation between the Tab contents within the modal. |
getParentSelector | function | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
shouldDelayOnClose | bool | - | true | Sets whether the ModalPage should delay calling its onClose function to allow the closing animation time to finish. This can be turned off if the developer is controlling the ModalPage only through the isOpen prop, and not abruptly mounting/unmounting it or one of its parent elements. You might also want to turn this off if you need to display a Prompt (for example to save changes) on the ModalPage before navigating out of it, as this option makes the Modal close itself before onClose is called. |
afterOpenStyles | string or object | - | - | Overwrite the default styles of afterOpen . You can pass a "class name" or a CSS-in-JS style object. This should be used only in cases the default styles are causing some layout issues. |
Static properties
Form Control Buttons
Pre-configured form control buttons to reuse in custom controls.
TabularModalPage.FormPrimaryButton = FormPrimaryButton;TabularModalPage.FormSecondaryButton = FormSecondaryButton;TabularModalPage.FormDeleteButton = FormDeleteButton;TabularModalPage.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<TabularModalPage// other props...formControls={<TabularModalPage.FormSecondaryButton// other props...label={TabularModalPage.Intl.revert}/>}/>
Components for dialogs
The following page components can be used on any page of the Custom Application. For example, showing a confirmation dialog before performing an important action, or showing additional information as an info box.
InfoDialog
Info dialogs are controlled components used to show more information about a particular feature, UI element, etc. They are mainly composed of text paragraphs.
Usage
import { InfoDialog, useModalState } from '@commercetools-frontend/application-components';const ChannelsInfo = () => {const infoModalState = useModalState()return (<InfoDialogtitle="About channels"isOpen={infoModalState.isModalOpen}onClose={infoModalState.closeModal}><Spacings.Stack scale="m"><Text.Body>{'Channels are ...'}</Text.Body></Spacings.Stack></InfoDialog>);}
Properties
Props | Type | Required | Values | Default | Description |
---|---|---|---|---|---|
title | string | ✅ | - | - | The title of the Info Dialog. |
isOpen | boolean | ✅ | - | - | Indicates whether the dialog is open or closed. The parent component needs to manage this state. |
onClose | function | ✅ | - | - | Called when the dialog closes: click in overlay, click in close button, press ESC . |
children | node | ✅ | - | - | Content rendered within the dialog. If the content is long in height (depending on the screen size) a scrollbar will appear. |
size | string | - | m , l , scale | l | Horizontal width of the dialog card. If scale is used, the dialog size expands to the viewport size, with some margin. |
zIndex | number | - | - | - | The z-index value to be applied to the overlay container. By default, all the modal containers are automatically assigned a correct z-index value. If this prop is defined, it will overwrite the assigned value. |
getParentSelector | function | - | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
ConfirmationDialog
Confirmation dialogs are controlled components used to prompt the user to confirm an important or destructive action. They are similar to Info dialogs but they have a primary and secondary button in the footer area.
Usage
import { ConfirmationDialog, useModalState } from '@commercetools-frontend/application-components';const ChannelDeletion = () => {const confirmationModalState = useModalState()const handleConfirm = useCallback(() => {// Do something async}, [])return (<ConfirmationDialogtitle="Confirm channel deletion"isOpen={confirmationModalState.isModalOpen}onClose={confirmationModalState.closeModal}onCancel={confirmationModalState.closeModal}onConfirm={handleConfirm}><Spacings.Stack scale="m"><Text.Body>{'Are you sure you want to delete this channel?'}</Text.Body></Spacings.Stack></ConfirmationDialog>);}
Properties
Props | Type | Required | Values | Default | Description |
---|---|---|---|---|---|
title | string | ✅ | - | - | The title of the Confirmation Dialog. |
isOpen | boolean | ✅ | - | - | Indicates whether the dialog is open or closed. The parent component needs to manage this state. |
onClose | function | - | - | - | Called when the dialog closes: click in overlay, click in close button, press ESC . If the function is not provided, the modal cannot be closed by any of the listed options. |
children | node | ✅ | - | - | Content rendered within the dialog. If the content is long in height (depending on the screen size) a scrollbar will appear. |
size | string | m , l , scale | l | Horizontal width limit of the dialog card. If scale is used, the dialog size expands to the viewport size, with some margin. | |
zIndex | number | - | - | - | The z-index value to be applied to the overlay container. By default, all the modal containers are automatically assigned a correct z-index value. If this prop is defined, it will overwrite the assigned value. |
labelSecondary | string | Intl message | - | Cancel | The label for the secondary button as a string, or as an Intl message ({ id, defaultMessage } ). See Static properties. | |
labelPrimary | string | Intl message | - | Confirm | The label for the primary button as a string, or as an Intl message ({ id, defaultMessage } ). See Static properties. | |
onCancel | function | ✅ | - | - | Called when the secondary button is clicked. |
onConfirm | function | ✅ | - | - | Called when the primary button is clicked. |
isPrimaryButtonDisabled | boolean | - | - | false | Indicates whether the primary button is deactivated or not. |
dataAttributesSecondaryButton | object | - | - | - | Use this prop to pass data- attributes to the secondary button. |
dataAttributesPrimaryButton | object | - | - | - | Use this prop to pass data- attributes to the primary button. |
getParentSelector | function | - | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
Static properties
ConfirmationDialog.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<ConfirmationDialog// other props...labelSecondary={ConfirmationDialog.Intl.revert}/>
FormDialog
Form dialogs are controlled components used to render a form or something that requires user input. They are similar to Confirmation dialogs but fulfill a different role semantically.
Usage
import { useFormik } from 'formik';import TextField from '@commercetools-uikit/text-field';import TextInput from '@commercetools-uikit/text-input';import { FormDialog, useModalState } from '@commercetools-frontend/application-components';const EmailForm = () => {const formModalState = useModalState()const formik = useFormik({initialValues: {email: '',},validate: (formikValues) => {if (TextInput.isEmpty(formikValues.email)) {return { email: { missing: true } };}return {};},onSubmit: async (formikValues) => {alert(`email: ${formikValues.email}`);// Do something async},});return (<FormDialogtitle="Update email"isOpen={formModalState.isModalOpen}onClose={formModalState.closeModal}isPrimaryButtonDisabled={formik.isSubmitting}onSecondaryButtonClick={formik.handleReset}onPrimaryButtonClick={formik.handleSubmit}><TextFieldname="email"title="Email"isRequired={true}value={formik.values.email}errors={formik.errors.email}touched={formik.touched.email}onChange={formik.handleChange}onBlur={formik.handleBlur}/></FormDialog>);}
Properties
Props | Type | Required | Values | Default | Description |
---|---|---|---|---|---|
title | string | ✅ | - | - | The title of the Form Dialog. |
isOpen | boolean | ✅ | - | - | Indicates whether the dialog is open or closed. The parent component needs to manage this state. |
onClose | function | - | - | - | Called when the dialog closes: click in overlay, click in close button, press ESC . If the function is not provided, the modal cannot be closed by any of the listed options. |
children | node | ✅ | - | - | Content rendered within the dialog. If the content is long in height (depending on the screen size) a scrollbar will appear. |
size | string | m , l , scale | l | Horizontal width limit of the dialog card. If scale is used, the dialog size expands to the viewport size, with some margin. | |
zIndex | number | - | - | - | The z-index value to be applied to the overlay container. By default, all the modal containers are automatically assigned a correct z-index value. If this prop is defined, it will overwrite the assigned value. |
labelSecondary | string | Intl message | - | Cancel | The label for the secondary button as a string, or as an Intl message ({ id, defaultMessage } ). See Static properties. | |
labelPrimary | string | Intl message | - | Save | The label for the primary button as a string, or as an Intl message ({ id, defaultMessage } ). See Static properties. | |
onSecondaryButtonClick | function | ✅ | - | - | Called when the secondary button is clicked. |
onPrimaryButtonClick | function | ✅ | - | - | Called when the primary button is clicked. |
iconLeftSecondaryButton | node | - | - | - | The icon for the secondary button label. |
isPrimaryButtonDisabled | boolean | - | - | false | Indicates whether the primary button is deactivated or not. |
dataAttributesSecondaryButton | object | - | - | - | Use this prop to pass data- attributes to the secondary button. |
dataAttributesPrimaryButton | object | - | - | - | Use this prop to pass data- attributes to the primary button. |
getParentSelector | function | - | - | - | The function should return an HTML element that will be used as the parent container to hold the modal DOM tree. If no function is provided, it's expected that an HTML element with the id="parent-container" is present in the DOM. In the NODE_ENV=test environment, the default HTML element is body . |
Static properties
FormDialog.Intl
This is a convenience proxy export to expose pre-defined Intl messages defined in the
@commercetools-frontend/i18n
package. The Intl messages can be used for button labels.<FormDialog// other props...labelSecondary={FormDialog.Intl.revert}/>
Other components
TabHeader
Tab Headers facilitate navigation within a tabular page.
In a tabular page, tabs must be rendered using the <TabHeader>
component via the tabControls
prop. A <TabHeader>
is rendered as a link and it assumes the "tab content" is controlled and rendered using <Route>
components.
<TabHeader>
tracks the route changes internally and a tab is active if the to
prop matches the current route.
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
to | string or LocationDescriptor | ✅ | - | A route path to redirect to when the tab is clicked. |
label | string | - | - | The label of the tab. Required if intlMessage is not provided. |
intlMessage | Intl message | - | - | The label of the tab, using an intl message object. Required if label is not provided. |
isDisabled | boolean | - | false | Indicates whether the tab is deactivated or not. |
exactPathMatch | boolean | - | false | If true , marks the tab as active if the link matches exactly the route. |
Page content components
When displaying the content of a page, it's important to structure it properly to establish a visual hierarchy and provide the users with a familiar user experience. To learn more about different layouts, see Page Content Layouts.
We provide the following components to help you create page content layouts:
PageContentNarrow
Renders the children in a narrow page content layout.
Usage
import { PageContentNarrow } from '@commercetools-frontend/application-components';const ChannelsDetails = () => {// ...return (<PageContentNarrow><Spacings.Stack><div>Title</div><ChannelsForm /></Spacings.Stack></PageContentNarrow>)};
Properties
Props | Type | Required | Description |
---|---|---|---|
children | node | ✅ | Content rendered within this layout. |
PageContentWide
Renders the children in a wide page content layout.
Usage
import { PageContentWide } from '@commercetools-frontend/application-components';const ChannelsDetailsSingleColumn = () => {// ...return (<PageContentWide><Spacings.Stack><div>Title</div><ChannelsForm /></Spacings.Stack></PageContentWide>)};const ChannelsDetailsTwoColumn1_1 = () => {// ...return (<PageContentWide columns="1/1"><div>Left side</div><div>Right side</div></PageContentWide>)};const ChannelsDetailsTwoColumn2_1 = () => {// ...return (<PageContentWide columns="2/1"><Spacings.Stack><ChannelsForm /></Spacings.Stack><Spacings.Stack><div>Meta info</div></Spacings.Stack></PageContentWide>)};
Properties
Props | Type | Required | Default | Description |
---|---|---|---|---|
columns | enum 1 , 1/1 , 2/1 | - | 1 | For a single-column layout, use the 1 . For a two-column layout with equal widths, use 1/1 . For a two-column layout with column widths in a 2:1 ratio, use 2/1 . |
gapSize | enum 10 , 20 | - | 20 | The space between the two columns. |
children | node | ✅ | - | Content rendered within this layout. |
In a two-column layout, the children are rendered from left to right in the order they're used.
PageContentFull
Renders the children in a full page content layout.
Usage
import { PageContentFull } from '@commercetools-frontend/application-components';const ChannelsDetails = () => {// ...return (<PageContentFull><ChannelsTable /></PageContentFull>)};
Properties
Props | Type | Required | Description |
---|---|---|---|
children | node | ✅ | Content rendered within this layout. |
Hooks
useModalState
Using the dialog or modal page components usually requires having some state to open/close these components.
Usage
import {useModalState,InfoDialog,} from '@commercetools-frontend/application-components';const MyComponent = () => {const infoModalState = useModalState();return (<div><button onClick={infoModalState.openModal}>Click me</button><InfoDialogisOpen={infoModalState.isModalOpen}onClose={infoModalState.closeModal}title="Welcome">Hi there.</InfoDialog></div>)}
Return type
The following is the definition of the state object returned by useModalState
:
isModalOpen
: Whether the state is open or closed.openModal
: Update theisModalOpen
state totrue
.closeModal
: Update theisModalOpen
state tofalse
.
Usage outside of Custom Applications
If you happen to use some of the components outside of a Custom Application, you need to additionally render the <PortalsContainer>
.
The <PortalsContainer>
renders an empty HTML element with a specific identifier and is used to render all modal components (for example dialogs or modal pages). Make sure to render this component once in your application.
import { PortalsContainer } from '@commercetools-frontend/application-components';const Application = () => (<main><PortalsContainer />{/* ... */}</main>)