1# Popup
2You can bind the **Popup** attribute to a component to create a popup, specifying its content and interaction logic, and display state. It is mainly used for screen recording and message notification.
3
4Popups can be defined with [PopupOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#popupoptions) or [CustomPopupOptions](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#custompopupoptions8). In **PopupOptions**, you can set **primaryButton** and **secondaryButton** to include buttons in the popup. In **CustomPopupOptions**, you can create a custom popup through [builder](../quick-start/arkts-builder.md).
5
6You can configure the modality of a popup through [mask](../reference/apis-arkui/arkui-ts/ts-universal-attributes-popup.md#popupoptions). Setting **mask** to **true** or a color value makes the popup a modal, and setting **mask** to **false** makes the popup a non-modal.
7
8## Creating a Text Popup
9
10Text popups are usually used to display text only and do not allow for user interactions. Bind the **Popup** attribute to a component. When the **show** parameter in the **bindPopup** attribute is set to **true**, a popup is displayed.
11
12If you bind the **Popup** attribute to a **\<Button>** component, each time the **\<Button>** button is clicked, the Boolean value of **handlePopup** changes. When it changes to **true**, the popup is displayed.
13
14```ts
15@Entry
16@Component
17struct PopupExample {
18  @State handlePopup: boolean = false
19
20  build() {
21    Column() {
22      Button('PopupOptions')
23        .onClick(() => {
24          this.handlePopup = !this.handlePopup
25        })
26        .bindPopup(this.handlePopup, {
27          message: 'This is a popup with PopupOptions',
28        })
29    }.width('100%').padding({ top: 5 })
30  }
31}
32```
33
34![en-us_image_0000001511740524](figures/en-us_image_0000001511740524.png)
35
36## Adding an Event Listener for Popup State Changes
37
38You can use the **onStateChange** parameter to add an event callback for popup state changes, so as to determine the current state of the popup.
39
40```ts
41@Entry
42@Component
43struct PopupExample {
44  @State handlePopup: boolean = false
45
46  build() {
47    Column() {
48      Button('PopupOptions')
49        .onClick(() => {
50          this.handlePopup = !this.handlePopup
51        })
52        .bindPopup(this.handlePopup, {
53          message: 'This is a popup with PopupOptions',
54          onStateChange: (e)=> {// Return the current popup state.
55            if (!e.isVisible) {
56              this.handlePopup = false
57            }
58          }
59        })
60    }.width('100%').padding({ top: 5 })
61  }
62}
63```
64
65![PopupOnStateChange](figures/PopupOnStateChange.gif)
66
67## Creating a Popup with Buttons
68
69You can add a maximum of two buttons to a popup through the **primaryButton** and **secondaryButton** attributes. For each of the buttons, you can set the **action** parameter to specify the operation to be triggered.
70
71```ts
72@Entry
73@Component
74struct PopupExample22 {
75  @State handlePopup: boolean = false
76
77  build() {
78    Column() {
79      Button('PopupOptions').margin({ top: 200 })
80        .onClick(() => {
81          this.handlePopup = !this.handlePopup
82        })
83        .bindPopup(this.handlePopup, {
84          message: 'This is a popup with PopupOptions',
85          primaryButton: {
86            value: 'Confirm',
87            action: () => {
88              this.handlePopup = !this.handlePopup
89              console.info('confirm Button click')
90            }
91          },
92          secondaryButton: {
93            value: 'Cancel',
94            action: () => {
95              this.handlePopup = !this.handlePopup
96            }
97          },
98          onStateChange: (e) => {
99            if (!e.isVisible) {
100              this.handlePopup = false
101            }
102          }
103        })
104    }.width('100%').padding({ top: 5 })
105  }
106}
107```
108
109![en-us_other_0000001500740342](figures/en-us_other_0000001500740342.jpeg)
110
111## Implementing Popup Animation
112
113You implement the entrance and exit animation effects of popups through **transition**.
114
115```ts
116// xxx.ets
117@Entry
118@Component
119struct PopupExample {
120  @State handlePopup: boolean = false
121  @State customPopup: boolean = false
122
123  // Define the popup content in the popup builder.
124  @Builder popupBuilder() {
125    Row() {
126      Text('Custom Popup with transitionEffect').fontSize(10)
127    }.height(50).padding(5)
128  }
129
130  build() {
131    Flex({ direction: FlexDirection.Column }) {
132      // PopupOptions for setting the popup
133      Button('PopupOptions')
134        .onClick(() => {
135          this.handlePopup = !this.handlePopup
136        })
137        .bindPopup(this.handlePopup, {
138          message: 'This is a popup with transitionEffect',
139          placementOnTop: true,
140          showInSubWindow: false,
141          onStateChange: (e) => {
142            if (!e.isVisible) {
143              this.handlePopup = false
144            }
145          },
146          // Set the popup animation to a combination of opacity and translation effects, with no exit animation.
147          transition:TransitionEffect.asymmetric(
148            TransitionEffect.OPACITY.animation({ duration: 1000, curve: Curve.Ease }).combine(
149              TransitionEffect.translate({ x: 50, y: 50 })),
150            TransitionEffect.IDENTITY)
151        })
152        .position({ x: 100, y: 150 })
153
154      // CustomPopupOptions for setting the popup
155      Button('CustomPopupOptions')
156        .onClick(() => {
157          this.customPopup = !this.customPopup
158        })
159        .bindPopup(this.customPopup, {
160          builder: this.popupBuilder,
161          placement: Placement.Top,
162          showInSubWindow: false,
163          onStateChange: (e) => {
164            if (!e.isVisible) {
165              this.customPopup = false
166            }
167          },
168          // Set the popup entrance and exit animations to be a scaling effect.
169          transition:TransitionEffect.scale({ x: 1, y: 0 }).animation({ duration: 500, curve: Curve.Ease })
170        })
171        .position({ x: 80, y: 300 })
172    }.width('100%').padding({ top: 5 })
173  }
174}
175```
176
177![popup_transition](figures/popup_transition.gif)
178
179## Creating a Custom Popup
180
181You can create a custom popup with **builder** in **CustomPopupOptions**, defining custom content in \@Builder. In addition, you can use parameters such as **popupColor** to control the popup style.
182
183```ts
184@Entry
185@Component
186struct Index {
187  @State customPopup: boolean = false
188  // Define the popup content in the popup builder.
189  @Builder popupBuilder() {
190    Row({ space: 2 }) {
191      Image($r("app.media.icon")).width(24).height(24).margin({ left: 5 })
192      Text('This is Custom Popup').fontSize(15)
193    }.width(200).height(50).padding(5)
194  }
195  build() {
196    Column() {
197      Button('CustomPopupOptions')
198        .position({x:100,y:200})
199        .onClick(() => {
200          this.customPopup = !this.customPopup
201        })
202        .bindPopup(this.customPopup, {
203          builder: this.popupBuilder, // Content of the popup.
204          placement:Placement.Bottom, // Position of the popup.
205          popupColor:Color.Pink // Background color of the popup.
206          onStateChange: (e) => {
207            if (!e.isVisible) {
208              this.customPopup = false
209            }
210          }
211        })
212    }
213    .height('100%')
214  }
215}
216```
217
218To place the popup in a specific position, set the **placement** parameter. The popup builder triggers a popup message to instruct the user to complete the operation.
219
220![en-us_other_0000001500900234](figures/en-us_other_0000001500900234.jpeg)
221
222## Defining the Popup Style
223
224You can define the popup style using both builder-based customization and through specific API configurations.
225
226Background color: While popups initially come with a transparent background, they have a blur effect, which is **COMPONENT_ULTRA_THICK** on phones.
227Mask style: Popups come with a default mask that is transparent.
228Size: The size of a popup is determined by the content within the builder or the length of the message it holds.
229Position: Popups are located below their host component by default. You can control the display position and alignment using the **Placement** API.
230The following example demonstrates how to configure a popup's style using **popupColor**, **mask**, **width**, and **placement**.
231
232```ts
233// xxx.ets
234
235@Entry
236@Component
237struct PopupExample {
238  @State handlePopup: boolean = false
239
240  build() {
241    Column({ space: 100 }) {
242      Button('PopupOptions')
243        .onClick(() => {
244          this.handlePopup = !this.handlePopup
245        })
246        .bindPopup(this.handlePopup, {
247          width: 200,
248          message: 'This is a popup.',
249          popupColor: Color.Red, // Set the background color for the popup.
250          mask: {
251            color: '#33d9d9d9'
252          },
253          placement: Placement.Top,
254          backgroundBlurStyle: BlurStyle.NONE // Remove the blur effect for the popup.
255        })
256    }
257    .width('100%')
258  }
259}
260```
261
262![image](figures/UIpopupStyle.gif)
263