Menu

Migrate from Flex UI 1.x.x to 2.x.x

This Flex UI 1.x.x to 2.x.x migration guide covers breaking changes to the Flex UI programming interfaces. It covers required changes you may need to make to custom code or plugins. The most notable changes are:

For details on each Flex UI interface mentioned in this migration guide, their description and usage code examples, check out the Flex UI API docs.

Enable Flex UI 2.0 on your account

Using the application on flex.twilio.com

Flex UI 2.0 is now in General Availability. You can install it by accessing the Versioning and updates page of your Flex app Admin Dashboard. If you are running a 1.x.x version, select 2.0.x and click Confirm. If you are on a Public Beta version of 2.0, install 2.0.x by clicking on the 2.0.x version link and then Install. Your application will now be upgraded to Flex UI 2.0.

Using the Configuration service API

To change the ui_version and reset your ui_dependencies, you can make the following curl request. You can retrieve your account SID and auth token from the Twilio Console.

curl --request POST \
 --url https://flex-api.twilio.com/v1/Configuration \
 -u ACXXXXXXXXXXXXXXXXXXXXX:auth_token \
 --header 'accountsid: ACXXXXXXXXXXXXXXXXXXXXX' \
 --header 'content-type: application/json' \
 --header 'i-twilio-auth-account: ACXXXXXXXXXXXXXXXXXXXXX' \
 --data '{
   "account_sid": "ACXXXXXXXXXXXXXXXXXXXXX",
   "ui_version": "~2.0.0",
   "ui_dependencies": {}
}'

Self-hosted Flex

You can install Flex UI 2.0 via yarn or npm:

yarn add @twilio/flex-ui@^2

npm install @twilio/flex-ui@^2

Refer to Upgraded dependencies if you run into compatibility issues which you will need to resolve.

Using the flex-ui-sample package

If you want to use or are using the flex-ui-sample package for bootstrapping your project, make sure to pull the latest from the main branch of the flex-ui sample repo which requires the @twilio/flex-ui@^2 package. We have also bumped React to version 17 to satisfy the Flex 2.0 requirements. This means that on any existing project, you have to resolve compatibility issues in your code should they occur.

New Flex access token update behaviour

In Flex UI 1.x your code may have listened to Flex access token updates in the following way:

manager.store.getState().flex.session.loginHandler.on('tokenUpdated', (token) => {});

With Flex 2.0, loginHandler no longer supports this functionality and you can instead use the native Flex 'tokenUpdated' Event to achieve the same behaviour:

import { Manager } from "@twilio/flex-ui";
const manager = Manager.getInstance();
manager.events.addListener("tokenUpdated", (tokenPayload) => {});

Build Plugins with Flex UI 2.0

Flex UI 2.0 works with Flex Plugins CLI 4.1.3 or higher.

Install the latest version of the Flex Plugins CLI.

Your plugins must use the Flex Plugins CLI in order to be served on Flex 2.0. If you have plugins built on older versions of the Plugin Builder, you need to migrate them to use the Plugins CLI.

Update Plugins for Flex 2.0

Based on the implementation of your plugin, you may need to update your plugin source code and its dependencies to be compatible with Flex UI 2.0. The changes are covered in this guide. Here are some guidelines to help you manage the migration of your plugins:

  1. Once you have updated your plugin code and dependencies to be compatible with 2.0, test your plugin locally by using the twilio flex:plugins:start command of the Flex Plugins CLI.
  2. Once you have tested your plugin to ensure that it works as expected, deploy your plugin to your dev or staging environment using the twilio:flex:plugins:deploy command. We recommend following the Semantic Versioning format for managing your plugin version. Since this plugin is compatible with 2.0, we recommend registering this plugin version as a new major version. Use the --major argument and write a clear description for the Changelog of this version.
  3. Enable the plugin deployed on your stage/dev account via the Plugins Dashboard or the Plugins CLI.
  4. Follow Steps 1 to 3 for migrating all your plugins to be compatible with Flex UI 2.0.
  5. Finally, create a release via the CLI or the Plugins Dashboard that contains all the plugins that you have migrated to 2.0. Leverage the description and the name fields to tag the release as being compatible with 2.0.

