Skip to main content

Version 12 to 13

This migration guide contains migration instructions for:

Note

Potential breaking changes ahead: this update might require a lot of changes, as Frontend libs is being simplified, and some parts extracted into Eightshift UI components.

Expected duration:

  • ~4h for basic replacements and checks
  • ~10-20h for complete replacements and checks (recommended)

Exact time will depend on number of blocks/components and how complex they are.

Helpers

Removed helpers

Some helpers were deprecated and removed, without a replacement. If they were used in the project before, you can take the source of the helper from Frontend libs 12 and include it in your project.

These helpers were removed:

  • getNavigatorVibrate
  • escapeString
  • elementChildrenHeight
  • device

Helpers moved to ES UI components

Import these helpers from @eightshift/ui-components/utilities instead of Frontend libs:

  • truncate
  • truncateMiddle
  • unescapeHTML
  • camelCase
  • pascalCase
  • snakeCase
  • kebabCase
  • isEmpty
  • lowerFirst
  • upperFirst
  • has
  • isPlainObject
  • isObject
  • isEqual
  • debounce
  • throttle

Helpers with new names

These helpers should be imported from @eightshift/ui-components/utilities instead of Frontend libs:

  • camelizecamelCase
  • classnamesclsx
  • ucfirstupperFirst

Classnames

classnames([
'class-1',
'class-2',
'class-3',
])

clsx(
'class-1',
'class-2',
'class-3',
)

If you're using selector and have the condition argument the same as the block argument, you can omit the condition and replace selector with bem.

clsx(
selector(blockClass, blockClass, 'something'),
...
)

clsx(
bem(blockClass, 'something'),
...
)

(bem comes from Frontend libs)

If you have a condition set, you can move it outside of the function call.

clsx(
selector(myCondition, blockClass, 'something'),
...
)

clsx(
myCondition && bem(blockClass, 'something'),
...
)

(bem comes from Frontend libs)

If there's a selector with the same 2 arguments, omit the function.

clsx(
selector(blockClass, blockClass),
...
)

clsx(
blockClass,
...
)

If you have only one entry within classnames/clsx, just keep that entry.

clsx(
classnames([bem(blockClass, selectorClass)]),
...
)

clsx(
bem(blockClass, selectorClass),
...
)

Icons

Import these from @eightshift/ui-components/icons instead of Frontend libs:

  • icons
  • illustrations
  • blockIcons
  • BlockIcon

Additionally, if you used dangerouslySetInnerHTML for rendering SVGs, you can now use the JsxSvg component to render it more safely and elegantly.

<JsxSvg svg="<svg ..." />

Styles

Utility classes

Frontend libs utility classes are deprecated and will be removed in the next version.

Remove them from your code if possible, and check if some of them can be replaced with ones from ES UI components (they have the es-uic- prefix).

CSS reset

The default CSS reset was updated. Do a quick look-around on your site to see if anything is different, but nothing major is expected.

SCSS

Some SCSS functionalities were removed from Frontend libs.

If you were using them, you can re-define them in your project. The previous implementation can be checked in Frontend libs v12 source.

Placeholders

Removed placeholders:

  • %absolute-center
  • %bg-image
  • %clearfix
  • %site-padding
  • %site-padding-correction
  • %link-transition
  • %heading-reset
  • %paragraph-reset
  • %dl-reset

Functions

Removed functions:

  • calc-column-width / calcCW
  • calc-dynamic-size / calcDS
  • calc-grid-width / calcGW
  • line-height / lh
  • em

Keyframes

Keyframes were removed from Frontend libs

Mixins

Removed mixins:

  • flex-container
  • box-sizing (replace with box-sizing, if no arguments were specified, the default is border-box)
  • column-offset-modifiers
  • flex-column-width-modifiers
  • flex-column-width
  • flex-grid-width-modifiers
  • flex-grid-width
  • flex-horizontal-align-modifiers
  • flex-vertical-align-modifiers
  • text-align-modifiers
  • stretch
  • placeholder
  • inline-font-colors
  • grid-offset-modifiers
  • font-smoothing
  • custom-bullets
  • link-modifiers
  • link
  • modifiers-deep
  • modifiers-range
  • modifiers
  • responsive-modifiers
  • responsive-selectors-visibility
  • responsive-selectors
  • responsive
  • for-each-attribute
  • es-eases

Component styles, editor overrides, ...

The previously included Gutenberg component style overrides are not included by default anymore. overrides-editor.scss is still present, but only a couple of styles are left for compatibility reasons. Instead, you can @import '~@eightshift/ui-components/dist/assets/wp-ui-enhancements.css'; from Eightshift UI components.

