Guides for migrating between major versions of Evergreen.
Evergreen v7 is primarily a maintenance release focusing on stability and simplicity. The most notable change in this release is the removal of glamor as a fallback css-in-js solution to ui-box. Glamor has not been maintained in a number of years, and we're finally able to close out some long-standing security vulnerability issues reported through this dependency - #1304, #1552, #1146, #1519, #1533, and so on.
While there should be no significant visual changes introduced with this change, there was a large internal refactoring (#1554) to swap component themes and internal styles to use the updated ui-box functionality to replace glamor.
ui-box@5.2.0 introduced the ability to define selectors for a Box component. Since a Box component can be polymorphic and accept arbitrary props, we needed a way to determine what props were meant to define hover, active, focus, etc. states. See the selectors section in the ui-box readme for more information.
Any pseudoselectors defined in a custom theme will need to be moved under a selectors object, for example:
const baseStyle = { outline: 'none', textDecoration: 'none', display: 'flex', position: 'relative', paddingX: 12, + selectors: { _isSelectable: { cursor: 'pointer' }, _disabled: { cursor: 'not-allowed', userSelect: 'none' } + } }
The classicTheme was maintained in v6 to allow consumers to upgrade without forcing an entirely new look-and-feel. However, there were some missed components (#1511), and new components like the FileUploader were not retrofitted for the old visual style.
Taking into account the refactoring effort for the selectors object and v6 being out for close to 2 years now, we think it's time to sunset the classic theme in favor of our modern visual design.
import React from 'react' -import { classicTheme, ThemeProvider } from 'evergreen-ui' +import { defaultTheme, ThemeProvider } from 'evergreen-ui' const App: React.FC = (props) => { const { children } = props - return <ThemeProvider value={classicTheme}>{children}</ThemeProvider> + return <ThemeProvider value={defaultTheme}>{children}</ThemeProvider> }
npm i -g jscodeshift && npx jscodeshift -t node_modules/evergreen-ui/codemods/dist/6.0.0-7.0.0/eject-classic-theme.js --parser=tsx --extensions=js,jsx,ts,tsx fileOrDirectory --dry --printTo easily change imports from evergreen-ui to the local classicTheme object you've ejected, you can use this codemod:
npm i -g jscodeshift && npx jscodeshift -t node_modules/evergreen-ui/codemods/dist/6.0.0-7.0.0/replace-imports-with-local-path.js --localPath=themes/classic-theme --importName=classicTheme --parser=tsx --extensions=js,jsx,ts,tsx fileOrDirectory --dry --printSimilar to the classicTheme, we are no longer exporting the deprecatedDefaultTheme object which contained color palette and typography tokens.
npm i -g jscodeshift && npx jscodeshift -t node_modules/evergreen-ui/codemods/dist/6.0.0-7.0.0/eject-deprecated-default-theme.js --parser=tsx --extensions=js,jsx,ts,tsx fileOrDirectory --dry --printTo easily change imports from evergreen-ui to the local deprecatedDefaultTheme object you've ejected, you can use this codemod:
npm i -g jscodeshift && npx jscodeshift -t node_modules/evergreen-ui/codemods/dist/6.0.0-7.0.0/replace-imports-with-local-path.js --localPath=themes/deprecated-default-theme --importName=deprecatedDefaultTheme --parser=tsx --extensions=js,jsx,ts,tsx fileOrDirectory --dry --printThe Nudge component has been replaced with a simpler component named Pulsar. This component has a similar look, but does not wrap children or include the tooltip functionality that was previously available.
import React from 'react' -import { Nudge, Paragraph } from 'evergreen-ui' +import { Pulsar, Pane, Paragraph } from 'evergreen-ui' -<Nudge position={Position.TOP_LEFT} isShown={true}> - <Paragraph>Hello world</Paragraph> -</Nudge> +<Pane position="relative" display="inline-block"> + <Pulsar position={Position.TOP_LEFT} /> + <Paragraph>Hello world</Paragraph> +</Pane>
Nudge components leveraging the tooltipContent prop will need to be updated to render a Tooltip or Popover similar to this:
import React from 'react' -import { Nudge, Paragraph } from 'evergreen-ui' +import { Tooltip, Pulsar, Pane, Paragraph } from 'evergreen-ui' -<Nudge isShown={true} tooltipContent="Hello world"> - <Paragraph>Hello world</Paragraph> -</Nudge> +<Pane position="relative" display="inline-block"> + <Tooltip content="Hello world"> + <Pulsar /> + </Tooltip> + <Paragraph>Hello world</Paragraph> +</Pane>
npm i -g jscodeshift && npx jscodeshift -t node_modules/evergreen-ui/codemods/dist/6.0.0-7.0.0/replace-nudge.js --parser=tsx --extensions=js,jsx,ts,tsx fileOrDirectory --dry --printThe SidebarTab component has been removed. The same visual style can be achieved by rendering a Tab with the direction="vertical" prop.
import React from 'react' -import { SidebarTab } from 'evergreen-ui' +import { Tab } from 'evergreen-ui' -<SidebarTab>Settings</SidebarTab> +<Tab direction="vertical">Settings</Tab>
npm i -g jscodeshift && npx jscodeshift -t node_modules/evergreen-ui/codemods/dist/6.0.0-7.0.0/replace-sidebar-tab.js --parser=tsx --extensions=js,jsx,ts,tsx fileOrDirectory --dry --printThe SegmentedControl component has been removed. The same visual style can be achieved by rendering a group of components (Button, TextInput, etc) in a Group.
Click event and active state management now needs to be handled manually - the Group component only manages the border/size styling as well as the role="group" attribute.
import React, { useState } from 'react' -import { SegmentedControl } from 'evergreen-ui' +import { Group, Button } from 'evergreen-ui' const OPTIONS = [ { label: 'Small (24px)', value: 'small' }, { label: 'Medium (32px)', value: 'medium' }, { label: 'Large (40px)', value: 'large' } ] const App: React.FC = () => { const [size, setSize] = useState<string>('small') return ( - <SegmentedControl - onChange={setSize} - options={OPTIONS} - value={size} - /> + <Group> + {OPTIONS.map(({ value, label }) => ( + <Button + isActive={value === size} + key={label} + onClick={() => setSize(value)} + > + {label} + </Button> + ))} + </Group> + ) ) }
The css object that the Positioner component returns is now in a slightly different shape - it now returns BoxProps which are meant to be spread onto a Box component (primarily to support the selectors object). Previously, you could pass this object to glamor and return a serialized class name reprsenting the styles.
Any consumers leveraging the Positioner component will need to be updated to use a wrapping Box for the css render prop. Take a look at the changes to the Popover or Tooltip components in #1554 for an example.