Building new plugins for Flex 2.0

When you leverage the create command of the Flex Plugins CLI to create a new plugin, you need to update the dependencies on the package.json file of the plugin to make it compatible with 2.0.

Note the differences between the dependencies and devDependencies on the following sample package.json files. You need to update the devDependencies in order to run your plugin locally via the twilio flex:plugins:start command of the CLI.

{
 "name": "plugin-sample",
 "version": "0.0.0",
 "private": true,
 "scripts": {
   "postinstall": "flex-plugin pre-script-check"
 },
 "dependencies": {
   "@twilio/flex-plugin-scripts": "5.1.1",
   "react": "16.5.2",
   "react-dom": "16.5.2",
   "react-emotion": "9.2.12"
 },
 "devDependencies": {
   "@twilio/flex-ui": "^1",
   "react-test-renderer": "16.5.2"
 }
{
  "name": "plugin-sample",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "postinstall": "flex-plugin pre-script-check"
  },
  "dependencies": {
    "@twilio/flex-plugin-scripts": "5.1.2",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "prop-types": "^15.7.2",
    "@twilio-paste/core": "^15.3.0",
    "@twilio-paste/icons": "^9.2.0"
  },
  "devDependencies": {
    "@twilio/flex-ui": "^2",
    "react-test-renderer": "17.0.2"
  }
}

Roll back changes to use Flex UI 1.x

If you run into issues with your Flex application on UI 2.0 that require you to roll back to a Flex UI 1.x.x version, do the following:

  1. Change the Flex UI version of your application to a minor version of Flex UI 1.x.
  2. Log in as an admin and access the Releases tab of the Plugins Dashboard. See the documentation for working with the Plugins Dashboard.
  3. Disable active plugins that are on Flex UI 2.0.
  4. Choose and redeploy prior versions of your plugins. If you had registered a major version for each of the plugin you migrated, it should be easier to determine the releases containing the plugins compatible with Flex UI 1.x.x.

Upgraded dependencies

The Flex UI uses a variety of dependencies in order to provide the highest quality user experience for your contact center users. Many of these dependencies have been updated as part of the new major version of Flex.

If you have deployed plugins to modify your instance of the Flex UI, they may be using incompatible versions of many dependencies. Make sure to update your plugin dependencies to be compatible with the Flex UI 2.0.

Node

Minimum required Node version was upgraded from 12 to 14.

React & React DOM

React & ReactDOM are now peer dependencies.

No changes are required, besides including React & ReactDOM as a dependency. The Flex UI 2.0 does not currently use any features that will introduce breaking changes.

Flex UI 2.0 requires React v17 as the minimum version and is not guaranteed to work with React v16*.

Flex 1.*

Flex 2.0 (as peer dependency)

"react": "^16.5.2",

"react": "^17.0.0",

"react-dom": "^16.5.2",

"react-dom": "^17.0.0",

Redux & React-redux

The Flex UI 2.0 does not currently use any features that will introduce breaking changes. If you have used these libraries directly, however, you could experience breaking changes.

Flex 1.*

Flex 2.0

"react-redux": "~5.1.0",

"react-redux": "^7.2.2",

"redux": "3.7.2",

"redux": "^4.0.5",

React-router-redux

The Flex UI relies solely on the react-router-dom dependency. You can update the version and remove the react-router and react-router-redux dependencies.

Flex 1.*

Flex 2.0

"react-router-dom": "4.3.1",

"react-router": "4.3.1",

"react-router-redux": "5.0.0-alpha.9"

"react-router-dom": "^5.2.0",

Import Router Context

React-router-dom is now based on React v17 Context. If you want to consume the router context from the Flex UI, you need to import withRouter directly from the Flex UI Package.

import { withRouter } from "@twilio/flex-ui";

Emotion

Package versions and structure

Emotion has updated their own package structure, so you will need to update both the versions and the package names.

Flex 1.*

Flex 2.0

"emotion": "9.2.6",

"@emotion/css": "^11.1.3",

"emotion-theming" : "9.2.6"

"react-emotion": "9.2.6",

"@emotion/react": "^11.1.5",

"create-emotion-styled": "^9.2.6",

"@emotion/styled": "^11.1.5",

