1e41f4b71Sopenharmony_ci# Modal Transition 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci 4e41f4b71Sopenharmony_ciModal transition is a type of transition achieved by a modal – a view that appears on top of the current view while the current view remains. 5e41f4b71Sopenharmony_ci 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ci**Table 1** Modal transition APIs 8e41f4b71Sopenharmony_ci| API | Description | Usage | 9e41f4b71Sopenharmony_ci| ---------------------------------------- | ----------------- | ---------------------------------------- | 10e41f4b71Sopenharmony_ci| [bindContentCover](../reference/apis-arkui/arkui-ts/ts-universal-attributes-modal-transition.md#bindcontentcover) | Binds a modal to the component. | Use this API to display a custom modal. It can work with the transition animation and shared element animation to implement complex transition animation effects, for example, displaying an image in full in the modal upon the click of a thumbnail.| 11e41f4b71Sopenharmony_ci| [bindSheet](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sheet-transition.md#bindsheet) | Binds a sheet to the component. | Use this API to display a custom sheet, for example, a sharing confirmation dialog box. | 12e41f4b71Sopenharmony_ci| [bindMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindmenu11) | Binds a menu to the component, which is displayed when the component is clicked. | Use this API where a menu is required, for example, for the plus sign (+), a common menu indicator in applications. | 13e41f4b71Sopenharmony_ci| [bindContextMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindcontextmenu12) | Binds a context menu to the component, which is displayed when the user long-presses or right-clicks the component.| Use this API for components that bounce up when long-pressed, for example, home screen icons. | 14e41f4b71Sopenharmony_ci| [bindPopup](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#bindpopup) | Binds a popup to the component. | Use this API to display a popup containing additional information about a component when the component is clicked. | 15e41f4b71Sopenharmony_ci| [if](../quick-start/arkts-rendering-control-ifelse.md) | Adds or deletes the component. | Use this API to display a temporary page in a certain state. In this mode, the return navigation needs to be implemented with a listener. | 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci 18e41f4b71Sopenharmony_ci## Creating Modal Transition with bindContentCover 19e41f4b71Sopenharmony_ci 20e41f4b71Sopenharmony_ciYou can bind a full-screen modal to a component through the [bindContentCover](../reference/apis-arkui/arkui-ts/ts-universal-attributes-modal-transition.md#bindcontentcover) attribute. Better yet, with the **ModalTransition** parameter, you can apply a transition effect for when the component appears or disappears. 21e41f4b71Sopenharmony_ci 22e41f4b71Sopenharmony_ci1. Define [bindContentCover](../reference/apis-arkui/arkui-ts/ts-universal-attributes-modal-transition.md#bindcontentcover). 23e41f4b71Sopenharmony_ci 24e41f4b71Sopenharmony_ci2. Define the modal view. 25e41f4b71Sopenharmony_ci 26e41f4b71Sopenharmony_ci ```ts 27e41f4b71Sopenharmony_ci // Use @Builder to build a modal view. 28e41f4b71Sopenharmony_ci @Builder MyBuilder() { 29e41f4b71Sopenharmony_ci Column() { 30e41f4b71Sopenharmony_ci Text('my model view') 31e41f4b71Sopenharmony_ci } 32e41f4b71Sopenharmony_ci // Use the transition API to implement the transition animation for component appearance and disappearance. The transition API must be added to the first component of the builder. 33e41f4b71Sopenharmony_ci .transition(TransitionEffect.translate({ y: 1000 }).animation({ curve: curves.springMotion(0.6, 0.8) })) 34e41f4b71Sopenharmony_ci } 35e41f4b71Sopenharmony_ci ``` 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci3. Call the modal API to display the modal. Implement an animation by using the animation or shared element transition APIs. 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci ```ts 40e41f4b71Sopenharmony_ci // Define the state variable to control the visibility of the modal. 41e41f4b71Sopenharmony_ci @State isPresent: boolean = false; 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci Button('Click to present model view') 44e41f4b71Sopenharmony_ci // Bind a modal to the component. ModalTransition.NONE means not to use the default transition animation for the modal. You can use onDisappear to control state variable changes. 45e41f4b71Sopenharmony_ci .bindContentCover(this.isPresent, this.MyBuilder(), { 46e41f4b71Sopenharmony_ci modalTransition: ModalTransition.NONE, 47e41f4b71Sopenharmony_ci onDisappear: () => { 48e41f4b71Sopenharmony_ci this.isPresent = !this.isPresent; 49e41f4b71Sopenharmony_ci } 50e41f4b71Sopenharmony_ci }) 51e41f4b71Sopenharmony_ci .onClick(() => { 52e41f4b71Sopenharmony_ci // Change the state variable to display the modal. 53e41f4b71Sopenharmony_ci this.isPresent = !this.isPresent; 54e41f4b71Sopenharmony_ci }) 55e41f4b71Sopenharmony_ci ``` 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci 58e41f4b71Sopenharmony_ciBelow is the complete sample code and effect. 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci```ts 63e41f4b71Sopenharmony_ciimport { curves } from '@kit.ArkUI'; 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ciinterface PersonList { 66e41f4b71Sopenharmony_ci name: string, 67e41f4b71Sopenharmony_ci cardnum: string 68e41f4b71Sopenharmony_ci} 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci@Entry 71e41f4b71Sopenharmony_ci@Component 72e41f4b71Sopenharmony_cistruct BindContentCoverDemo { 73e41f4b71Sopenharmony_ci private personList: Array<PersonList> = [ 74e41f4b71Sopenharmony_ci { name: 'Wang **', cardnum: '1234***********789' }, 75e41f4b71Sopenharmony_ci { name: 'Song*', cardnum: '2345***********789' }, 76e41f4b71Sopenharmony_ci { name: 'Xu **', cardnum: '3456***********789' }, 77e41f4b71Sopenharmony_ci { name: 'Tang*', cardnum: '4567***********789' } 78e41f4b71Sopenharmony_ci ]; 79e41f4b71Sopenharmony_ci // Step 1: Define bindContentCover. 80e41f4b71Sopenharmony_ci // Define the state variable to control the visibility of the modal. 81e41f4b71Sopenharmony_ci @State isPresent: boolean = false; 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ci // Step 2: Define the modal view. 84e41f4b71Sopenharmony_ci // Use @Builder to build a modal view. 85e41f4b71Sopenharmony_ci @Builder 86e41f4b71Sopenharmony_ci MyBuilder() { 87e41f4b71Sopenharmony_ci Column() { 88e41f4b71Sopenharmony_ci Row() { 89e41f4b71Sopenharmony_ci Text('Select passengers') 90e41f4b71Sopenharmony_ci .fontSize(20) 91e41f4b71Sopenharmony_ci .fontColor(Color.White) 92e41f4b71Sopenharmony_ci .width('100%') 93e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 94e41f4b71Sopenharmony_ci .padding({ top: 30, bottom: 15 }) 95e41f4b71Sopenharmony_ci } 96e41f4b71Sopenharmony_ci .backgroundColor(0x007dfe) 97e41f4b71Sopenharmony_ci 98e41f4b71Sopenharmony_ci Row() { 99e41f4b71Sopenharmony_ci Text('+ Add') 100e41f4b71Sopenharmony_ci .fontSize(16) 101e41f4b71Sopenharmony_ci .fontColor(0x333333) 102e41f4b71Sopenharmony_ci .margin({ top: 10 }) 103e41f4b71Sopenharmony_ci .padding({ top: 20, bottom: 20 }) 104e41f4b71Sopenharmony_ci .width('92%') 105e41f4b71Sopenharmony_ci .borderRadius(10) 106e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 107e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 108e41f4b71Sopenharmony_ci } 109e41f4b71Sopenharmony_ci 110e41f4b71Sopenharmony_ci Column() { 111e41f4b71Sopenharmony_ci ForEach(this.personList, (item: PersonList, index: number) => { 112e41f4b71Sopenharmony_ci Row() { 113e41f4b71Sopenharmony_ci Column() { 114e41f4b71Sopenharmony_ci if (index % 2 == 0) { 115e41f4b71Sopenharmony_ci Column() 116e41f4b71Sopenharmony_ci .width(20) 117e41f4b71Sopenharmony_ci .height(20) 118e41f4b71Sopenharmony_ci .border({ width: 1, color: 0x007dfe }) 119e41f4b71Sopenharmony_ci .backgroundColor(0x007dfe) 120e41f4b71Sopenharmony_ci } else { 121e41f4b71Sopenharmony_ci Column() 122e41f4b71Sopenharmony_ci .width(20) 123e41f4b71Sopenharmony_ci .height(20) 124e41f4b71Sopenharmony_ci .border({ width: 1, color: 0x007dfe }) 125e41f4b71Sopenharmony_ci } 126e41f4b71Sopenharmony_ci } 127e41f4b71Sopenharmony_ci .width('20%') 128e41f4b71Sopenharmony_ci 129e41f4b71Sopenharmony_ci Column() { 130e41f4b71Sopenharmony_ci Text(item.name) 131e41f4b71Sopenharmony_ci .fontColor(0x333333) 132e41f4b71Sopenharmony_ci .fontSize(18) 133e41f4b71Sopenharmony_ci Text(item.cardnum) 134e41f4b71Sopenharmony_ci .fontColor(0x666666) 135e41f4b71Sopenharmony_ci .fontSize(14) 136e41f4b71Sopenharmony_ci } 137e41f4b71Sopenharmony_ci .width('60%') 138e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Start) 139e41f4b71Sopenharmony_ci 140e41f4b71Sopenharmony_ci Column() { 141e41f4b71Sopenharmony_ci Text ('Edit') 142e41f4b71Sopenharmony_ci .fontColor(0x007dfe) 143e41f4b71Sopenharmony_ci .fontSize(16) 144e41f4b71Sopenharmony_ci } 145e41f4b71Sopenharmony_ci .width('20%') 146e41f4b71Sopenharmony_ci } 147e41f4b71Sopenharmony_ci .padding({ top: 10, bottom: 10 }) 148e41f4b71Sopenharmony_ci .border({ width: { bottom: 1 }, color: 0xf1f1f1 }) 149e41f4b71Sopenharmony_ci .width('92%') 150e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 151e41f4b71Sopenharmony_ci }) 152e41f4b71Sopenharmony_ci } 153e41f4b71Sopenharmony_ci .padding({ top: 20, bottom: 20 }) 154e41f4b71Sopenharmony_ci 155e41f4b71Sopenharmony_ci Text ('OK') 156e41f4b71Sopenharmony_ci .width('90%') 157e41f4b71Sopenharmony_ci .height(40) 158e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 159e41f4b71Sopenharmony_ci .borderRadius(10) 160e41f4b71Sopenharmony_ci .fontColor(Color.White) 161e41f4b71Sopenharmony_ci .backgroundColor(0x007dfe) 162e41f4b71Sopenharmony_ci .onClick(() => { 163e41f4b71Sopenharmony_ci this.isPresent = !this.isPresent; 164e41f4b71Sopenharmony_ci }) 165e41f4b71Sopenharmony_ci } 166e41f4b71Sopenharmony_ci .size({ width: '100%', height: '100%' }) 167e41f4b71Sopenharmony_ci .backgroundColor(0xf5f5f5) 168e41f4b71Sopenharmony_ci // Use the transition API to implement the transition animation for component appearance and disappearance. 169e41f4b71Sopenharmony_ci .transition(TransitionEffect.translate({ y: 1000 }).animation({ curve: curves.springMotion(0.6, 0.8) })) 170e41f4b71Sopenharmony_ci } 171e41f4b71Sopenharmony_ci 172e41f4b71Sopenharmony_ci build() { 173e41f4b71Sopenharmony_ci Column() { 174e41f4b71Sopenharmony_ci Row() { 175e41f4b71Sopenharmony_ci Text('Ticket details') 176e41f4b71Sopenharmony_ci .fontSize(20) 177e41f4b71Sopenharmony_ci .fontColor(Color.White) 178e41f4b71Sopenharmony_ci .width('100%') 179e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 180e41f4b71Sopenharmony_ci .padding({ top: 30, bottom: 60 }) 181e41f4b71Sopenharmony_ci } 182e41f4b71Sopenharmony_ci .backgroundColor(0x007dfe) 183e41f4b71Sopenharmony_ci 184e41f4b71Sopenharmony_ci Column() { 185e41f4b71Sopenharmony_ci Row() { 186e41f4b71Sopenharmony_ci Column() { 187e41f4b71Sopenharmony_ci Text('00:25') 188e41f4b71Sopenharmony_ci Text('From') 189e41f4b71Sopenharmony_ci } 190e41f4b71Sopenharmony_ci .width('30%') 191e41f4b71Sopenharmony_ci 192e41f4b71Sopenharmony_ci Column() { 193e41f4b71Sopenharmony_ci Text('G1234') 194e41f4b71Sopenharmony_ci Text ('8 h 1 min') 195e41f4b71Sopenharmony_ci } 196e41f4b71Sopenharmony_ci .width('30%') 197e41f4b71Sopenharmony_ci 198e41f4b71Sopenharmony_ci Column() { 199e41f4b71Sopenharmony_ci Text('08:26') 200e41f4b71Sopenharmony_ci Text ('To') 201e41f4b71Sopenharmony_ci } 202e41f4b71Sopenharmony_ci .width('30%') 203e41f4b71Sopenharmony_ci } 204e41f4b71Sopenharmony_ci } 205e41f4b71Sopenharmony_ci .width('92%') 206e41f4b71Sopenharmony_ci .padding(15) 207e41f4b71Sopenharmony_ci .margin({ top: -30 }) 208e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 209e41f4b71Sopenharmony_ci .shadow({ radius: 30, color: '#aaaaaa' }) 210e41f4b71Sopenharmony_ci .borderRadius(10) 211e41f4b71Sopenharmony_ci 212e41f4b71Sopenharmony_ci Column() { 213e41f4b71Sopenharmony_ci Text('+ Select passengers') 214e41f4b71Sopenharmony_ci .fontSize(18) 215e41f4b71Sopenharmony_ci .fontColor(Color.Orange) 216e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 217e41f4b71Sopenharmony_ci .padding({ top: 10, bottom: 10 }) 218e41f4b71Sopenharmony_ci .width('60%') 219e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 220e41f4b71Sopenharmony_ci .borderRadius(15)// Bind a modal to the component. ModalTransition.DEFAULT means to use the slide-up and slide-down animation type. You can use onDisappear to control state variable changes. 221e41f4b71Sopenharmony_ci .bindContentCover(this.isPresent, this.MyBuilder(), { 222e41f4b71Sopenharmony_ci modalTransition: ModalTransition.DEFAULT, 223e41f4b71Sopenharmony_ci onDisappear: () => { 224e41f4b71Sopenharmony_ci this.isPresent = !this.isPresent; 225e41f4b71Sopenharmony_ci } 226e41f4b71Sopenharmony_ci }) 227e41f4b71Sopenharmony_ci .onClick(() => { 228e41f4b71Sopenharmony_ci // Step 3: Call the modal API to display the modal. Implement an animation by using the animation or shared element transition APIs. 229e41f4b71Sopenharmony_ci // Change the state variable to display the modal. 230e41f4b71Sopenharmony_ci this.isPresent = !this.isPresent; 231e41f4b71Sopenharmony_ci }) 232e41f4b71Sopenharmony_ci } 233e41f4b71Sopenharmony_ci .padding({ top: 60 }) 234e41f4b71Sopenharmony_ci } 235e41f4b71Sopenharmony_ci } 236e41f4b71Sopenharmony_ci} 237e41f4b71Sopenharmony_ci``` 238e41f4b71Sopenharmony_ci 239e41f4b71Sopenharmony_ci 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ci 242e41f4b71Sopenharmony_ci 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ci 245e41f4b71Sopenharmony_ci## Creating Sheet Transition with bindSheet 246e41f4b71Sopenharmony_ci 247e41f4b71Sopenharmony_ciYou can bind a sheet to a component through the [bindSheet](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sheet-transition.md#bindsheet) attribute. You can also set the sheet to the preset or custom height for when the component appears. The process of creating a sheet transition is basically the same as that of creating a modal transition using [bindContentCover](../reference/apis-arkui/arkui-ts/ts-universal-attributes-modal-transition.md#bindcontentcover). 248e41f4b71Sopenharmony_ci 249e41f4b71Sopenharmony_ciBelow is the complete sample code and effect. 250e41f4b71Sopenharmony_ci 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ci```ts 253e41f4b71Sopenharmony_ci@Entry 254e41f4b71Sopenharmony_ci@Component 255e41f4b71Sopenharmony_cistruct BindSheetDemo { 256e41f4b71Sopenharmony_ci // Set visibility of the sheet. 257e41f4b71Sopenharmony_ci @State isShowSheet: boolean = false; 258e41f4b71Sopenharmony_ci private menuList: string[] = ['No ice', 'Light ice', 'Extra ice', 'Light sauce', 'Extra sauce', 'Plastic cutlery', 'No plastic cutlery']; 259e41f4b71Sopenharmony_ci 260e41f4b71Sopenharmony_ci // Use @Builder to build a sheet view. 261e41f4b71Sopenharmony_ci @Builder 262e41f4b71Sopenharmony_ci mySheet() { 263e41f4b71Sopenharmony_ci Column() { 264e41f4b71Sopenharmony_ci Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) { 265e41f4b71Sopenharmony_ci ForEach(this.menuList, (item: string) => { 266e41f4b71Sopenharmony_ci Text(item) 267e41f4b71Sopenharmony_ci .fontSize(16) 268e41f4b71Sopenharmony_ci .fontColor(0x333333) 269e41f4b71Sopenharmony_ci .backgroundColor(0xf1f1f1) 270e41f4b71Sopenharmony_ci .borderRadius(8) 271e41f4b71Sopenharmony_ci .margin(10) 272e41f4b71Sopenharmony_ci .padding(10) 273e41f4b71Sopenharmony_ci }) 274e41f4b71Sopenharmony_ci } 275e41f4b71Sopenharmony_ci .padding({ top: 18 }) 276e41f4b71Sopenharmony_ci } 277e41f4b71Sopenharmony_ci .width('100%') 278e41f4b71Sopenharmony_ci .height('100%') 279e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 280e41f4b71Sopenharmony_ci } 281e41f4b71Sopenharmony_ci 282e41f4b71Sopenharmony_ci build() { 283e41f4b71Sopenharmony_ci Column() { 284e41f4b71Sopenharmony_ci Text ('Preferences') 285e41f4b71Sopenharmony_ci .fontSize(28) 286e41f4b71Sopenharmony_ci .padding({ top: 30, bottom: 30 }) 287e41f4b71Sopenharmony_ci Column() { 288e41f4b71Sopenharmony_ci Row() { 289e41f4b71Sopenharmony_ci Row() 290e41f4b71Sopenharmony_ci .width(10) 291e41f4b71Sopenharmony_ci .height(10) 292e41f4b71Sopenharmony_ci .backgroundColor('#a8a8a8') 293e41f4b71Sopenharmony_ci .margin({ right: 12 }) 294e41f4b71Sopenharmony_ci .borderRadius(20) 295e41f4b71Sopenharmony_ci 296e41f4b71Sopenharmony_ci Column() { 297e41f4b71Sopenharmony_ci Text('Customize') 298e41f4b71Sopenharmony_ci .fontSize(16) 299e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Medium) 300e41f4b71Sopenharmony_ci } 301e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Start) 302e41f4b71Sopenharmony_ci 303e41f4b71Sopenharmony_ci Blank() 304e41f4b71Sopenharmony_ci 305e41f4b71Sopenharmony_ci Row() 306e41f4b71Sopenharmony_ci .width(12) 307e41f4b71Sopenharmony_ci .height(12) 308e41f4b71Sopenharmony_ci .margin({ right: 15 }) 309e41f4b71Sopenharmony_ci .border({ 310e41f4b71Sopenharmony_ci width: { top: 2, right: 2 }, 311e41f4b71Sopenharmony_ci color: 0xcccccc 312e41f4b71Sopenharmony_ci }) 313e41f4b71Sopenharmony_ci .rotate({ angle: 45 }) 314e41f4b71Sopenharmony_ci } 315e41f4b71Sopenharmony_ci .borderRadius(15) 316e41f4b71Sopenharmony_ci .shadow({ radius: 100, color: '#ededed' }) 317e41f4b71Sopenharmony_ci .width('90%') 318e41f4b71Sopenharmony_ci .alignItems(VerticalAlign.Center) 319e41f4b71Sopenharmony_ci .padding({ left: 15, top: 15, bottom: 15 }) 320e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 321e41f4b71Sopenharmony_ci // Bind a sheet to the component. Set height (sheet height; large by default) and DragBar (whether to display the drag bar; true by default). You can use onDisappear to control state variable changes. 322e41f4b71Sopenharmony_ci .bindSheet(this.isShowSheet, this.mySheet(), { 323e41f4b71Sopenharmony_ci height: 300, 324e41f4b71Sopenharmony_ci dragBar: false, 325e41f4b71Sopenharmony_ci onDisappear: () => { 326e41f4b71Sopenharmony_ci this.isShowSheet = !this.isShowSheet; 327e41f4b71Sopenharmony_ci } 328e41f4b71Sopenharmony_ci }) 329e41f4b71Sopenharmony_ci .onClick(() => { 330e41f4b71Sopenharmony_ci this.isShowSheet = !this.isShowSheet; 331e41f4b71Sopenharmony_ci }) 332e41f4b71Sopenharmony_ci } 333e41f4b71Sopenharmony_ci .width('100%') 334e41f4b71Sopenharmony_ci } 335e41f4b71Sopenharmony_ci .width('100%') 336e41f4b71Sopenharmony_ci .height('100%') 337e41f4b71Sopenharmony_ci .backgroundColor(0xf1f1f1) 338e41f4b71Sopenharmony_ci } 339e41f4b71Sopenharmony_ci} 340e41f4b71Sopenharmony_ci``` 341e41f4b71Sopenharmony_ci 342e41f4b71Sopenharmony_ci 343e41f4b71Sopenharmony_ci 344e41f4b71Sopenharmony_ci 345e41f4b71Sopenharmony_ci## Creating a Menu with bindMenu 346e41f4b71Sopenharmony_ci 347e41f4b71Sopenharmony_ciYou can bind a menu to component through the [bindMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindmenu) attribute. The menu can then be triggered by clicking. Below is the complete sample code and effect. 348e41f4b71Sopenharmony_ci 349e41f4b71Sopenharmony_ci 350e41f4b71Sopenharmony_ci```ts 351e41f4b71Sopenharmony_ciclass BMD{ 352e41f4b71Sopenharmony_ci value:ResourceStr = '' 353e41f4b71Sopenharmony_ci action:() => void = () => {} 354e41f4b71Sopenharmony_ci} 355e41f4b71Sopenharmony_ci@Entry 356e41f4b71Sopenharmony_ci@Component 357e41f4b71Sopenharmony_cistruct BindMenuDemo { 358e41f4b71Sopenharmony_ci 359e41f4b71Sopenharmony_ci // Step 1: Define a data array to represent menu items. 360e41f4b71Sopenharmony_ci @State items:BMD[] = [ 361e41f4b71Sopenharmony_ci { 362e41f4b71Sopenharmony_ci value:'Menu item 1', 363e41f4b71Sopenharmony_ci action: () => { 364e41f4b71Sopenharmony_ci console.info('handle Menu1 select') 365e41f4b71Sopenharmony_ci } 366e41f4b71Sopenharmony_ci }, 367e41f4b71Sopenharmony_ci { 368e41f4b71Sopenharmony_ci value:'Menu item 2', 369e41f4b71Sopenharmony_ci action: () => { 370e41f4b71Sopenharmony_ci console.info('handle Menu2 select') 371e41f4b71Sopenharmony_ci } 372e41f4b71Sopenharmony_ci }, 373e41f4b71Sopenharmony_ci ] 374e41f4b71Sopenharmony_ci 375e41f4b71Sopenharmony_ci build() { 376e41f4b71Sopenharmony_ci Column() { 377e41f4b71Sopenharmony_ci Button('click') 378e41f4b71Sopenharmony_ci .backgroundColor(0x409eff) 379e41f4b71Sopenharmony_ci .borderRadius(5) 380e41f4b71Sopenharmony_ci // Step 2: Bind the menu data to the component through bindMenu. 381e41f4b71Sopenharmony_ci .bindMenu(this.items) 382e41f4b71Sopenharmony_ci } 383e41f4b71Sopenharmony_ci .justifyContent(FlexAlign.Center) 384e41f4b71Sopenharmony_ci .width('100%') 385e41f4b71Sopenharmony_ci .height(437) 386e41f4b71Sopenharmony_ci } 387e41f4b71Sopenharmony_ci} 388e41f4b71Sopenharmony_ci``` 389e41f4b71Sopenharmony_ci 390e41f4b71Sopenharmony_ci 391e41f4b71Sopenharmony_ci 392e41f4b71Sopenharmony_ci 393e41f4b71Sopenharmony_ci## Creating a Context Menu with bindContextMenu 394e41f4b71Sopenharmony_ci 395e41f4b71Sopenharmony_ciYou can bind a menu to component through the [bindContextMenu](../reference/apis-arkui/arkui-ts/ts-universal-attributes-menu.md#bindcontextmenu8) attribute. The menu can then be triggered by long-pressing or right-clicking. 396e41f4b71Sopenharmony_ci 397e41f4b71Sopenharmony_ciBelow is the complete sample code and effect. 398e41f4b71Sopenharmony_ci 399e41f4b71Sopenharmony_ci 400e41f4b71Sopenharmony_ci```ts 401e41f4b71Sopenharmony_ci@Entry 402e41f4b71Sopenharmony_ci@Component 403e41f4b71Sopenharmony_cistruct BindContextMenuDemo { 404e41f4b71Sopenharmony_ci private menu: string[] = ['Save', 'Favorite', 'Search']; 405e41f4b71Sopenharmony_ci private pics: Resource[] = [$r('app.media.icon_1'), $r('app.media.icon_2')]; 406e41f4b71Sopenharmony_ci 407e41f4b71Sopenharmony_ci // Use @Builder to build custom menu items. 408e41f4b71Sopenharmony_ci @Builder myMenu() { 409e41f4b71Sopenharmony_ci Column() { 410e41f4b71Sopenharmony_ci ForEach(this.menu, (item: string) => { 411e41f4b71Sopenharmony_ci Row() { 412e41f4b71Sopenharmony_ci Text(item) 413e41f4b71Sopenharmony_ci .fontSize(18) 414e41f4b71Sopenharmony_ci .width('100%') 415e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 416e41f4b71Sopenharmony_ci } 417e41f4b71Sopenharmony_ci .padding(15) 418e41f4b71Sopenharmony_ci .border({ width: { bottom: 1 }, color: 0xcccccc }) 419e41f4b71Sopenharmony_ci }) 420e41f4b71Sopenharmony_ci } 421e41f4b71Sopenharmony_ci .width(140) 422e41f4b71Sopenharmony_ci .borderRadius(15) 423e41f4b71Sopenharmony_ci .shadow({ radius: 15, color: 0xf1f1f1 }) 424e41f4b71Sopenharmony_ci .backgroundColor(0xf1f1f1) 425e41f4b71Sopenharmony_ci } 426e41f4b71Sopenharmony_ci 427e41f4b71Sopenharmony_ci build() { 428e41f4b71Sopenharmony_ci Column() { 429e41f4b71Sopenharmony_ci Row() { 430e41f4b71Sopenharmony_ci Text ('View image') 431e41f4b71Sopenharmony_ci .fontSize(20) 432e41f4b71Sopenharmony_ci .fontColor(Color.White) 433e41f4b71Sopenharmony_ci .width('100%') 434e41f4b71Sopenharmony_ci .textAlign(TextAlign.Center) 435e41f4b71Sopenharmony_ci .padding({ top: 20, bottom: 20 }) 436e41f4b71Sopenharmony_ci } 437e41f4b71Sopenharmony_ci .backgroundColor(0x007dfe) 438e41f4b71Sopenharmony_ci 439e41f4b71Sopenharmony_ci Column() { 440e41f4b71Sopenharmony_ci ForEach(this.pics, (item: Resource) => { 441e41f4b71Sopenharmony_ci Row(){ 442e41f4b71Sopenharmony_ci Image(item) 443e41f4b71Sopenharmony_ci .width('100%') 444e41f4b71Sopenharmony_ci .draggable(false) 445e41f4b71Sopenharmony_ci } 446e41f4b71Sopenharmony_ci .padding({ top: 20, bottom: 20, left: 10, right: 10 }) 447e41f4b71Sopenharmony_ci .bindContextMenu(this.myMenu, ResponseType.LongPress) 448e41f4b71Sopenharmony_ci }) 449e41f4b71Sopenharmony_ci } 450e41f4b71Sopenharmony_ci } 451e41f4b71Sopenharmony_ci .width('100%') 452e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Center) 453e41f4b71Sopenharmony_ci } 454e41f4b71Sopenharmony_ci} 455e41f4b71Sopenharmony_ci``` 456e41f4b71Sopenharmony_ci 457e41f4b71Sopenharmony_ci 458e41f4b71Sopenharmony_ci 459e41f4b71Sopenharmony_ci 460e41f4b71Sopenharmony_ci## Creating a Popup with bindPopUp 461e41f4b71Sopenharmony_ci 462e41f4b71Sopenharmony_ciYou can bind a popup to a component through the [bindpopup](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#bindpopup) attribute, specifying its content, interaction logic, and display status. 463e41f4b71Sopenharmony_ci 464e41f4b71Sopenharmony_ciBelow is the complete sample code and effect. 465e41f4b71Sopenharmony_ci 466e41f4b71Sopenharmony_ci 467e41f4b71Sopenharmony_ci```ts 468e41f4b71Sopenharmony_ci@Entry 469e41f4b71Sopenharmony_ci@Component 470e41f4b71Sopenharmony_cistruct BindPopupDemo { 471e41f4b71Sopenharmony_ci 472e41f4b71Sopenharmony_ci // Step 1: Define the state variable to control the visibility of the popup. 473e41f4b71Sopenharmony_ci @State customPopup: boolean = false; 474e41f4b71Sopenharmony_ci 475e41f4b71Sopenharmony_ci // Step 2: Use @Builder to build a custom popup. 476e41f4b71Sopenharmony_ci @Builder popupBuilder() { 477e41f4b71Sopenharmony_ci Column({ space: 2 }) { 478e41f4b71Sopenharmony_ci Row().width(64) 479e41f4b71Sopenharmony_ci .height(64) 480e41f4b71Sopenharmony_ci .backgroundColor(0x409eff) 481e41f4b71Sopenharmony_ci Text('Popup') 482e41f4b71Sopenharmony_ci .fontSize(10) 483e41f4b71Sopenharmony_ci .fontColor(Color.White) 484e41f4b71Sopenharmony_ci } 485e41f4b71Sopenharmony_ci .justifyContent(FlexAlign.SpaceAround) 486e41f4b71Sopenharmony_ci .width(100) 487e41f4b71Sopenharmony_ci .height(100) 488e41f4b71Sopenharmony_ci .padding(5) 489e41f4b71Sopenharmony_ci } 490e41f4b71Sopenharmony_ci 491e41f4b71Sopenharmony_ci build() { 492e41f4b71Sopenharmony_ci Column() { 493e41f4b71Sopenharmony_ci 494e41f4b71Sopenharmony_ci Button('click') 495e41f4b71Sopenharmony_ci // Step 4: Add a click event to control the visibility of the popup. 496e41f4b71Sopenharmony_ci .onClick(() => { 497e41f4b71Sopenharmony_ci this.customPopup = !this.customPopup; 498e41f4b71Sopenharmony_ci }) 499e41f4b71Sopenharmony_ci .backgroundColor(0xf56c6c) 500e41f4b71Sopenharmony_ci // Step 5: Bind the popup to the component through bindPopup. 501e41f4b71Sopenharmony_ci .bindPopup(this.customPopup, { 502e41f4b71Sopenharmony_ci builder: this.popupBuilder, 503e41f4b71Sopenharmony_ci placement: Placement.Top, 504e41f4b71Sopenharmony_ci maskColor: 0x33000000, 505e41f4b71Sopenharmony_ci popupColor: 0xf56c6c, 506e41f4b71Sopenharmony_ci enableArrow: true, 507e41f4b71Sopenharmony_ci onStateChange: (e) => { 508e41f4b71Sopenharmony_ci if (!e.isVisible) { 509e41f4b71Sopenharmony_ci this.customPopup = false; 510e41f4b71Sopenharmony_ci } 511e41f4b71Sopenharmony_ci } 512e41f4b71Sopenharmony_ci }) 513e41f4b71Sopenharmony_ci } 514e41f4b71Sopenharmony_ci .justifyContent(FlexAlign.Center) 515e41f4b71Sopenharmony_ci .width('100%') 516e41f4b71Sopenharmony_ci .height(437) 517e41f4b71Sopenharmony_ci } 518e41f4b71Sopenharmony_ci} 519e41f4b71Sopenharmony_ci``` 520e41f4b71Sopenharmony_ci 521e41f4b71Sopenharmony_ci 522e41f4b71Sopenharmony_ci 523e41f4b71Sopenharmony_ci 524e41f4b71Sopenharmony_ci 525e41f4b71Sopenharmony_ci 526e41f4b71Sopenharmony_ci## Creating Modal Transition with if 527e41f4b71Sopenharmony_ci 528e41f4b71Sopenharmony_ciIn addition to the preceding modal transition APIs, you can also use the **if** syntax to create a modal transition, eliminating the need for binding to the component and listening for state variable changes. 529e41f4b71Sopenharmony_ci 530e41f4b71Sopenharmony_ciBelow is the complete sample code and effect. 531e41f4b71Sopenharmony_ci 532e41f4b71Sopenharmony_ci 533e41f4b71Sopenharmony_ci```ts 534e41f4b71Sopenharmony_ci@Entry 535e41f4b71Sopenharmony_ci@Component 536e41f4b71Sopenharmony_cistruct ModalTransitionWithIf { 537e41f4b71Sopenharmony_ci private listArr: string[] = ['WLAN', 'Bluetooth', 'Personal hotspot', 'Connected devices']; 538e41f4b71Sopenharmony_ci private shareArr: string[] = ['Projection', 'Printing', 'VPN','Private DNS', 'NFC']; 539e41f4b71Sopenharmony_ci // Step 1: Define a state variable to control page display. 540e41f4b71Sopenharmony_ci @State isShowShare: boolean = false; 541e41f4b71Sopenharmony_ci private shareFunc(): void { 542e41f4b71Sopenharmony_ci animateTo({ duration: 500 }, () => { 543e41f4b71Sopenharmony_ci this.isShowShare = !this.isShowShare; 544e41f4b71Sopenharmony_ci }) 545e41f4b71Sopenharmony_ci } 546e41f4b71Sopenharmony_ci 547e41f4b71Sopenharmony_ci build(){ 548e41f4b71Sopenharmony_ci // Step 2: Define a stack layout to display the current view and modal view. 549e41f4b71Sopenharmony_ci Stack() { 550e41f4b71Sopenharmony_ci Column() { 551e41f4b71Sopenharmony_ci Column() { 552e41f4b71Sopenharmony_ci Text('Settings') 553e41f4b71Sopenharmony_ci .fontSize(28) 554e41f4b71Sopenharmony_ci .fontColor(0x333333) 555e41f4b71Sopenharmony_ci } 556e41f4b71Sopenharmony_ci .width('90%') 557e41f4b71Sopenharmony_ci .padding({ top: 30, bottom: 15 }) 558e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Start) 559e41f4b71Sopenharmony_ci 560e41f4b71Sopenharmony_ci TextInput({ placeholder: 'Search by keyword' }) 561e41f4b71Sopenharmony_ci .width('90%') 562e41f4b71Sopenharmony_ci .height(40) 563e41f4b71Sopenharmony_ci .margin({ bottom: 10 }) 564e41f4b71Sopenharmony_ci .focusable(false) 565e41f4b71Sopenharmony_ci 566e41f4b71Sopenharmony_ci List({ space: 12, initialIndex: 0 }) { 567e41f4b71Sopenharmony_ci ForEach(this.listArr, (item: string, index: number) => { 568e41f4b71Sopenharmony_ci ListItem() { 569e41f4b71Sopenharmony_ci Row() { 570e41f4b71Sopenharmony_ci Row() { 571e41f4b71Sopenharmony_ci Text(`${item.slice(0, 1)}`) 572e41f4b71Sopenharmony_ci .fontColor(Color.White) 573e41f4b71Sopenharmony_ci .fontSize(14) 574e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 575e41f4b71Sopenharmony_ci } 576e41f4b71Sopenharmony_ci .width(30) 577e41f4b71Sopenharmony_ci .height(30) 578e41f4b71Sopenharmony_ci .backgroundColor('#a8a8a8') 579e41f4b71Sopenharmony_ci .margin({ right: 12 }) 580e41f4b71Sopenharmony_ci .borderRadius(20) 581e41f4b71Sopenharmony_ci .justifyContent(FlexAlign.Center) 582e41f4b71Sopenharmony_ci 583e41f4b71Sopenharmony_ci Column() { 584e41f4b71Sopenharmony_ci Text(item) 585e41f4b71Sopenharmony_ci .fontSize(16) 586e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Medium) 587e41f4b71Sopenharmony_ci } 588e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Start) 589e41f4b71Sopenharmony_ci 590e41f4b71Sopenharmony_ci Blank() 591e41f4b71Sopenharmony_ci 592e41f4b71Sopenharmony_ci Row() 593e41f4b71Sopenharmony_ci .width(12) 594e41f4b71Sopenharmony_ci .height(12) 595e41f4b71Sopenharmony_ci .margin({ right: 15 }) 596e41f4b71Sopenharmony_ci .border({ 597e41f4b71Sopenharmony_ci width: { top: 2, right: 2 }, 598e41f4b71Sopenharmony_ci color: 0xcccccc 599e41f4b71Sopenharmony_ci }) 600e41f4b71Sopenharmony_ci .rotate({ angle: 45 }) 601e41f4b71Sopenharmony_ci } 602e41f4b71Sopenharmony_ci .borderRadius(15) 603e41f4b71Sopenharmony_ci .shadow({ radius: 100, color: '#ededed' }) 604e41f4b71Sopenharmony_ci .width('90%') 605e41f4b71Sopenharmony_ci .alignItems(VerticalAlign.Center) 606e41f4b71Sopenharmony_ci .padding({ left: 15, top: 15, bottom: 15 }) 607e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 608e41f4b71Sopenharmony_ci } 609e41f4b71Sopenharmony_ci .width('100%') 610e41f4b71Sopenharmony_ci .onClick(() => { 611e41f4b71Sopenharmony_ci // Step 3: Change the state variable to display the modal view. 612e41f4b71Sopenharmony_ci if(item.slice(-2) === 'Share'){ 613e41f4b71Sopenharmony_ci this.shareFunc(); 614e41f4b71Sopenharmony_ci } 615e41f4b71Sopenharmony_ci }) 616e41f4b71Sopenharmony_ci }, (item: string): string => item) 617e41f4b71Sopenharmony_ci } 618e41f4b71Sopenharmony_ci .width('100%') 619e41f4b71Sopenharmony_ci } 620e41f4b71Sopenharmony_ci .width('100%') 621e41f4b71Sopenharmony_ci .height('100%') 622e41f4b71Sopenharmony_ci .backgroundColor(0xfefefe) 623e41f4b71Sopenharmony_ci 624e41f4b71Sopenharmony_ci // Step 4: Define the modal view in if and display it at the top layer. Use if to control the appearance and disappearance of the modal view. 625e41f4b71Sopenharmony_ci if(this.isShowShare){ 626e41f4b71Sopenharmony_ci Column() { 627e41f4b71Sopenharmony_ci Column() { 628e41f4b71Sopenharmony_ci Row() { 629e41f4b71Sopenharmony_ci Row() { 630e41f4b71Sopenharmony_ci Row() 631e41f4b71Sopenharmony_ci .width(16) 632e41f4b71Sopenharmony_ci .height(16) 633e41f4b71Sopenharmony_ci .border({ 634e41f4b71Sopenharmony_ci width: { left: 2, top: 2 }, 635e41f4b71Sopenharmony_ci color: 0x333333 636e41f4b71Sopenharmony_ci }) 637e41f4b71Sopenharmony_ci .rotate({ angle: -45 }) 638e41f4b71Sopenharmony_ci } 639e41f4b71Sopenharmony_ci .padding({ left: 15, right: 10 }) 640e41f4b71Sopenharmony_ci .onClick(() => { 641e41f4b71Sopenharmony_ci this.shareFunc(); 642e41f4b71Sopenharmony_ci }) 643e41f4b71Sopenharmony_ci Text('Connected devices') 644e41f4b71Sopenharmony_ci .fontSize(28) 645e41f4b71Sopenharmony_ci .fontColor(0x333333) 646e41f4b71Sopenharmony_ci } 647e41f4b71Sopenharmony_ci .padding({ top: 30 }) 648e41f4b71Sopenharmony_ci } 649e41f4b71Sopenharmony_ci .width('90%') 650e41f4b71Sopenharmony_ci .padding({bottom: 15}) 651e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Start) 652e41f4b71Sopenharmony_ci 653e41f4b71Sopenharmony_ci List({ space: 12, initialIndex: 0 }) { 654e41f4b71Sopenharmony_ci ForEach(this.shareArr, (item: string) => { 655e41f4b71Sopenharmony_ci ListItem() { 656e41f4b71Sopenharmony_ci Row() { 657e41f4b71Sopenharmony_ci Row() { 658e41f4b71Sopenharmony_ci Text(`${item.slice(0, 1)}`) 659e41f4b71Sopenharmony_ci .fontColor(Color.White) 660e41f4b71Sopenharmony_ci .fontSize(14) 661e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Bold) 662e41f4b71Sopenharmony_ci } 663e41f4b71Sopenharmony_ci .width(30) 664e41f4b71Sopenharmony_ci .height(30) 665e41f4b71Sopenharmony_ci .backgroundColor('#a8a8a8') 666e41f4b71Sopenharmony_ci .margin({ right: 12 }) 667e41f4b71Sopenharmony_ci .borderRadius(20) 668e41f4b71Sopenharmony_ci .justifyContent(FlexAlign.Center) 669e41f4b71Sopenharmony_ci 670e41f4b71Sopenharmony_ci Column() { 671e41f4b71Sopenharmony_ci Text(item) 672e41f4b71Sopenharmony_ci .fontSize(16) 673e41f4b71Sopenharmony_ci .fontWeight(FontWeight.Medium) 674e41f4b71Sopenharmony_ci } 675e41f4b71Sopenharmony_ci .alignItems(HorizontalAlign.Start) 676e41f4b71Sopenharmony_ci 677e41f4b71Sopenharmony_ci Blank() 678e41f4b71Sopenharmony_ci 679e41f4b71Sopenharmony_ci Row() 680e41f4b71Sopenharmony_ci .width(12) 681e41f4b71Sopenharmony_ci .height(12) 682e41f4b71Sopenharmony_ci .margin({ right: 15 }) 683e41f4b71Sopenharmony_ci .border({ 684e41f4b71Sopenharmony_ci width: { top: 2, right: 2 }, 685e41f4b71Sopenharmony_ci color: 0xcccccc 686e41f4b71Sopenharmony_ci }) 687e41f4b71Sopenharmony_ci .rotate({ angle: 45 }) 688e41f4b71Sopenharmony_ci } 689e41f4b71Sopenharmony_ci .borderRadius(15) 690e41f4b71Sopenharmony_ci .shadow({ radius: 100, color: '#ededed' }) 691e41f4b71Sopenharmony_ci .width('90%') 692e41f4b71Sopenharmony_ci .alignItems(VerticalAlign.Center) 693e41f4b71Sopenharmony_ci .padding({ left: 15, top: 15, bottom: 15 }) 694e41f4b71Sopenharmony_ci .backgroundColor(Color.White) 695e41f4b71Sopenharmony_ci } 696e41f4b71Sopenharmony_ci .width('100%') 697e41f4b71Sopenharmony_ci }, (item: string): string => item) 698e41f4b71Sopenharmony_ci } 699e41f4b71Sopenharmony_ci .width('100%') 700e41f4b71Sopenharmony_ci } 701e41f4b71Sopenharmony_ci .width('100%') 702e41f4b71Sopenharmony_ci .height('100%') 703e41f4b71Sopenharmony_ci .backgroundColor(0xffffff) 704e41f4b71Sopenharmony_ci // Step 5: Define the mode in which the modal view disappears. 705e41f4b71Sopenharmony_ci .transition(TransitionEffect.OPACITY 706e41f4b71Sopenharmony_ci .combine(TransitionEffect.translate({ x: '100%' })) 707e41f4b71Sopenharmony_ci .combine(TransitionEffect.scale({ x: 0.95, y: 0.95 }))) 708e41f4b71Sopenharmony_ci } 709e41f4b71Sopenharmony_ci } 710e41f4b71Sopenharmony_ci } 711e41f4b71Sopenharmony_ci} 712e41f4b71Sopenharmony_ci``` 713e41f4b71Sopenharmony_ci 714e41f4b71Sopenharmony_ci 715