es-component-styles.scss (in Frontend libs) are not bundled with overrides-editor.scss anymore, and should be imported separately if needed.

Replace components

This will take some time, but the guide below should make it easier. Our recommendation is to go block by block (instead of replacing one type of UI component at a time).

Note

Some components will still have fallbacks not to break everything immediately, but replacing them is strongly recommended, as everything will be removed in the next version.

Tip

After replacing components, check if there are any new props that might be useful for your use case.

All components

  • remove noBottomSpacing
  • remove reducedBottomSpacing

AdvancedColorPicker

Removed props:

  • isTileButton
  • popoverPosition

Renamed props:

  • additionalClassesclassName

AnimatedContentVisibility

Replace with AnimatedVisibility from Eightshift UI components.

Rename props:

  • showIfvisible
  • additionalContainerClassesclassName

Control

Replace with BaseControl from Eightshift UI components.

Rename props:

  • additionalClassesclassName
  • additionalLabelClasseslabelClassName
  • inlineLabelinline

Removed props:

  • wrapChildren

BlockInserter

Rename props:

  • additionalClassesclassName

Label-specific:

  • If hasLabel was set, replace it with label
  • If customLabel was set, remove hasLabel and rename customLabel to label

Collapsable

Replace with Expandable from Eightshift UI components.

Rename props:

  • additionalClassesclassName

ColorPalette

Replace with ColorPicker from Eightshift UI components.

Rename props:

  • additionalClassesclassName
  • noShadeGroupingnoColorGroups

Removed props:

  • inlineLabel
  • layout
  • searchable
  • actions

ColorPicker

Replace with ColorPicker from Eightshift UI components.

Rename props:

  • noShadeGroupingnoColorGroups
  • helpsubtitle

If type is set to generic, replace that with default.

Removed props:

  • pickerPopupTitle
  • searchable
  • colorPaletteLayout
  • expanded
  • border
  • inlineLabel
  • additionalClasses
  • additionalTriggerClasses
  • popoverPosition
  • additionalControls
  • buttonIconOverride
  • additionalButtonArgs
  • additionalColorPaletteArgs

ColorSwatch

Replace with ColorSwatch from Eightshift UI components.

Rename props:

  • additionalClassesclassName

Removed props:

  • selected
  • larger

Select

Replace with Select from Eightshift UI components.

Rename props:

  • inlineLabelinline
  • closeMenuAfterSelectkeepMenuOpenAfterSelect (also invert the logic!)
  • additionalSelectClassesclassName

Removed props:

  • additionalProps - instead, pass props to the component directly
  • additionalClasses

MultiSelect

Replace with MultiSelect from Eightshift UI components.

Rename props:

  • inlineLabelinline
  • additionalSelectClassesclassName

Removed props:

  • additionalProps - instead, pass props to the component directly
  • additionalClasses

AsyncSelect

Replace with AsyncSelect from Eightshift UI components.

Rename props:

  • inlineLabelinline
  • closeMenuAfterSelectkeepMenuOpenAfterSelect (also invert the logic!)
  • additionalSelectClassesclassName

Removed props:

  • additionalProps - instead, pass props to the component directly
  • additionalClasses
  • noOptionCaching

AsyncMultiSelect

Replace with AsyncMultiSelect from Eightshift UI components.

Rename props:

  • inlineLabelinline
  • additionalSelectClassesclassName
  • customDropdownArrowcustomDropdownIndicator

Removed props:

  • additionalProps - instead, pass props to the component directly
  • additionalClasses
  • noOptionCaching

react-select component wrappers

Everything works the same, just import the components from @eightshift/ui-components instead.

Slider

Replace with Slider from Eightshift UI components.

Rename props:

  • marksmarkers
  • onAfterChangeonChangeEnd
  • leftAdditionbefore
  • rightAdditionafter

Removed props:

  • discrete
  • reverse
  • onBeforeChange
  • handleColor
  • additionalClass
  • additionalSliderClass
  • noTooltip
  • tooltipPlacement
  • tooltipFormat
  • valueDisplay
  • valueDisplayElement

RangeSlider

Replace with Slider from Eightshift UI components.

Rename props:

  • marksmarkers
  • onAfterChangeonChangeEnd
  • leftAdditionbefore
  • rightAdditionafter

Removed props:

  • discrete
  • reverse
  • onBeforeChange
  • handleColor
  • additionalClass
  • additionalSliderClass
  • noTooltip
  • tooltipPlacement
  • tooltipFormat
  • valueDisplay
  • valueDisplayElement
  • pushable
  • noCross
  • draggableTrack

ColumnConfigSlider