Import theme and style

Emotion version 11 uses React v17 Context. If you want to consume styles coming from the Flex UI theme, you need to import withTheme and styled directly from the Flex UI Package

import { withTheme, styled } from "@twilio/flex-ui";

Material UI

Package versions

Material UI has been updated. Note you’ll need to address the changes related to the new major version of this library. If you are using MUI versions earlier than 5.x, you must use the new Flex.setProviders() API to prevent clashes between Flex and Material UI style classes. See the ThemeProvider section for more details.

Flex 1.*

Flex 2.0

"@material-ui/core": "3.9.4",

"@material-ui/core": "^4.11.3",

If you are overriding the Material theme with a Flex Theme, you will need to re-register the MuiThemeProvider in your plugin to use React v17 Context, and provide the Flex Theme overrides in the createMuiTheme arguments.

Main Update Script

The following script will update all Flex UI dependencies to use 2.0 dependencies, and remove any unneeded dependencies. It will save these changes in your package.json, and ignore legacy peer dependencies (which can cause issues for users who are currently using NPM v7.0.0 and higher.)

You will still need to update your Plugin code to use the new dependencies correctly.

npm install \
@emotion/css@^11.1.3 @emotion/react@^11.1.5 @emotion/styled@^11.1.5 \
@material-ui/core@^4.11.3 \
react@17.0.2 react-dom@17.0.2 \
react-redux@^7.2.2 redux@^4.0.5 \
react-router-dom@^5.2.0 \
react-test-renderer@^17.0.2 \
--save --legacy-peer-deps && \
npm uninstall react-router react-router-redux --save

Degraded mode

We have introduced a Degraded mode for Flex UI - now Flex UI will initialize with limited capabilities, even if some of the components like SDKs (TaskRouter, Conversations, Voice, or Sync) are down. In case of disruptions to Twilio's services, Flex users can still log in to Flex and perform certain tasks related to operational services. For example, in the case of Twilio Voice experiencing an incident, your agent will still be able to handle messaging tasks.

Users will see a notification informing them of a possible disruption in the normal work of Flex UI and they will be able to download a thorough report with error details and logs.

For more on error handling and reporting, check out our Troubleshooting the Flex UI guide.

Conversations SDK

Currently, the Flex UI uses the Programmable Chat SDK to handle messaging channels. In 2.0, the Flex UI uses the Conversations SDK to replicate this functionality.

To ease migration of plugins from Flex UI 1.x to 2.x, we want to create a virtual bridge to also export Chat SDK-compatible constructs. Therefore, you can still use your Chat-based customizations with fewer changes. This bridge logic will render a warning highlighting that the accessed methods and properties are actually deprecated.

Identified differences between the Chat and Conversation libraries

Here are the properties and methods that have been changed or removed.

Chat Client

Type

Chat Client

Conversation Client

property

channels

conversations

method

createChannel

createConversation

method

getChannelBySid

getConversationBySid

method

getChannelByUniqueName

getConversationByUniqueName

method

getSubscribedChannels

getSubscribedConversations

method

getUserDescriptor

// pass user instead

method

getLocalChannels

// get subscribed channels

event

channelAdded

conversationAdded

event

channelInvited

conversationInvited

event

channelJoined

conversationJoined

event

channelLeft

conversationLeft

event

channelRemoved

conversationRemoved

event

channelUpdated

conversationUpdated

event

memberJoined

participantJoined

event

memberLeft

participantLeft

event

memberUpdated

participantUpdated

Channel vs Conversations

type

Channel

Conversation

Notes

property

isPrivate

Returns true

property

lastConsumedMessageIndex

lastReadMessageIndex

property

type

Returns a string ‘private’

property

advanceLastConsumedMessageIndex

advanceLastReadMessageIndex

property

members

participants

Not exposed

method

getMemberByIdentity

getParticipantByIdentity

method

getMemberBySid

getParticipantBySid

method

getMembers

getParticipants

method

getMembersCount

getParticipantsCount

method

getUnconsumedMessagesCount

getUnreadMessagesCount

method

removeMember

removeParticipant

method

setAllMessagesConsumed

setAllMessagesRead

method

setNoMessagesConsumed

