-
Notifications
You must be signed in to change notification settings - Fork 22
Migrating to V4
We have moved away from Styled Components (CSS-in-JS) to Linaria (build-time CSS extraction). This improves compatibility with projects that:
- rely on SSR
- use strict CSP
- prefer to use another styling framework
If your project uses V3, follow these steps to install V4.
Prerequisites:
- Upgrade to the latest V3 release and ensure your build and unit tests are passing first. This will help us with troubleshooting V4-specific issues.
- Upgrade to Styled Components v6
- For NextJS projects, upgrade to v16 with Turbopack enabled
npm i @lifesg/react-design-system@3
1. Upgrade to the V4 Design System
npm i @lifesg/react-design-system@4
2. Import the theme stylesheet
In your application's JavaScript entrypoint (e.g. pages/_app.tsx or app/layout.tsx in a NextJS project):
import "@lifesg/react-design-system/theme/styles/lifesg.css";Or in an existing .css file:
@import "@lifesg/react-design-system/theme/styles/lifesg.css";3. Set up the new ThemeProvider
Replace the Styled Components ThemeProvider or DSThemeProvider with the new ThemeProvider from @lifesg/react-design-system/theme:
- import { DSThemeProvider, LifeSGTheme } from "@lifesg/react-design-system/theme";
- import { ThemeProvider } from "styled-components";
+ import { ThemeProvider } from "@lifesg/react-design-system/theme";
- <ThemeProvider theme={LifeSGTheme}>{children}</ThemeProvider>
- <DSThemeProvider theme={LifeSGTheme}>{children}</DSThemeProvider>
+ <ThemeProvider theme="lifesg">{children}</ThemeProvider>Important
If DSThemeProvider was not previously used, add mode="light" to disable the default dark mode in V4.
<ThemeProvider theme="lifesg" mode="light">
{children}
</ThemeProvider>4. Run codemod to migrate imports
$ npx lifesg-react-design-system
Select codemods to run:
❯◉ migrate-popover5. Migrate design token usages
Refer to the Design tokens in styling and Design tokens at runtime sections.
General
- Design tokens in styling
- Design tokens at runtime
- Breakpoint tokens
- Dark mode
- ThemeProvider
- ThemeSpec and customisation
- Subpath imports
- V2 modules removed
Components
- Border
- Button
- ButtonWithIcon
- Divider
- DSThemeProvider
- ErrorDisplay
- Form.CustomField
- Form.Label
- IconButton
- Markup
- Masonry
- Popover
- PopoverV2
- TextList
- Tooltip
In V3, design tokens could be called as functions that accepted props.
V3 usage
import { Colour } from "@lifesg/react-design-system/theme";
const ExampleComponent = styled.div`
background: ${(props) => Colour["bg"](props)};
`;V4 usage
In V4, design tokens are CSS variable strings. Update usages depending on the context:
-
In Styled Components (or other CSS-in-JS libraries):
import { Colour } from "@lifesg/react-design-system/theme"; const ExampleComponent = styled.div` background: ${Colour["bg"]}; `;
-
In inline styles:
<div style={{ color: Colour["text"] }} />
If you need the resolved CSS value at runtime (e.g. to pass to a third-party library or perform calculations), use the useDesignToken hook:
import { Colour, useDesignToken } from "@lifesg/react-design-system/theme";
const ExampleComponent = () => {
const color = useDesignToken(Colour["text"]);
// color is a resolved CSS value e.g. "#1d2939"
return <ThirdPartyChart color={color} />;
};For tokens that resolve to a numeric length unit (e.g. radius, spacing or breakpoints), use parsePxOrRemValue to get a number:
import { Spacing, useDesignToken } from "@lifesg/react-design-system/theme";
import { parsePxOrRemValue } from "@lifesg/react-design-system/theme";
const ExampleComponent = () => {
const gap = parsePxOrRemValue(useDesignToken(Spacing["spacing-16"]));
// gap is a number e.g. 16
return <ThirdPartyChart gap={gap} />;
};In V3, you had to extract the breakpoint value at runtime by invoking the design token.
V3 usage
import { Breakpoint } from "@lifesg/react-design-system/theme";
import { useTheme } from "styled-components";
const ExampleComponent = () => {
const theme = useTheme();
const tablet = Breakpoint["lg-max"]({ theme });
const isTablet = useMediaQuery({ maxWidth: tablet });
};V4 usage
In V4, media query hooks are provided out of the box:
import {
Breakpoint,
useSafeMaxWidthMediaQuery,
} from "@lifesg/react-design-system/theme";
const ExampleComponent = () => {
const isTablet = useSafeMaxWidthMediaQuery(Breakpoint["lg-max"]);
};If the actual pixel value is required at runtime:
import { Breakpoint, useDesignToken } from "@lifesg/react-design-system/theme";
import { parsePxOrRemValue } from "@lifesg/react-design-system/theme";
const ExampleComponent = () => {
const tablet = parsePxOrRemValue(useDesignToken(Breakpoint["lg-max"]));
const handleResize = () => {
if (window.innerWidth <= tablet) {
// do something
}
};
};In V4, dark mode is enabled by default. ThemeProvider follows the user's system preference unless a mode is explicitly set.
If your project does not support dark mode, set mode="light" to opt out:
import { ThemeProvider } from "@lifesg/react-design-system/theme";
<ThemeProvider theme="lifesg" mode="light">
{children}
</ThemeProvider>;The Styled Components ThemeProvider should be replaced with the new ThemeProvider from @lifesg/react-design-system/theme.
V3 usage
import { LifeSGTheme } from "@lifesg/react-design-system/theme";
import { ThemeProvider } from "styled-components";
<ThemeProvider theme={LifeSGTheme}>
<Component />
</ThemeProvider>;V4 usage
import { ThemeProvider } from "@lifesg/react-design-system/theme";
<ThemeProvider theme="lifesg">
<Component />
</ThemeProvider>;Import the corresponding theme stylesheet in your entrypoint:
import "@lifesg/react-design-system/theme/styles/lifesg.css";The ThemeSpec object and the overrides and componentOverrides API have been removed in V4.
V3 usage
import { LifeSGTheme, ThemeSpec } from "@lifesg/react-design-system/theme";
import { ThemeProvider } from "styled-components";
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={customTheme}>
<Component />
</ThemeProvider>
);
};The V3 ThemeSpec object can be mapped to the V4 theme prop as follows:
V3 ThemeSpec
|
V4 theme
|
|---|---|
LifeSGTheme |
lifesg |
BookingSGTheme |
bookingsg |
RBSTheme |
rbs |
MyLegacyTheme |
mylegacy |
CCubeTheme |
ccube |
OneServiceTheme |
oneservice |
PATheme |
pa |
A11yPlaygroundTheme |
a11y-playground |
SupportGoWhereTheme |
supportgowhere |
SGWDigitalLobbyTheme |
sgw-digital-lobby |
IMDATheme |
imda |
SPFTheme |
spf |
SMGSTheme |
(not available yet) |
V4 usage
For ad hoc customisation, override CSS variables directly. Choose an approach based on your project's constraints:
-
Option 1: CSS stylesheet — override entire theme
Override the theme globally by targeting the
data-fds-themeattribute set byThemeProvider.[data-fds-theme="lifesg"] { --fds-colour-bg-primary: #0043ce; --fds-colour-text-inverse: #ffffff; } [data-fds-theme="lifesg"][data-fds-theme-mode="dark"] { --fds-colour-bg-primary: #0043ce; --fds-colour-text-inverse: #000000; }
-
Option 2: Inline style
Suitable for dynamic overrides driven by runtime values.
const App = ({ customTheme }) => { return ( <ThemeProvider style={ { "--fds-colour-bg-primary": customTheme.primaryColour, "--fds-colour-text-inverse": "#ffffff", } as React.CSSProperties } > <Component /> </ThemeProvider> ); };
-
Option 3:
useApplyStyleUse this if your project enforces a strict Content Security Policy that disallows inline styles.
import { useRef } from "react"; import { useApplyStyle } from "@lifesg/react-design-system/theme/utils"; const App = ({ customTheme }) => { const themeRef = useRef<HTMLDivElement>(null); useApplyStyle(themeRef, { "--fds-colour-bg-primary": customTheme.primaryColour, "--fds-colour-text-inverse": "#ffffff", }); return ( <ThemeProvider ref={themeRef}> <Component /> </ThemeProvider> ); };
A mapping of V3 design tokens to the corresponding CSS variable is provided in the following sections:
primitiveColour, primitiveColourDark
| V3 | V4 |
|---|---|
brand-10 |
--fds-colour-brand-10 |
brand-20 |
--fds-colour-brand-20 |
brand-30 |
--fds-colour-brand-30 |
brand-40 |
--fds-colour-brand-40 |
brand-50 |
--fds-colour-brand-50 |
brand-60 |
--fds-colour-brand-60 |
brand-70 |
--fds-colour-brand-70 |
brand-80 |
--fds-colour-brand-80 |
brand-90 |
--fds-colour-brand-90 |
brand-95 |
--fds-colour-brand-95 |
brand-100 |
--fds-colour-brand-100 |
primary-10 |
--fds-colour-primary-10 |
primary-20 |
--fds-colour-primary-20 |
primary-30 |
--fds-colour-primary-30 |
primary-40 |
--fds-colour-primary-40 |
primary-50 |
--fds-colour-primary-50 |
primary-60 |
--fds-colour-primary-60 |
primary-70 |
--fds-colour-primary-70 |
primary-80 |
--fds-colour-primary-80 |
primary-90 |
--fds-colour-primary-90 |
primary-95 |
--fds-colour-primary-95 |
primary-100 |
--fds-colour-primary-100 |
secondary-10 |
--fds-colour-secondary-10 |
secondary-20 |
--fds-colour-secondary-20 |
secondary-30 |
--fds-colour-secondary-30 |
secondary-40 |
--fds-colour-secondary-40 |
secondary-50 |
--fds-colour-secondary-50 |
secondary-60 |
--fds-colour-secondary-60 |
secondary-70 |
--fds-colour-secondary-70 |
secondary-80 |
--fds-colour-secondary-80 |
secondary-90 |
--fds-colour-secondary-90 |
secondary-95 |
--fds-colour-secondary-95 |
secondary-100 |
--fds-colour-secondary-100 |
neutral-10 |
--fds-colour-neutral-10 |
neutral-20 |
--fds-colour-neutral-20 |
neutral-30 |
--fds-colour-neutral-30 |
neutral-40 |
--fds-colour-neutral-40 |
neutral-50 |
--fds-colour-neutral-50 |
neutral-60 |
--fds-colour-neutral-60 |
neutral-70 |
--fds-colour-neutral-70 |
neutral-80 |
--fds-colour-neutral-80 |
neutral-90 |
--fds-colour-neutral-90 |
neutral-95 |
--fds-colour-neutral-95 |
neutral-100 |
--fds-colour-neutral-100 |
success-10 |
--fds-colour-success-10 |
success-20 |
--fds-colour-success-20 |
success-30 |
--fds-colour-success-30 |
success-40 |
--fds-colour-success-40 |
success-50 |
--fds-colour-success-50 |
success-60 |
--fds-colour-success-60 |
success-70 |
--fds-colour-success-70 |
success-80 |
--fds-colour-success-80 |
success-90 |
--fds-colour-success-90 |
success-95 |
--fds-colour-success-95 |
success-100 |
--fds-colour-success-100 |
warning-10 |
--fds-colour-warning-10 |
warning-20 |
--fds-colour-warning-20 |
warning-30 |
--fds-colour-warning-30 |
warning-40 |
--fds-colour-warning-40 |
warning-50 |
--fds-colour-warning-50 |
warning-60 |
--fds-colour-warning-60 |
warning-70 |
--fds-colour-warning-70 |
warning-80 |
--fds-colour-warning-80 |
warning-90 |
--fds-colour-warning-90 |
warning-95 |
--fds-colour-warning-95 |
warning-100 |
--fds-colour-warning-100 |
error-10 |
--fds-colour-error-10 |
error-20 |
--fds-colour-error-20 |
error-30 |
--fds-colour-error-30 |
error-40 |
--fds-colour-error-40 |
error-50 |
--fds-colour-error-50 |
error-60 |
--fds-colour-error-60 |
error-70 |
--fds-colour-error-70 |
error-80 |
--fds-colour-error-80 |
error-90 |
--fds-colour-error-90 |
error-95 |
--fds-colour-error-95 |
error-100 |
--fds-colour-error-100 |
info-10 |
--fds-colour-info-10 |
info-20 |
--fds-colour-info-20 |
info-30 |
--fds-colour-info-30 |
info-40 |
--fds-colour-info-40 |
info-50 |
--fds-colour-info-50 |
info-60 |
--fds-colour-info-60 |
info-70 |
--fds-colour-info-70 |
info-80 |
--fds-colour-info-80 |
info-90 |
--fds-colour-info-90 |
info-95 |
--fds-colour-info-95 |
info-100 |
--fds-colour-info-100 |
white |
--fds-colour-white |
black |
--fds-colour-black |
primary-inverse |
--fds-colour-primary-inverse |
semanticColour, semanticColourDark
| V3 | V4 |
|---|---|
text |
--fds-colour-text |
text-subtle |
--fds-colour-text-subtle |
text-subtler |
--fds-colour-text-subtler |
text-subtlest |
--fds-colour-text-subtlest |
text-primary |
--fds-colour-text-primary |
text-primary-strongest |
--fds-colour-text-primary-strongest |
text-hover |
--fds-colour-text-hover |
text-selected |
--fds-colour-text-selected |
text-selected-hover |
--fds-colour-text-selected-hover |
text-disabled |
--fds-colour-text-disabled |
text-disabled-subtle |
--fds-colour-text-disabled-subtle |
text-disabled-subtlest |
--fds-colour-text-disabled-subtlest |
text-selected-disabled |
--fds-colour-text-selected-disabled |
text-success |
--fds-colour-text-success |
text-warning |
--fds-colour-text-warning |
text-error |
--fds-colour-text-error |
text-info |
--fds-colour-text-info |
text-inverse |
--fds-colour-text-inverse |
icon |
--fds-colour-icon |
icon-subtle |
--fds-colour-icon-subtle |
icon-strongest |
--fds-colour-icon-strongest |
icon-primary |
--fds-colour-icon-primary |
icon-primary-subtle |
--fds-colour-icon-primary-subtle |
icon-primary-subtlest |
--fds-colour-icon-primary-subtlest |
icon-hover |
--fds-colour-icon-hover |
icon-selected |
--fds-colour-icon-selected |
icon-selected-hover |
--fds-colour-icon-selected-hover |
icon-disabled |
--fds-colour-icon-disabled |
icon-disabled-subtle |
--fds-colour-icon-disabled-subtle |
icon-selected-disabled |
--fds-colour-icon-selected-disabled |
icon-success |
--fds-colour-icon-success |
icon-warning |
--fds-colour-icon-warning |
icon-error |
--fds-colour-icon-error |
icon-error-strong |
--fds-colour-icon-error-strong |
icon-info |
--fds-colour-icon-info |
icon-inverse |
--fds-colour-icon-inverse |
icon-primary-inverse |
--fds-colour-icon-primary-inverse |
border |
--fds-colour-border |
border-strong |
--fds-colour-border-strong |
border-stronger |
--fds-colour-border-stronger |
border-primary |
--fds-colour-border-primary |
border-primary-subtle |
--fds-colour-border-primary-subtle |
border-hover |
--fds-colour-border-hover |
border-hover-strong |
--fds-colour-border-hover-strong |
border-selected |
--fds-colour-border-selected |
border-selected-subtle |
--fds-colour-border-selected-subtle |
border-selected-subtlest |
--fds-colour-border-selected-subtlest |
border-selected-hover |
--fds-colour-border-selected-hover |
border-focus |
--fds-colour-border-focus |
border-focus-strong |
--fds-colour-border-focus-strong |
border-disabled |
--fds-colour-border-disabled |
border-selected-disabled |
--fds-colour-border-selected-disabled |
border-success |
--fds-colour-border-success |
border-warning |
--fds-colour-border-warning |
border-error |
--fds-colour-border-error |
border-error-focus |
--fds-colour-border-error-focus |
border-error-focus-strong |
--fds-colour-border-error-focus-strong |
border-error-strong |
--fds-colour-border-error-strong |
border-info |
--fds-colour-border-info |
bg |
--fds-colour-bg |
bg-strong |
--fds-colour-bg-strong |
bg-stronger |
--fds-colour-bg-stronger |
bg-strongest |
--fds-colour-bg-strongest |
bg-hover |
--fds-colour-bg-hover |
bg-hover-strong |
--fds-colour-bg-hover-strong |
bg-hover-subtle |
--fds-colour-bg-hover-subtle |
bg-hover-neutral |
--fds-colour-bg-hover-neutral |
bg-hover-neutral-strong |
--fds-colour-bg-hover-neutral-strong |
bg-selected |
--fds-colour-bg-selected |
bg-selected-hover |
--fds-colour-bg-selected-hover |
bg-selected-strong |
--fds-colour-bg-selected-strong |
bg-selected-stronger |
--fds-colour-bg-selected-stronger |
bg-selected-strongest |
--fds-colour-bg-selected-strongest |
bg-selected-strongest-hover |
--fds-colour-bg-selected-strongest-hover |
bg-disabled |
--fds-colour-bg-disabled |
bg-selected-disabled |
--fds-colour-bg-selected-disabled |
bg-selected-stronger-disabled |
--fds-colour-bg-selected-stronger-disabled |
bg-success |
--fds-colour-bg-success |
bg-success-hover |
--fds-colour-bg-success-hover |
bg-success-strong |
--fds-colour-bg-success-strong |
bg-success-strong-hover |
--fds-colour-bg-success-strong-hover |
bg-warning |
--fds-colour-bg-warning |
bg-warning-hover |
--fds-colour-bg-warning-hover |
bg-warning-strong |
--fds-colour-bg-warning-strong |
bg-warning-strong-hover |
--fds-colour-bg-warning-strong-hover |
bg-info |
--fds-colour-bg-info |
bg-info-hover |
--fds-colour-bg-info-hover |
bg-info-strong |
--fds-colour-bg-info-strong |
bg-info-strong-hover |
--fds-colour-bg-info-strong-hover |
bg-error |
--fds-colour-bg-error |
bg-error-hover |
--fds-colour-bg-error-hover |
bg-error-strong |
--fds-colour-bg-error-strong |
bg-error-strong-hover |
--fds-colour-bg-error-strong-hover |
bg-inverse |
--fds-colour-bg-inverse |
bg-inverse-subtle |
--fds-colour-bg-inverse-subtle |
bg-inverse-subtler |
--fds-colour-bg-inverse-subtler |
bg-inverse-subtlest |
--fds-colour-bg-inverse-subtlest |
bg-inverse-hover |
--fds-colour-bg-inverse-hover |
bg-primary |
--fds-colour-bg-primary |
bg-primary-subtle |
--fds-colour-bg-primary-subtle |
bg-primary-subtler |
--fds-colour-bg-primary-subtler |
bg-primary-subtlest |
--fds-colour-bg-primary-subtlest |
bg-available |
--fds-colour-bg-available |
bg-primary-hover |
--fds-colour-bg-primary-hover |
bg-primary-subtlest-hover |
--fds-colour-bg-primary-subtlest-hover |
bg-primary-subtlest-selected |
--fds-colour-bg-primary-subtlest-selected |
overlay-strong |
--fds-colour-overlay-strong |
overlay-subtle |
--fds-colour-overlay-subtle |
hyperlink |
--fds-colour-hyperlink |
hyperlink-hover |
--fds-colour-hyperlink-hover |
hyperlink-visited |
--fds-colour-hyperlink-visited |
hyperlink-inverse |
--fds-colour-hyperlink-inverse |
focus-ring |
--fds-colour-focus-ring |
focus-ring-inverse |
--fds-colour-focus-ring-inverse |
fontSpec
| V3 | V4 |
|---|---|
heading-size-xxl |
--fds-font-heading-size-xxl |
heading-size-xl |
--fds-font-heading-size-xl |
heading-size-lg |
--fds-font-heading-size-lg |
heading-size-md |
--fds-font-heading-size-md |
heading-size-sm |
--fds-font-heading-size-sm |
heading-size-xs |
--fds-font-heading-size-xs |
heading-lh-xxl |
--fds-font-heading-lh-xxl |
heading-lh-xl |
--fds-font-heading-lh-xl |
heading-lh-lg |
--fds-font-heading-lh-lg |
heading-lh-md |
--fds-font-heading-lh-md |
heading-lh-sm |
--fds-font-heading-lh-sm |
heading-lh-xs |
--fds-font-heading-lh-xs |
heading-ls-xxl |
--fds-font-heading-ls-xxl |
heading-ls-xl |
--fds-font-heading-ls-xl |
heading-ls-lg |
--fds-font-heading-ls-lg |
heading-ls-md |
--fds-font-heading-ls-md |
heading-ls-sm |
--fds-font-heading-ls-sm |
heading-ls-xs |
--fds-font-heading-ls-xs |
weight-light |
--fds-font-weight-light |
weight-regular |
--fds-font-weight-regular |
weight-semibold |
--fds-font-weight-semibold |
weight-bold |
--fds-font-weight-bold |
font-family |
Removed |
heading-font-family |
--fds-font-family-heading |
body-font-family |
--fds-font-family-body |
body-size-baseline |
--fds-font-body-size-baseline |
body-size-md |
--fds-font-body-size-md |
body-size-sm |
--fds-font-body-size-sm |
body-size-xs |
--fds-font-body-size-xs |
body-lh-baseline |
--fds-font-body-lh-baseline |
body-lh-md |
--fds-font-body-lh-md |
body-lh-sm |
--fds-font-body-lh-sm |
body-lh-xs |
--fds-font-body-lh-xs |
body-ls-baseline |
--fds-font-body-ls-baseline |
body-ls-md |
--fds-font-body-ls-md |
body-ls-sm |
--fds-font-body-ls-sm |
body-ls-xs |
--fds-font-body-ls-xs |
form-label-size |
--fds-font-form-label-size |
form-description-size |
--fds-font-form-description-size |
form-label-lh |
--fds-font-form-label-lh |
form-description-lh |
--fds-font-form-description-lh |
form-label-ls |
--fds-font-form-label-ls |
form-description-ls |
--fds-font-form-description-ls |
| - | --fds-font-variant |
font
fontSpec
breakpoint
| V3 | V4 |
|---|---|
xxs-min |
--fds-breakpoint-xxs-min |
xxs-max |
--fds-breakpoint-xxs-max |
xs-min |
--fds-breakpoint-xs-min |
xs-max |
--fds-breakpoint-xs-max |
sm-min |
--fds-breakpoint-sm-min |
sm-max |
--fds-breakpoint-sm-max |
md-min |
--fds-breakpoint-md-min |
md-max |
--fds-breakpoint-md-max |
lg-min |
--fds-breakpoint-lg-min |
lg-max |
--fds-breakpoint-lg-max |
xl-min |
--fds-breakpoint-xl-min |
xl-max |
--fds-breakpoint-xl-max |
xxl-min |
--fds-breakpoint-xxl-min |
xxs-column |
--fds-breakpoint-column-xxs |
xs-column |
--fds-breakpoint-column-xs |
sm-column |
--fds-breakpoint-column-sm |
md-column |
--fds-breakpoint-column-md |
lg-column |
--fds-breakpoint-column-lg |
xl-column |
--fds-breakpoint-column-xl |
xxl-column |
--fds-breakpoint-column-xxl |
xxs-gutter |
--fds-breakpoint-gutter-xxs |
xs-gutter |
--fds-breakpoint-gutter-xs |
sm-gutter |
--fds-breakpoint-gutter-sm |
md-gutter |
--fds-breakpoint-gutter-md |
lg-gutter |
--fds-breakpoint-gutter-lg |
xl-gutter |
--fds-breakpoint-gutter-xl |
xxl-gutter |
--fds-breakpoint-gutter-xxl |
xxs-margin |
--fds-breakpoint-margin-xxs |
xs-margin |
--fds-breakpoint-margin-xs |
sm-margin |
--fds-breakpoint-margin-sm |
md-margin |
--fds-breakpoint-margin-md |
lg-margin |
--fds-breakpoint-margin-lg |
xl-margin |
--fds-breakpoint-margin-xl |
xxl-margin |
--fds-breakpoint-margin-xxl |
motion
| V3 | V4 |
|---|---|
duration-150 |
--fds-motion-duration-150 |
duration-250 |
--fds-motion-duration-250 |
duration-350 |
--fds-motion-duration-350 |
duration-500 |
--fds-motion-duration-500 |
duration-800 |
--fds-motion-duration-800 |
duration-1000 |
--fds-motion-duration-1000 |
ease-default |
--fds-motion-timing-ease-default |
ease-standard |
--fds-motion-timing-ease-standard |
ease-entrance |
--fds-motion-timing-ease-entrance |
ease-exit |
--fds-motion-timing-ease-exit |
spacing
| V3 | V4 |
|---|---|
spacing-0 |
--fds-spacing-0 |
spacing-4 |
--fds-spacing-4 |
spacing-8 |
--fds-spacing-8 |
spacing-12 |
--fds-spacing-12 |
spacing-16 |
--fds-spacing-16 |
spacing-20 |
--fds-spacing-20 |
spacing-24 |
--fds-spacing-24 |
spacing-32 |
--fds-spacing-32 |
spacing-40 |
--fds-spacing-40 |
spacing-48 |
--fds-spacing-48 |
spacing-64 |
--fds-spacing-64 |
spacing-72 |
--fds-spacing-72 |
layout-xs |
--fds-layout-xs |
layout-sm |
--fds-layout-sm |
layout-md |
--fds-layout-md |
layout-lg |
--fds-layout-lg |
layout-xl |
--fds-layout-xl |
layout-xxl |
--fds-layout-xxl |
layout-xxxl |
--fds-layout-xxxl |
border
| V3 | V4 |
|---|---|
width-005 |
--fds-border-width-005 |
width-010 |
--fds-border-width-010 |
width-020 |
--fds-border-width-020 |
width-040 |
--fds-border-width-040 |
solid |
--fds-border-style-solid |
radius
| V3 | V4 |
|---|---|
none |
--fds-radius-none |
xs |
--fds-radius-xs |
sm |
--fds-radius-sm |
md |
--fds-radius-md |
lg |
--fds-radius-lg |
full |
--fds-radius-full |
shadow
| V3 | V4 |
|---|---|
xs-subtle |
--fds-shadow-xs-subtle |
xs-strong |
--fds-shadow-xs-strong |
xs-focus-strong |
--fds-shadow-xs-focus-strong |
xs-error-strong |
--fds-shadow-xs-error-strong |
sm-subtle |
--fds-shadow-sm-subtle |
sm-strong |
--fds-shadow-sm-strong |
md-subtle |
--fds-shadow-md-subtle |
md-strong |
--fds-shadow-md-strong |
lg-subtle |
--fds-shadow-lg-subtle |
lg-strong |
--fds-shadow-lg-strong |
resourceScheme
Button
| V3 | V4 |
|---|---|
button-radius |
--fds-button-radius |
button-default-colour-bg |
--fds-button-default-colour-bg |
button-default-colour-bg-hover |
--fds-button-default-colour-bg-hover |
button-default-colour-text |
--fds-button-default-colour-text |
button-secondary-colour-border |
--fds-button-secondary-colour-border |
button-secondary-colour-text |
--fds-button-secondary-colour-text |
button-light-colour-text |
--fds-button-light-colour-text |
button-link-colour-text |
--fds-button-link-colour-text |
Animation
| V3 | V4 |
|---|---|
loading-dots-spinner-colour |
--fds-animation-loading-dots-spinner-colour |
Navbar
| V3 | V4 |
|---|---|
navbar-full-height |
--fds-navbar-full-height |
navbar-full-logo-height |
--fds-navbar-full-logo-height |
navbar-compressed-height |
--fds-navbar-compressed-height |
navbar-compressed-logo-height |
--fds-navbar-compressed-logo-height |
navbar-mobile-height |
--fds-navbar-mobile-height |
navbar-mobile-logo-height |
--fds-navbar-mobile-logo-height |
navbar-colour-bg |
--fds-navbar-colour-bg |
navbar-colour-icon |
--fds-navbar-colour-icon |
navbar-link-colour-text |
--fds-navbar-link-colour-text |
navbar-link-colour-text-hover |
--fds-navbar-link-colour-text-hover |
navbar-link-colour-text-selected-hover |
--fds-navbar-link-colour-text-selected-hover |
Footer
| V3 | V4 |
|---|---|
footer-colour-bg |
--fds-footer-colour-bg |
footer-colour-text |
--fds-footer-colour-text |
footer-link-colour-text |
--fds-footer-link-colour-text |
footer-link-colour-text-hover |
--fds-footer-link-colour-text-hover |
footer-disclaimer-link-colour-text |
--fds-footer-disclaimer-link-colour-text |
footer-disclaimer-link-colour-text-hover |
--fds-footer-disclaimer-link-colour-text-hover |
V4 restricts imports to the root @lifesg/react-design-system or pre-defined subpath entrypoints i.e. @lifesg/react-design-system/<component>. Internal file paths that were previously accessible (e.g. deep imports into @lifesg/react-design-system/<component>/*) are no longer reachable.
If you were importing a type directly from an internal path, update it to use the nearest public entrypoint instead:
- import type { AlertProps } from "@lifesg/react-design-system/alert/types";
+ import type { AlertProps } from "@lifesg/react-design-system/alert";If the type you need is not yet exported from any public entrypoint, raise a PR to expose it.
Modules under the following paths have been removed:
@lifesg/react-design-system/v2_color@lifesg/react-design-system/v2_design-token@lifesg/react-design-system/v2_layout@lifesg/react-design-system/v2_media@lifesg/react-design-system/v2_spec@lifesg/react-design-system/v2_text-list@lifesg/react-design-system/v2_text@lifesg/react-design-system/v2_theme@lifesg/react-design-system/v2_transition
Border.Util has been removed. For dashed border styling, use the DashedBorder utility component instead.
V3 usage
Border.Util["dashed-default"] could be applied directly in Styled Components declarations.
import { Border } from "@lifesg/react-design-system/theme";
const ExampleComponent = styled.div`
${Border.Util["dashed-default"]({
radius: Radius["sm"],
thickness: Border["width-040"],
colour: Colour["border"],
})}
`;V4 usage
A generic utility component is provided.
import { DashedBorder } from "@lifesg/react-design-system/dashed-border";
<DashedBorder
radius={Radius["sm"]}
thickness={Border["width-040"]}
colour={Colour["border"]}
>
{/* original children here */}
</DashedBorder>;Button.Default, Button.Small and Button.Large have been deprecated. Use Button with the sizeType prop instead.
- <Button.Large>Click me</Button.Large>
- <Button.Small>Click me</Button.Small>
- <Button.Default>Click me</Button.Default>
+ <Button sizeType="large">Click me</Button>
+ <Button sizeType="small">Click me</Button>
+ <Button>Click me</Button>| Deprecated |
sizeType value |
|---|---|
Button.Large |
large |
Button.Small |
small |
Button.Default |
default (or omit) |
ButtonWithIcon has been merged into Button. Update the import and replace the component.
- import { ButtonWithIcon } from "@lifesg/react-design-system/button-with-icon";
+ import { Button } from "@lifesg/react-design-system/button";
- <ButtonWithIcon icon={<Icon />}>Label</ButtonWithIcon>
+ <Button icon={<Icon />}>Label</Button>The V2 desktopCols, tabletCols and mobileCols props have been removed. Switch to the V3 xxsCols - xlCols.
Refer to the Layout section in the V3 migration docs for more information.
DSThemeProvider has been removed. Replace with the new ThemeProvider. See ThemeProvider.
ErrorDisplay.ImagePathAttributes has been renamed to ErrorDisplayImagePathAttributes.
- import { ErrorDisplay } from "@lifesg/react-design-system/error-display";
- type MyProps = ErrorDisplay.ImagePathAttributes;
+ import { ErrorDisplayImagePathAttributes } from "@lifesg/react-design-system/error-display";
+ type MyProps = ErrorDisplayImagePathAttributes;The disabled prop is unused and has been removed.
The disabled prop is unused and has been removed.
IconButton has been merged into Button. Update the import and replace the component.
- import { IconButton } from "@lifesg/react-design-system/icon-button";
+ import { Button } from "@lifesg/react-design-system/button";
- <IconButton icon={<Icon />} />
+ <Button icon={<Icon />} />The underlying baseTextSize prop type has been moved from the internal TypographySizeType to FontSize.
- import type { TypographySizeType } from "@lifesg/react-design-system/theme/font/types";
+ import type { FontSize } from "@lifesg/react-design-system/theme";The accepted values are unchanged:
"heading-xxl" | "heading-xl" | "heading-lg" | "heading-md" | "heading-sm" | "heading-xs"
| "body-baseline" | "body-md" | "body-sm" | "body-xs"
This deprecated module has been removed.
The deprecated components have been replaced with the V2 implementation, which offers improved positioning and easier usage.
Codemod
A codemod is available to migrate to the new Popover.
$ npx lifesg-react-design-system
Select codemods to run:
❯◉ migrate-popoverThis version is now the default implementation and the import path has been updated:
- import { PopoverTrigger } from "@lifesg/react-design-system/popover-v2";
+ import { PopoverTrigger } from "@lifesg/react-design-system/popover";The following interfaces have been renamed:
| Old | New |
|---|---|
| PopoverV2 | Popover |
| PopoverV2Props | PopoverProps |
| PopoverV2TriggerType | PopoverTriggerType |
| PopoverV2Position | PopoverPosition |
| PopoverV2TriggerProps | PopoverTriggerProps |
Codemod
A codemod is available to update the imports.
$ npx lifesg-react-design-system
Select codemods to run:
❯◉ migrate-popoverThe underlying size prop type has been moved from the internal TypographySizeType to TextListSize.
- import type { TypographySizeType } from "@lifesg/react-design-system/theme/font/types";
+ import type { TextListSize } from "@lifesg/react-design-system/text-list";The accepted values are unchanged:
"heading-xxl" | "heading-xl" | "heading-lg" | "heading-md" | "heading-sm" | "heading-xs"
| "body-baseline" | "body-md" | "body-sm" | "body-xs"
This deprecated module has been removed.
If you are using Styled Components v5, upgrade to v6