Replace with ColumnConfigSlider from Eightshift UI components.

Rename props:

  • numOfColumnscolumns
  • noOffsetHandledisableOffset
  • noWidthHandledisableWidth

Removed props:

  • additionalClass

FancyDivider

Replace with Spacer from Eightshift UI components.

Rename props:

  • labeltext
  • additionalClassesclassName

Removed props:

  • additionalClass
  • hasTopSpacing
  • noBottomSpacing

IconLabel

Replace with RichLabel from Eightshift UI components.

Rename props:

  • additionalClassesclassName

Removed props:

  • standalone
  • addSubtitleGap

Notification

Replace with Notice from Eightshift UI components.

Rename props:

  • additionalClassesclassName
  • textlabel
  • iconOverrideicon

LinkInput/LinkEditComponent

Replace with LinkInput from Eightshift UI components.

Rename props:

  • additionalClassesclassName
  • textlabel
  • iconOverrideicon

Removed props:

  • anchorIcon
  • noDelete
  • hideAnchorNotice
  • additionalOptions (make sure to relocate those components somewhere else)
  • additionalOptionTiles (make sure to relocate those components somewhere else)
Warning

New tab control has been detached from this component. Use a Toggle (from Eightshift UI components) below it instead.

MatrixAlignControl

Replace with MatrixAlign from Eightshift UI components.

Rename props:

  • additionalClassesclassName
  • textlabel
  • iconOverrideicon

Removed props:

  • type
  • additionalTriggerClasses

Replace with MenuSeparator from Eightshift UI components.

Replace with MenuItem from Eightshift UI components.

Rename props:

  • additionalClassclassName

Removed props:

  • customProps - instead, pass props to the component directly

Replace with Menu from Eightshift UI components.

Rename props:

  • icontriggerIcon
  • labeltriggerLabel
  • buttonPropstriggerProps

Removed props:

  • customProps - instead, pass props to the component directly
  • disabled - instead, pass through triggerProps={{ disabled: disabled }}
  • popoverAdditionalClass - instead, pass through popoverProps={{ className: 'your-class-name-here' }}
  • isSubmenu - instead, check docs for real submenus
  • additionalClass - instead, pass through triggerProps={{ className: 'your-class-name-here' }}

NumberPicker

Replace with NumberPicker from Eightshift UI components.

Rename props:

  • icontriggerIcon

Removed props:

  • noDragToChange
  • actions
  • additionalClasses
  • inputField
  • prefixClass
  • suffixClass
  • extraButton - instead, pass that as a child of the NumberPicker component
  • noExtraButtonSeparator
  • roundToDecimals

OptionSelector

Replace with OptionSelect from Eightshift UI components.

Rename props:

  • inlineLabelinline
  • iconOnlynoItemLabel
  • additionalButtonClassclassName
  • additionalContainerClassitemClassName

Removed props:

  • optionLabels - merge into options if needed
  • border
  • noWrap
  • alignment - add the vertical prop if alignment='vertical' was used
  • largerIcons
  • compactButtons - if needed, can be implemented with itemProps={{ size: 'small' }}
  • labelOnlyOnActive
  • additionalClass

PopoverWithTrigger

Replace with TriggeredPopover from Eightshift UI components.

Rename props:

  • popoverClassclassName
  • positionplacement

Removed props:

  • contentClass - merge into className
  • noArrow
  • trigger - Important: check your component and add triggerButtonLabel / triggerButtonIcon props as needed. If you need a custom trigger, pass it via the trigger prop. It should be a component that's clickable, similar to a button.
  • additionalCloseActions - can be reimplemented with onOpenChange, check the docs
  • additionalPopoverProps - pass props directly to the component instead
  • allowCloseFromChildren

Toggle

Replace with:

  • Toggle from Eightshift UI components if type was toggle
  • Checkbox from Eightshift UI components if type was checkbox
  • ToggleButton from Eightshift UI components if type was button, iconButton or tileButton