setAllMessagesUnread

method

updateLastConsumedMessageIndex

updateLastReadMessageIndex

ChannelDescriptor

No parallel in the Conversations SDK, we fall back to Conversation.

UserDescriptor

No parallel in the Conversations SDK, we fall back to User.

Chat User vs Conversation User

type

Chat User

Conversation User

property

online

isOnline

property

notifiable

isNotifiable

Chat Message vs Conversation Message

type

Message

Message

Notes

property

channel

conversation

property

memberSid

participantSid

Chat Member vs Conversation Participant

type

Member

Participant

Note

property

channel

conversation

property

lastConsumedMessageIndex

lastReadMessageIndex

property

lastConsumptionTimestamp

lastReadTimestamp

method

getUserDescriptor

Use getUser

event argument

updateReason 'lastConsumedMessageIndex'

updatedReason

'lastReadMessageIndex'

event argument

updateReason 'lastConsumptionTimestamp’

updatedReason

‘lastReadTimestamp’

Chat SDK methods and concepts dropped in the Conversations SDK

  1. There’s no concept of a public channel. All the conversations are private.
  2. Descriptors have been removed. They used to be a “snapshot” of the described entity. This is easily replaceable by returning the actual entity and unsubscribing from its changes.
  3. There is no invite method anymore on conversations. We fall back to the add method as their functionalities are very similar.

Flex UI changes

Deprecated reducers

  • channels
  • channelInput

Deprecated props

  • channel
  • channelSid
  • isMemberOfChannel
  • member
  • autoInitChannel
  • activeChatChannel
  • chatChannel (on taskContext)

Deprecated Helpers

  • ChatChannelHelper - replaced by ConversationHelper

Deprecated methods

  • TaskHelper.getTaskChannelSid

Deprecated notifications ID

  • ChatOrchestrationAddToConversationFailed
  • ChatOrchestrationDeactivateConversationFailed
  • ChatOrchestrationLeaveConversationFailed

Voice SDK

The Flex UI 1.x.x uses the twilio-client SDK for voice communications. In 2.0, it uses the twilio-voice SDK for this functionality since the twilio-client is now deprecated. Functionality and usage of the new Voice SDK remains largely the same with a few exceptions:

  • The events Connect, Disconnect, and Cancel which used to apply to the Device instance now applies to the Call instance instead.
  • The Device ready event has been replaced with a registered event. Likewise for online which is now unregistered.
  • The structure of the Device state has changed to:
   namespace Device {
   isBusy: boolean;
   enum State {
     Unregistered = 'unregistered';
     Registering = 'registering';
     Registered = 'registered';
     Destroyed = 'destroyed';
   }
 }

Listen for a running call on Flex UI 2.0

To detect a running call within the Flex UI 2.0, you can listen for an incoming Voice event through the Flex Manager. For detecting a call using UI actions, see "Common use cases and examples" on Use UI Actions.

const manager = Flex.Manager.getInstance();
manager.voiceClient.on('incoming', onVoiceClientConnectListener);

// Listener function
function onVoiceClientConnectListener (){  
  console.log("Call detected");
  // Do something
}   

For more details on the changes from the twilio-client to the twilio-voice SDK, see this migration guide. Also refer to the Twilio.Device and Twilio.Call pages for more details on the Device and Call objects of the Twilio Voice JavaScript SDK.

New Actions and Flex Events for the TaskRouter SDK

We have added new Flex actions wrapping TaskRouter:

import { Actions } from "@twilio/flex-ui";

// Set worker attributes
Actions.invokeAction("SetWorkerAttributes", { attributes: {}, mergeExisting: true });

// Update worker token
Actions.invokeAction("UpdateWorkerToken", { token: "newToken" });

// Update task attributes
Actions.invokeAction("SetTaskAttributes", { sid: "WRxxxxx", attributes: {}, mergeExisting: true });

// Issue a Call to a Worker
Actions.invokeAction("IssueCallToWorker", { callerId: "callerId", twiMLUrl: "twiMLUrl", options: {} });

// Dequeue the Reservation to the Worker.
// This will perform telephony to dequeue a Task that was enqueued using the Enqueue TwiML verb.
// A contact_uri must exist in the Worker's attributes for this call to go through.
Actions.invokeAction("DequeueTask", { options: {} })

