This page provides a detailed list of changes and migration guide for Fluent UI React version 8. See the release notes for a higher-level overview.
- Easier migration
- Using codemods
- Supported dependency versions
- Package renames
- Function component conversions
- Theming changes
- Individual components: new features
- Individual components: breaking changes
- Keytips
- Child window support
- Other changes
- Known issues
As of 2022-09-05, Fluent UI React v7 has been updated to ease migration from @uifabric
and office-ui-fabric-react
to @fluentui
packages and imports.
If you first update your package references and imports to the @fluentui
name while remaining on v7, moving to v8 will require fewer changes. You will be able to focus on the few breaking changes between v7 and v8.
The following packages were added to v7 that publish the @uifabric
exports as equivalent @fluentui
exports.
Important! v8 removed implicit exports which removed deep imports beyond the lib level. The stub packages only re-export top-level and lib level exports. For example,
office-ui-fabric-react/lib/components/Button/CommandBarButton/CommandBarButton
should become@fluentui/react/lib/Button
if you are still doing lib level imports or@fluent/react
if moving to package-level imports.
@uifabric package | @fluentui stub package |
---|---|
charting | react-charting |
experiments | react-experiments |
file-type-icons | react-file-type-icons |
icons | font-icons-mdl2 |
merge-styles | merge-style |
react-cards | react-cards |
react-hooks | react-hooks |
styling | style-utilities |
utilities | utilities |
variants | scheme-utilities |
Fixes and additions were made to both v7 and v8 to make migration easier. Many were ensuring that the getStyles methods for various components were exported under unique names at the top level. Others included exporting types and methods that were previously implicit exports.
v8:
v7:
- Exported lib/Decorators
- Exported ActivityItem getStyles
- Exported CommandBar getStyles
- Exported DetailsList getStyles
- Exported ContextualMenu getItemStyles
- Exported Layer getStyles and notifications
- Exported Picker getStyles
- Exported TextField getStyles
- Exported GroupedListUtilities
We've provided a number of codemods to help make picking up name and API changes easier.
Run npx @fluentui/codemods
to automatically upgrade your repo! This will result in changes being made to files so be sure to run it separate from an other active changes that you have.
More documentation here.
The minimum supported React version remains at 16.8. React 17 is also supported but has not yet been thoroughly tested due to tooling issues, so if you encounter any problems, please file an issue and we'll fix it.
The minimum supported TypeScript version has increased to 3.9. Later versions should also work. Our tslib
dependency has been updated to version 2, as required by TS 3.9.
React 16.8 and TypeScript 3.9 will continue to be our minimum supported versions for the duration of @fluentui/react
version 8.
(We've updated our tooling within the repo to TypeScript 4.1, but we'll ensure that this does not affect our public APIs.)
As the Fabric brand has evolved to Fluent UI, we've renamed our main package from office-ui-fabric-react
to @fluentui/react
. The @uifabric
sub-packages have also been moved to the @fluentui
scope and in some cases renamed.
As of version 8, the office-ui-fabric-react
package has been discontinued in favor of @fluentui/react
.
Update: Although deep imports won't create as much of an immediate issue now that we've reverted the
@fluentui/react-internal
addition from the original beta and moved most files back to their original locations (details here), we still highly recommend removing deep imports! This should be easier now since recent versions of 7 and 8-beta fixed the majority of exports that were missing from the package root.
Some partners have deep imports into the current Fabric package; for example:
import { ICalloutProps } from 'office-ui-fabric-react/lib/components/Callout/Callout.types';
This has never been supported officially, as we've always recommended to use either the package import or a "top-level import," meaning a file directly under the /lib/
path.
import { ICalloutProps } from '@fluentui/react'; // Good
import { ICalloutProps } from '@fluentui/react/lib/Callout'; // Also good
We cannot guarantee any deep import will continue working across major releases. They will break any time any given file is moved, renamed, or even when the casing is changed. This would create a massive surface contract that we are not able to support.
If you have deep imports in your product, please update them now to only use package or top-level imports. (And please, let us know if you depend on something that is not exported. We can fix that.)
The @uifabric
sub-packages have been moved to the @fluentui
scope and in some cases renamed to reflect our current naming conventions.
These renames can automatically be picked up in TypeScript code by running codemods, though references in package.json
and other configuration files will need to be updated manually.
The following table shows the new package names. For more details and history, see this issue. (The UMD global name is probably only relevant for codepen examples or prototypes, not apps which use a bundler.)
Old name (under @uifabric ) |
New name (under @fluentui ) |
New UMD global name |
---|---|---|
azure-themes |
same | FluentUIAzureThemes |
charting |
react-charting |
FluentUIReactCharting |
date-time |
react-date-time |
FluentUIReactDateTime |
example-app-base |
react-docsite-components |
|
example-data |
same | FluentUIExampleData |
experiments |
react-experiments |
FluentUIReactExperiments |
file-type-icons |
react-file-type-icons |
|
foundation |
foundation-legacy |
FluentUIFoundationLegacy |
icons |
font-icons-mdl2 |
|
jest-serializer-merge-styles |
same | |
merge-styles |
same | MergeStyles |
monaco-editor |
same | FluentUIReactMonacoEditor |
office-ui-fabric-react |
@fluentui/react |
FluentUIReact |
react-cards |
same (reintroduced here) | FluentUIReactCards |
react-hooks |
same | FluentUIReactHooks |
set-version |
same | |
styling |
style-utilities |
|
test-utilities |
same | |
theme-samples |
same | FluentUIThemeSamples |
tsx-editor |
react-monaco-editor |
|
utilities |
same | |
variants |
scheme-utilities |
FluentUISchemeUtilities |
webpack-utils |
webpack-utilities |
The following packages have been discontinued:
@uifabric/fluent-theme
: Constants have been moved to@fluentui/theme
. Styles are now the default.@uifabric/mdl2-theme
: This styling is deprecated (though you can continue to use version 7 of the package if needed).
A preview of ThemeProvider
was published with version 7 under @fluentui/react-theme-provider
. For various reasons, it was moved from that package into @fluentui/react
itself in version 8, so do not use @fluentui/react-theme-provider
in version 8.
As part of the work to support React strict mode and unblock adoption of React concurrent mode once it's released, some components were converted from class components to function components. This results in some API surface changes and may also require updates to tests.
While the function component conversions may require a bit of extra work to pick up in the short term, they also unblock future changes to more easily share state and interaction logic between components, which will help reduce bundle sizes and make behavior more consistent across components.
The following components have been converted. (Any component not on this list remains the same component type, class or function, as it was in version 7.)
- Breadcrumb
- Calendar
- Callout
- Checkbox
- ChoiceGroup (and ChoiceGroupOption)
- Coachmark (and Beak, PositioningContainer)
- ComboBox
- ContextualMenu
- DatePicker
- Dropdown
- Fabric
- Grid (renamed to ButtonGrid)
- Image
- Layer
- Link
- MaskedTextField
- MessageBar
- Modal
- OverflowSet
- Persona (and PersonaCoin, PersonaPresence)
- Pivot
- Popup
- Rating
- ResizeGroup
- SearchBox
- Shimmer
- Slider
- SpinButton
- SwatchColorPicker
- TeachingBubble
- Toggle
There are a few breaking behavior and API changes for the converted components. Most of these are inherent differences between the behavior of class and function components in React, not specific to Fluent UI React.
The ref
prop no longer refers to a component class instance; instead, the ref is forwarded to the underlying DOM. All our function components should correctly return a reference to the root DOM element.
For components with an imperative API (example: IDropdown.focus()
), you can still access that via componentRef
.
See React's docs for useRef
and forwardRef
for more on using refs with function components.
The deprecated ReactDOM.findDOMNode
API can't be used to find root elements of function components (this is a React limitation). Instead, use ref
as described above.
Since function component state is handled with hooks rather than a state
member, it can no longer be accessed from outside the component.
Most important state properties should be accessible via componentRef
on the IComponentName
"imperative handle" interface.
If you need a former state property which is not included in the relevant IComponentName
interface, please file an issue and we can consider adding it.
If you were using class extension on a component that was converted, it will no longer work. We recommend using composition instead: wrap the Fluent UI component inside another component which handles the prop or callback customizations which were previously done in the child class.
Even for components which were not converted, class extension is not recommended since we'll be converting the remaining components to function components in the future, possibly within a minor release. (Exception: Class extension of Pickers will continue to be supported for now since the current architecture relies on it. We'd like to change this in the future, but not within v8.)
If you have components which use our converted function components, certain test operations may need to be wrapped in act()
(from react-dom/test-utils
). This is a new requirement from React itself when testing function components that use hooks, and React will log console warnings if the wrapper is missing. More details here.
We know that the number of possible theming approaches and lack of clear guidance has been confusing to Fabric/Fluent UI React users in the past, so for version 8 we've added ThemeProvider
as a unified approach to applying and accessing themes.
Please see this wiki page and the ThemeProvider README for details about usage and migration.
The Fabric
and Customizer
components have been deprecated in favor of ThemeProvider
. (If you're using Customizer
for purposes besides theming, please let us know.)
NOTE: ThemeProvider
was previously published under @fluentui/react-theme-provider
. For various reasons, it was moved from that package into @fluentui/react
itself in version 8, so do not use @fluentui/react-theme-provider
in version 8.
This has moved back to dev status--see this comment for details.
(Note: when the beta was announced, we planned to officially release the new buttons with version 8 and export them by default from @fluentui/react
. However, it became apparent that a bit more time was needed to ensure that we're using the right patterns to provide a good foundation for building components moving forward.)
Calendar
and DatePicker
have been replaced with the versions from the @fluentui/react-date-time
package (formerly @uifabric/date-time
). These versions contain various bug fixes and have been converted from SCSS to CSS-in-JS. They should be almost identical in visuals and functionality, though there are some changes to how to customize styles. See under "Breaking changes" below for details.
Pivot
supports displaying an overflow menu when there is not enough room to display all of the tabs. This can be enabled by setting overflowBehavior="menu"
on the Pivot
.
It's now possible to use Rating
as an uncontrolled component by setting IRatingProps.defaultRating
.
For either controlled or uncontrolled Rating
s, the current value is now accessible via componentRef
as IRating.rating
. (Use this instead if you were previously accessing Rating.state.rating
.)
SpinButton
(finally) has a standard onChange
prop. This means you can easily use it as a controlled component without having to re-implement the default increment/decrement/validate handlers.
SwatchColorPicker
now has a standard onChange
prop. onColorChanged
is still available but has been deprecated.
Also added support for the standard controlled/uncontrolled pattern: provide selectedId
for controlled behavior and defaultSelectedId
for uncontrolled behavior.
Due to a change of plans, there are no breaking changes to Button in v8. The old version of Button remains exported by default from @fluentui/react
for this release, and the previously proposed "compat" import path for the old Button (@fluentui/react/lib/compat/Button
) has been removed.
Calendar
has been replaced with the version from the @fluentui/react-date-time
package (formerly @uifabric/date-time
).
- Converted styling from legacy SCSS to CSS-in-JS. Styling can now be customized using
ICalendarProps.styles
or sub-component props, such asICalendarProps.calendarDayProps.styles
.- See here for details of how to override sub-components' style props and related outstanding issues.
- The DOM structure has changed, and most global classNames are no longer available. We may add some of the classNames back if needed (see details here) but haven't implemented this yet.
- Removed the following props:
autoNavigateOnSelection
: Now the default behavior.selectDateOnClick
: Now the default behavior.shouldFocusOnMount
: UseICalendar.focus()
instead (viacomponentRef
)yearPickerHidden
: Moved toICalendarMonthProps
(settable viaICalendarProps.calendarMonthProps
)
- Prop
onDismiss?: (ev?: any) => void;
is nowonDismiss?: (ev?: Event | React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>) => void;
Checkbox
no longer accepts arbitrary native props at the root (ICheckboxProps
no longer extends React.ButtonHTMLAttributes<HTMLElement | HTMLInputElement>
). This actually is not a behavior change: any native props or data-*
props previously being passed through were ignored, and now the types accurately reflect the behavior.
To apply arbitrary native props to the hidden checkbox input element (used for accessibility and forms), use ICheckboxProps.inputProps
instead. Note that data-*
props are supported in ICheckboxProps.inputProps
but will require casting since TS < 4.1 doesn't provide a way to express this. This should be adequate for most scenarios, but please comment on this issue if you have a scenario where you need native props on the root element.
- Setting
checked
on individual options to indicate their checked state is no longer supported. Instead, usedefaultSelectedKey
orselectedKey
. - Moved
root
style to the actual root element and removedapplicationRole
style. - Removed deprecated props and types:
onChanged
fromIChoiceGroupProps
(useonChange
)checked
fromIChoiceGroupOption
(see above for alternative)- Note that this is still available via
IChoiceGroupOptionProps
for custom rendering purposes only, and will be set correctly by the parentChoiceGroup
.
- Note that this is still available via
- Type aliases
OnFocusCallback
andOnChangeCallback
: useIChoiceGroupOptionProps['onFocus']
andIChoiceGroupOptionProps['onChange']
- Only if manually rendering the
ChoiceGroupOption
component, the new propitemKey
is now required. (You can still usekey
when passing options viaIChoiceGroupProps.options
, which is by far the most common.)
- Removed deprecated
isBeaconAnimating
andisMeasured
style props
- The return type of
IComboBox.focus()
has changed fromboolean
tovoid
to reflect its actual behavior (the implementation does not return a value and can't easily be modified to do so).
DatePicker
has been replaced with the version from the @fluentui/react-date-time
package (formerly @uifabric/date-time
), which also uses the Calendar
from that package. See the notes on Calendar
above for details and potential breaking changes.
Dropdown options no longer infer title
values from their text
prop as it was redundant.
Grid
has been renamed to ButtonGrid
to better reflect what it is, and to free up the more generic name for a possible future abstraction of CSS grid. (The new name is also available in version 7.) Exported IGridStyles
are now IButtonGridStyles
.
- Contents of the
OverflowSet
are no longer wrapped in aFocusZone
. - Removed deprecated
focusZoneProps
anddoNotContainWithinFocusZone
from types.
- The picker input and selected tags are no longer wrapped in a
FocusZone
. - The text of selected tags is no longer focusable; only the remove button is in the tab order.
- Removed deprecated and redundant props from v7, including
initialSelectedKey
anddefaultSelectedIndex
. UseselectedKey
ordefaultSelectedKey
to define the selected tab, and provideitemKey
on pivot item children. IPivotStyleProps
changes- Replaced
rootIsLarge
withlinkSize
. - Replaced
rootIsTabs
andlinkFormat
. - Removed deprecated prop
linkIsSelected
.
- Replaced
- Updated enums to string union type:
PivotLinkFormat
,PivotLinkSize
. (#13370)
- Updated signature of
onDismiss
to include the nativeKeyboardEvent
as a possible type of theev
parameter:onDismiss?: (ev?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement> | KeyboardEvent) => any
- Removed deprecated props:
onChanged
(useonChange
)ariaLabelId
(usegetAriaLabel
)
- Passing
null
forIRatingProps.rating
is no longer supported. To determine whether the user has interacted with the rating yet, setallowZeroStars: true
and check whether the rating is 0. - Minor typing corrections:
IRatingProps
now extendsReact.HTMLAttributes
rather thanReact.AllHTMLAttributes
. The old interface included some props which don't actually apply to adiv
.- Corrected type of
IRatingProp.onChange
'sevent
parameter to reflect how it's used internally. It should beReact.FormEvent<HTMLElement>
, notReact.FocusEvent<HTMLElement>
.
- If
value
is provided, theSearchBox
will now use strict controlled behavior (the displayed value won't update until thevalue
prop changes). UsedefaultValue
for uncontrolled behavior.
- Removed default values of
min
andmax
(formerly 0 and 100). - If
value
is provided, theSpinButton
will now use strict controlled behavior (the displayed value won't update until thevalue
prop changes). UsedefaultValue
for uncontrolled behavior. onChange
now has custom handling and is only called when the SpinButton's value is "committed" (blur, enter, or spin). If you were previously using the nativeonChange
prop (applied to the component's rootdiv
) to be notified of every keystroke, useonInput
instead.- Simplified props to
ISpinButtonStyles
to include only the parts of the component to bring in line with other components. As a result, the following props have been removed (see below for migration tips):arrowButtonsContainerDisabled
inputDisabled
inputTextSelected
labelDisabled
labelWrapperStart
labelWrapperEnd
spinButtonWrapperDisabled
spinButtonWrapperFocused
spinButtonWrapperHovered
spinButtonWrapperTopBottom
- Replaced
getClassNames
legacy prop withstyles
prop to bring component consistent to other components and improve cacheability of internal styles.
If you're using a removed ISpinButtonStyles
prop, you can instead pass a style function which returns appropriate styles based on the current state of the component. The following code snippet shows how to do this for each removed prop.
<SpinButton styles={(props: ISpinButtonStyleProps) => {
const { disabled, isFocused, labelPosition, theme } = props;
return {
spinButtonWrapper: [
disabled && { /* spinButtonWrapperDisabled styles */ },
isFocused && { /* spinButtonWrapperFocused styles */ },
!disabled && { ':hover': { /* spinButtonWrapperHovered styles */ } }
],
input: [
disabled && { /* inputDisabled styles */ },
!disabled && { '::selection': { /* inputTextSelected styles */ } }
],
label: [
disabled && { /* labelDisabled styles */ }
],
labelWrapper: [
(labelPosition === Position.top || labelPosition === Position.bottom)
&& { /* spinButtonWrapperTopBottom styles */ },
labelPosition === Position.left && { /* labelWrapperStart styles */ },
labelPosition === Position.right && { /* labelWrapperEnd styles */ },
],
arrowButtonsContainer: [
disabled && { /* arrowButtonsContainerDisabled styles */ }
]
}
}}>
- Removed unused
componentRef
prop fromShimmer
types as it doesn't use any public methods.
- Selection state is now tracked internally based on
IColorCellProps.id
, not item index. Ensure that all color cells have a uniqueid
property. - Removed deprecated props:
positionInSet
: useariaPosInSet
setSize
: useariaSetSize
- Deprecated
isControlled
. ProvideselectedId
for controlled behavior anddefaultSelectedId
for uncontrolled behavior. - Added an
onChange
prop and deprecatedonColorChanged
.
- Removed
rootElementRef
from public API.
Text
now uses either the selected font variant's color, or theme.semanticColors.bodyText
as its color by default. This will only cause problems if you were previously relying on Text
inheriting color from its parent.
- Added separate interfaces for
MaskedTextField
:IMaskedTextFieldProps
andIMaskedTextField
- Moved
MaskedTextField
-specific propsmask
,maskChar
, andmaskCharData
from the generalITextFieldProps
toIMaskedTextFieldProps
onChange
is now called synchronously in the change event handler, before updating state (previously it was called asynchronously after the state update). This more closely matches other components and React itself, but may cause issues if anyone was depending on the old behavior.
Previously, KeytipData
was built into different components which needed Keytip support. This added extra bundle size to our components. In version 8, we have removed KeytipData
and keytipProps
props from Link
, Toggle
, Checkbox
, ComboBox
, Dropdown
, and SpinButton
.
Here is an example on how to migrate from this change:
Before:
<Checkbox label="Checkbox" keytipProps={checkboxKeytips} />
After:
import { useKeytipRef } from '@fluentui/react/lib/Keytips';
const checkboxRef = useKeytipRef({ keytipProps: checkboxKeytips });
<Checkbox label="Checkbox" ref={checkboxRef} />;
You can find more code examples on the public documentation site here.
- If the component is disabled and you don't want to enable keytips in that case, make sure you are passing
disabled: true
tokeytipProps
. It's possible you weren't settingdisabled
previously and still worked because the value was populated within the component which usesKeytipData
. - If you have another
ref
that needs to be passed to a component apart from theref
returned byuseKeytipRef
, you can useuseMergedRefs
from@fluentui/react-hooks
to merge multiple refs into one then pass it to the component.
WindowProvider
is required for child windows/embeds. This can be imported from @fluentui/react/lib/WindowProvider
or the @fluentui/react-window-provider
package.
The following components have been removed or deprecated from @fluentui/react-experiments
(formerly @uifabric/experiments
):
- Removed
Button
: didn't provide desired performance gains, and is superseded by convergence work.MicroFeedback
now uses the button from@fluentui/react
; this will affect valid slot prop overrides.
- Deprecated
Slider
: we kept this one for now since it provides some functionality not currently implemented by the@fluentui/react
Slider
, but it will also be superseded by convergence work in the future. - Removed
Toggle
: superseded by convergence work.
The previous implementation of As of this PR, the deprecated experimental Card has been re-introduced under Card
(which was never officially released) has been entirely removed.@fluentui/react-cards
. Please don't use it in new code.
FluentStyles
is removed from@fluentui/react-experiments
since it re-exportedFluentStyles
from@uifabric/fluent-theme
. Leverage@fluentui/theme
if you want to replicate the original behavior inside your project, although this should not be needed since theFluentStyles
are the default ones.- Removed various files which were originally in
office-ui-fabric-react
and not intended to be part of the public API:office-ui-fabric-react/src/components/Theme/defaultTheme.ts
(use@fluentui/theme
)office-ui-fabric-react/src/customizations/TeamsTheme.ts
(use@fluentui/theme-samples
)office-ui-fabric-react/src/utilities/exampleData.ts
(use@fluentui/example-data
)
- (list may be incomplete)
If you encounter any breaking changes which were not mentioned here, feel free to file an issue or let us know internally.
-
Although we've added React 17 to our peer dependency range, the library has not been fully tested with React 17. Please file an issue if you encounter problems.
-
Azure theme styling for DatePicker and Calendar may not fully work - #17156