Rename props:

  • additionalClassesclassName
  • helpsubtitle (doesn't apply to ToggleButton)

Removed props:

  • inlineHelp

ResponsiveToggleButton

Replace with ResponsiveLegacy from Eightshift UI components.

Sample replacement:

<ResponsiveLegacy
hidden={!showXyz} // If you had '{showXyz && <ResponsiveToggleButton ... />}'
{...getResponsiveLegacyData(manifest.responsiveAttributes.buttonWidth, attributes, manifest, setAttributes)} // 'getResponsiveLegacyData' comes from Frontend libs
breakpointData={globalManifest.globalVariables.breakpoints}
icon={icons.width} // Copy over from 'ResponsiveToggleButton'
label={__('Full-width', 'my-project')} // Copy over from 'ResponsiveToggleButton'
options={[
{ value: 'default', label: __('Fit content', 'my-project') }, // Can be replaced with "{ value: false, label: __('Off', 'my-project') }" if more generic
{ value: 'block', label: __('Full', 'my-project') }, // Can be replaced with "{ value: true, label: __('On', 'my-project') }" if more generic
]}
allowUndefined // If the responsive value can be undefined (= if any of the attribute has no default set). If not, remove this prop and add provide 'inheritValue'.
inline // Optional, but recommended with compact setups
>
{({ currentValue, options, handleChange }) => (
// Replace with any other relevant component, e.g. 'Switch'
<OptionSelect
value={currentValue}
options={options}
onChange={handleChange}
/>
)}
</ResponsiveLegacy>

ResponsiveNumberPicker

Replace with ResponsiveLegacy from Eightshift UI components.

Sample replacement:

<ResponsiveLegacy
hidden={!showXyz} // If you had '{showXyz && <ResponsiveNumberPicker ... />}'
{...getResponsiveLegacyData(manifest.responsiveAttributes.xyz, attributes, manifest, setAttributes)}
label={__('Width', 'my-project')} // Copy over from 'ResponsiveNumberPicker'
icon={icons.width} // Copy over from 'ResponsiveNumberPicker'
options={generateOptionsFromValue('xyz', attributes, manifest)} // 'generateOptionsFromValue' is from Frontend libs
breakpointData={globalManifest.globalVariables.breakpoints}
allowUndefined // If the responsive value can be undefined (= if any of the attribute has no default set). If not, remove this prop and add provide
inline // Optional, but recommended with compact setups
>
{({ currentValue, handleChange, breakpoint }) => {
return (
// Replace with any other relevant component
<NumberPicker
aria-label={sprintf(__('Width - %s', 'my-project'), breakpoint)}
value={currentValue ?? null} // '?? null' is required if 'allowUndefined' is set
onChange={handleChange}
// This is from previous 'minMaxStepOptionName'
min={manifest.options.carouselItemWidth.min}
max={manifest.options.carouselItemWidth.max}
step={manifest.options.carouselItemWidth.step} // Optional, '1' is the default
size='small'
/>
);
}}
</ResponsiveLegacy>

Responsive

Replace with ResponsiveLegacy from Eightshift UI components.

Sample replacement:

<ResponsiveLegacy
hidden={!showXyz} // If you had '{showXyz && <Responsive ... />}'
{...getResponsiveLegacyData(manifest.responsiveAttributes.buttonAlign, attributes, manifest, setAttributes)}
label={__('Align', 'my-project')} // Copy over from 'Responsive'
icon={icons.horizontalAlign} // Copy over from 'Responsive'
options={options.buttonAlign} // or use 'getOption' helper
breakpointData={globalManifest.globalVariables.breakpoints}
allowUndefined // If the responsive value can be undefined (= if any of the attribute has no default set). If not, remove this prop and add provide
inline // Optional, but recommended with compact setups
>
{({ currentValue, options, handleChange }) => (
// Replace with any other relevant component
<OptionSelect
value={currentValue}
options={options}
onChange={handleChange}
/>
)}
</ResponsiveLegacy>
Note

In some cases, replacement might be too complicated. It's OK to skip it then, but try to keep this to a minimum.

Repeater

Replace with Repeater from Eightshift UI components.

Note

In some cases, replacement might be too complicated. It's OK to skip it then, but try to keep this to a minimum.

Modify components

PresetPicker

Removed props:

  • showAsCollapsable

Replace Gutenberg components

Button

Replace Button from @wordpress/components:

  • if isPressed is present, with ToggleButton from @eightshift/ui-components.
  • otherwise, Button from @eightshift/ui-components.

If label was set and the button itself doesn't have a label, set an aria-label with the same value. Optionally, also set tooltip to the same value.

PanelBody

Replace PanelBody from @wordpress/components with ContainerPanel from @eightshift/ui-components.

After that:

  • add the closable attribute.
  • if you had an icon in the panel, separate it from the title and pass it to the icon prop
  • if there were extra controls by the title, pass them to actions

TextControl

Replace TextControl from @wordpress/components with InputField from @eightshift/ui-components.

After that:

  • if you had an icon in the panel, separate it from the label and pass it to the icon prop

TextAreaControl

Replace TextAreaControl from @wordpress/components with InputField from @eightshift/ui-components.

After that:

  • set type to multiline
  • if you had an icon in the panel, separate it from the label and pass it to the icon prop