Migrating from another CSS-in-JS library
Devup UI reads styled-components, Emotion, vanilla-extract and StyleX source directly. You do not rewrite call sites, and you do not keep the original library installed — the build rewrites the imports and compiles every call into static CSS.
What happens to your code
1// what you wrote 2import styled from 'styled-components' 3 4const Card = styled.div` 5 color: red; 6`1// what you wrote 2import styled from 'styled-components' 3 4const Card = styled.div` 5 color: red; 6`
1// what ships — no styled-components, no runtime 2const Card = ({ style, className, ...rest }) => ( 3 <div 4 {...rest} 5 className={['a', className].filter(Boolean).join(' ')} 6 style={style} 7 /> 8)1// what ships — no styled-components, no runtime 2const Card = ({ style, className, ...rest }) => ( 3 <div 4 {...rest} 5 className={['a', className].filter(Boolean).join(' ')} 6 style={style} 7 /> 8)
1.a { 2 color: red; 3}1.a { 2 color: red; 3}
The import is not merely re-pointed at @devup-ui/react: the extractor consumes the call and removes the specifier, so the import statement disappears from the output entirely.
Two passes
- Import rewrite —
import { style } from '@vanilla-extract/css'becomesimport { css as style } from '@devup-ui/react'. Only names with a real Devup UI counterpart move; the rest stay put so their own types keep working. - Extraction —
style({ ... })is compiled to a class name, the specifier is dropped, and the now-empty import is deleted.
Because of the second pass, the intermediate css as style alias never reaches your bundle.
Enabling it
Every plugin turns the default aliases on automatically:
1// vite.config.ts 2import { DevupUI } from '@devup-ui/vite-plugin' 3 4export default DevupUI({})1// vite.config.ts 2import { DevupUI } from '@devup-ui/vite-plugin' 3 4export default DevupUI({})
The defaults cover styled-components, @emotion/styled, @emotion/react and @vanilla-extract/css. StyleX needs no alias — @stylexjs/stylex is recognised directly.
Opt a package out when you want to keep using the real thing:
1DevupUI({ 2 importAliases: { 3 'styled-components': false, 4 }, 5})1DevupUI({ 2 importAliases: { 3 'styled-components': false, 4 }, 5})
Uninstalling the original package
Once the imports are rewritten you can drop the dependency. TypeScript still has to resolve the specifier you wrote, so the plugins generate <distDir>/compat.d.ts with ambient declarations for the aliases you have enabled:
1/// <reference types="@devup-ui/react/compat/styled-components" /> 2/// <reference types="@devup-ui/react/compat/emotion" /> 3/// <reference types="@devup-ui/react/compat/stylex" /> 4/// <reference types="@devup-ui/react/compat/vanilla-extract" />1/// <reference types="@devup-ui/react/compat/styled-components" /> 2/// <reference types="@devup-ui/react/compat/emotion" /> 3/// <reference types="@devup-ui/react/compat/stylex" /> 4/// <reference types="@devup-ui/react/compat/vanilla-extract" />
That file lands next to theme.d.ts inside your project, so tsconfig.json picks it up with no extra configuration. Disabled aliases are left out on purpose — an ambient declaration wins over an installed package, and a library you opted out of must keep its own types.
Where the absorbed APIs live
Anything that exists only to absorb another library — ThemeProvider, createGlobalStyle, ServerStyleSheet, and friends — is exported from @devup-ui/react/compat, never from @devup-ui/react. Using Devup UI directly means never seeing them, and it lets the compat entry keep the original spelling: its useTheme cannot collide with Devup UI's own useTheme.
1// rewritten for you1// rewritten for you