// Redirect the active Call tied to this Reservation
Actions.invokeAction("RedirectCallTask", { callSid: "callSid", twiMLUrl: "twiMLUrl", options: {} });

// Update the Worker's leg in the Conference associated to this Reservation
Actions.invokeAction("UpdateWorkerParticipant", { options: {} });

// Update the Customer leg in the Conference associated to this Task
Actions.invokeAction("UpdateCustomerParticipant", { options: {} });

and introduced new Flex Events wrapping TaskRouter events:

import { Manager } from "@twilio/flex-ui";
const manager = Manager.getInstance();

// Emitted when a worker receives a new task
manager.events.addListener("taskReceived", (task: ITask) => {});

// Emitted when the worker's activity changes
manager.events.addListener("workerActivityUpdated", (activity: Activity, allActivities: Map<string, Activity>) => {});

// Emitted when the worker's attributes changes
manager.events.addListener("workerAttributesUpdated", (newAttributes: Record<string, any>) => {});

// Emitted when the worker's task status gets updated
manager.events.addListener("taskUpdated", (task:ITask) => {});

// Emitted when the worker's task gets set to 'accepted'
manager.events.addListener("taskAccepted", (task:ITask) => {});

// Emitted when the worker's task gets set to 'canceled'
manager.events.addListener("taskCanceled", (task:ITask) => {});

// Emitted when the worker's task gets set to 'completed'
manager.events.addListener("taskCompleted", (task:ITask) => {});

// Emitted when the worker's task gets set to 'rejected'
manager.events.addListener("taskRejected", (task:ITask) => {});

// Emitted when the worker's task gets set to 'rescinded'
manager.events.addListener("taskRescinded", (task:ITask) => {});

// Emitted when the worker's task gets set to 'timeout'
manager.events.addListener("taskTimeout", (task:ITask) => {});

// Emitted when the worker's task gets set to 'wrapup'
manager.events.addListener("taskWrapup", (task:ITask) => {});

Now you can use exclusively Flex UI Actions Framework when working with TaskRouter SDK, without needing to access its methods directly.

Visit our Flex UI API docs for more details on Actions and Events.

Theme and Branding

Flex UI 2.0 uses a new theming structure that more closely maps to the Twilio Paste design system. This new structure is based on the concept of design tokens, a set of variables that you can modify. This structure promotes both consistency, customization and web accessibility.

Theme configuration changes

config.colorTheme is deprecated. There is a new configuration key called config.theme with the following structure:

interface ThemeConfigProps {
   isLight?: boolean; // Represents if light or dark theme
   tokens?: Tokens; // Paste tokens
   componentThemeOverrides?: Object; // Object containing styles of the component which is to be overridden.
}

config.theme.componentThemeOverrides has the same structure as deprecated config.colorTheme.overrides.

Styled components theme props changes

Components which receive the theme as props have the following changes:

  1. props.theme.calculated is deprecated.
    1. Use props.theme.isLight instead of props.theme.calculated.lightTheme
    2. Use props.theme.tokens.textColors.colorText instead of props.theme.calculated.textColor.
  2. props.theme.colors is deprecated.
  3. props.theme.tokens is introduced:.
interface Tokens {
   backgroundColors: BackgroundColors;
   textColors: TextColors;
   borderColors: BorderColors;
   borderWidths: typeof BorderWidth;
   radii: typeof BorderRadius;
   fontSizes: typeof FontSize;
   fontWeights: typeof FontWeight;
   lineHeights: typeof LineHeight;
   sizings: typeof Sizing;
   spacings: typeof Spacing;

}

For more on each token information, please refer to Twilio Paste.

Deprecated Predefined themes

Flex UI 2.0 deprecates all predefined themes like DarkTheme, MediumTheme, BlueDarkTheme, BlueMediumTheme. It will now have 2 modes of Flex: Light and Dark.

List of deprecated tokens

