Skip to content

Commit adcca2c

Browse files
authored
Animated Accordion (#91)
Animated accordion component implemented using native components in Power Apps Canvas. Great for FAQ and any other foldable UI objects.
2 parents 47b6d68 + 9025b87 commit adcca2c

File tree

8 files changed

+744
-0
lines changed

8 files changed

+744
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Animated Accordions
2+
3+
Animated accordion component implemented using native components in Power Apps Canvas. Great for FAQs, navigation menus, interactive forms, and any other foldable UI objects that require content organization.
4+
5+
> [!WARNING]
6+
> All native Power Apps snippets offer limited performance in Studio mode. If you see any performance issues, test via published app/player mode first!
7+
8+
### Animated Accordion
9+
Basic accordion dedicated to FAQ content. Row items are dynamically generated on Gallery items, all content is passed directly to text fields.
10+
![preview](./assets/animated-accordion-demo.gif)
11+
12+
### Animated Form
13+
Manually built container set, inspired on top of the idea of an animated accordion. It can scale to any number of items. Great for building forms and menus.
14+
![preview](./assets/animated-form-demo.gif)
15+
16+
17+
## Authors
18+
19+
Author|Socials
20+
--------|---------
21+
Jan Chlebek | [LinkedIn](https://www.linkedin.com/in/jan-chlebek/) - ([GitHub](https://github.com/jan-chlebek) )
22+
23+
## Minimal path to awesome
24+
25+
1. Open your Power App in edit mode
26+
2. Copy the contents of either the **[animated-accordion.pa.yaml](./source/animated-accordion.pa.yaml)** or **[animated-form.pa.yaml](./source/animated-form.pa.yaml)** depending on your preference
27+
3. Right-click on the screen where you want to add the snippet and select `Paste`
28+
29+
## Disclaimer
30+
31+
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
32+
33+
<img src="https://m365-visitor-stats.azurewebsites.net/powerplatform-snippets/power-apps/animated-accordions" aria-hidden="true" />
1.75 MB
Loading
Binary file not shown.
1.68 MB
Loading
Binary file not shown.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[
2+
{
3+
"$schema": "https://developer.microsoft.com/en-us/json-schemas/pnp/samples/v1.0/metadata-schema.json",
4+
"name": "pnp-powerplatform-snippets-animated-accordions",
5+
"version": "1.0.0.0",
6+
"source": "pnp",
7+
"creationDateTime": "2025-05-22T00:00:00.000Z",
8+
"updateDateTime": "2025-05-22T00:00:00.000Z",
9+
"title": "Animated Accordions",
10+
"shortDescription": "Animated accordion component implemented using native components in Power Apps Canvas.",
11+
"longDescription": [
12+
"Animated accordion component implemented using native components in Power Apps Canvas. Great for FAQ, navigation menus, interactive forms and any other foldable UI objects that require content organization."
13+
],
14+
"url": "https://github.com/pnp/powerplatform-snippets/tree/main/power-apps/animated-accordions/",
15+
"products": [
16+
"Power Platform",
17+
"Power Apps",
18+
"powerplatform-snippets",
19+
"power-apps-snippets"
20+
],
21+
"tags": [
22+
],
23+
"categories": [
24+
],
25+
"thumbnails": [
26+
{
27+
"type": "image",
28+
"order": 100,
29+
"url": "https://raw.githubusercontent.com/pnp/powerplatform-snippets/main/power-apps/animated-accordions/assets/animated-accordion-demo.gif",
30+
"alt": "Preview GIF - Animated Accordion"
31+
},
32+
{
33+
"type": "image",
34+
"order": 100,
35+
"url": "https://raw.githubusercontent.com/pnp/powerplatform-snippets/main/power-apps/animated-accordions/assets/animated-form-demo.gif",
36+
"alt": "Preview GIF - Animated Form"
37+
}
38+
],
39+
40+
"metadata": [
41+
{
42+
"key": "Product",
43+
"value": "Power Apps"
44+
},
45+
{
46+
"key": "Type",
47+
"value": "Snippet"
48+
}
49+
],
50+
"authors": [
51+
{
52+
"gitHubAccount": "jan-chlebek",
53+
"name": "Jan Chlebek",
54+
"pictureUrl": "https://github.com/jan-chlebek.png"
55+
}
56+
]
57+
}
58+
]
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
- cntAnimatedAccordion:
2+
Control: GroupContainer@1.3.0
3+
Variant: ManualLayout
4+
Properties:
5+
ContentLanguage: |-
6+
=""
7+
/*
8+
Animated Form - Canvas App code snippet
9+
Author: Jan Chlebek, May 2025
10+
Linkedin: https://www.linkedin.com/in/jan-chlebek/
11+
GitHub: https://github.com/jan-chlebek
12+
*/
13+
DropShadow: =DropShadow.None
14+
Height: =galAccordion.Height
15+
RadiusBottomLeft: =0
16+
RadiusBottomRight: =0
17+
RadiusTopLeft: =0
18+
RadiusTopRight: =0
19+
Width: =galAccordion.Width
20+
X: =422
21+
Y: =156
22+
Children:
23+
- galAccordion:
24+
Control: Gallery@2.15.0
25+
Variant: VariableHeight
26+
Properties:
27+
ContentLanguage: |-
28+
=""
29+
/*
30+
Animated Accordion - Canvas App code snippet
31+
Author: Jan Chlebek, May 2025
32+
Linkedin: https://www.linkedin.com/in/jan-chlebek/
33+
GitHub: https://github.com/jan-chlebek
34+
*/
35+
Height: =Self.AllItemsCount * cntAccordionHeader.Height + Self.MaxTemplateSize
36+
Items: |-
37+
=[
38+
{Header: "Is it doable?", Value: "DOABLE. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."},
39+
{Header: "Is it styled?", Value: "STYLED. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. "},
40+
{Header: "Is it animated?", Value: "ANIMATED. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. "},
41+
]
42+
MaxTemplateSize: =Self.TemplateHeight
43+
Width: =500
44+
Children:
45+
- shpAccordionSpacer:
46+
Control: Rectangle@2.3.0
47+
Properties:
48+
Height: =0.5
49+
OnSelect: =Select(Parent)
50+
Width: =Parent.TemplateWidth - cntAccordionContent.PaddingLeft - cntAccordionContent.PaddingRight - cntAccordionContent.RadiusBottomLeft - cntAccordionContent.RadiusBottomRight
51+
X: =cntAccordionContent.PaddingLeft + cntAccordionContent.RadiusBottomLeft
52+
Y: =cntAccordionContent.Height-2
53+
- cntAccordionContent:
54+
Control: GroupContainer@1.3.0
55+
Variant: AutoLayout
56+
Properties:
57+
DropShadow: =DropShadow.None
58+
Height: "=46 + If(\r\n // As animation do not work in Studio Editor, additional state is added to ensure app can be fully tested\r\n StartsWith(Host.Version, \"PowerApps-Studio\"),\r\n If(ThisItem.Header = lclCurrentSelectedAccordionItem, txtAccordionItem.Height),\r\n\r\n With(\r\n {_timerStep: tmrAccordionTimer.Value / tmrAccordionTimer.Duration},\r\n If(\r\n ThisItem.Header = lclCurrentSelectedAccordionItem, \r\n txtAccordionItem.Height * (_timerStep) * (2 - _timerStep), \r\n\r\n ThisItem.Header = lclLastSelectedAccordionItem,\r\n txtAccordionItem.Height* (1 - (_timerStep) * (2 - _timerStep)),\r\n \r\n 0\r\n )\r\n )\r\n)"
59+
LayoutDirection: =LayoutDirection.Vertical
60+
PaddingBottom: =2
61+
PaddingLeft: =2
62+
PaddingRight: =2
63+
PaddingTop: =2
64+
Width: =Parent.TemplateWidth
65+
Children:
66+
- cntAccordionHeader:
67+
Control: GroupContainer@1.3.0
68+
Variant: AutoLayout
69+
Properties:
70+
AlignInContainer: =AlignInContainer.SetByContainer
71+
DropShadow: =DropShadow.None
72+
Fill: =Color.White
73+
FillPortions: =0
74+
Height: =40
75+
LayoutAlignItems: =LayoutAlignItems.Center
76+
LayoutDirection: =LayoutDirection.Horizontal
77+
Width: =Parent.Width - Parent.PaddingLeft - Parent.PaddingRight
78+
Children:
79+
- btnAccordionTitle:
80+
Control: Button@0.0.45
81+
Properties:
82+
Align: =Align.Left
83+
Appearance: ='ButtonCanvas.Appearance'.Transparent
84+
IconStyle: ='ButtonCanvas.IconStyle'.Outline
85+
OnSelect: =Select(btnAccordionChevron)
86+
Text: =ThisItem.Header
87+
Width: =Parent.Width - btnAccordionChevron.Width
88+
- btnAccordionChevron:
89+
Control: Button@0.0.45
90+
Properties:
91+
Appearance: ='ButtonCanvas.Appearance'.Transparent
92+
Icon: ="ChevronDown"
93+
IconRotation: "=\r\nIf(\r\n ThisItem.Header = lclCurrentSelectedAccordionItem, \r\n If(\r\n StartsWith(Host.Version, \"PowerApps-Studio\"),\r\n 180,\r\n tmrAccordionTimer.Value / tmrAccordionTimer.Duration * 180\r\n ),\r\n\r\n ThisItem.Header = lclLastSelectedAccordionItem,\r\n If(\r\n StartsWith(Host.Version, \"PowerApps-Studio\"),\r\n 0,\r\n (1 - tmrAccordionTimer.Value / tmrAccordionTimer.Duration) * 180\r\n ),\r\n \r\n 0\r\n)"
94+
Layout: ='ButtonCanvas.Layout'.IconOnly
95+
OnSelect: |
96+
=Reset(tmrAccordionTimer);
97+
UpdateContext({lclStartTimer: false});
98+
UpdateContext({
99+
lclStartTimer: true,
100+
lclLastSelectedAccordionItem: lclCurrentSelectedAccordionItem,
101+
lclCurrentSelectedAccordionItem: If(lclCurrentSelectedAccordionItem = ThisItem.Header, Blank(), ThisItem.Header)}
102+
)
103+
Text: =ThisItem.Header
104+
Width: =32
105+
- txtAccordionItem:
106+
Control: Text@0.0.51
107+
Properties:
108+
AutoHeight: =true
109+
Height: =40
110+
PaddingBottom: =10
111+
PaddingLeft: =5
112+
PaddingRight: =5
113+
PaddingTop: =10
114+
Text: =ThisItem.Value
115+
Visible: |-
116+
=// To ensure proper tabulation support and component memory management, we hide item content when it won't be visible. Without this statement, when tabulating through the component, the user could see its content without expanding it and breaking the UI
117+
ThisItem.Header = lclCurrentSelectedAccordionItem || (ThisItem.Header = lclLastSelectedAccordionItem && lclStartTimer)
118+
Width: =Parent.Width - Parent.PaddingLeft - Parent.PaddingRight
119+
Y: =40
120+
- tmrAccordionTimer:
121+
Control: Timer@2.1.0
122+
Properties:
123+
AutoPause: =false
124+
AutoStart: =true
125+
Duration: =400
126+
OnTimerEnd: |-
127+
=UpdateContext({lclStartTimer: false})
128+
Start: =lclStartTimer
129+
Text: =Self.Value
130+
Visible: =false
131+
Y: =360

0 commit comments

Comments
 (0)