Post

Theme with styled-components and TypeScript

Project 를 진행하면서 styled-components package와 TypeScript 를 이용한 theme 설정하는 방법에 대해 정리한다.

Installation

1
$ npm install @types/styled-components

Style Declaration

Create styled.d.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import "styled-components";
interface IPalette {
  main: string;
  contrast: string;
}
declare module "styled-components" {
  export interface DefaultTheme {
    backgroundColor: string;
    textColor: string;
    primary: IPalette;
    secondary: IPalette;
    common: {
      black: string;
      white: string;
    };
  }
}

Create a theme

Create theme.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import { DefaultTheme } from "styled-components";
export const defaultTheme: DefaultTheme = {
  backgroundColor: "white",
  textColor: "black",
  common: {
    black: "black",
    white: "white",
  },
  primary: {
    main: "blue",
    contrast: "orange",
  },
  secondary: {
    main: "green",
    contrast: "brown",
  },
};

export const lightTheme = {
  backgroundColor: "white",
  textColor: "black",
  common: {
    black: "black",
    white: "white",
  },
  primary: {
    main: "blue",
    contrast: "orange",
  },
  secondary: {
    main: "green",
    contrast: "brown",
  },
};

export const darkTheme = {
  backgroundColor: "darkgray",
  textColor: "white",
  common: {
    black: "black",
    white: "white",
  },
  primary: {
    main: "lightblue",
    contrast: "orange",
  },
  secondary: {
    main: "lightgreen",
    contrast: "brown",
  },
};

Theme Provider

In App.tsx

Apollo client 에서 반응형 변수 (Reactive variable) 을 사용하여 theme 의 상태를 정한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { ThemeProvider } from "styled-components";
import { darkTheme, lightTheme } from "./theme";

export default function App() {
  (...)
  const isDarkMode = useReactiveVar(isDarkModeVar);
  const preloadAssets = () => {
    (...)
  };
  const preload = async () => {
    (...)
    const theme = await AsyncStorage.getItem("darkMode");
    if (theme) {
      isDarkModeVar(true);
    }
    return preloadAssets();
  };

  return (
    <ThemeProvider theme={isDarkMode ? lightTheme : darkTheme}>
      <NavigationContainer>
        {isLoggedIn ? <LoggedInNav /> : <LoggedOutNav />}
      </NavigationContainer>
    </ThemeProvider>
  );
}

Use theme from Components

  1. Using styled-components

    1
    2
    3
    
    const Container = styled.View`
      background-color: ${(props) => props.theme.backgroundColor};
    `;
    
  2. Add theme on render

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    import { useTheme } from "styled-components";
    const Card = () => {
      const theme = useTheme();
      return (
        <View>
          <Text style={{ color: theme.textColor }}>Test String</Text>
        </View>
      );
    };
    export default Card;
    

References:

This post is licensed under CC BY 4.0 by the author.