const deprecatedTokens = [
   "errorColor",
   "errorGlow",
   "buttonHoverColor",
   "tabSelectedColor",
   "connectingColor",
   "disconnectedColor",
   "notificationBackgroundColorInformation",
   "notificationBackgroundColorSuccess",
   "notificationBackgroundColorWarning",
   "notificationBackgroundColorError",
   "notificationIconColorError",
   "notificationIconColorWarning",
   "userAvailableColor",
   "userUnavailableColor",
   "defaultButtonColor",
   "lightTextColor",
   "darkTextColor",
   "disabledColor",
   "focusColor",
   "focusGlow",
   "holdColor",
   "declineColor",
   "acceptColor",
   "declineTextColor",
   "acceptTextColor",
   "completeTaskColor",
   "flexBlueColor",
   "agentBusyColor"
];

Deprecating Channel colors

const deprecatedChannelColors = [
   "inactive",
   "call",
   "video",
   "chat",
   "sms",
   "facebook",
   "line",
   "whatsapp",
   "custom"
];

ThemeProvider

Introducing a new API, Flex.setProviders(), which can be used to load providers once at the root level. Developers won’t have to worry about wrapping again, as the context will be set correctly. Now to use Paste in Flex plugins, developers do not need to wrap the Paste ThemeProvider over all Paste components.

When using Paste, developers need to pass the CustomizationProvider from Paste to Flex using Flex.setProviders as shown in the following example. Ensure this is done before declaring any components. By doing this, we’ll wrap Flex with the passed Provider and developers don’t have to worry about fetching the right theme and passing it on.

import { CustomizationProvider } from "@twilio-paste/core/customization";
import { Button as PasteButton } from "@twilio-paste/core/button";
 
Flex.setProviders({
   PasteThemeProvider: CustomizationProvider
});
 
Flex.AgentDesktopView.Panel1.Content.add(
   <PasteButton key="A" variant="primary">
       Paste Button
   </PasteButton>
);
 
Flex.AgentDesktopView.Panel1.Content.add(
   <PasteButton key="B" variant="primary">
       Paste Button
   </PasteButton>
);

Flex.setProviders() also allows developers to pass their own custom provider which is needed to be set on the root level. They can do it as below:

Flex.setProviders({
   CustomProvider: (RootComponent) => (props) => {
       return (
           <Context.Provider value={{ test: "123" }}>
               <RootComponent {...props} />
           </Context.Provider>
       );
   }
});
 
Flex.AgentDesktopView.Panel1.Content.add(
   <Context.Consumer>
       {(value) => {
           <div>{value.foo}</div> // Will print 123
       }}
   </Context.Consumer>
);

When using Material UI for styling, it is important to wrap our plugins with a StylesProvider with a classNameGenerator that sets a productionPrefix and a seed so styles classes don't clash between plugins and Flex. The below example shows how to use a custom provider for styling Material UI components:

import { StylesProvider, createGenerateClassName } from '@material-ui/core/styles';

Flex.setProviders({
      CustomProvider: (RootComponent) => (props) => {
          return (
            <StylesProvider generateClassName={createGenerateClassName({
              productionPrefix: 'pluginXYZ',
              seed: 'pluginXYZ',
            })}>
                  <RootComponent {...props} />
              </StylesProvider>
          );
      }
});

If you would like to gradually migrate from Material UI to Twilio Paste, you may use both in a single plugin by setting both a CustomProvider and a PasteThemeProvider:

import { StylesProvider, createGenerateClassName } from '@material-ui/core/styles';
import { CustomizationProvider } from "@twilio-paste/core/customization";

Flex.setProviders({
      CustomProvider: (RootComponent) => (props) => {
          return (
            <StylesProvider generateClassName={createGenerateClassName({
              productionPrefix: 'pluginXYZ',
              seed: 'pluginXYZ',
            })}>
                  <RootComponent {...props} />
              </StylesProvider>
          );
      },
      PasteThemeProvider: CustomizationProvider
});

Flex Messaging UI V2 changes

This change is implemented in version alpha.15 and is turned off for accounts signed up for Flex UI 2.0 Private Beta prior to this version being released as it is a breaking change in the component API. Please reach out to your technical account manager to have the new messaging UI enabled.

Moving to Flex Conversations with Flex 2.0 has enabled us to provide an even more customisable Messaging UI, and this comes with a few of changes which you may need to adjust to.

