I have been playing around with some simple data visuals on Power Apps. This is an area that clearly needs improvement, in my humble opinion, since the default canvas Power Apps charts are really not that amazing and because in an automation solution it is interesting to have the analytics layer integrated with the User Interface / User Experience. Together, these two allow for action – not analysis alone.
In short, this is what I’ve found: you can go a long way with user defined functions (UDF) in Power Apps that take data values as arguments and create SVG charts as outputs.
What are User Defined Functions (UDFs) in Power Apps?
In Power Apps, User Defined Functions (UDFs) are essentially reusable formulas or pieces of logic that you define once and call multiple times throughout your app. Unlike typical formulas that are tied to specific controls or data cards, UDFs are stored centrally in the Formulas property of your app, making it more modular, easier to maintain, and much cleaner to read.
Think of them as the Power Apps version of functions in traditional programming languages — you pass parameters to them, and they return a value (in this case, often a string of SVG code, a calculation, or a formatted output).
In order to create and use UDFs in Power Apps, you must activate them through the “Settings” panel:
So now you may write the definition of the UDFs in the Formulas property of your app, and they’ll be ready to be used everywhere in your app.
What is SVG and how can it be used in Power Apps?
SVG stands for Scalable Vector Graphics. It’s an XML-based format for describing two-dimensional graphics such as shapes, lines, curves, and text. The big advantage of SVG is that, unlike traditional image formats (like PNG or JPEG), it’s resolution-independent — meaning it scales perfectly at any size without losing quality. Plus, because it’s text-based, it can be dynamically generated or modified using code.
In Power Apps, SVGs are incredibly powerful because they can be treated like any other string. You can dynamically generate SVG code using Power Fx formulas and display it inside a Label or HTML Text control. This opens up a world of possibilities: from simple shapes and icons to fully customized charts and dashboards, all driven by your app’s data.
For example, by calculating values (like sales percentages, progress bars, or performance indicators) within your app, you can feed those values into an SVG template and render visuals that adapt in real-time based on user interaction or underlying data changes.
The thing I like the most about SVG in canvas Power Apps is that everything is contained within your Power App — no need to embed images or use external chart libraries. No external dependencies!
Building data visuals with SVG and User Defined Functions in a Power Apps canvas app
To create these visuals, we’ll use the Image control from the Modern controls stack. Make sure to enable Modern controls in the Settings panel first:
Now, add an Image control to a screen and enter the following code in the Image property:
"data:image/svg+xml;utf8," & EncodeUrl(" <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20' width='100%' height='100%'> <style> .fill-bar { animation: fillprogress 1.5s ease-in-out forwards; } @keyframes fillprogress { from { width: 1px; } to { width: 80px ; } } </style> <!-- Fundo da barra --> <rect x='0' y='5' width='100' height='10' fill='rgb(33,38,43)' opacity='0.15' rx='5' ry='5'></rect> <!-- Barra de progresso animada --> <rect class='fill-bar' x='0' y='5' width='1' height='10' fill='#30A97F' rx='5' ry='5'></rect> </svg>")
This code dynamically generates an SVG image and displays it in the Image control by setting its Image property. Specifically, it creates a progress bar visual with a smooth animation effect:
- The data:image/svg+xml;utf8, prefix tells Power Apps that the image is an inline SVG.
- EncodeUrl() ensures the SVG code is properly URL-encoded so it can be rendered correctly.
Inside the SVG:
- A background rectangle (rect) acts as the progress bar’s base, with a subtle opacity.
- Another rectangle represents the animated progress bar, starting from width 1px and smoothly expanding to 80px using the @keyframes fillprogress animation.
- Styling and animation are handled directly within the <style> tags, making the visual both scalable and dynamic.
The result would be something like this:
We now have a green progress bar that can be used to track the result of an indicator versus a target. The green area represents the proportion of the achievement and is now a static 80% value.
Suppose we want to reuse this visual in multiple screens within our app and we want to calculate the value dynamically with Power Fx and choose whatever color we want. To do this, we need to create a UDF, like the following:
/// -- Barra Progresso Personalizável fncBarraProgreso(ValorProgresso: Text, CorBarra: Text): Text = "data:image/svg+xml; utf8, " & EncodeUrl( "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 20' width='100%' height='100%'> <style> .fill-bar { animation: fillprogress 1.5s ease-in-out forwards; } @keyframes fillprogress { from { width: 0%; } to { width: " & ValorProgresso & "%; } } </style> <!-- Fundo da barra --> <rect x='0' y='5' width='100' height='10' fill='rgba(33, 38, 43, 0.15)' rx='5' ry='5'></rect> <!-- Barra de progresso animada --> <rect class='fill-bar' x='0' y='5' width='0' height='10' fill='" & CorBarra & "' rx='5' ry='5'></rect> </svg>" );
This function takes two parameters: the value and the bar color, and it may be used with an Image control like:
fncBarraProgreso(70, "#FF5733")
Which will now render the following animated visual with a different color for the values you choose or are dynamically calculated:
Evolving the solution: Building a visual component library
Once you have a solid, flexible SVG-based visual functions like fncBarraProgreso, the next step is to scale and standardize your visuals by creating a Component Library. This allows you to centralize all your custom visuals — not just progress bars, but also other types of charts and UI elements — and reuse them across multiple apps with consistency.
Why Create a Visual Component Library?
- Reusability: Use the same components in multiple apps without rewriting formulas.
- Consistency: Ensure a cohesive look and feel across your organization’s Power Apps.
- Maintenance: Update the visuals or logic in one place, and changes propagate automatically to all apps using the library.
- Scalability: Add new visual types (e.g., pie charts, gauges, icons) as needed without cluttering each individual app.
For example, the following card could be achieved, combining the SVG function we just described and a component library:
The input properties of this component are:
- The value of the indicator (50 in this example)
- Border color
- Text color
- Border radius
- Indicator name (“Taxa anual de crescimento faturação” in this exemple)
- Bar color (green in this example)
- Target
- Use of decimals or integers
- the possibilities are endless!
Here’s another example of a more elaborate component that compares the achievement of an indicator versus its target.
In this case, we are creating a circle, in which the actual result (20) is compared with the target (100). Here we have the indicator name, the actual value and the proportion. And we can replicate this idea and create other interesting visuals, like gauges, bullet charts, and others.
For example, this visual shows a gauge for the number of customers KPI. The target is 60, but we only achieved 30 so far.
And a simple bullet chart. Note that we may add labels to show the actual values and the targets:
The interesting part here is that instead of switching between dashboards (Power BI, Excel, etc.) and the app where actions are taken, users can see the data and act immediately — all in one place. This reduces friction and speeds up decision-making and by connecting visuals directly to app data sources (Dataverse, SharePoint, SQL, etc.), you ensure that data is always up-to-date and visuals can change dynamically based on user inputs, filters, or selections within the app.