Skip to content

Migrating to V4

Ruo Ling edited this page Mar 9, 2026 · 54 revisions

What's new in V4?

We have moved away from Styled Component (CSS-in-JS) to Linaria (build-time), which improves compatibility with projects that rely on SSR or strict CSP.

Migrating from V3

If your project uses V3, follow these steps to install V4.

Changes

General

<TOC>

Components

<TOC>

ErrorDisplay

  • Replace usage of ErrorDisplay.ImagePathAttributes with ErrorDisplayImagePathAttributes

ThemeProvider

  • Usage instructions

ThemeSpec object

  • Removed
  • No mixing and matching of schemes
  • Use a custom stylesheet or adhoc customisation instead

Border

  • Removed Border.Util

Breakpoint

  • Order of media query
  • Extracting the value with useDesignToken

Customisation

What changes in V4

In V3, ad hoc theming was typically done by modifying the styled-components theme object (for example by injecting a modified colourScheme into token helpers).

In V4, ThemeProvider only accepts theme and mode. Theme extension for ad hoc customisation is done through CSS variable overrides using useApplyStyle.

In V4, you can style a scoped theme container directly:

  1. Use the V4 ThemeProvider to define the scope
  2. Get its themeElement from useTheme()
  3. Apply ad hoc CSS variables with useApplyStyle

Extending theme presets: V3 vs V4

In V3, you can construct a custom ThemeSpec and set overrides.

import { LifeSGTheme, ThemeSpec } from "@lifesg/react-design-system/theme";
import { ThemeProvider } from "styled-components";
import { Component } from "./index";

const customTheme: ThemeSpec = {
    ...LifeSGTheme,
    overrides: {
        primitiveColour: {
            "primary-10": "#F3C85C",
        },
        font: {
            "heading-size-xxl": "4rem",
            "heading-lh-xxl": "4.5rem",
            "heading-ls-xxl": "0.056rem",
        },
    },
};

const App = () => {
    return (
        <ThemeProvider theme={myCustomTheme}>
            <Component />
        </ThemeProvider>
    );
};

export default App;

In V4, there is no ThemeSpec / overrides API in ThemeProvider. For ad hoc customisation, scope your overrides to the provider element:

  1. Wrap scope with V4 ThemeProvider
  2. Read themeElement from useTheme()
  3. Apply CSS variable overrides with useApplyStyle
import styled, { css } from "styled-components";
import { V3_Colour } from "@lifesg/react-design-system/V3_theme";

const Card = styled.div`
    ${(props) => {
        const modifiedProps = {
            ...props,
            theme: {
                ...props.theme,
                colourScheme: "bookingsg",
            },
        };

        return css`
            background: ${V3_Colour["bg-primary"](modifiedProps)};
            color: ${V3_Colour["text-inverse"](modifiedProps)};
        `;
    }}
`;

Element-level styling migration

In V3 advanced usage, element-level customisation was done by constructing modifiedProps and calling token helpers with that temporary theme.

In v4, apply styles directly to the target element ref:

import { useRef } from "react";
import { useApplyStyle } from "@lifesg/react-design-system/theme/utils";

const SomeComponent = () => {
    const targetRef = useRef<HTMLDivElement>(null);

    useApplyStyle(targetRef, {
        "--fds-colour-bg-primary": "#0043ce",
        "--fds-colour-text-inverse": "#ffffff",
    });

    return <TargetComponent ref={targetRef}>Custom target</TargetComponent>;
};

Clone this wiki locally