New Dynamic Component structure - MessageInputV2

The new default input component in the messaging canvas is the dynamic component MessageInputV2 . This includes the text area component and a new dynamic component, MessageInputActions , and is structured like so:

<MessageInputV2>
    <MessageInputArea key="textarea"/>
    <MessageInputActions key="actions"/>
</MessageInputV2>

MessageInputActions contains the message send button and the file attachment button (if file attachment is enabled).

You can use custom actions for this component via the add, replace, and remove methods.

New default props

MessageInputV2 has two new default props: hideSendButton and rows. These control the rendering of the send button and row height of the text area respectively. You can use hideSendButton together with returnKeySendsMessage to enable sending message on Enter.

Combined text and media messages

The SendMessage action is now capable of sending file attachments and text in the same message. Files can be passed to the SendMessage action on the attachedFiles field of its Action payload.The SendMedia action is deprecated but is still available.

Learn more about new components in the Flex UI API docs.

User and Activity controls

  • A new programmable component Activity is added to MainHeader.
  • Changes made to the UserControls component. We have removed activity controls and change the layout. Activity can be changed in a new component Activity
  • Theme deprecated for UserActivityControls
  • Remove Activity controls from the NoTaskCanvas

This is a potential breaking change if you have customized UserCard and its child components using CSS.

State Management Changes

As part of the upgrades to our core APIs, Flex UI 2.0 includes the Redux Toolkit and some new APIs for managing your internal state. These tools provide some guardrails for your state management, helping you set up boilerplate code more easily and with better defaults.

We recommend using single Redux store, either let Flex UI create its own store or pass a custom store using Manager.create() API

useFlexSelector

A wrapper around Redux's useSelector method. It exposes the same API but adds some Flex validations to ensure Flex's internal state is usable. This selector is specific for working with Flex state itself. Outside of accessing Flex state, we recommend using the default useSelector.

const MyComponent = (props) => {
   const viewState = useFlexSelector(state => state.view);
   return (
       {viewState.isSideNavOpen &&
           <div>My Custom Code</div>
       }
   )
}

The selector takes the current view state for the custom component. The selector guarantees that the state being selected is safe to read and can be used in the application without side effects. This couldn’t be guaranteed with useSelector.

useFlexDispatch

A wrapper around Redux's useDispatch method. It prevents dispatches from causing side effects to Flex's state, ensuring your changes work as expected. Use this hook for interacting with Flex's state. You can use the native useDispatch method outside of Flex’s state.

const MyComponent = (props) => {
   const viewState = useFlexSelector(state => state.view);
   const dispatch = useFlexDispatch();
   return (
       {viewState.isSideNavOpen &&
               <button onClick={() => dispatch({type: 'close_side_bar'})}>My Custom Code</button>
       }
   )
}

MessageInput.defaultProps.useSeparateInputStore

The Flex UI 2.0 no longer uses the MessageInput.defaultProps.useSeparateInputStore flag and its behavior has been deprecated. All Flex UI development must now be done with a separate Store. You can remove the flag without any repercussions.

AppConfig changes

You need to update your AppConfig structure to utilize the new config structure’s names and capabilities.

Flex 1.*

Flex 2.0

changes

Notifications.browser

Notifications.enabled

renamed

warmTransfers

-

removed

colorTheme

theme

Updated (more info)

Action changes

Download Media Attachment changes

DownloadMedia action no longer requires “message” as a part of the payload. Instead, a new property “media” of type “Media” from @twilio/conversations is required.

Renamed actions

These actions were renamed to follow the action naming convention:

Flex UI 1.0

Flex UI 2.0

InsightsPlayer:play

InsightsPlayerPlay

InsightsPlayer:show

InsightsPlayerShow

InsightsPlayer:hide

InsightsPlayerHide

InsightsPlayer:initialized

InsightsPlayerInitialized

HistoricalReporting:view

HistoricalReportingView

Teams View changes

