1# Configuring In-Application Theme Skinning
2
3## Overview
4
5For applications developed with ArkTS, you can switch themes within the application, such as toggling between dark and light modes or changing the skin. Note that this feature is limited to in-application use and does not apply at the UIAbility or window level. It is not available for the C-API and Node-API.
6
7## Customizing Theme Colors
8To implement theme skinning for your application, you must define custom theme colors. Use [CustomTheme](../reference/apis-arkui/js-apis-arkui-theme.md#customtheme) to specify the colors you wish to modify. Properties of **CustomTheme** are optional: Only overridden properties are applied, and the rest inherits from the system's default settings. For details, see [System Default Token Color Values](#system-default-token-color-values). The following is an example of how to define custom theme colors:
9
10  ```ts
11    import { CustomColors, CustomTheme } from '@kit.ArkUI'
12
13    export class AppColors implements CustomColors {
14      // Custom theme colors
15      brand: ResourceColor = '#FF75D9';
16    }
17
18    export class AppTheme implements CustomTheme {
19      public colors: AppColors = new AppColors()
20    }
21
22    export let gAppTheme: CustomTheme = new AppTheme()
23  ```
24
25## Setting Custom Theme Colors for Application Components
26- To apply custom theme colors to your application components, set them at the page entry point. Ensure that [ThemeControl](../reference/apis-arkui/js-apis-arkui-theme.md#themecontrol) is executed before the page is built.
27  Use the [onWillApplyTheme](../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onwillapplytheme12) callback function to allow custom components to access the currently active **Theme** object.
28
29  ```ts
30    import { Theme, ThemeControl } from '@kit.ArkUI'
31    import { gAppTheme } from './AppTheme'
32
33    // Execute ThemeControl before the page builds.
34    ThemeControl.setDefaultTheme(gAppTheme)
35
36    @Entry
37    @Component
38    struct DisplayPage {
39      @State menuItemColor: ResourceColor = $r('sys.color.background_primary')
40
41      onWillApplyTheme(theme: Theme) {
42        this.menuItemColor = theme.colors.backgroundPrimary;
43      }
44
45      build() {
46        Column() {
47          List({ space: 10 }) {
48            ListItem() {
49              Column({ space: '5vp' }) {
50                Text('Color mode')
51                  .margin({ top: '5vp', left: '14fp' })
52                  .width('100%')
53                Row() {
54                  Column() {
55                    Text('Light')
56                      .fontSize('16fp')
57                      .textAlign(TextAlign.Start)
58                      .alignSelf(ItemAlign.Center)
59                    Radio({ group: 'light or dark', value: 'light' })
60                      .checked(true)
61                  }
62                  .width('50%')
63
64                  Column() {
65                    Text('Dark')
66                      .fontSize('16fp')
67                      .textAlign(TextAlign.Start)
68                      .alignSelf(ItemAlign.Center)
69                    Radio({ group: 'light or dark', value: 'dark' })
70                  }
71                  .width('50%')
72                }
73              }
74              .width('100%')
75              .height('90vp')
76              .borderRadius('10vp')
77              .backgroundColor(this.menuItemColor)
78            }
79
80            ListItem() {
81              Column() {
82                Text('Brightness')
83                  .width('100%')
84                  .margin({ top: '5vp', left: '14fp' })
85                Slider({ value: 40, max: 100 })
86              }
87              .width('100%')
88              .height('70vp')
89              .borderRadius('10vp')
90              .backgroundColor(this.menuItemColor)
91            }
92
93            ListItem() {
94              Column() {
95                Row() {
96                  Column({ space: '5vp' }) {
97                    Text('Touch sensitivity')
98                      .fontSize('16fp')
99                      .textAlign(TextAlign.Start)
100                      .width('100%')
101                    Text('Increase the touch sensitivity of your screen' +
102                      ' for use with screen protectors')
103                      .fontSize('12fp')
104                      .fontColor(Color.Blue)
105                      .textAlign(TextAlign.Start)
106                      .width('100%')
107                  }
108                  .alignSelf(ItemAlign.Center)
109                  .margin({ left: '14fp' })
110                  .width('75%')
111
112                  Toggle({ type: ToggleType.Switch, isOn: true })
113                    .margin({ right: '14fp' })
114                    .alignSelf(ItemAlign.Center)
115                }
116                .width('100%')
117                .height('80vp')
118              }
119              .width('100%')
120              .borderRadius('10vp')
121              .backgroundColor(this.menuItemColor)
122            }
123          }
124        }
125        .padding('10vp')
126        .backgroundColor('#dcdcdc')
127        .width('100%')
128        .height('100%')
129      }
130    }
131  ```
132
133- To set [ThemeControl](../reference/apis-arkui/js-apis-arkui-theme.md#themecontrol) in a UIAbility, you need to use [setDefaultTheme](../reference/apis-arkui/js-apis-arkui-theme.md#setdefaulttheme) in the **onWindowStageCreate()** API.
134
135  ```ts
136    import {AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
137    import { hilog } from '@kit.PerformanceAnalysisKit';
138    import { window, CustomColors, ThemeControl } from '@kit.ArkUI';
139
140    class AppColors implements CustomColors {
141      fontPrimary = 0xFFD53032
142      iconOnPrimary = 0xFFD53032
143      iconFourth = 0xFFD53032
144    }
145
146    const abilityThemeColors = new AppColors();
147
148    export default class EntryAbility extends UIAbility {
149      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
150        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
151      }
152
153      onDestroy() {
154        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
155      }
156
157      onWindowStageCreate(windowStage: window.WindowStage) {
158        // The main window is created. Set a main page for this ability.
159        hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
160
161        windowStage.loadContent('pages/Index', (err, data) => {
162          if (err.code) {
163            hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
164            return;
165          }
166          hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
167          // Call setDefaultTheme in the onWindowStageCreate() API.
168          ThemeControl.setDefaultTheme({ colors: abilityThemeColors })
169          hilog.info(0x0000, 'testTag', '%{public}s', 'ThemeControl.setDefaultTheme done');
170        });
171      }
172
173    }
174  ```
175
176![systemTheme](figures/systemTheme.png)
177
178> **NOTE**
179>
180>If the parameter for **setDefaultTheme** is undefined, the default value is used. See [System Default Token Color Values](#system-default-token-color-values) for the default color values associated with the tokens.
181
182## Setting a Custom Theme Style for Specific Application Pages
183Use [WithTheme](../reference/apis-arkui/arkui-ts/ts-container-with-theme.md) to apply the color scheme of a custom theme to the default styles of components within the scope This way, the colors of components within the **WithTheme** scope align with the theme's color scheme.
184
185In the example below, components within the scope are styled with a custom theme using **WithTheme({ theme: this.myTheme })**. You can switch to a different theme style by updating **this.myTheme**. The [onWillApplyTheme](../reference/apis-arkui/arkui-ts/ts-custom-component-lifecycle.md#onwillapplytheme12) callback function allows custom components to access the currently active **Theme** object.
186
187  ```ts
188    import { CustomColors, CustomTheme, Theme } from '@kit.ArkUI'
189
190    class AppColors implements CustomColors {
191      fontPrimary: ResourceColor = $r('app.color.brand_purple')
192      backgroundEmphasize: ResourceColor = $r('app.color.brand_purple')
193    }
194
195    class AppColorsSec implements CustomColors {
196      fontPrimary: ResourceColor = $r('app.color.brand')
197      backgroundEmphasize: ResourceColor = $r('app.color.brand')
198    }
199
200    class AppTheme implements CustomTheme {
201      public colors: AppColors = new AppColors()
202    }
203
204    class AppThemeSec implements CustomTheme {
205      public colors: AppColors = new AppColorsSec()
206    }
207
208    @Entry
209    @Component
210    struct DisplayPage {
211      @State customTheme: CustomTheme = new AppTheme()
212      @State message: string = 'Set a custom theme style for specific pages'
213      count = 0;
214
215      build() {
216        WithTheme({ theme: this.customTheme }) {
217          Row(){
218            Column() {
219              Text('WithTheme')
220                .fontSize(30)
221                .margin({bottom: 10})
222              Text(this.message)
223                .margin({bottom: 10})
224              Button('Change Theme').onClick(() => {
225                this.count++;
226                if (this.count > 1) {
227                  this.count = 0;
228                }
229                switch (this.count) {
230                  case 0:
231                    this.customTheme = new AppTheme();
232                    break;
233                  case 1:
234                    this.customTheme = new AppThemeSec();
235                    break;
236                }
237              })
238            }
239            .width('100%')
240          }
241          .height('100%')
242          .width('100%')
243        }
244      }
245    }
246  ```
247
248![customTheme](figures/customTheme.gif)
249
250## Setting the Color Mode for Application Pages
251Use [WithTheme](../reference/apis-arkui/arkui-ts/ts-container-with-theme.md) to set the color mode.
252
253Within the **WithTheme** scope, component styles adapt to the specified color mode by accessing the corresponding system and application resource values. This means that the color schemes of components are adjusted according to the chosen color mode.
254
255In the example below, components within the scope are set to dark mode using **WithTheme({ colorMode: ThemeColorMode.DARK })**.
256
257For the light and dark modes to take effect, add a **dark.json** resource file.
258
259![resources_dark](figures/resources_dark.png)
260
261Example of the **dark.json** file content:
262  ```ts
263    {
264      "color": [
265        {
266          "name": "start_window_background",
267          "value": "#FFFFFF"
268        }
269      ]
270    }
271  ```
272
273  ```ts
274    @Entry
275    @Component
276    struct DisplayPage {
277      @State message: string = 'Hello World';
278      @State colorMode: ThemeColorMode = ThemeColorMode.DARK;
279
280      build() {
281        WithTheme({ colorMode: this.colorMode }) {
282          Row() {
283            Column() {
284              Text(this.message)
285                .fontSize(50)
286                .fontWeight(FontWeight.Bold)
287              Button('Switch ColorMode').onClick(() => {
288                if (this.colorMode === ThemeColorMode.LIGHT) {
289                  this.colorMode = ThemeColorMode.DARK;
290                } else if (this.colorMode === ThemeColorMode.DARK) {
291                  this.colorMode = ThemeColorMode.LIGHT;
292                }
293              })
294            }
295            .width('100%')
296          }
297          .backgroundColor($r('sys.color.background_primary'))
298          .height('100%')
299          .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.END, SafeAreaEdge.BOTTOM, SafeAreaEdge.START])
300        }
301      }
302    }
303  ```
304
305![lightDarkMode](figures/lightDarkMode.png)
306
307## System Default Token Color Values
308
309| Token                                      | Category| Light |           | Dark    |                                              |
310|--------------------------------------------|-----| --- |-----------| ------- | -------------------------------------------- |
311| theme.colors.brand                         | Brand color.|#ff0a59f7| ![](figures/ff0a59f7.png "#ff0a59f7") |#ff317af7|![](figures/ff317af7.png "#ff317af7")|
312| theme.colors.warning                       | Alert color.|#ffe84026| ![](figures/ffe84026.png "#ffe84026") |#ffd94838|![](figures/ffd94838.png "#ffd94838")|
313| theme.colors.alert                         | Warning color.|#ffed6f21| ![](figures/ffed6f21.png "#ffed6f21") |#ffdb6b42|![](figures/ffdb6b42.png "#ffdb6b42")|
314| theme.colors.confirm                       | Confirmation color.|#ff64bb5c| ![](figures/ff64bb5c.png "#ff64bb5c") |#ff5ba854|![](figures/ff5ba854.png "#ff5ba854")|
315| theme.colors.fontPrimary                   | Primary text color.| #e5000000 | ![](figures/e5000000.png "#e5000000") |#e5ffffff|![](figures/e5ffffff.png "#e5ffffff")|
316| theme.colors.fontSecondary                 | Secondary text color.| #99000000 | ![](figures/99000000.png "#99000000") |#99ffffff|![](figures/99ffffff.png "#99ffffff")|
317| theme.colors.fontTertiary                  | Tertiary text color.| #66000000 | ![](figures/66000000.png "#66000000") |#66ffffff|![](figures/66ffffff.png "#66ffffff")|
318| theme.colors.fontFourth                    | Quaternary text color.| #33000000 | ![](figures/33000000.png "#33000000") |#33ffffff|![](figures/33ffffff.png "#33ffffff")|
319| theme.colors.fontEmphasize                 | Highlight text color.| #ff0a59f7 | ![](figures/ff0a59f7.png "#ff0a59f7") |#ff317af7|![](figures/ff317af7.png "#ff317af7")|
320| theme.colors.fontOnPrimary                 | Primary text invert color.| #ffffffff | ![](figures/ffffffff.png "#ffffffff") |#ff000000|![](figures/ff000000.png "#ff000000")|
321| theme.colors.fontOnSecondary               | Secondary text invert color.| #99ffffff | ![](figures/99ffffff.png "#99ffffff") |#99000000|![](figures/99000000.png "#99000000")|
322| theme.colors.fontOnTertiary                | Tertiary text invert color.| #66ffffff | ![](figures/66ffffff.png "#66ffffff") |#66000000|![](figures/66000000.png "#66000000")|
323| theme.colors.fontOnFourth                  | Quaternary text invert color.| #33ffffff | ![](figures/33ffffff.png "#33ffffff") |#33000000|![](figures/33000000.png "#33000000")|
324| theme.colors.iconPrimary                   | Primary icon color.| #e5000000 | ![](figures/e5000000.png "#e5000000") |#e5ffffff|![](figures/e5ffffff.png "#e5ffffff")|
325| theme.colors.iconSecondary                 | Secondary icon color.| #99000000 | ![](figures/99000000.png "#99000000") |#99ffffff|![](figures/99ffffff.png "#99ffffff")|
326| theme.colors.iconTertiary                  | Tertiary icon color.| #66000000 | ![](figures/66000000.png "#66000000") |#66ffffff|![](figures/66ffffff.png "#66ffffff")|
327| theme.colors.iconFourth                    | Quaternary icon color.| #33000000 | ![](figures/33000000.png "#33000000") |#33ffffff|![](figures/33ffffff.png "#33ffffff")|
328| theme.colors.iconEmphasize                 | Emphasis icon color.| #ff0a59f7 | ![](figures/ff0a59f7.png "#ff0a59f7") |#ff317af7|![](figures/ff317af7.png "#ff317af7")|
329| theme.colors.iconSubEmphasize              | Emphasis auxiliary icon color.| #660a59f7 | ![](figures/660a59f7.png "#660a59f7") |#66317af7|![](figures/66317af7.png "#66317af7")|
330| theme.colors.iconOnPrimary                 | Primary icon invert color.| #ffffffff | ![](figures/ffffffff.png "#ffffffff") |#ff000000|![](figures/ff000000.png "#ff000000")|
331| theme.colors.iconOnSecondary               | Secondary icon invert color.| #99ffffff | ![](figures/99ffffff.png "#99ffffff") |#99000000|![](figures/99000000.png "#99000000")|
332| theme.colors.iconOnTertiary                | Tertiary icon invert color.| #66ffffff | ![](figures/66ffffff.png "#66ffffff") |#66000000|![](figures/66000000.png "#66000000")|
333| theme.colors.iconOnFourth                  | Quaternary icon invert color.| #33ffffff | ![](figures/33ffffff.png "#33ffffff") |#33000000|![](figures/33000000.png "#33000000")|
334| theme.colors.backgroundPrimary             | Primary background color (solid, opaque).| #ffffffff | ![](figures/ffffffff.png "#ffffffff") |#ffe5e5e5|![](figures/ffe5e5e5.png "#ffe5e5e5")|
335| theme.colors.backgroundSecondary           | Secondary background color (solid, opaque).| #fff1f3f5 | ![](figures/fff1f3f5.png "#fff1f3f5") |#ff191a1c|![](figures/ff191a1c.png "#ff191a1c")|
336| theme.colors.backgroundTertiary            | Tertiary background color (solid, opaque).| #ffe5e5ea | ![](figures/ffe5e5ea.png "#ffe5e5ea") |#ff202224|![](figures/ff202224.png "#ff202224")|
337| theme.colors.backgroundFourth              | Quaternary background color (solid, opaque).| #ffd1d1d6 | ![](figures/ffd1d1d6.png "#ffd1d1d6") |#ff2e3033|![](figures/ff2e3033.png "#ff2e3033")|
338| theme.colors.backgroundEmphasize           | Emphasis background color (solid, opaque).| #ff0a59f7 | ![](figures/ff0a59f7.png "#ff0a59f7") |#ff317af7|![](figures/ff317af7.png "#ff317af7")|
339| theme.colors.compForegroundPrimary         | Foreground.| #ff000000 | ![](figures/ff000000.png "#ff000000") | #ffe5e5e5 |![](figures/ffe5e5e5.png "#ffe5e5e5")|
340| theme.colors.compBackgroundPrimary         | White background.| #ffffffff |![](figures/ffffffff.png "#ffffffff")| #ffffffff |![](figures/ffffffff.png "#ffffffff")|
341| theme.colors.compBackgroundPrimaryTran     | White transparent background.| #ffffffff |![](figures/ffffffff.png "#ffffffff")| #33ffffff |![](figures/33ffffff.png "#33ffffff")|
342| theme.colors.compBackgroundPrimaryContrary | Always-on background.| #ffffffff |![](figures/ffffffff.png "#ffffffff")| #ffe5e5e5 |![](figures/ffe5e5e5.png "#ffe5e5e5")|
343| theme.colors.compBackgroundGray            | Gray background.| #fff1f3f5 |![](figures/fff1f3f5.png "#fff1f3f5")| #ffe5e5ea |![](figures/ffe5e5ea.png "#ffe5e5ea")|
344| theme.colors.compBackgroundSecondary       | Secondary background.| #19000000 |![](figures/19000000.png "#19000000")| #19ffffff |![](figures/19ffffff.png "#19ffffff")|
345| theme.colors.compBackgroundTertiary        | Tertiary background.| #0c000000 |![](figures/0c000000.png "#0c000000")| #0cffffff |![](figures/0cffffff.png "#0cffffff")|
346| theme.colors.compBackgroundEmphasize       | Emphasis background.| #ff0a59f7 |![](figures/ff0a59f7.png "#ff0a59f7")| #ff317af7 |![](figures/ff317af7.png "#ff317af7")|
347| theme.colors.compBackgroundNeutral         | Black, neutral, emphasis background.| #ff000000 |![](figures/ff000000.png "#ff000000")| #ffffffff |![](figures/ffffffff.png "#ffffffff")|
348| theme.colors.compEmphasizeSecondary        | 20% emphasis background.| #330a59f7 |![](figures/330a59f7.png "#330a59f7")| #33317af7 |![](figures/33317af7.png "#33317af7")|
349| theme.colors.compEmphasizeTertiary         | 10% emphasis background.| #190a59f7 |![](figures/190a59f7.png "#190a59f7")| #19317af7 |![](figures/19317af7.png "#19317af7")|
350| theme.colors.compDivider                   | Divider color.| #33000000 |![](figures/33000000.png "#33000000")| #33ffffff |![](figures/33ffffff.png "#33ffffff")|
351| theme.colors.compCommonContrary            | Common invert color.| #ffffffff |![](figures/ffffffff.png "#ffffffff")| #ff000000 |![](figures/ff000000.png "#ff000000")|
352| theme.colors.compBackgroundFocus           | Background color in the focused state.| #fff1f3f5 |![](figures/fff1f3f5.png "#fff1f3f5")| #ff000000 |![](figures/fff1f3f5.png "#fff1f3f5")|
353| theme.colors.compFocusedPrimary            | Primary inverted color in the focused state.| #e5000000 |![](figures/e5000000.png "#e5000000")| #e5ffffff |![](figures/e5ffffff.png "#e5ffffff")|
354| theme.colors.compFocusedSecondary          | Secondary inverted color in the focused state.| #99000000 |![](figures/99000000.png "#99000000")| #99ffffff |![](figures/99ffffff.png "#99ffffff")|
355| theme.colors.compFocusedTertiary           | Tertiary inverted color in the focused state.| #66000000 |![](figures/66000000.png "#66000000")| #66ffffff |![](figures/66ffffff.png "#66ffffff")|
356| theme.colors.interactiveHover              | Common interactive color for the hover state.| #0c000000 |![](figures/0c000000.png "#0c000000")| #0cffffff |![](figures/0cffffff.png "#0cffffff")|
357| theme.colors.interactivePressed            | Common interactive color for the pressed state.| #19000000 |![](figures/19000000.png "#19000000")| #19ffffff |![](figures/19ffffff.png "#19ffffff")|
358| theme.colors.interactiveFocus              | Common interactive color for the focused state.| #ff0a59f7 |![](figures/ff0a59f7.png "#ff0a59f7")| #ff317af7 |![](figures/ff317af7.png "#ff317af7")|
359| theme.colors.interactiveActive             | Common interactive color for the active state.| #ff0a59f7 |![](figures/ff0a59f7.png "#ff0a59f7")| #ff317af7 |![](figures/ff317af7.png "#ff317af7")|
360| theme.colors.interactiveSelect             | Common interactive color for the selected state.| #33000000 |![](figures/33000000.png "#33000000")| #33ffffff |![](figures/33ffffff.png "#33ffffff")|
361| theme.colors.interactiveClick              | Common interactive color for the clicked state.| #19000000 |![](figures/19000000.png "#19000000")| #19ffffff |![](figures/19ffffff.png "#19ffffff")|
362