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 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 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 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 306 307## System Default Token Color Values 308 309| Token | Category| Light | | Dark | | 310|--------------------------------------------|-----| --- |-----------| ------- | -------------------------------------------- | 311| theme.colors.brand | Brand color.|#ff0a59f7|  |#ff317af7|| 312| theme.colors.warning | Alert color.|#ffe84026|  |#ffd94838|| 313| theme.colors.alert | Warning color.|#ffed6f21|  |#ffdb6b42|| 314| theme.colors.confirm | Confirmation color.|#ff64bb5c|  |#ff5ba854|| 315| theme.colors.fontPrimary | Primary text color.| #e5000000 |  |#e5ffffff|| 316| theme.colors.fontSecondary | Secondary text color.| #99000000 |  |#99ffffff|| 317| theme.colors.fontTertiary | Tertiary text color.| #66000000 |  |#66ffffff|| 318| theme.colors.fontFourth | Quaternary text color.| #33000000 |  |#33ffffff|| 319| theme.colors.fontEmphasize | Highlight text color.| #ff0a59f7 |  |#ff317af7|| 320| theme.colors.fontOnPrimary | Primary text invert color.| #ffffffff |  |#ff000000|| 321| theme.colors.fontOnSecondary | Secondary text invert color.| #99ffffff |  |#99000000|| 322| theme.colors.fontOnTertiary | Tertiary text invert color.| #66ffffff |  |#66000000|| 323| theme.colors.fontOnFourth | Quaternary text invert color.| #33ffffff |  |#33000000|| 324| theme.colors.iconPrimary | Primary icon color.| #e5000000 |  |#e5ffffff|| 325| theme.colors.iconSecondary | Secondary icon color.| #99000000 |  |#99ffffff|| 326| theme.colors.iconTertiary | Tertiary icon color.| #66000000 |  |#66ffffff|| 327| theme.colors.iconFourth | Quaternary icon color.| #33000000 |  |#33ffffff|| 328| theme.colors.iconEmphasize | Emphasis icon color.| #ff0a59f7 |  |#ff317af7|| 329| theme.colors.iconSubEmphasize | Emphasis auxiliary icon color.| #660a59f7 |  |#66317af7|| 330| theme.colors.iconOnPrimary | Primary icon invert color.| #ffffffff |  |#ff000000|| 331| theme.colors.iconOnSecondary | Secondary icon invert color.| #99ffffff |  |#99000000|| 332| theme.colors.iconOnTertiary | Tertiary icon invert color.| #66ffffff |  |#66000000|| 333| theme.colors.iconOnFourth | Quaternary icon invert color.| #33ffffff |  |#33000000|| 334| theme.colors.backgroundPrimary | Primary background color (solid, opaque).| #ffffffff |  |#ffe5e5e5|| 335| theme.colors.backgroundSecondary | Secondary background color (solid, opaque).| #fff1f3f5 |  |#ff191a1c|| 336| theme.colors.backgroundTertiary | Tertiary background color (solid, opaque).| #ffe5e5ea |  |#ff202224|| 337| theme.colors.backgroundFourth | Quaternary background color (solid, opaque).| #ffd1d1d6 |  |#ff2e3033|| 338| theme.colors.backgroundEmphasize | Emphasis background color (solid, opaque).| #ff0a59f7 |  |#ff317af7|| 339| theme.colors.compForegroundPrimary | Foreground.| #ff000000 |  | #ffe5e5e5 || 340| theme.colors.compBackgroundPrimary | White background.| #ffffffff || #ffffffff || 341| theme.colors.compBackgroundPrimaryTran | White transparent background.| #ffffffff || #33ffffff || 342| theme.colors.compBackgroundPrimaryContrary | Always-on background.| #ffffffff || #ffe5e5e5 || 343| theme.colors.compBackgroundGray | Gray background.| #fff1f3f5 || #ffe5e5ea || 344| theme.colors.compBackgroundSecondary | Secondary background.| #19000000 || #19ffffff || 345| theme.colors.compBackgroundTertiary | Tertiary background.| #0c000000 || #0cffffff || 346| theme.colors.compBackgroundEmphasize | Emphasis background.| #ff0a59f7 || #ff317af7 || 347| theme.colors.compBackgroundNeutral | Black, neutral, emphasis background.| #ff000000 || #ffffffff || 348| theme.colors.compEmphasizeSecondary | 20% emphasis background.| #330a59f7 || #33317af7 || 349| theme.colors.compEmphasizeTertiary | 10% emphasis background.| #190a59f7 || #19317af7 || 350| theme.colors.compDivider | Divider color.| #33000000 || #33ffffff || 351| theme.colors.compCommonContrary | Common invert color.| #ffffffff || #ff000000 || 352| theme.colors.compBackgroundFocus | Background color in the focused state.| #fff1f3f5 || #ff000000 || 353| theme.colors.compFocusedPrimary | Primary inverted color in the focused state.| #e5000000 || #e5ffffff || 354| theme.colors.compFocusedSecondary | Secondary inverted color in the focused state.| #99000000 || #99ffffff || 355| theme.colors.compFocusedTertiary | Tertiary inverted color in the focused state.| #66000000 || #66ffffff || 356| theme.colors.interactiveHover | Common interactive color for the hover state.| #0c000000 || #0cffffff || 357| theme.colors.interactivePressed | Common interactive color for the pressed state.| #19000000 || #19ffffff || 358| theme.colors.interactiveFocus | Common interactive color for the focused state.| #ff0a59f7 || #ff317af7 || 359| theme.colors.interactiveActive | Common interactive color for the active state.| #ff0a59f7 || #ff317af7 || 360| theme.colors.interactiveSelect | Common interactive color for the selected state.| #33000000 || #33ffffff || 361| theme.colors.interactiveClick | Common interactive color for the clicked state.| #19000000 || #19ffffff || 362