Removed

  • Removed FilterData (shouldn't be needed) and TeamFiltersPanelProps (use TeamFiltersPanelChildrenProps instead) interfaces from Flex.Supervisor.
  • Removed uniqueName from TaskCanvasTabsChildrenProps.
  • Removed the deprecated WorkerProfile.defaultProps.details prop. Use WorkerProfile.Content to add additional details to the worker profile panel.
  • Removed insights.client and supervisor.listener from redux state.
  • Legacy filtering in TeamsView was removed. Filters from WorkersDataTable.defaultProps.filters will still be added to the new filter panel, but the support for filter factories was dropped.
  • WorkersDataTable.defaultProps.initialCompareFunction was removed. Support for sorting was added to the workers table and you can now use sortWorkers, sortCalls and sortTasks on WorkersDataTable.defaultProps to specify the compare functions used by the workers, calls and tasks columns.
  • WorkersDataTable.defaultProps.tablePlaceholder was removed. The message displayed when the table is empty can be modified with the TeamsViewResultsSummaryNoWorkersDisplayedTitle and TeamsViewResultsSummaryNoWorkersDisplayed templates.
  • Cleaned up the WorkersDataTableChildrenProps. Only workers, selectedTask, selectedWorker, and monitoredTaskSid are now available.
  • WorkersDataTable no longer forces updates every second. This could be considered breaking for customers who added columns, which contain some timers (eg. task age) and which will no longer tick every second.

Other changes

We have also cleaned up our api and renamed or remove objects and interfaces. Most of the changes should not have any impact on plugins.

Removed/renamed deprecated objects and interfaces

  • UserControlsImplProps has been removed. Refer to UserControlsChildrenProps instead
  • call.oldHold removed from TaskContext and state.phone.connection.onHold removed from state. Use TaskHelper.isCallOnHold(task) to get the status of the call.
  • DeprecatedLoginView component removed
  • DeprecatedRuntimeLoginView component removed
  • state.flex.phone.connections property removed. Refer to state.flex.phone.connection instead.
  • Event selectedViewChanged now only receives one argument (newViewName) and it’s not triggered on view resize anymore. To listen to view resize events, please subscribe to the viewResized event.
  • ActionsImpl object has been removed. Please refer to Actions instead.
  • registerGlobalStyles has been removed. Please refer to registerStyles instead
  • AudioManager’s ErrorCode has been renamed to AudioErrorCode
  • Actions.emit has been removed - use Actions.invokeActions instead.
  • Actions.removeAllListeners has been removed - please use Actions.removeListener and provide the specific listeners you want to remove.
  • Removed export of Flex.ErrorManager. This functionality has been replaced with Flex.Monitor.sendDebuggerEvent
  • Removed selectionStart/selectionEnd from MessageState, MessageInputArea, MessageInput, ConversationState
  • Removed show and hide methods from the ModalPopupWithEntryControl
  • Changed hiddenQueueFilter to queueFilter which takes a predicate function. See "Add a Worker Directory Tabs Queue Filter" on Work with Components and Props for usage details

Removed unused objects and interfaces

  • ChatModule
  • ChatStateCallback
  • chatReducer
  • registerGlobalStyles
  • StateMachineCb
  • StateMachine
  • initWithStrings
  • Version (not VERSION)
  • Initialize (from flex-core)
  • DeepPartial
  • NotificationManager
  • withDefaultPropsUpdate
  • AggregatedDataTile
  • ArrayInterpolation
  • FunctionInterpolation
  • Interpolation
  • StyledOptions
  • Themed
  • CreateStyled
  • CreateStyledOtherComponent
  • CreateStyledStatelessComponent
  • StyledComponent
  • StyledComponentMethods
  • StyledOtherComponent
  • StyledStatelessComponent,
  • getBackgroundWithHoverCSS
  • ThemeSupport
  • Utils
  • CountryManager
  • Animations
  • SVGContainerProps
  • FrameConstants
  • StyledUl
  • CSSProps

Component and config changes

  • TaskInfoPanel inner html styles tweaked to accommodate new design
  • TaskInfoPanelContent string inner html updated
  • TaskCanvasTabs resets to default task when switching between tabs
  • Flag file-attachments-in-chat is deprecated
Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.

Thank you for your feedback!

Please select the reason(s) for your feedback. The additional information you provide helps us improve our documentation:

Sending your feedback...
🎉 Thank you for your feedback!
Something went wrong. Please try again.

Thanks for your feedback!

thanks-feedback-gif