UNPKG

@atlaskit/primitives

Version:

Primitives are token-backed low-level building blocks.

137 lines (106 loc) 3.53 kB
--- title: Migrating your app to XCSS description: XCSS is a safer, tokens-first approach to CSS-in-JS. order: 2 --- ## Summary of changes ### Changes for developers There are two key changes to be mindful of when migrating to XCSS. The first is updating callsites to remove any nested styles and tokenized values. ```diff - import { css } from '@emotion/react'; + import { xcss } from '@atlaskit/primitives'; - const someStyles = css({ + const someStyles = xcss({ // token based properties will no longer need to be wrapped - padding: token('space.100'), + padding: 'space.100' // no change is required for non-tokenized values transform: 'scale(2)' }); ``` The second change is that for the `xcss` function to be applied correctly it must be applied on a component with an `xcss` JSXAttribute. This won't work with the `css` or `className` JSXAttributes, be aware if you're not seeing your styles appear. ```diff - <div css={someStyles} /> + <Box xcss={someStyles} /> ``` ### Changing the way you express styles Why are nested selectors a problem? A key philosophy of XCSS is encouraging more deterministic style application. Restricting nested styles eliminates side-effects and encourages component encapsulation. Consider the below example: ```tsx const myComponentStyles = css({ '> *': { color: 'color.text.danger', }, }); const MyComponent = () => ( <div css={myComponentStyles}> <p>Text here</p> </div> ); ``` Here the component is applying styles that are implicitly meant for the text wrapped in the `p` below. In this simple example, it may seem okay, desirable even, but cases like these often occur across module or component boundaries. This makes the visibility of these dependencies harder to capture or reason about. Styles that are inherited or indirectly apply make a UI vulnerable to change and harder to maintain. Instead, if the same styles are applied directly to the affected element this can minimize and in some cases completely eliminate this problem. ```diff const myTextStyles = xcss({ - '> *': { color: 'color.text.danger', - } }); const MyComponent = () => ( - <div xcss={myComponentStyles}> + <Box + <Text xcss={myTextStyles}>Text here</Text> </Box> ); ``` There will likely be cases where nesting is the only option. While not desirable, nesting can be used minimally, and when the potential impact is considered. ## FAQ Migration to XCSS is simple for the majority of cases. Here are some common strategies for migrations. ### Non-tokenized values Before migrating to tokens, there are two options. Migrate to tokens first and then on a second pass migrate to XCSS or make the jump directly to use both tokens and XCSS. ```tsx const someStyles = css({ color: 'red', }); // ->>> Optional middle step const someStyles = css({ color: token('color.text.danger'), }); // ->>> The final state const someStyles = xcss({ color: 'color.text.danger', }); ``` ### Moving from the `styled` API If currently using the `styled` API there are a few steps to migrate. The safest approach is to use object styles, migrate to tokens (optionally) and then migrate to XCSS. ```tsx const MyComponent = styled.div` color: red; `; // ->>> move to object styles const MyComponent = styled.div({ color: 'red'; }); // ->>> move to tokens const MyComponent = styled.div({ color: token('color.text.danger'), }); // ->>> move to Box const myComponentStyles = xcss({ color: 'color.text.danger', }); const MyComponent = () => <Box xcss={myComponentStyles} /> ```