# What is Digia Studio?

**Digia Studio** is a low-code workspace for building native mobile apps with a server-driven UI (SDUI) engine. You design pages, bind data, and wire actions in the browser, while Digia ships that configuration to lightweight SDKs in real-time. This lets you deploy instant updates without waiting for app store builds.

Digia combines native performance with instant updates for copy, layouts, and experiments. It empowers developers, designers, and product managers to ship faster, from MVP to production scale.

{% embed url="<https://www.youtube.com/watch?v=rpwtwesOI2o>" %}

### Why Digia Studio?

Traditional native development slows you down with long review cycles and rigid builds. Digia Studio decouples your UI from your binary to enable:

* **Instant Updates** – Push configuration changes through Digia Hot Reload; no app store reviews required.
* **Extend with Code** – Write custom widgets or native modules in Swift/Kotlin/Dart when you need more than the built-in library.
* **Safe Release Workflows** – Manage `dev`, `staging`, and `prod` environments with built-in versioning and rollback.
* **Design System Sync** – Share reliable components and tokens across teams to prevent UI drift.
* **Role-Based Access** – Designers own the pixels, PMs own the copy, and you own the logic.

***

### How it Works

Digia decoupled the visual layer from the underlying native code, enabling a seamless workflow from design to deployment.

{% @mermaid/diagram content="graph LR
%% Styles
classDef studio fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#01579b;
classDef cloud fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#e65100;
classDef app fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px,color:#1b5e20;

```
subgraph Studio [Digia Studio]
    direction TB
    Builder[Visual Builder]:::studio
end

subgraph Cloud [Digia Cloud]
    direction TB
    JSON[JSON Config]:::cloud
end

subgraph App [Your App]
    direction TB
    SDK[Digia SDK]:::app
    Native[Native Components]:::app
end

Builder ==>|Publishes| JSON
JSON ==>|Syncs to| SDK
SDK -.->|Renders| Native

%% Spacing hacks
linkStyle default stroke-width:2px,fill:none,stroke:gray;" %}
```

For a deep dive into the request flow and rendering engine, read the [Digia Architecture & Runtime](/introduction/architecture) guide.

***

### The Building Blocks

* **Server-Driven UI (SDUI)** – UI and logic ship as JSON, not compiled binaries. See [What is SDUI?](/introduction/what-is-sdui)
* **Pages & Components** – Pages are full screens; components are reusable pieces with their own inputs and actions.
* **Variables & Actions** – Variables store state; actions update that state, call APIs, or navigate.
* **Environments** – Each environment (dev, staging, prod) has unique access keys and release history.

***

### Who Is It For?

* **Frontend & mobile developers** – Build logic, wire APIs, and extend the runtime when needed.
* **Designers / UX engineers** – Turn design systems into live components without Xcode or Android Studio.
* **Product and growth teams** – Launch experiments or localized flows with guardrails and auditability.
* **Agencies and enterprises** – Manage multiple apps or brands from one shared workspace.

***

### Is Digia Studio right for your use case?

**Good fit when you need**

* Fast iterations on content-heavy or transactional apps
* Shared UI across iOS and Android without duplicating work
* A/B tests, merchandising, or onboarding tweaks that can’t wait for app-store review
* Hooks for custom analytics, payments, or platform SDK features

**Probably not ideal when you need**

* Always-offline apps with large local datasets
* Highly custom native rendering (AR, heavy 3D, high-frequency graphics)
* Real-time workloads that are better in handwritten code

***

### Choose your next step

* **Brand new?** Complete the [Quick Start Guide](/quick-start-and-setup/quick-start).
* **Need the preview app and workspace access?** Follow [Setup](/quick-start-and-setup/setup).
* **Want runtime details?** Read the [Digia Architecture & Runtime](/introduction/architecture) guide.
* **Embedding Digia in an existing app?** Visit [SDK Integration](/sdk-integration/sdk-integration).

***


# What is SDUI?

**Server-Driven UI (SDUI)** is an architectural pattern where the server controls the layout, content, and logic of a native application. Instead of hardcoding screens in the app binary, the device renders a UI based on a JSON configuration sent by the backend.

Basically: **The server defines&#x20;*****what*****&#x20;to show; the app knows&#x20;*****how*****&#x20;to render it.**

## Client-Driven vs Server-Driven

<div align="center"><img src="/files/vDojg9fcszRmSpd0c1ZQ" alt="SDUI vs CDUI comparison" width="100%"></div>

Traditional mobile development is **Client-Driven**: logic and layout are hardcoded in the app binary. This is like the early days of desktop software—to change anything, you must ship a new version.

**Server-Driven UI (SDUI)** flips this model. It operates like a modern web browser.

Just as a browser renders HTML & CSS sent from a server, an SDUI app renders native widgets based on a JSON schema.

```html
<!-- Web: The Browser receives structure -->
<div class="card">
  <h1>Welcome Back</h1>
  <button onclick="login()">Sign In</button>
</div>
```

```json
// SDUI: Example JSON structure
{
  "type": "column",
  "style": "card",
  "children": [
    { "type": "text", "value": "Welcome Back", "style": "h1" },
    { "type": "button", "label": "Sign In", "action": "login" }
  ]
}
```

This allows you to ship updates, run experiments, and change layouts instantly, decoupling your release cycle from the App Store.

## SDUI vs. CMS: Spotting the Difference

You might be thinking, "**Isn't this just a Headless CMS?**" It’s a fair question, but the difference is fundamental.

**Think of a CMS like a Coloring Book.** The outlines (layout) are already printed. You can choose to color the sky blue or purple (content), but you can’t move the sun or turn the tree into a car. The structure is fixed.

**SDUI is like a LEGO set.** The server gives you the bricks *and* the instruction manual. It sends a payload that says, "Take these header bricks, snap them onto this list, and put a button at the bottom." Today you build a castle; tomorrow you build a spaceship.

<div align="center"><img src="/files/ODzWf6WDP60HoWtvYeTJ" alt="SDUI vs CMS comparison" width="100%"></div>

### The Breakdown

* **Architectural Focus**: CMS sends **data** (Text/Images). SDUI sends **UI definitions** (View Models).
* **Level of Control**: With a CMS, the *Client* decides how to present content. With SDUI, the *Server* dictates the layout.
* **The Difference**: CMS lets you change the paint; **SDUI lets you move the walls**.

## Why Developers Choose SDUI

* **Instant Updates**: Ship bug fixes, copy changes, or entire new flows instantly without waiting for App Store/Play Store review.
* **Cross-Platform Consistency**: Define your UI once in JSON and have it render natively on both iOS and Android.
* **Faster Experimentation**: Run A/B tests on layouts or components by simply serving different JSON responses to different users.
* **Thinner Clients**: Logic moves to the server, making the client app lighter and focused purely on performant rendering.

## Trade-offs to Consider

* **Offline Handling**: Since the UI definition comes from the server, you need a robust caching strategy for offline experiences.
* **Complex Gestures**: Highly interactive functionalit (like complex games or heavy animations) is often better implemented purely natively.
* **Debugging**: Errors in the JSON schema can cause rendering failures, requiring good validation tools.

## How Digia Implements SDUI

**Digia Studio** gives you the best of both worlds: a visual interface to build the configuration, and a native engine to render it.

1. **Visual Definition**: You build screens in the Digia Studio dashboard.
2. **JSON Generation**: Digia compiles your design into an optimized JSON schema.
3. **Native Rendering**: The Digia SDK (Flutter/React Native) interprets this JSON and renders **real native widgets**, ensuring 60fps performance and a native feel.


# Digia Architecture & Runtime

This guide details how Digia transforms a visual definition into a native mobile experience at runtime.

**Core Philosophy**: Just as a **Web Browser** reads HTML to render a webpage, the **Digia SDK** reads a JSON configuration to render Native Widgets. The Server sends the blueprint; the Device builds the house.

## 1. High-Level Architecture

Digia operates on a decoupled architecture where the UI definition is separated from the rendering logic.

* **Digia Studio (The IDE)**: A specialized environment for building server-driven apps. It handles static analysis, data binding, visual layout, and state management to produce a robust UI definition.
* **Digia Cloud (The CDN)**: Hosts the compiled JSON configuration, ensuring global low-latency availability.
* **Digia SDK (The Runtime)**: A lightweight engine inside your app that fetches the configuration and renders native components.

{% @mermaid/diagram content="graph LR
%% Styles
classDef studio fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#01579b;
classDef api fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#e65100;
classDef client fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px,color:#1b5e20;

```
subgraph Design [Design Time]
    Studio[Digia Studio]:::studio
    Compiler[Compiler Service]:::studio
end

subgraph Runtime [Runtime]
    CDN[Edge CDN]:::api
    SDK[Digia SDK]:::client
end

Studio -->|Save & Compile| Compiler
Compiler -->|Publish JSON| CDN
CDN -->|Fetch Config| SDK" %}
```

## 2. The Protocol (JSON Schema)

The core communication language between Digia Cloud and your app is the **SDUI JSON Protocol**.

Unlike traditional APIs that just fetch *data* (e.g., a list of users), the Digia configuration contains **everything** needed to run the module:

* **Pages & Navigation**: The structure of every screen.
* **Components & Styling**: Layouts, colors, fonts, and themes.
* **Logic & Actions**: What happens when a user taps a button or submits a form.
* **API Calls**: Definitions of network requests to your own backend.

```json
{
  "appSettings": {
    "initialRoute": "home"
  },
  "pages": {
    "home": {
      "layout": {
        "root": {
          "type": "scaffold",
          "props": { "backgroundColor": "#FFFFFF" },
          "children": {
            "body": [
              {
                "type": "text",
                "props": {
                  "text": "Hello, Server-Driven World!",
                  "style": { "fontSize": 24, "color": "#000000" }
                }
              },
              {
                "type": "button",
                "props": { "label": "Click Me" },
                "actions": { "onTap": "navigateToSettings" }
              }
            ]
          }
        }
      }
    }
  }
}
```

## 3. The Runtime (Digia UI SDK)

The Digia SDK (available for Flutter, React Native, iOS, Android) is the engine that interprets the protocol. It is not just a UI mapper; it is a full-fledged runtime environment composed of some key layers:

{% @mermaid/diagram content="graph TD
%% Styles
classDef layer fill:#e3f2fd,stroke:#1565c0,stroke-width:2px;
classDef core fill:#fff3e0,stroke:#e65100,stroke-width:2px;

```
subgraph SDK [Digia SDK Runtime]
    direction TB
    Config[Config Manager]:::layer
    Renderer[Recursive Renderer]:::core
    State[State Manager]:::layer
    Logic[Actions & Expressions]:::layer

    Config --> Renderer
    Renderer <--> State
    Renderer <--> Logic
end" %}
```

### 3.1 Core Engine (Recursive Renderer)

At its core, the SDK is a **Recursive Renderer**. It loops through the JSON tree and instantiates the native widgets.

* **Direct Mapping**: Each JSON node translates directly to a native widget. There is no "Virtual DOM" layer.
* **Reactive Updates**: When state changes, the SDK simply rebuilds the affected part of the tree. It relies on the native platform (Flutter, SwiftUI, Compose) to render the changes efficiently.

{% hint style="info" %}
**Performance**: Since the SDK maps JSON directly to **Native Widgets** (e.g., `UIButton`, `RecyclerView`), you get 60fps scrolling and native gesture handling. There are no WebViews involved.
{% endhint %}

### 3.2 State Management System

Digia manages data at multiple levels, ensuring that complex apps can be built without fighting the framework:

1. **Global Store**: App-wide data (e.g., User Profile, Auth Token) accessible from any page.
2. **Page State**: Data scoped to a single screen (e.g., Form data).
3. **Local State**: Ephemeral state for individual components (e.g., Is this dropdown open?).

### 3.3 Logic & Interactivity

The SDK handles dynamic behavior without needing a server round-trip for every action:

* **Expression Library**: Supports dynamic bindings like `${user.name}` or conditional visibility `${gt(cart.total, 0)}`.
* **Actions Manager**: Orchestrates events such as navigation, API calls, or state updates (e.g., `onTap: navigateToPage`).

### 3.4 Config Manager (Network & Caching)

This layer handles the synchronization of your UI definition. It is responsible for fetching, caching, and validating the JSON/Protobuf payload.

{% @mermaid/diagram content="sequenceDiagram
%%{init: {'theme': 'base', 'themeVariables': { 'mainBkg': '#ffffff', 'textColor': '#000000', 'background': '#fff3e0' }}}%%
participant App as Client App
participant SDK as Digia SDK
participant Cloud as Digia Cloud

```
App->>SDK: Initialize SDK
SDK->>Cloud: Check for Updates (Current Version)
Cloud->>Cloud: Compare with Published Version
alt New Version Available
    Cloud-->>SDK: Return New JSON Config
    SDK->>SDK: Update Cache & Render
else Version Match
    Cloud-->>SDK: 304 Not Modified
    SDK->>SDK: Load from Local Cache
end" %}
```

You can configure the update strategy based on your app's needs:

1. **Sync Fetch (Instant Updates)**:
   * On startup, the SDK checks for a new version.
   * If available, it downloads and applies it **immediately** for the current session.
   * *Best for:* Critical fixes or apps that must always show the latest content.
2. **Async Fetch (Background Updates)**:
   * On startup, the SDK immediately requires the **cached** config (zero latency).
   * It checks for updates in the **background**. If a new version is found, it is downloaded silently and saved.
   * The *next* app session will use the new configuration.
   * *Best for:* Optimizing startup time and non-critical updates.

{% hint style="info" %}
**Resilience & Offline Mode**: Our global CDN is backed by industry-standard cloud infrastructure, ensuring 99.99% uptime. However, in the unlikely event of a service disruption or network failure, the app remains fully functional by seamlessly falling back to its **local cache**.
{% endhint %}

## 4. Adoption Strategy: Start Small

You do not need to rebuild your entire app to use Digia. The architecture supports **Incremental Adoption**.

* **Widget Integration**: Use Digia for a single dynamic section, like a "Holiday Sale" banner or a "Feedback Form".
* **Screen Integration**: Embed a Digia view inside an existing native screen.
* **Flow Integration**: Build an entire "Explore" tab or "Onboarding" flow in Digia while keeping the rest of the app as-is.

## 5. Extending the Runtime

Sometimes you need a specialized UI element that isn't in the standard library (e.g., a 3D Model Viewer or a specialized Camera view).

**Custom Widgets** allow you to register your own native components with the SDK. Once registered, you can drop them into the Digia Studio visual builder just like any other component. For implementation details, see [Building Custom Widgets](/extend-and-ship/custom-widgets).

```dart
void registerCustomButton() {
  DUIFactory().registerWidget<CustomButtonProps>(
    'custom/button-v1', // Unique ID used in Digia Studio
    CustomButtonProps.fromJson,
    (props, childGroups) => CustomButton(
      props: props,
      commonProps: null,
      parent: null,
      refName: 'custom_button',
    ),
  );
}
```


# Why Dynamic Apps & SDUI Adoption

Mobile development has historically been "Static"—once you ship an app to the store, it's frozen in time until the user updates it. This slows down product teams, marketing campaigns, and critical bug fixes.

**Dynamic Apps** break this cycle. By adopting Server-Driven UI (SDUI), you allow your application to evolve at the speed of the web, while retaining native performance.

## The Case for Dynamic Apps

### 1. Escaping the "App Store Tax"

Not the 30% revenue cut, but the **Time Tax** on innovation.

Traditional workflows demand a full release cycle (build, submit, review, user update) for even minor changes. This process can take days or weeks.

**Dynamic Apps bypass this bottleneck.** By fetching UI configurations over the network, updates are applied instantly—just like deploying a website—without waiting for App Store approvals.

{% @mermaid/diagram content="graph LR
%% Styles
classDef bad fill:#ffebee,stroke:#c62828,stroke-width:2px,color:#c62828;
classDef good fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px,color:#1b5e20;

```
subgraph Traditional ["Traditional Release (Weeks)"]
    direction LR
    Fix[Code Fix] --> Build --> Submit --> Review[App Review] --> Update[User Update]
end

subgraph Dynamic ["Dynamic Release (Seconds)"]
    direction LR
    JsonFix[JSON Fix] --> Publish --> Instant[Instant Update]
end

class Traditional bad
class Dynamic good" %}
```

### 2. Marketing & Operations Autonomy

Marketing teams often need to run flash sales, update holiday banners, or change featured collections.

* **Without SDUI**: "Can we squeeze this banner into the next sprint?" (Often "No").
* **With SDUI**: Marketing updates the JSON configuration (via a dashboard/CMS) and the app updates instantly. Engineering isn't the bottleneck.

### 3. Personalization & A/B Testing

Running experiments on native apps is notoriously hard. With Dynamic Apps, you can serve different layouts to different user segments from the server:

* **New Users**: Show a simplified "Getting Started" home page.
* **Power Users**: Show dense data tables and advanced dashboards.

## Adoption Strategies: How to Start

You don't need to rewrite your entire application. Most teams adopt SDUI incrementally.

{% @mermaid/diagram content="graph TD
%% Styles taken from README.md
classDef studio fill:#e1f5fe,stroke:#01579b,stroke-width:2px,color:#01579b;
classDef cloud fill:#fff3e0,stroke:#e65100,stroke-width:2px,color:#e65100;
classDef app fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px,color:#1b5e20;

```
Level1[Level 1: Widget Integration] -->|Grow| Level2[Level 2: Screen Integration]
Level2 -->|Scale| Level3[Level 3: Flow Integration]

Level1 --- L1Desc[Banner / Card]
Level2 --- L2Desc[Entire 'Home' Feed]
Level3 --- L3Desc[Onboarding Flow]

class Level1 studio
class Level2 app
class Level3 cloud" %}
```

### Level 1: Widget Integration

Start with a single, highly volatile component.

* **Use Case**: A "Promotional Banner" or "Announcement Card" on the home screen.
* **Risk**: Near Zero. If it fails, the rest of the app works.
* **Value**: Immediate capability to run promos without app updates.

### Level 2: Screen Integration

Power an entire dynamic screen while keeping navigation native.

* **Use Case**: The "Discover" or "Home" feed.
* **Architecture**: The native app handles the TabBar and Navigation. The internal content area is a Digia Surface.
* **Value**: Product Managers can reorder sections (e.g., move "Best Sellers" to the top) instantly.

### Level 3: Flow Integration

Build multi-screen flows that change frequently.

* **Use Case**: Onboarding wizards, Surveys, or Help Centers.
* **Value**: These flows change often based on analytics. SDUI lets you add/remove steps in the onboarding wizard without touching native code.

## When NOT to use SDUI

While powerful, SDUI isn't a silver bullet.

| Feature Type          | Recommendation | Reason                                                                           |
| --------------------- | -------------- | -------------------------------------------------------------------------------- |
| **Video Editor**      | 🔴 Native      | Requires heavy GPU usage, complex gestures, and low-level hardware access.       |
| **AR/VR**             | 🔴 Native      | Needs direct access to camera/sensors and 3D rendering engines.                  |
| **Complex Games**     | 🔴 Native      | Physics engines and high-frequency touch loops belong in native code (or Unity). |
| **Maps & Navigation** | 🟡 Native      | Heavy map rendering and complex interactive markers are best handled natively.   |
| **Settings Page**     | 🟡 Native      | Usually static. Doesn't change often enough to justify fetching config.          |
| **Home Feeds**        | 🟢 **SDUI**    | Highly dynamic content, frequent reordering, diverse card types.                 |
| **Profile Pages**     | 🟢 **SDUI**    | Standard layout, mostly data display.                                            |
| **Forms/Surveys**     | 🟢 **SDUI**    | Fields change often (e.g., adding a "Phone Number" field).                       |


# Quick Start Guide

Welcome to the Digia Studio Quickstart Guide! This guide is designed for those eager to dive right into building their first Digia Studio application. Here, you'll build a screen that lets users adjust the quantity of a product before adding it to their shopping cart.

This quickstart is designed to be straightforward and accessible, introducing you to basic Digia Studio concepts quickly.

## What you'll learn

• Creating layouts (add widgets) • Adding interactivity to UI elements • Managing state and data flow • Running your app in preview mode

The steps to build the app are as follows:

1. Create a new project
2. Building UI
3. Customize style
4. Manage state
5. Run the app

## 1. Create a new project

To kick off your project, the first step is to [create a new project](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/introduction/platform-overview/project.md) in Digia Studio.

## 2. Building UI

In this section, we'll see how to build the user interface (UI) for this feature. This involves creating a layout and adding various widgets to our page.

## 3. Customize Style

The next step is to customize the style of UI elements. This includes changing the colors, fonts, and sizes of your buttons and labels.

## 4. Manage State

Once your UI is set up, it's time to make your app interactive by adding state. This means setting up your app to respond to user interactions.

## 5. Run the App

Now that you've built and customized your app, it's time to run it. Digia Studio allows you to test a fully-functional version of your app in preview mode.

Congratulations! You've built your first app with Digia Studio.

## Problems?

If you're experiencing any issues with the app, ensure that you have followed the instructions correctly.

To seek assistance from the [Community Forum](https://community.digia.tech). If you're still encountering problems, don't hesitate to report the issue to our support team.


# Setup

## Setting Up Digia Studio

Before you begin building with Digia Studio, here’s how to get set up and start previewing your apps.

***

### What You'll Need

To use Digia Studio, you'll need:

* A web browser (we recommend Chrome)
* A Digia Studio account (sign up at [app.digia.tech](https://app.digia.tech/))
* A mobile device (iOS or Android) to preview your app
* The **Digia Preview App** installed from the App Store or Play Store (see below)

***

### Previewing Your App

To see your app in action during development, download the **Digia Preview App** on your phone.

#### Download for Android

[📲 Google Play Store](https://play.google.com/store/apps/details?id=com.digia.preview)

#### Download for iOS

[📲 Apple App Store](https://apps.apple.com/us/app/digia-preview/id6499570725)

Once installed:

1. Open the Digia Preview App.
2. Log in with your Digia Studio account.
3. Select the project and version you want to preview.
4. Start testing your app in real-time.

OR

If you want to run your Digia project inside your app read [SDK Integration Docs](/sdk-integration/sdk-integration).


# Dashboard

## Understanding the Dashboard

The Digia Studio dashboard is your command center for creating, managing, and launching mobile app projects. This section walks you through the main interface elements and how to use them effectively.

***

### Dashboard Overview

When you log into Digia Studio, you land on the **Projects Dashboard**, where you can create or access your app projects.

***

### Key Sections

#### 1. **Navigation Panel (Left Sidebar)**

This contains quick links to the main areas of Digia Studio:

* **Projects** – View and manage all your app projects
* **Templates (Coming Soon)** – Chose from a variety of pre build templates to ramp up quickly
* **Resources** – Link to documentation and helpful guides
* **Invitations** – Invite team members to collaborate on your workspace

***

#### 2. **Top Navigation**

* **🔔 Notifications**\
  View system notifications, version updates, and account-level messages.
* **👤 User Profile**\
  Displays your account info and provides access to account settings, plan details and app usage.

***

#### 3. **Main Workspace Area**

This is where your app projects appear. If you haven't created any projects yet, you’ll see a prompt to:

> **Create First Project**\
> “& bring your ideas into life.”

Clicking this opens the[ project creation flow](https://docs.digia.tech/studio-workspace/pages/PID4uhDuaW91cFCyo9GC#id-2.-creating-a-new-project), where you can name your project and choose starting configurations.

As you create more projects, they will populate this space for quick access and management.


# Builder Tool

## 🛠️ Builder Interface Overview

When you open a project, the builder is divided into five main sections that work together to help you visually design and configure your app:

***

### 1. 📚 [Navigation Menu](/studio-workspace/builder-tool/navigation-menu)

The [Navigation Menu](/studio-workspace/builder-tool/navigation-menu) is located on the far left of the screen. It allows you to switch between different functional areas of the project:

* **Builder** – Design your app visually.
* **Global State** – Manage shared app state and variables.
* **API** – Configure external data connections.
* **Theme** – Set colors, typography, and styles.
* **Functions** – Write reusable custom logic.
* **Versioning & Release** – Create and manage release versions.
* **Members** – Invite and manage team access.
* **Settings** – Project-level configuration.

***

### 2. 🧰 [Toolbar](/studio-workspace/builder-tool/tool-bar)

Located at the top of the canvas area, the Toolbar provides quick access to project-level actions:

* **Notifications** – View system updates and alerts.
* **Bug Reports** – Monitor known issues or system errors.
* **Connect to GitHub** – Link your project to a GitHub repository for version control.
* **Create Version** – Take a snapshot of the current project state for release or rollback.

***

### 3. 📄 [Pages & Widget Panel](/studio-workspace/builder-tool/pages-and-widgets-panel)

Positioned on the left side of the canvas:

* Shows the **current page name**, which can be clicked to switch between pages and components.
* The **➕ button** allows you to add new pages or reusable components.
* The **Widget Tree** shows the hierarchical structure of the current screen's UI.
  * You can reorder, nest, delete, duplicate, or wrap widgets directly in this panel.

***

### 4. 🎨 [Canvas Area](/studio-workspace/builder-tool/canvas-area)

The central workspace where you visually build your app UI:

* Displays a **live frame** of the selected page as it would appear on a mobile device.
* Includes controls at the top to:
  * **Undo/Redo** changes
  * **Change canvas background color**
  * **Toggle preview mode**
* A **widget list toggle** on the top-left corner allows you to access and drag new widgets onto the canvas.

***

### 5. ⚙️ [Properties Panel](/studio-workspace/builder-tool/properties-panel)

Located on the right side of the canvas, this panel updates based on the selected widget:

* Includes **default properties** for layout, appearance, and interactions.
* Below those, it displays **widget-specific properties** depending on the selected component (e.g., text, image, button).
* Allows binding values, adding logic, and customizing styles in a structured manner.

***

Each of these sections plays a key role in making the builder intuitive, flexible, and powerful for visual app development.


# Navigation Menu

## 🧭 Project Navigation Overview

When you open a project in our SaaS tool, the left-hand navigation pane provides quick access to all core areas of your app configuration. This guide walks you through each section and what you can do there.

***

### 📦 Builder

The **Builder** is your visual editor — a no-code/low-code interface to create, structure, and design pages for your app. Use it to:

* Add screens and layouts
* Drag and drop components
* Bind components to state or APIs
* Preview UI across devices

***

### 🌐 Global State

Manage your app’s state centrally. The **Global State** section allows you to:

* Define variables and stores shared across screens
* Set default values and persist state
* Watch live updates and bind state to UI elements

***

### 🔌 API

This is where you connect your app to external data. In the **API** section, you can:

* Add REST or GraphQL APIs
* Define request/response schemas
* Add authentication headers
* Test endpoints and use them in logic
* Mock Responses if your backend is not ready

***

### 🎨 Theme

Customize the look and feel of your app. The **Theme** tab lets you:

* Define color palettes and typography
* Configure and Add custom components that you create in code

***

### ⚙️ Functions

Add custom business logic using JavaScript. In the **Functions** section, you can:

* Write and organize reusable utility functions
* Test the functions with different values

***

### 🕒 Versioning & Release

Track changes and control releases. The **Versioning & Release** area allows you to:

* Create and manage versions of your app configuration
* Stage versions that are stable to give to QA
* Trigger release to production and manage rollouts

***

### 👥 Members

Invite collaborators to your project. In the **Members** section, you can:

* Add or remove team members
* Assign roles and permissions (Admin, Developer, Viewer, etc.)
*

***

### ⚙️ Settings

Configure project-level preferences and integrations.

***

> 📝 **Tip:** Hovering over an icon will show its label. This sidebar stays consistent across all your projects to help you navigate quickly.


# Tool Bar

## 🛠️ Project Toolbar Overview

The top toolbar in your project workspace provides quick access to essential tools and actions related to project collaboration, versioning, and monitoring. This guide explains each item in the toolbar from left to right.

\[ Insert image here ]

***

### 🔔 Notifications

Stay up to date with real-time alerts. This section includes:

* System messages
* Versioning activity
* Build or release alerts
* Workspace or project-level notifications

> 🔧 Hovering over the icon or clicking it will open a dropdown with detailed updates.

***

### 🐛 Bug Reports

The green badge with a bug icon shows the number of **open issues** or **bugs** related to this project. You can:

* Click the icon to view reported issues
* See unresolved or recent bugs
* Track active debugging and status

> ✅ Green badge = no known issues.\
> 🔴 Red badge = critical issues detected.

***

### 🔗 Connect to GitHub

{% hint style="success" %}
Available only on Teams Plan
{% endhint %}

Easily link your project to a GitHub repository. This enables:

* Create commits and branches for your team to work on
* Syncing project structure and changes
* Create pull requests

> 📝 You may be asked to authenticate or select a repository when connecting for the first time.

***

### 📦 Create Version

Use this button to create a snapshot of the current state of your project. A version represents a **stable checkpoint** that can be:

* Released to production or staging
* Rolled back to in case of errors
* Shared or previewed by teammates

> ⚠️ Only users with the required permissions can create or release versions.

***

This toolbar stays persistent across all screens to make project management seamless and efficient.


# Pages and Widgets Panel

## 🧱 Page Selection & Widget Tree

This panel gives you full control over your app’s pages and UI structure. It’s divided into two main sections — **Page Selector** and **Widget Tree** — which help you manage and build your app's interface efficiently.

***

### 📄 Page Selector

At the top, you’ll see the **currently selected page name** (e.g., `HomePage`) with a dropdown indicator.

#### Features:

* **Clicking the page name** opens a dropdown to view and switch between different pages and components.
* **➕ Plus button** on the top right:
  * Add a new page
  * Add a reusable component
* Helps you organize your app’s structure by grouping screens and reusable UI elements.

***

### 🌲 Widget Tree

Below the page selector is the **Widget Tree**, a visual hierarchy of all the widgets present on the selected page.

#### Features:

* Displays the **structure of the UI** in a tree format.
* Each widget (e.g., `image1`, `text1`, `button1`) is shown as a node under parent widgets (e.g., `column1`, `body`, `HomePage`).
* Sections like `appBar`, `body`, and `bottomNavigationBar` are automatically detected where applicable.

#### What You Can Do:

* **Add Widgets**: Click the ➕ icon beside any widget to add a child widget inside it.
* **Reorder Widgets**: Drag and drop widgets to reorganize layout or nesting.
* **Edit Widget Names**: Rename widgets for better readability and maintenance.
* **Right-click Options**:
  * Delete
  * Copy / Paste
  * Duplicate
  * Wrap with container or column
  * Move up/down

> 📝 Tip: Use the **search** icon to quickly locate widgets in large trees, and the **sort** icon to organize or collapse sections.

***

This panel is your central workspace for defining and managing how your app looks and behaves.


# Canvas Area

## 🎨 Canvas Area

The **Canvas Area** is your visual playground where you build, arrange, and preview your app's user interface. It gives you a real-time preview of your current screen, lets you interact with widgets directly, and provides controls to customize the design experience.

***

### 🧱 Canvas Layout

The canvas is divided into three key parts:

#### 1. 📂 Widget List Toggle (Top-Left Button)

* Located in the upper-left corner.
* Clicking this button opens or collapses the **widget list panel**, allowing you to browse and drag widgets into the canvas.
* Use it to quickly access your available components and design elements.

***

#### 2. 🖼️ Page Frame (Center)

* This is the **actual visual layout** of your app screen.
* The selected page (e.g., `HomePage`) is rendered here as it would appear in the final app.
* You can:
  * **Select widgets** directly by clicking them
  * **Drag to reposition** (if layout allows)
  * See widget outlines, labels (e.g., `text1`), and selection states for active elements

***

#### 3. 🛠️ Top Bar Controls (Above the Page Frame)

These tools enhance your editing workflow:

* **Undo / Redo Buttons**: Quickly reverse or reapply your recent changes.
* **Canvas Background Color**: Select a background color for the canvas (does not affect app UI).
* **Light/Dark Toggle**: Preview your screen in light or dark theme if supported.
* **Preview Mode Button**: Switch from editing mode to live preview — test interactions, navigation, and animations.

***

### 🔍 Zoom Controls (Top-Right Corner)

* Allows zooming in/out of the canvas.
* Useful for working on large layouts or closely inspecting spacing and alignment.
* You can also zoom in and out on
  * Mac using Trackpad pinch in/out and pan using 2 fingers
  * Linux and Windows using Ctrl + 2 finger

***

> 💡 Tip: Selecting a widget from the canvas will auto-highlight it in the Widget Tree, making it easier to modify properties or manage nesting.

The canvas gives you full control over how your app looks and feels — instantly.


# Properties Panel

## ⚙️ Property Panel

The **Property Panel** is where you configure and customize each widget’s appearance, layout, and behavior. When you select a widget from the Canvas or Widget Tree, its properties are shown here.

***

### 🧱 Panel Structure

The panel is divided into two main sections:

***

#### 1. 🧩 Default Properties

This section appears for almost all widgets and contains three key groups:

**➕ Layout**

* **Visible:** Toggle widget visibility at runtime.
* **Width & Height:** Set dimensions (PX, %,).
* **Padding & Margin:** Control spacing inside and around the widget.
* **Alignment:** Use quick-align buttons to position elements horizontally or vertically.

**🎨 Appearance**

* **Fill Color:** Background color of the widget.
* **Border Radius:** Controls corner roundness.
* **Border:** Set border style, color, and width.

**⚡ Interactions**

* **onClick:** Define event-based actions like navigation, updating state, calling functions, etc.

***

#### 2. 📦 Additional Properties

Below the default properties, each widget shows **its own set of properties** depending on its type.

* For example, a **Text** widget may show font controls, while an **Image** widget will show source and fit options.
* These settings are contextual and may include content, media, data bindings, styling, and logic options.

***

> 📝 **Note:** Some widgets may not include all three default sections, and the additional properties are entirely dependent on the selected widget’s type and capabilities.

The Property Panel gives you full control over how a widget behaves and appears inside your app.


# Finding Page/Component Slugs

Page and component slugs are unique identifiers used in Digia Studio to reference specific pages and components in your app. These slugs are essential when configuring actions that navigate between pages or reference components programmatically.

## What are Slugs?

Slugs are unique identifiers automatically generated for pages and components in Digia Studio. They consist of:

* **Base name**: Lowercase letters and numbers derived from the page/component name
* **Hyphens**: Used instead of spaces and special characters
* **Random suffix**: 6-digit random alphanumeric string appended for uniqueness

**Examples:**

* Page name: "User Profile" → Slug: `user-profile-a1b2c3`
* Component name: "Login Form" → Slug: `login-form-x9y8z7`

The random 6-digit suffix ensures that slugs remain unique even when multiple pages or components have similar names, preventing conflicts in your app.

## Why You Need Slugs

Slugs are required in various actions and configurations where you need to reference specific pages or components:

* **API calls**: Reference pages in routing configurations
* **Deep linking**: Direct links to specific pages
* **SDK Integration**: Navigate to pages using `DUIFactory().createPage(slug, args)` or `DUIFactory().createComponent(slug, args)`

## Finding Slugs

### Method 1: Pages/Coponent Slug

<figure><img src="/files/JuNKtT61kNI77X9U1XL1" alt="Copy Slugs"><figcaption><p>Copy Slug</p></figcaption></figure>

\*\[Screenshot: Pages Panel showing page names with slugs]\*

### Method 2: Custom Widget Slugs

*\[Screenshot: Properties Panel showing Page ID field]*

## Best Practices

### Naming Conventions

* Use descriptive, readable names that become good slugs
* Avoid special characters that might cause issues
* Keep slugs consistent with your app's

### Maintenance

* Document important slugs in your project documentation
* Use variables for frequently referenced slugs

## Troubleshooting

### Common Issues

**"Page not found" errors:**

* Verify the slug is spelled correctly
* Check if the page exists and is published

**"Component not found" errors:**

* Confirm the component slug is accurate
* Check if the component is properly configured

### Getting Help

If you can't find a slug:

1. Check the Pages Panel or Component Tree for the item
2. Verify the page/component exists and is not deleted
3. Contact your project administrator
4. Use the Digia Studio support channels
5. Review the component/page hierarchy carefully

## Related Documentation

* [Go To Page Action](/logic-and-interaction/actions/go-to-page) - Navigation between pages
* [Open Dialog Action](/logic-and-interaction/actions/open-dialog) - Display components as dialogs
* [Show Bottom Sheet Action](/logic-and-interaction/actions/show-bottom-sheet) - Display components in bottom sheets
* [Pages Overview](/ui-building-blocks/pages) - Understanding page structure and properties
* [SDK Integration Flutter](broken://pages/KvYi8BYZ9GRff1rXy4p3) - Using slugs in Flutter SDK integration

***

*Asset Placeholder: Tutorial video demonstrating how to locate and copy page/component slugs in Digia Studio*


# Project

## 📦 Projects in Digia

A **Project** in Digia represents a complete mobile application configuration that can be visually designed, tested, and managed—all without writing code. Projects serve as the central unit for organizing screens, components, logic, and integrations within the Digia Studio.

***

### 1. 🔍 What is a Project?

A project in Digia defines the structure, behavior, and styling of your mobile app. It includes:

* Pages and widgets
* Navigation rules
* Functions and API calls
* Design tokens and themes
* Build and test settings

Each project is isolated, version-controlled, and can be independently previewed, exported, or integrated with GitHub.

***

### 2. ➕ Creating a New Project

To create a new project:

1. Click **New Project** from the dashboard.
2. Enter a **project name**.
3. (Optional) Upload a **thumbnail** to visually identify your project.
4. Click **Create**.

The project will be initialized with a default page.

***

### 3. ✨ Start from Scratch vs Template

When creating a project, you will soon be able to choose between:

* **Start from Scratch**: Build your app page by page.
* **Start from Template** *(coming soon)*: Use a pre-designed app structure to speed up development.

***

### 4. 🧪 Running & Testing a Project

You can test your app instantly using:

* **Preview Mode**: Launch a real-time, interactive preview within the Digia Studio.
* [**Preview App**](/quick-start-and-setup/setup#previewing-your-app)**:** Download Digia Preview app from Playstore and Appstore and login test your project on a physical device.
* [**SDK Integration**](broken://pages/KvYi8BYZ9GRff1rXy4p3): Integrate Digia's SDK in your existing app and run your project.

***

### 5. 🤝 Collaborate on Projects

{% hint style="warning" %}
Only Admins and Maintainers can Release projects
{% endhint %}

{% hint style="success" %}
Collaboration is only Available on Teams plan
{% endhint %}

Collaborate seamlessly with your team:

* Invite members from the **Members** section in the Navigation Menu.
* Share access to preview, edit, and manage the app together.
* Changes are auto-synced and versioned.

***

### 7. 🕒 Versioning

Versions are like Git tags. Digia automatically saves every change but you can also:

* **Create named versions** before major updates.
* **Revert** to any previous version with one click.

Use versioning to safeguard your work and create snapshots of your work.

***

### 8. 🚀 Release Management

{% hint style="warning" %}
Only Admins and Maintainers can Release projects
{% endhint %}

When you're ready to publish:

* Use the **“Create Release”** button to package the current configuration.
* Releases are **read-only snapshots** that can be shared, tested, or exported.
* Digia enforces **release limits** based on your plan (e.g. one active release in the Free Plan).

***

> 💡 Pro Tip: Regularly create versions before big edits and release only tested versions to ensure app stability.

### 9. ⚙️ Project Settings

Access the **Project Settings** from the Navigation Menu to:

* Change the **Project Name**
* Edit the **Package Name** used during build and export
* View project metadata and configurations

***

#### 🔗 Related Documentation

* [Finding Page/Component Slugs](/studio-workspace/builder-tool/finding-slugs) - How to locate and copy page/component slugs within your project
* [Pages](/ui-building-blocks/pages) - Creating and managing pages in your project
* [Previewing Your App](/quick-start-and-setup/setup#previewing-your-app) - Testing your project during development


# Design System

The Design System is the visual foundation of your Digia application. Before you start building pages or components, it's essential to define your global styles. This ensures consistency across your entire app and makes updates effortless.

## Core Elements

* [**Colors**](/ui-building-blocks/design-system/colors): Define your primary, secondary, and accent colors. These tokens are available throughout the builder.
* [**Typography**](/ui-building-blocks/design-system/typography): Set up your text styles (Headings, Body, Captions) to maintain readability and visual hierarchy.

## Why Start Here?

Defining your Design System first allows you to:

1. **Build Faster**: No need to manually pick hex codes for every button.
2. **Maintain Consistency**: Change a color in one place, and it updates everywhere.
3. **Stay On-Brand**: Ensure every screen matches your brand guidelines.


# Colors

<figure><img src="/files/hcU79bIKVlTCcfqNB9yg" alt=""><figcaption></figcaption></figure>

## Colors

The **Colors** section allows you to create, customize, and manage the color tokens used across your application.

### Custom Colors

You can add your own **Custom Colors** by clicking the **Add New** button. These colors can be used anywhere in your app, alongside the default palette.

### Light & Dark Theme Palettes

Your app comes with a predefined **Light Theme** and **Dark Theme** color palette.\
Each theme includes colors for:

* **Brand** (Primary & Secondary)
* **Content** (Primary, Secondary, Tertiary)
* **Background** (Primary, Secondary, Tertiary)
* **Status** (Success, Error, Warning, Info)
* **Accents**

You can switch between light and dark themes in your app, and customize both to fit your brand.

### Editing Colors

To modify a color:

1. Click on the color box.
2. Select a new color using the color picker, or enter a hex code.

### More Options

Clicking the **three dots** menu next to a color provides options to:

* **Copy Color Token** – Use this token name in expressions and styling references.
* **Copy Hex Code** – Quickly copy the color’s hex value.

These tools help ensure design consistency and make it easier to apply colors programmatically.

### Using Colors in Components

<figure><img src="/files/0YlbZuYorNohOJf9yRHg" alt="" width="375"><figcaption></figcaption></figure>

When configuring components (e.g., button text, background), you can:

* Choose from the **predefined color tokens** in the library.
* Set a **custom inline color** directly for that specific element.

### Light/Dark Mode Toggle

At the top of the canvas, you can toggle between **Light** and **Dark** modes using the ��**/**☾ **icon** .

> **Note:** This toggle only affects components styled with **tokenized colors**. Inline colors are fixed and will not adapt when switching themes.


# Typography

<figure><img src="/files/8pRdCc5KCxVzwrAMfm5I" alt=""><figcaption></figcaption></figure>

## Typography

The **Typography** section allows you to create and customize font tokens for consistent text styling across your application.

### Custom Fonts

You can add your own **Custom Fonts** by clicking the **Add New** button.\
Custom fonts can be used alongside the predefined library fonts to match your brand guidelines.

### Library Fonts

The platform comes with a predefined set of **Library Fonts** that follow a standard type scale.\
Each font token includes:

* **Token Name** – The reference name used in your app (e.g., *Heading Large*, *Body Default*).
* **Font Size** – The size of the text in pixels.
* **Font Weight** – The thickness of the font (e.g., *regular*, *medium*, *semiBold*).
* **Font Height** – The line height (e.g., 1.15, 1.25).
* **Font Family** – The typeface used (default is *Inter*).

### Editing Fonts

To edit a font token:

1. Click the **edit icon** (✏️) next to the font you want to change.
2. Adjust font size, weight, height, or family as needed.
3. Changes will be applied wherever that font token is used in your app.

### Why Use Font Tokens?

Font tokens ensure:

* **Consistency** – All text elements follow a unified style.
* **Easy Theme Updates** – Changing a font token updates all components using it.
* **Scalability** – You can maintain a clear typography hierarchy without manually adjusting each element.


# Pages

## Overview

In Digia, a **Page** represents a distinct screen within your mobile app. It acts as the container for your layout, state, and logic. Every screen user navigates to—whether it's a Login screen or a Product Details screen—is a Page.

## Anatomy of a Page

A Page is not just a blank canvas; it has a specific structure that Digia enforces to ensure consistency.

### 1. The Scaffold Foundation

Every page in Digia starts with a **Scaffold**. The Scaffold is the basic structure of a visual interface. It provides standard app elements such as:

* **App Bar**: The top navigation bar.
* **Body**: The main content area.
* **Floating Action Button**: A primary action button.
* **Background Color**: The base color of the screen.

> \[!TIP] Learn more about configuring the Scaffold in the [**Scaffold Documentation**](/ui-building-blocks/widgets/layout-structure-widgets/scaffold).

### 2. The Widget Tree

Inside the Scaffold's **Body**, you build your specific layout using a **Widget Tree**. This is where you drag-and-drop Rows, Columns, Texts, and Buttons to create your UI.

## Data & Logic

Pages are dynamic. They accept data, maintain their own state, and react to lifecycle events.

### Page Arguments (Inputs)

Pages often behave like functions that require inputs. **Page Arguments** are immutable parameters passed from the "outside world" (the previous screen/route).

**Examples:**

* **Product Details Page**: Requires `productId` (String).
* **Order Confirmation Page**: Requires `orderId` (Integer) and `totalAmount` (Double).

These arguments are defined in the Page Properties tab and are available to use via Data Binding anywhere on the page.

### Page State (Internal)

While Arguments come from outside, **Page State** is strictly internal. These are mutable variables that your page uses to handle interactivity.

**Examples:**

* `isLoading`: Sets to true while fetching data, false when done.
* `selectedSize`: Stores the user's choice ('S', 'M', 'L').

> \[!NOTE] Read the full [State Management Guide](/data-and-state/state-management) for details.

## Page Lifecycle

A Page goes through a specific lifecycle: **Created ➝ Painted ➝ Destroyed**. You can hook into specific moments of this lifecycle to run logic.

### onPageLoad (After First Paint)

This action triggers **after the page has been built and painted** on the screen.

* **When it runs**: It acts like a "Post Frame Callback". It basically runs immediately after the user sees the screen.
* **Use Case**: Ideal for triggering analytics (`ScreenView`) or kicking off fresh data fetches.
* **Correction**: It has no direct relation to API calls. An API call is just one *kind* of action you *might* trigger here.

### onBackPress (Dismissal Notification)

This action triggers when the user attempts to close the page (e.g., swiping back or pressing the system Back button).

* **Behavior**: This is a **notification** that the page is closing. It **DOES NOT STOP** the dismissal. The page *will* close regardless of what logic you run here.
* **Warning**: Do not start long-running tasks here (like a complex database save) because the page context is about to be destroyed.

## Entry Point (The "First Page")

Any page can be designated as the **First Page**.

* **In Digia Studio/Preview**: This tells the previewer which page to load first.
* **in Native Apps**: If you embedding Digia pages into an existing Flutter app, you predominantly control the entry point via your native code (`DUIPage(slug)`).

## Working in Studio

### Creating a Page

1. Open the **Pages Panel** from the left sidebar.
2. Click the **+** button.
3. Choose **Create Blank Page** (or pick a template).
4. Enter a unique name (e.g., `ProfileSettings`).

### Managing Pages

* **Duplicate**: Hover over a page in the list ➝ Click `...` ➝ **Duplicate**. Useful for creating variants.
* **Delete**: Hover over a page ➝ Click `...` ➝ **Delete**.


# Components

## Overview

**Components** are the building blocks of reusability in Digia. A Component is a custom widget you create once and use everywhere. By bundling multiple widgets and logic into a single unit, you ensure consistency and drastically reduce development time.

## Use Cases

Whenever you find yourself copying-and-pasting a group of widgets, you should probably turn it into a Component.

### Example: Product Card

Imagine an E-commerce app. On the "Listing Page", you display a grid of products. Each cell has:

* An Image
* A Title
* A Price Tag
* A "Add to Cart" Button

Instead of building this grid 50 times, you build **one** "Product Card" component. You then place this component 50 times, passing different data (Image, Title, Price) to each instance.

## Anatomy of a Component

Just like a Page, a Component has inputs and internal state.

### 1. Component Arguments (Inputs)

Arguments are the data a component *needs* to function. When you place a component on a page, the builder asks you to provide values for these arguments.

* **Definition**: You define arguments in the **Component Properties** tab.
* **Example**: For `ProductCard`, you would define:
  * `productImage` (Image URL)
  * `productName` (String)
  * `price` (Double)
* **Usage**: Inside the component, you bind these arguments to widgets (e.g., bind `productName` to a Text widget).

### 2. Component State (Internal)

State represents the *internal behavior* of the component that doesn't affect the parent page directly.

* **Definition**: Mutable variables specific to *this instance* of the component.
* **Example**: An `isLiked` toggle or a `quantity` counter inside the card.

> \[!NOTE] Learn more in the [Page & Component State](/data-and-state/state-management/page-and-component-state) guide.

## Component Lifecycle

Components have a simple lifecycle: **Mount** and **Unmount**.

1. **Mount**: The component is added to the widget tree and painted on the screen.
2. **Unmount**: The component is removed from the widget tree (e.g., scrolled off-screen or part of a conditional builder that turned false).

> \[!IMPORTANT] **No Exposed Lifecycle Actions** Unlike Pages, components **do not** currently expose lifecycle triggers like `OnMount` or `OnDispose` in the builder. You cannot run logic automatically when a component appears. All logic must be triggered by user interaction (e.g., `OnTap`).

## Working in Studio

### Creating a Component

1. **From Scratch**: Go to the **Components Panel**, click **+**, and select **Create Blank Component**.
2. **From Selection**: Select a widget tree on a Page ➝ Right Click ➝ **Extract to Component**. This is the fastest way to componentize existing UI.

### Defining Properties

Once inside the component editor:

1. Select the root or click the background.
2. Go to the **Properties Panel**.
3. Add **Parameters** (Inputs) to define what data this component accepts.


# Layout System

## What is a Layout?

At its core, a **Layout** is a negotiation of space. It is the process where the system decides where to place a widget and how big that widget should be.

In Digia, you don't use absolute pixels (e.g., "Place this button at x=50, y=100"). Instead, you describe the **relationship** between widgets (e.g., "Place this button in the center of the screen").

## Why Understanding Layout Matters

Digia uses a **Server-Driven UI** model. You define the layout JSON once, and it renders using the native rendering engines of the target platform (Flutter, Android/Jetpack Compose, or iOS/SwiftUI).

While Digia handles the translation for you, understanding how these engines "think" helps you build interfaces that:

1. **Adapt Responsively**: Work on both an iPhone SE and an iPad Pro.
2. **Avoid Errors**: Prevent "Pixel Overflow" or "Clipped Content" issues.
3. **Perform**: Render efficiently without unnecessary calculations.

## Core Layout Principles

Modern UI frameworks all follow a similar pattern known as **Declarative Layout**.

### 1. Flutter

The motto of Flutter's layout engine is:

> **"Constraints go down. Sizes go up. Parent sets position."**

1. **Constraints Down**: A parent (like a Column) tells its child: *"You can be as wide as the screen, but only 50px high."*
2. **Sizes Up**: The child (like a Button) calculates its content and replies: *"Okay, I will be 100px wide and 50px high."*
3. **Parent Sets Position**: The parent then decides coordinates: *"I will place you at x=0, y=0."*

### 2. Android (Jetpack Compose)

Compose uses a similar logic called **Single Pass Layout**.

> **"Constraints flow down, measurements flow up."**

Parents pass `Constraints` to children, and children return `Placeables` (with a width and height). Parents are strictly forbidden from measuring a child twice, ensuring high performance.

### 3. iOS (SwiftUI)

SwiftUI follows a three-step process:

> **"Parent proposes a size. Child chooses its own size. Parent places the child."**

1. **Proposal**: The parent offers the child a size (e.g., the whole screen).
2. **Choice**: The child decides how much of that it needs (e.g., "I only need 200x50").
3. **Placement**: The parent respects that choice and positions the child (e.g., centered).

## The WYSIWYG Reality

Digia Studio acts as a **unified layout engine** in your browser. It mimics these native behaviors so that what you see is *mostly* what you get.

However, each platform has subtle text rendering engines, spacing defaults, and safe area calculations.

> \[!WARNING] **Always Test on Device** While the Digia Studio preview is 99% accurate, the final 1% (text kerning, shadow rendering, precise safe areas) depends on the physical device. Use **Digia Preview** on a real phone to verify your layouts before publishing.


# Widget Catalog

In Digia Studio, you create the design of a page using things called [Widgets](/ui-building-blocks/widgets). These Widgets are organized into six main categories based on their functionality: [Layout & Structure](/ui-building-blocks/widgets/layout-structure-widgets), [Content & Display](/ui-building-blocks/widgets/content-display-widgets), [Input & Interaction](/ui-building-blocks/widgets/input-interaction-widgets), [Navigation](/ui-building-blocks/widgets/navigation-widgets), [Scrolling](/ui-building-blocks/widgets/scrolling-widgets), and [Media & Async](/ui-building-blocks/widgets/media-async-widgets).

Some Widgets like [Text](/ui-building-blocks/widgets/content-display-widgets/text), [Buttons](/ui-building-blocks/widgets/input-interaction-widgets/button) and [Images](/ui-building-blocks/widgets/content-display-widgets/image) can be seen on the screen. Others, like [Containers](/ui-building-blocks/widgets/layout-structure-widgets/container), [Rows](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/layout-structure-widgets/row.md), and [Columns](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/layout-structure-widgets/column.md), are not visible, but they help in putting everything in the right place on the page.

To build a page, you pick and combine different widgets from these groups. It's like putting together building blocks to create the look and feel of your app. By using these widgets in the right way, you can make the app look just the way you want it to.

Widgets are essential in creating the user interface of your app. On this page, you will learn what is a widget, Widget tree, how to work with them, and how to use widget properties.

For extending Digia UI with custom native Flutter components, see [Custom Widgets](/extend-and-ship/custom-widgets).

<figure><img src="/files/bTtaVjEDkIiX4t5NTmyb" alt=""><figcaption></figcaption></figure>

## What is a Widget?

In Digia Studio, the widget is the UI element that helps you build the layout of your page. Almost everything that you see on the page is a widget. You build the UI by combining the widgets in a parent-child relationship.

[Text](/ui-building-blocks/widgets/content-display-widgets/text), [Row](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/layout-structure-widgets/row.md), [Column](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/layout-structure-widgets/column.md), and [Container](/ui-building-blocks/widgets/layout-structure-widgets/container) are the most basic types of widgets. You will learn about using them to build a layout here.

## Widget tree

When you put widgets together or place them inside another widget, they create something called a "Widget Tree." This tree can be found in the [Pages and Widget Panel](broken://pages/WnkDCQcy8jtp2hvS9d3u) on the left side of your screen. It shows how many widgets are on a page and how they're connected (as a parent-child relationship). This helps you understand your app's structure and how things fit together visually.

As the complexity of a UI increases, the widget tree tends to become longer and deeper, making it challenging to locate specific widgets.

<figure><img src="/files/8qC8D6YRs3sJmp9aq6Re" alt=""><figcaption><p>Example Widget Tree</p></figcaption></figure>


# Layout & Structure

The Layout System is the structural framework of your application. It defines how widgets are arranged, aligned, and positioned on the screen. Understanding these core concepts is crucial for building responsive and adaptive interfaces.

## Core Concepts

Before diving into individual widgets, understand the three main layout models:

1. **Box Model (Container & Sized Box)**: Every widget is a box. You can control its size, padding, and margins.
2. **Flex Layout (Row & Column)**: The most common way to arrange widgets linearly (horizontally or vertically).
3. **Stack Layout (Stack & Overlay)**: Positioning widgets on top of each other, useful for background images or floating badges.

## Layout Widgets Catalog

Below are the specific widgets used to implement these concepts:

### Container & Spacing

* [**Container**](/ui-building-blocks/widgets/layout-structure-widgets/container) - A versatile box with styling, padding, and dimensions.
* [**Sized Box**](/ui-building-blocks/widgets/layout-structure-widgets/sized-box) - precise control over spacing and fixed dimensions.

### Linear & Flow Layouts

* [**Row & Column**](/ui-building-blocks/widgets/layout-structure-widgets/flex) - The workhorses of layout; arrange children in a line.
* [**Wrap**](/ui-building-blocks/widgets/layout-structure-widgets/wrap) - Like a row/column, but wraps to the next line when space runs out.

### Layered Layouts

* [**Stack**](/ui-building-blocks/widgets/layout-structure-widgets/stack) - Place widgets on top of each other (z-axis).
* [**Overlay**](/ui-building-blocks/widgets/layout-structure-widgets/overlay) - Float content above the entire application.

### Screen Structure

* [**Scaffold**](/ui-building-blocks/widgets/layout-structure-widgets/scaffold) - The standard page layout structure (AppBar, Body, Floating Action Button).
* [**Safe Area**](/ui-building-blocks/widgets/layout-structure-widgets/safe-area) - Avoids system intrusions like the notch or home indicator.
* [**AppBar**](/ui-building-blocks/widgets/layout-structure-widgets/appbar) - The standard top navigation bar.


# Container

<figure><img src="/files/CnYrOY5B6eQL0KlCiRHd" alt="A hero image illustrating a Container widget with various styling properties like padding, border, and shadow."><figcaption><p>A powerful widget for styling, sizing, and positioning other widgets.</p></figcaption></figure>

The **Container** is a fundamental layout widget that can hold a single child widget. It allows you to apply advanced styling and sizing rules that go beyond the standard `Default Properties`.

It is one of the most versatile widgets for building complex user interfaces.

{% embed url="<https://www.youtube.com/watch?v=m0iw3EbtAxk>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=m0iw3EbtAxk>

{% hint style="info" %}
Our Container widget works exactly like Flutter's `Container` widget. For an in-depth technical understanding, you can refer to the official Flutter Container documentation.
{% endhint %}

### Core Concept: Layout Behavior

A Container's size on the screen is determined by a set of rules based on its properties and its child. Understanding this behavior is key to mastering layout.

| Has Child? | Dimensions or Constraints Set? | Alignment Set? | Parent's Constraints | Container's Behavior                                                          |
| ---------- | ------------------------------ | -------------- | -------------------- | ----------------------------------------------------------------------------- |
| No         | No                             | No             | Unbounded            | Tries to be as small as possible.                                             |
| No         | Yes                            | No             | Any                  | Tries to be as small as possible given its own and parent's constraints.      |
| No         | No                             | No             | Bounded              | Expands to fit the parent's constraints.                                      |
| Yes        | Any                            | Yes            | Unbounded            | Sizes itself to fit around the child.                                         |
| Yes        | Any                            | Yes            | Bounded              | Expands to fit the parent and positions the child according to the alignment. |
| Yes        | No                             | No             | Any                  | Passes constraints from parent to child and matches the child's size.         |

***

### Properties

#### Layout & Sizing

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Width</code> / <code>Height</code></td><td>The fixed dimensions of the container.</td></tr><tr><td><code>Padding</code></td><td>The space between the container's border and its child widget.</td></tr><tr><td><code>Margin</code></td><td>The space around the outside of the container, separating it from other widgets.</td></tr><tr><td><code>Child Alignment</code></td><td>Aligns the child widget within the container (e.g., <code>Top Left</code>, <code>Center</code>, <code>Bottom Right</code>).</td></tr></tbody></table>

<figure><img src="/files/lYzlXpQHYlApkuwm0sqT" alt="An illustration showing how the Child Alignment property positions a child widget within a Container."><figcaption><p>Use <code>Child Alignment</code> to position a child within the Container's bounds.</p></figcaption></figure>

#### Constraints

These properties allow you to define a flexible size range for the container.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Min Width</code> / <code>Min Height</code></td><td>The minimum size the container can shrink to.</td></tr><tr><td><code>Max Width</code> / <code>Max Height</code></td><td>The maximum size the container can expand to.</td></tr></tbody></table>

#### Appearance

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Color</code></td><td>The solid background color of the container.</td></tr><tr><td><code>Gradient</code></td><td>A color gradient for the background. This will be drawn on top of the <code>Color</code>.</td></tr><tr><td><code>Box Shape</code></td><td>The shape of the container. Options are <code>Rectangle</code> or <code>Circle</code>.</td></tr><tr><td><code>Border</code></td><td>Defines the border style, width, and color.</td></tr><tr><td><code>Border Radius</code></td><td>Rounds the corners when <code>Box Shape</code> is <code>Rectangle</code>.</td></tr><tr><td><code>Elevation</code></td><td>The z-axis elevation, used to create a shadow effect.</td></tr><tr><td><code>Shadow</code></td><td>A list of shadow effects to apply, allowing for complex, layered shadow designs.</td></tr></tbody></table>

***

### Container vs. Default Properties

The `Container` widget offers a superset of the styling properties found in `Default Properties`.

* **Shared Properties**: `Width`, `Height`, `Padding`, `Margin`, `Background Color`, `Border`, `Border Radius`.
* **Container-Only Properties**: `Gradient`, `Shadow`, `Elevation`, `Constraints` (Min/Max Width/Height), `Child Alignment`, and `Box Shape`.

This makes the Container a powerful tool for creating custom "cards," decorated boxes, and other complex layout elements.

***

### Default Properties

The Container widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Interactions**

**Alignment**

**Visibility**

### Use Cases

Use a **Container** when you need a **box that styles and positions other widgets**.

* **Group content**\
  Wrap text, icons, rows, or columns into a single block (like a card or section).
* **Add styling**\
  Give something a background color, border, radius, or shadow.
* **Control spacing & size**\
  Add padding, margin, fixed width/height, and alignment around a child.
* **Clickable areas**\
  Make a whole row/section feel like one tappable block (with gesture/tap outside).


# Row & Column

<figure><img src="/files/P5J0rq8IsLzhiCsG1LaD" alt=""><figcaption></figcaption></figure>

**Row** and **Column** are the most fundamental layout widgets. They allow you to arrange multiple child widgets in a flexible way, either horizontally or vertically. Mastering them is the key to building almost any user interface.

* The **Row** widget arranges its children horizontally.
* The **Column** widget arranges its children vertically.

{% embed url="<https://www.youtube.com/watch?v=xt_OdO8o67Q>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=xt_OdO8o67Q>

{% embed url="<https://www.youtube.com/watch?v=zH3HB3K009M>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=zH3HB3K009M>

### Use Case

Use **Row** when you want to place widgets **horizontally side by side**.

* Buttons next to each other (e.g., *Cancel* | *Save*)
* Icon + text combinations (e.g., 🕒 + “2 min ago”)
* Price + discount + tag in one line
* Chips, filters, or tabs laid out in a single horizontal line

Use **Column** when you want to place widgets **vertically one below another**.

* Page layouts: title → subtitle → content → button
* Form fields stacked top to bottom
* List of texts, settings, or options in a vertical flow

### Core Concepts

#### 1. Main Axis vs. Cross Axis

The core concept to understand when working with `Row` and `Column` is the axis direction:

* **Main Axis**: The primary direction of arrangement. For a **Row**, it's horizontal. For a **Column**, it's vertical.
* **Cross Axis**: The direction perpendicular to the main axis. For a **Row**, it's vertical. For a **Column**, it's horizontal.

  <figure><img src="/files/DKX2xsYvXMLlDI1DNYad" alt="A diagram showing the Main Axis and Cross Axis for a Row (horizontal/vertical) and a Column (vertical/horizontal)."><figcaption><p>The Main and Cross axes for Row and Column widgets.</p></figcaption></figure>

  All alignment and sizing properties operate based on these two axes.

#### 2. Static vs. Dynamic Children

A `Row` or `Column` can be populated with widgets in two ways. You can add a fixed number of widgets individually in the builder (**Static Children**), or you can generate a list of widgets from a data source (**Dynamic Children**). This flexibility allows you to build both fixed layouts and data-driven, repeating lists.

Learn more about Static and Dynamic Children here.

***

### Properties

The properties for `Row` and `Column` are identical and determine how their children are positioned and sized.

#### Main Axis Alignment

This property defines how the free space is distributed between children along the **main axis**.

<figure><img src="/files/T3rPo53C8nU148AoI9NV" alt="A visual comparison of Main Axis Alignment options for a Row, showing horizontal distribution of items."><figcaption><p>Main Axis Alignment in a <strong>Row</strong> (controls horizontal spacing).</p></figcaption></figure>

<figure><img src="/files/5fHJulZIqZ7FJquzF8Ho" alt="A visual comparison of Main Axis Alignment options for a Column, showing vertical distribution of items."><figcaption><p>Main Axis Alignment in a <strong>Column</strong> (controls vertical spacing).</p></figcaption></figure>

<table><thead><tr><th width="176.25390625">Value</th><th>Description</th></tr></thead><tbody><tr><td><code>Start</code></td><td>Places children at the beginning of the main axis.</td></tr><tr><td><code>Center</code></td><td>Places children in the middle of the main axis.</td></tr><tr><td><code>End</code></td><td>Places children at the end of the main axis.</td></tr><tr><td><code>Space Between</code></td><td>Distributes children evenly, with no space at the start or end.</td></tr><tr><td><code>Space Around</code></td><td>Distributes children evenly, with half the spacing at the start and end as between them.</td></tr><tr><td><code>Space Evenly</code></td><td>Distributes children with equal spacing between all items, including at the start and end.</td></tr></tbody></table>

#### Cross Axis Alignment

This property defines how children are positioned relative to each other along the **cross axis**.

<figure><img src="/files/mDcpqTjM1G3qA2jwVjYG" alt="A visual comparison of Cross Axis Alignment options for a Row, showing vertical alignment of items."><figcaption><p>Cross Axis Alignment in a <strong>Row</strong> (controls vertical alignment).</p></figcaption></figure>

<figure><img src="/files/5as8TncKZ2nm9G1mR5yb" alt="A visual comparison of Cross Axis Alignment options for a Column, showing horizontal alignment of items."><figcaption><p>Cross Axis Alignment in a <strong>Column</strong> (controls horizontal alignment).</p></figcaption></figure>

<table><thead><tr><th width="176.25390625">Value</th><th>Description</th></tr></thead><tbody><tr><td><code>Start</code></td><td>Aligns children to the beginning of the cross axis.</td></tr><tr><td><code>Center</code></td><td>Aligns children to the center of the cross axis.</td></tr><tr><td><code>End</code></td><td>Aligns children to the end of the cross axis.</td></tr><tr><td><code>Stretch</code></td><td>Stretches each child to fill the available space along the cross axis.</td></tr></tbody></table>

#### Main Axis Size

This property determines how much space the `Row` or `Column` should occupy along its main axis.

<figure><img src="/files/Ppw1I39rcCg1o6fCDiYj" alt="A visual comparison of Main Axis Size: Max vs. Min."><figcaption><p><code>Max</code> fills available space, while <code>Min</code> shrinks to fit its children.</p></figcaption></figure>

<table><thead><tr><th width="176.25390625">Value</th><th>Description</th></tr></thead><tbody><tr><td><code>Max</code></td><td>The widget expands to fill all available space along its main axis. This is the default.</td></tr><tr><td><code>Min</code></td><td>The widget shrinks to fit the combined size of its children along the main axis.</td></tr></tbody></table>

#### Scrollable

If the content of a `Row` or `Column` exceeds its available space, enabling the `Scrollable` property will allow users to scroll through the content. This is essential for creating scrollable lists or carousels.

#### Spacing

These properties allow you to add fixed spacing along the main axis, offering an alternative to using `Main Axis Alignment` for space distribution.

<figure><img src="/files/XgLPPsGh7CpTPD1CRCFn" alt="A diagram illustrating Item Spacing, Start Spacing, and End Spacing in a Row and Column."><figcaption><p>Use spacing properties for precise control over gaps between children.</p></figcaption></figure>

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Item Spacing</code></td><td>The amount of empty space to place between each child widget along the main axis.</td></tr><tr><td><code>Start Spacing</code></td><td>The amount of empty space to place before the first child widget along the main axis.</td></tr><tr><td><code>End Spacing</code></td><td>The amount of empty space to place after the last child widget along the main axis.</td></tr></tbody></table>

***

### Children: Static vs. Dynamic

You can populate a `Row` or `Column` with child widgets in two ways:

#### 1. Static Children

Add a fixed number of child widgets directly in the builder. Each child you add will appear in the widget tree, and its properties can be configured individually. This is ideal for layouts where the number of items is known and doesn't change.

#### 2. Dynamic Children

To generate children from a list of data, you can use the **`Data Source`** property. This turns the `Row` or `Column` into a powerful list builder.

1. Enable the `Data Source` toggle in the properties panel.
2. Provide data by either entering a fixed `JsonArray` in the JSON editor or binding it to an expression that returns a `JsonArray` (e.g., from an API call or App State).
3. Add a **single child widget** to the `Row` or `Column`. This widget acts as a template that will be repeated for each item in the data source.
4. Inside this template child, use the `currentItem` variable to access the data for each item.
   * If your data is a list of objects (e.g., `[{"name": "Apple"}, {"name": "Banana"}]`), access properties with dot notation: `${currentItem.name}`.
   * If your data is a list of simple values (e.g., `["Apple", "Banana"]`), `currentItem` refers to the value itself: `${currentItem}`.

This is perfect for building small, repeating UI elements like a row of filter chips, a list of user avatars, or a set of feature icons.

{% hint style="warning" %}
**Important Note on Performance**

While enabling `Scrollable` on a `Row` or `Column` with dynamic children works, it is **not** optimized for long or infinite lists. The `Row` and `Column` widgets build all their children at once, which can cause performance issues with large datasets.

For displaying long, scrollable lists of data, it is highly recommended to use the **ListView** or **GridView** widgets, as they are specifically designed to build items lazily as they scroll into view.
{% endhint %}

***

### Controlling Child Size: Expanded & Flexible

When you have static children inside a `Row` or `Column`, you can control how they occupy the **remaining space** along the main axis. After placing children, you can find the **Children Flex** section in the properties panel of the `Row` or `Column` itself. Here, you can individually configure the expansion type for each child.

{% hint style="info" %}
**Note:** The Children Flex setting only applies to **static children**. It has no effect when children are generated dynamically from a data source.
{% endhint %}

#### Expansion Types

<table><thead><tr><th width="176.25390625">Type</th><th>Name in Properties</th><th>Description</th></tr></thead><tbody><tr><td><strong>Expanded</strong></td><td><code>Tight</code></td><td>Forces the child to fill all remaining empty space along the main axis. If multiple children are set to <code>Tight</code>, the space is divided according to their <code>Flex Value</code>.</td></tr><tr><td><strong>Flexible</strong></td><td><code>Loose</code></td><td>Allows the child to expand into the remaining space, but does not force it to. The child will grow no larger than its flex value allows, but can be smaller if its content is smaller.</td></tr><tr><td><strong>None</strong></td><td><code>None</code></td><td>The child takes up only its intrinsic (natural) size. It will not be expanded or flexed. This is the default.</td></tr></tbody></table>

#### Flex Value

When you set a child's expansion `Type` to `Loose` or `Tight`, the **`Flex Value`** (a number) determines its share of the remaining space relative to its siblings.

* A child with `Flex Value: 2` will take up twice as much space as a sibling with `Flex Value: 1`.
* If all expanded children have `Flex Value: 1`, they will share the space equally.
* A child with `Flex Value: 2` will take up twice as much space as a sibling with `Flex Value: 1`.
* If all expanded children have `Flex Value: 1`, they will share the space equally.

#### Expanded vs. Flexible: A Deeper Dive

While both `Expanded` and `Flexible` use the `Flex Value` to claim a share of the remaining space, their behavior is fundamentally different. Understanding this difference is crucial for mastering layouts.

#### The Key Difference: Forcing vs. Allowing

* **Expanded (`Tight`) forces a child to fill the space.** It's a rigid rule. The child's own intrinsic size is ignored, and it expands to occupy the full share of remaining space defined by its `Flex Value`.
* **Flexible (`Loose`) allows a child to fill the space.** It's a flexible rule. The child can grow *up to* its share of the remaining space, but if its content is smaller, it will only take up the space it needs.

Here’s a summary of what each can do that the other cannot:

| Feature            | Expanded (`Tight`)                                                                                       | Flexible (`Loose`)                                                                         |
| ------------------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| **Behavior**       | **Forces** the child to fill its share of remaining space.                                               | **Allows** the child to fill its share of remaining space, but doesn't force it.           |
| **Sizing**         | The child's size is determined by the `Flex Value` and remaining space. Its own content size is ignored. | The child's size is the **smaller** of its content size and its allocated flex space.      |
| **What it can do** | Force a small widget (like an icon) to grow and occupy a large area.                                     | Allow a widget to be smaller than its potential flex space if its content doesn't need it. |

#### When to Use Each

* **Use `Expanded` (`Tight`) when:**

  * You need to divide the screen into proportional sections that always fill the available space (e.g., a 70/30 split for a main content area and a sidebar).
  * You want a specific widget to take up all the leftover space in a `Row` or `Column`, pushing other widgets to the edges.
  * You are creating a layout where the components must stretch to fit, regardless of their content size.

  *Example: A `Row` with two `Expanded` children will always cause them to fill the full width of the `Row`.*
* **Use `Flexible` (`Loose`) when:**

  * You want a widget (like a `Text` widget) to have room to grow if its content is long, but you don't want to force it to be huge if the content is short.
  * You have a widget with a natural size, but you want it to expand slightly if there's extra space, without taking over the layout.
  * You want to give a widget a "max-width" or "max-height" that is proportional to the remaining space.

  *Example: In a `Row`, a `Button` with `Flexible` will keep its normal size if there's no extra space, but will expand to fill some of the remaining space if the `Row` is wider than its children.*

***

### Default Properties

The Row and Column widgets support all [Default Properties](/ui-building-blocks/widgets/default-properties).


# Stack

<figure><img src="/files/BqeKkhJ9GBViL81fTB4y" alt="A hero image illustrating the Stack widget with multiple layers, like an image with text and an icon on top."><figcaption><p>The Stack widget is essential for creating complex, layered user interfaces.</p></figcaption></figure>

The **Stack** widget is a powerful layout widget that allows you to place widgets on top of each other, creating layered and overlapping UIs. It arranges its children in a back-to-front order, with the first child being at the bottom and the last child at the top.

{% embed url="<https://www.youtube.com/watch?v=nG6iYEcuSJs>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=nG6iYEcuSJs>

#### Adding a Stack Widget

The Stack widget is located in the **Layout Elements** section of the Widget Palette. Once added, you can add child widgets to it and configure its properties from the **Widget Properties Panel**.

### Core Concept: Layering and Positioning

The primary purpose of a Stack is to layer widgets along the Z-axis (depth). Children of a Stack can be either **non-positioned** or **positioned**, which determines how they are placed.

* **Stacking Order**: Children are painted in the order they appear in the `children` list. The first widget is at the bottom, and subsequent widgets are painted on top of it.
* **Non-Positioned Children**: By default, a child is non-positioned. Its alignment is controlled by the parent Stack's `Alignment` property, and its size is determined by the `Fit` property.
* **Positioned Children**: A child becomes "positioned" when you set one or more of its position properties (`top`, `bottom`, `left`, `right`) in the **Children Position** section of the Stack's properties. This gives you precise control over its location and size relative to the Stack's boundaries, overriding the Stack's `Alignment` and `Fit` for that specific child.

<figure><img src="/files/mHvtpsmK0lALolwsT755" alt=""><figcaption><p>The Stack widget enables complex, layered user interfaces.</p></figcaption></figure>

***

### Properties

#### Stack Properties

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Alignment</code></td><td>Controls the alignment of all <strong>non-positioned</strong> children within the Stack's bounds. The default is <code>TopStart</code> (top-left corner).</td></tr><tr><td><code>Fit</code></td><td>Determines how to size the <strong>non-positioned</strong> children. Options are: <code>Loose</code> (children can be smaller than the Stack), <code>Expand</code> (children are forced to be as big as the Stack), and <code>Passthrough</code> (children's constraints are passed through from the Stack's parent).</td></tr><tr><td><code>Clip Behavior</code></td><td>Defines whether children are allowed to paint outside the Stack's boundaries. Options include <code>HardEdge</code> (content is clipped), and <code>None</code> (content is not clipped).</td></tr></tbody></table>

***

### Positioning Children

The key to creating precisely arranged layouts within a Stack is the **Children Position** section in the widget's property panel. This section lists all direct children, allowing you to set a `Position` for each one by defining the properties below.

#### Position Properties

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Top</code></td><td>The distance to offset the child from the top edge of the Stack.</td></tr><tr><td><code>Bottom</code></td><td>The distance to offset the child from the bottom edge of the Stack.</td></tr><tr><td><code>Left</code></td><td>The distance to offset the child from the left edge of the Stack.</td></tr><tr><td><code>Right</code></td><td>The distance to offset the child from the right edge of the Stack.</td></tr></tbody></table>

#### Positioning Behaviors

By combining the position properties, you can achieve several distinct layout behaviors.

<table><thead><tr><th width="200">Behavior</th><th width="250">Properties Set</th><th>Description &#x26; Use Case</th></tr></thead><tbody><tr><td><strong>Non-Positioned</strong></td><td>None (<code>top</code>, <code>left</code>, <code>right</code>, <code>bottom</code> are all unset).</td><td>The child's position is determined by the parent Stack's <code>Alignment</code> property. The child retains its natural size, unless the Stack's <code>Fit</code> is <code>Expand</code>.</td></tr><tr><td><strong>Corner Pinning</strong></td><td>Two non-opposing properties (e.g., <code>top</code> and <code>left</code>, or <code>bottom</code> and <code>right</code>).</td><td>Pins the child to a specific corner. The child maintains its intrinsic size and stays at a fixed offset from that corner, even if the Stack resizes.</td></tr><tr><td><strong>Axis Stretching &#x26; Aligning</strong></td><td>Two opposing properties (e.g., <code>left</code> and <code>right</code>, or <code>top</code> and <code>bottom</code>).</td><td>The child stretches along one axis and is positioned on the other axis by the parent Stack's <code>Alignment</code> property. <strong>Use Case:</strong> A header that stretches across the top of a card (by setting <code>top</code>, <code>left</code>, and <code>right</code>).</td></tr><tr><td><strong>Edge Pinning &#x26; Axis Stretching</strong></td><td>Three properties (e.g., <code>top</code>, <code>left</code>, and <code>right</code>).</td><td>Pins the child to one edge and stretches it along the opposite axis. For example, setting <code>top</code>, <code>left</code>, and <code>right</code> pins the child to the top edge and forces it to stretch horizontally.</td></tr><tr><td><strong>Full Stretch</strong></td><td>All four properties (<code>top</code>, <code>left</code>, <code>right</code>, and <code>bottom</code>).</td><td>Forces the child to stretch in both directions, filling the space defined by the four offsets. The child will grow and shrink dynamically as the parent Stack resizes. <strong>Use Case:</strong> A background image that should always fill the entire Stack.</td></tr></tbody></table>

<figure><img src="/files/9FFVhl2ZUAoJFikcmxsE" alt="A diagram explaining how the top, right, bottom, and left properties work to place a child within a Stack."><figcaption><p>The <code>Position</code> properties give you precise control over a child's layout behavior inside a Stack.</p></figcaption></figure>

#### Best Practices for Positioning

* **Avoid Over-Constraining**: You usually don't need to set all four properties (`top`, `bottom`, `left`, `right`). For example, to pin a widget to the top-left, you only need to set `top` and `left`. Setting all four can sometimes lead to unexpected layout behavior if the parent Stack's size changes.
* **Use `Alignment` for Simplicity**: For simple layouts where all children are aligned the same way (e.g., centered), it's easier to use a non-positioned child and set the Stack's `Alignment` property. Reserve positioning for widgets that need a unique location.
* **Responsive Design**: Be mindful of how your positioned children will behave on different screen sizes. Using a combination of `top`/`left` and `bottom`/`right` can help, but always test your layouts.

***

### Children of Stack

| Slot       | Description                                                                                                                                                     |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | The child widgets that are layered on top of each other. The first child is at the bottom, and subsequent children are stacked on top in the order they appear. |

***

### Default Properties

The Stack widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

***

### Use Cases

The **Stack** widget lets you **place widgets on top of each other** (z-axis), instead of just side-by-side or top-to-bottom.

Use **Stack** when you want to:

* **Overlay content**
  * Text or gradient overlay on top of an image (e.g., banner with title on image)
  * Badge on a product image (SALE, NEW, % OFF)
  * Online/offline indicator dot on a profile avatar
* **Floating elements**
  * Floating action button over content
  * Positioned icons/buttons on the corners of a card or image
* **Custom layered UI**
  * Background decoration behind main content
  * Progress or status layer on top of another widget


# Wrap

The **Wrap** widget is a powerful layout component that arranges its children in a horizontal or vertical sequence, automatically "wrapping" them to the next line when there isn't enough space. This is incredibly useful for creating responsive layouts with a variable number of items, such as a list of tags, a photo gallery, or a set of filter chips.

{% embed url="<https://www.youtube.com/watch?v=haYNAaamK18>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=haYNAaamK18>

### Core Concepts

#### 1. Axis and Wrapping

Unlike `Row` or `Column`, which force children into a single line, `Wrap` is flexible. It attempts to lay out children along its main axis (`Direction`) and, if it runs out of room, it simply moves to the next line on the cross axis.

* **Direction**: The primary axis along which children are placed. This can be `Horizontal` (like a `Row`) or `Vertical` (like a `Column`).
* **Wrapping**: When children overflow the available space on the main axis, they wrap onto a new "run" on the cross axis.

<figure><img src="/files/wW6UPx2yqCysrh8hQ2dx" alt="A diagram showing the main and cross axis of a Wrap widget."><figcaption><p>Example of a Wrap widget where items wrap to a new line.</p></figcaption></figure>

#### 2. Dynamic Children

Similar to `Row` and `Column`, the `Wrap` widget is perfect for displaying dynamic data. By connecting it to a `Data Source`, you can generate a list of child widgets from a `JsonArray`. This makes it ideal for rendering lists of tags, user-selected choices, or any collection of items where the count is not fixed.

***

### Properties

#### Layout & Spacing

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Direction</code></td><td>Determines the primary axis for laying out children. <code>Horizontal</code> arranges them in rows, while <code>Vertical</code> arranges them in columns.</td></tr><tr><td><code>Alignment</code></td><td>Defines how children are positioned along the <strong>main axis</strong> (e.g., <code>Start</code>, <code>Center</code>, <code>End</code>, <code>Space Between</code>). This is similar to <code>Main Axis Alignment</code> in a Row/Column.</td></tr><tr><td><code>Run Alignment</code></td><td>Defines how the "runs" (the lines of wrapped children) are distributed along the <strong>cross axis</strong>. For example, if you have a <code>Horizontal</code> wrap with two lines of children, <code>Run Alignment</code> controls the vertical spacing between those lines.</td></tr><tr><td><code>Cross Axis Alignment</code></td><td>Defines how children within the same run are aligned relative to each other along the <strong>cross axis</strong>. For example, in a <code>Horizontal</code> wrap, this controls whether taller and shorter children align to the top, center, or bottom of their line.</td></tr><tr><td><code>Spacing</code></td><td>The amount of empty space to place between each child along the <strong>main axis</strong>.</td></tr><tr><td><code>Run Spacing</code></td><td>The amount of empty space to place between each run along the <strong>cross axis</strong>. For a <code>Horizontal</code> wrap, this is the vertical gap between lines.</td></tr></tbody></table>

### Alignment in horizontal and vertical

The alignment property is used to align the children in the main axis.

<figure><img src="/files/zByQdrdb221fh9zBpbCD" alt="An image showing horizontal alignment in a Wrap widget."><figcaption><p>The <code>Alignment</code> property controlling the horizontal distribution of children in a <code>Horizontal</code> wrap.</p></figcaption></figure>

<figure><img src="/files/bL6GNi0CUbLJXNT6tLoQ" alt="An image showing vertical alignment in a Wrap widget."><figcaption><p>The <code>Alignment</code> property controlling the vertical distribution of children in a <code>Vertical</code> wrap.</p></figcaption></figure>

### RunAlignment in horizontal and vertical

The runAlignment property is used to align the runs in the cross axis.

<figure><img src="/files/W9T9ZND5zR6MDLN6txNm" alt="An image showing horizontal run alignment in a Wrap widget."><figcaption><p>The <code>RunAlignment</code> property controlling the vertical distribution of runs in a <code>Horizontal</code> wrap.</p></figcaption></figure>

<figure><img src="/files/H8N7opuANWbUvOhjvPnU" alt="An image showing vertical run alignment in a Wrap widget."><figcaption><p>The <code>RunAlignment</code> property controlling the horizontal distribution of runs in a <code>Vertical</code> wrap.</p></figcaption></figure>

### Spacing and RunSpacing

The spacing and runSpacing properties are used to add space between the children and runs respectively.

<figure><img src="/files/ft5v4sGXTnh4wqUGh7bP" alt="An image showing spacing between children in a Wrap widget."><figcaption><p>The <code>Spacing</code> property adds space between children along the run axis</p></figcaption></figure>

<figure><img src="/files/HyFU8WZh0BcIvd0Q3jCe" alt="An image showing spacing between runs in a Wrap widget."><figcaption><p>The <code>RunSpacing</code> property adds space between runs.</p></figcaption></figure>

### CrossAxisAlignment in horizontal and vertical

CrossAxisAlignment is used to align the children relative to each other in the cross axis.

<figure><img src="/files/4MuF7jsg0wJuJ9cjxPUs" alt="An image showing CrossAxisAlignment for children in a Horizontal wrap."><figcaption><p>The <code>CrossAxisAlignment</code> property controlling the vertical alignment of children within a run in a <code>Horizontal</code> wrap.</p></figcaption></figure>

<figure><img src="/files/6qP43gmBEmlFKqKh4Nq0" alt="An image showing CrossAxisAlignment for children in a Vertical wrap."><figcaption><p>The <code>CrossAxisAlignment</code> property controlling the horizontal alignment of children within a run in a <code>Vertical</code> wrap.</p></figcaption></figure>

***

### Children: Static vs. Dynamic

You can populate a `Wrap` widget with child widgets in two ways:

#### 1. Static Children

Add a fixed number of child widgets directly in the builder. Each child you add will appear in the widget tree, and its properties can be configured individually. This is ideal for layouts where the number of items is known and doesn't change.

#### 2. Dynamic Children

To generate children from a list of data, you can use the **`Data Source`** property. This turns the `Wrap` widget into a powerful list builder.

1. Enable the `Data Source` toggle in the properties panel.
2. Provide data by either entering a fixed `JsonArray` in the JSON editor or binding it to an expression that returns a `JsonArray` (e.g., from an API call or App State).
3. Add a **single child widget** to the `Wrap`. This widget acts as a template that will be repeated for each item in the data source.
4. Inside this template child, use the `currentItem` variable to access the data for each item.
   * If your data is a list of objects (e.g., `[{"name": "Apple"}, {"name": "Banana"}]`), access properties with dot notation: `${currentItem.name}`.
   * If your data is a list of simple values (e.g., `["Apple", "Banana"]`), `currentItem` refers to the value itself: `${currentItem}`.

This is perfect for building a dynamic list of filter chips, product tags, or any other repeating UI element that needs to wrap gracefully.

***

## Default Properties

The Wrap widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

The **Wrap** widget is used when items need to **automatically move to the next line** instead of overflowing.

Use **Wrap** when you want to:

* **Display chips or tags**
  * Filters, categories, interests, labels that may be many in number
  * They should wrap onto the next line when they don’t fit in one row
* **Responsive pill / button groups**
  * Small buttons, shortcuts, or options that should flow naturally on small and large screens
* **Inline icon/text groups that wrap**
  * Badges, info pills, or small cards that shouldn’t require horizontal scrolling


# Sized Box

The **Sized Box** is a simple, invisible widget that creates a box with a specific width and height. Its primary purpose is to add fixed-size gaps or spacing within layouts.

{% embed url="<https://youtu.be/AfcFB7VpHgc?si=rzegOV-PMqbYAyWf>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=AfcFB7VpHgc>

### Core Concept: Creating Space

Think of the Sized Box as a rigid, empty spacer. While other widgets like `Container` can have padding and margins, the Sized Box has only one job: to occupy a precise amount of space. This makes it the most efficient and straightforward way to add gaps between widgets in a `Column` or `Row`.

* In a `Column`, a Sized Box with a `Height` creates vertical space.
* In a `Row`, a Sized Box with a `Width` creates horizontal space.

<figure><img src="/files/oRWyLuVlTXei4429W2L7" alt="A diagram showing a Sized Box creating vertical space in a Column and horizontal space in a Row."><figcaption><p>Using a Sized Box to add vertical space in a Column and horizontal space in a Row.</p></figcaption></figure>

### Properties

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Width</code></td><td>The width of the box. Can be a fixed value in pixels (px).</td></tr><tr><td><code>Height</code></td><td>The height of the box. Can be a fixed value in pixels (px).</td></tr></tbody></table>

***

### Default Properties

The Sized Box is a highly specialized layout widget. Its core properties (`Width` and `Height`) define its entire function, so it does not use the standard Default Properties for styling (like `Background Color` or `Border`).

### Use Cases

The **Sized Box** widget is mainly for **spacing and fixed size**.

Use **Sized Box** when you want to:

* Add **space** between widgets
  * Vertical gap between texts, buttons, sections
  * Horizontal gap between icons or buttons in a row
* Give a widget a **fixed width/height**
  * Make icons, images, or custom widgets a consistent size
  * Create a fixed square or rectangle area
* Create an **empty placeholder**
  * Reserve space for content that may appear later
  * Keep layout alignment even when something is hidden


# Safe Area

{% embed url="<https://youtu.be/ffflBgt6f14?si=ulSx4fnvkhdVt8Qz>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=ffflBgt6f14>

The **Safe Area** widget ensures that its child content **doesn’t get hidden behind system UI** like the status bar, navigation bar, home indicator, or device notches. It automatically adds padding so your UI stays within the “safe” visible area of the screen.

<figure><img src="/files/y2iNK2vYoBN0v8Igta6s" alt="A diagram showing how Safe Area widget prevents content from being hidden behind system UI elements like status bar and notch."><figcaption><p>The Safe Area widget ensures content stays within the visible area, avoiding system UI intrusions.</p></figcaption></figure>

### **Core Concepts**

* **System Intrusions**
  * Areas occupied by system UI:
    * Status bar (top)
    * Notch / camera cutout
    * Navigation bar / gesture bar (bottom)
  * Safe Area avoids these so your content is never hidden or overlapped.
* **Automatic Padding**
  * Safe Area calculates how much space is needed on each edge and applies padding to the child widget.
  * You can choose which sides (left/top/right/bottom) should respect the safe area.
* **Per-Side Control**
  * Sometimes you only want safe spacing at the **top** (for the notch) but want **edge-to-edge content** at the bottom (e.g., full-screen image).
  * The `left`, `top`, `right`, and `bottom` properties control this behavior.

### **Properties**

| Property | Description                                                                                                       |
| -------- | ----------------------------------------------------------------------------------------------------------------- |
| `left`   | If `true`, applies safe padding on the left side to prevent content from overlapping device curves or intrusions. |
| `top`    | If `true`, applies safe padding on the top side to avoid the status bar and notches.                              |
| `right`  | If `true`, applies safe padding on the right side to prevent clipping on curved or intruded areas.                |
| `bottom` | If `true`, applies safe padding on the bottom side to avoid navigation bars or gesture/home indicators.           |

#### Default Properties

The Safe Area widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### **Use Cases**

You should use **Safe Area** when:

* Your screen has content near the **top** (titles, search bars, tabs) that might clash with the **status bar** or **notch**.
* You’re designing for phones with **curved edges** or **punch-hole cameras** and want to avoid clipping important content.
* You’re building **full-screen layouts** (e.g., detail pages, forms, lists) where headers or footers could overlap with:
  * Status bar
  * Navigation bar
  * Gesture/home indicator
* You want a **single layout** that looks correct across:
  * iOS & Android
  * Different screen sizes
  * Devices with/without notches

Typical scenarios:

* Wrapping the **entire page** in Safe Area so all content is protected.
* Wrapping only **header / top sections** to avoid the notch, while letting the rest be edge-to-edge.
* Wrapping **bottom buttons** or navigation sections to keep them above the gesture bar or system navigation.


# Scaffold

{% embed url="<https://youtu.be/UJ0OzpgdsQ8?si=-bGv3zN1iRbIGeJO>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=UJ0OzpgdsQ8>

The **Scaffold** widget provides a **structured layout for a screen** in your app.\
It gives you predefined slots for common UI regions like:

* **App Bar** (top)
* **Body** (main content)
* **Bottom Navigation Bar** (bottom)

This helps you build consistent, reusable screen layouts without manually arranging these elements every time.

<figure><img src="/files/WnTahR76dk2H8xdlUYLS" alt="A demonstration of the Scaffold widget showing the structured layout with App Bar at top, Body in center, and Bottom Navigation Bar at bottom."><figcaption><p>The Scaffold widget provides a structured layout for a screen with predefined slots for App Bar, Body, and Bottom Navigation Bar.</p></figcaption></figure>

> 📚 **Learn More**: To understand the underlying Flutter implementation, see the [Flutter Scaffold documentation](https://api.flutter.dev/flutter/material/Scaffold-class.html).

### **Use Cases**

Use **Scaffold** whenever you’re building a full screen, such as:

* 🌐 **Main app screens**
  * Home, Dashboard, Profile, Settings, Product Listing, etc.
* 🧭 **Apps with tab or bottom navigation**
  * Screens that need a persistent bottom navigation bar.
* 📱 **Standard page layouts**
  * Screens with a top App Bar and scrollable content below.
* 🔁 **Reusable screen templates**
  * Define a common structure (App Bar + Body + Bottom Nav) and reuse it across multiple pages for consistent UX.

Typical scenarios:

* A product listing screen:
  * `appBar`: title + search icon
  * `body`: product grid/list
  * `bottomNavigationBar`: app-wide navigation tabs
* A profile screen:
  * `appBar`: back button + title
  * `body`: user info, settings, actions

Scaffold makes sure all these pieces sit in the right place without you managing positioning manually.

### **Core Concepts**

* **Screen Shell / Layout Frame**
  * Scaffold acts as the **outer frame** of a page.
  * It organizes top, bottom, and center content into predictable, platform-friendly positions.
* **Dedicated Slots**
  * Instead of nesting a bunch of containers manually, you plug widgets into named slots:
    * `appBar` for header/navigation bar.
    * `body` for main UI.
    * `bottomNavigationBar` for tab bars or primary navigation.
* **Safe Area Integration**
  * With `enableSafeArea = true`, the `body` is automatically wrapped in a **Safe Area** to avoid:
    * Status bar
    * Notch
    * Navigation bar / gesture area
  * This keeps content visible and unclipped across devices.
* **Background Styling at Screen Level**
  * `scaffoldBackgroundColor` lets you define the **background color for the entire screen**, not just the body, ensuring consistent visual design.

### Properties

| Property                  | Description                                                                                                                                                                                       |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `scaffoldBackgroundColor` | Sets the background color for the entire screen area managed by the Scaffold. This color appears behind the body, app bar, and any empty spaces.                                                  |
| `enableSafeArea`          | If `true`, automatically wraps the `body` in a Safe Area to avoid system intrusions (notch, status bar, navigation bar). This ensures that your main content doesn’t get hidden behind system UI. |

#### Children of Scaffold

| Children              | Description                                                                                                                    | Allowed Widgets                        |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------- |
| `appBar`              | The area at the top of the screen for the App Bar. Typically used for titles, actions, navigation icons.                       | `AppBar`                               |
| `bottomNavigationBar` | The area at the bottom of the screen for primary navigation or tabs. It stays fixed while the body content changes or scrolls. | `NavigationBar`, `NavigationBarCustom` |
| `body`                | The main content area of the screen. This is where most of your page UI lives.                                                 | Any widget                             |

### Default Properties

The **Scaffold** widget **does not** use the standard default properties like `width`, `height`, `padding`, etc.\
Instead:

* Its **layout & appearance** are controlled via:
  * `scaffoldBackgroundColor`
  * `enableSafeArea`
  * The widgets you place in its **slots** (`appBar`, `body`, `bottomNavigationBar`).

In practice, Scaffold is meant to be the **root layout** of a screen, so you don’t usually resize or position it— you structure the content inside its children.


# AppBar

The AppBar widget is a standard application bar that appears at the top of the screen. It can contain a title, leading and trailing action buttons, and a flexible space for collapsible headers.

{% embed url="<https://youtu.be/JSLWiX2xckY?si=G3LowvL3CAk5gVVt>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=JSLWiX2xckY>

### Core Concepts

1. **Top Navigation & Context Bar**\
   The **AppBar** is the **top bar** of a screen. It gives users:
   * **Context** → title, page name, or branding
   * **Navigation** → back button, close button, menu icon
   * **Quick actions** → search, filter, notifications, more menu
2. **Consistent Structure Across Screens**\
   The AppBar keeps your app feeling **consistent**:
   * Same height and placement on each screen
   * Familiar layout: leading (left) → title → actions (right)
   * Can optionally include tabs, avatars, or secondary text
3. **Leading, Title, Actions**
   * **Leading**: back arrow, menu icon, logo, or avatar
   * **Title**: screen name or key label (e.g., “Orders”, “Profile”)
   * **Actions**: icons/buttons for high-frequency actions (search, sort, cart, settings)

### Flutter Implementation Reference

The AppBar widget is based on Flutter's material design components:

* **Regular AppBar**: When `enableCollapsibleAppBar` is `false` (default), this widget behaves exactly like Flutter's [AppBar](https://api.flutter.dev/flutter/material/AppBar-class.html) - a fixed-height application bar.
* **Collapsible AppBar**: When `enableCollapsibleAppBar` is `true`, this widget behaves exactly like Flutter's [SliverAppBar](https://api.flutter.dev/flutter/material/SliverAppBar-class.html) - a material design app bar that can expand, collapse, and float based on scroll position.

> 📚 **Learn More**:
>
> * [Flutter AppBar documentation](https://api.flutter.dev/flutter/material/AppBar-class.html)
> * [Flutter SliverAppBar documentation](https://api.flutter.dev/flutter/material/SliverAppBar-class.html)

### Properties

#### General Properties

| Property                    | Description                                                               |
| --------------------------- | ------------------------------------------------------------------------- |
| `backgroundColor`           | The background color of the AppBar.                                       |
| `elevation`                 | The z-axis elevation of the AppBar, which creates a shadow effect.        |
| `shadowColor`               | The color of the shadow.                                                  |
| `centerTitle`               | If `true`, the title will be centered horizontally.                       |
| `titleSpacing`              | The spacing around the title.                                             |
| `automaticallyImplyLeading` | If `true`, a leading back button will be automatically added if possible. |
| `defaultButtonColor`        | The default color for action buttons in the AppBar.                       |
| `visibility`                | If `false`, the AppBar will be hidden.                                    |

#### Title Properties

| Property    | Description                                |
| ----------- | ------------------------------------------ |
| `text`      | The text to display as the title.          |
| `textStyle` | The TextStyle for the title.               |
| `alignment` | The alignment of the title.                |
| `maxLines`  | The maximum number of lines for the title. |
| `overflow`  | How title overflow is handled.             |

#### Collapsible AppBar Properties

| Property                  | Description                                                                               |
| ------------------------- | ----------------------------------------------------------------------------------------- |
| `enableCollapsibleAppBar` | If `true`, enables the collapsible app bar functionality.                                 |
| `expandedHeight`          | The height of the AppBar when fully expanded.                                             |
| `collapsedHeight`         | The height of the AppBar when fully collapsed.                                            |
| `pinned`                  | If `true`, the AppBar will remain visible at the top of the screen when scrolling.        |
| `floating`                | If `true`, the AppBar will become visible as soon as the user scrolls up.                 |
| `snap`                    | If `true`, the AppBar will snap into view when scrolling up.                              |
| `useFlexibleSpace`        | If `true`, allows the use of a flexible space widget for more complex background effects. |
| `titlePadding`            | The padding around the title in the flexible space.                                       |
| `collapseMode`            | The collapse mode for the flexible space (`parallax`, `pin`, `none`).                     |
| `expandedTitleScale`      | The scale of the title when the AppBar is fully expanded.                                 |

#### Shape Properties

| Property       | Description                                                |
| -------------- | ---------------------------------------------------------- |
| `value`        | The shape of the AppBar.                                   |
| `borderRadius` | The corner radius for a rounded rectangle shape.           |
| `eccentricity` | The eccentricity for a continuous rounded rectangle shape. |
| `borderColor`  | The color of the border.                                   |
| `borderWidth`  | The width of the border.                                   |
| `borderStyle`  | The style of the border.                                   |

#### Children of AppBar

| Slot         | Description                                                                            |
| ------------ | -------------------------------------------------------------------------------------- |
| `title`      | A custom widget to use as the title, which will override the default title properties. |
| `leading`    | A widget to display before the title (e.g., a menu icon or back button).               |
| `actions`    | A list of widgets to display after the title (e.g., action buttons).                   |
| `bottom`     | A widget to display at the bottom of the AppBar (e.g., a TabBar).                      |
| `background` | A widget to display as the background of the flexible space.                           |

***

### Default Properties

The AppBar widget does not have the standard default properties. Its appearance and behavior are controlled by the properties and children listed above.

### Use Cases

Use **AppBar** when you want to:

* **Show which screen the user is on**
  * “Home”, “Explore”, “Cart”, “Settings”, “Order Details”, etc.
* **Provide navigation controls**
  * Back/close button for detail pages
  * Drawer/menu button for opening side navigation
* **Expose key actions**
  * Search, filter, sort, cart, share, edit, more options
  * Notification bell or profile shortcut
* **Brand the experience**
  * Show logo, brand colors, or a custom styled top bar


# Overlay

{% embed url="<https://youtu.be/H9tM7qjowIE?si=MlWvrFj-swXBJufG>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=H9tM7qjowIE>

The **Overlay** widget is used to display a widget **on top of** another widget.\
It’s ideal for **floating UI elements** like pop-up menus, tooltips, dropdowns, and custom dialogs that appear above the main content.

<figure><img src="/files/eMajmr8pHRY7fb7QXndv" alt="A demonstration of the Overlay widget showing popup content appearing above the main widget."><figcaption><p>The Overlay widget displays floating UI elements like menus, tooltips, and dropdowns on top of main content.</p></figcaption></figure>

### Core Concepts

1. **Base vs Popup Content**
   * `childWidget` is the **main widget** that always stays visible (e.g., button, icon, text).
   * `popupWidget` is the **floating content** that appears on top (e.g., menu, tooltip, card).
2. **Positioning & Alignment**
   * `childAlignment` controls how the main child is aligned inside the Overlay.
   * `popupAlignment` defines **where the popup appears** relative to the child (top, bottom, left, right, center, etc.).
   * `offset.xAxis` / `offset.yAxis` fine-tune the position to nudge the popup slightly up/down/left/right.
3. **Dismiss Behavior**
   * `dismissOnTapOutside` → Close the popup when the user taps anywhere outside it.
   * `dismissOnTapInside` → Close the popup when the user taps **inside** the popup itself (good for simple info views or one-tap dismiss).

These controls make the Overlay feel natural and predictable for users.

### Properties

| Property                      | Description                                                                                   |
| ----------------------------- | --------------------------------------------------------------------------------------------- |
| `childAlignment`              | Alignment of the main `childWidget` inside the Overlay.                                       |
| `popupAlignment`              | Alignment of the `popupWidget` relative to the main child (e.g., above, below, centered).     |
| `offset.xAxis / offset.yAxis` | Horizontal and vertical offset applied to the popup’s position to adjust its exact placement. |
| `dismissOnTapOutside`         | If `true`, tapping outside the popup hides it.                                                |
| `dismissOnTapInside`          | If `true`, tapping inside the popup hides it.                                                 |

#### Children of Overlay

| Slot          | Description                                                                                            |
| ------------- | ------------------------------------------------------------------------------------------------------ |
| `childWidget` | The single main child widget that is always visible (e.g., button, icon, text).                        |
| `popupWidget` | The single child widget displayed as the popup on top of the main content (e.g., tooltip, menu, card). |

### Default Properties

The Overlay widget supports the following section of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`
* `align`

### Use Cases

Use the **Overlay** widget when you want to:

* Show a **popup menu** when a button is tapped (e.g., more options, actions menu).
* Display a **tooltip** near an icon or label to give extra information.
* Create **dropdowns** for filters, selectors, or input fields.
* Show **floating panels** like small info cards, quick actions, or contextual menus.
* Build lightweight **custom popups** that don’t require full-screen dialogs or navigation.

Anywhere you need a **temporary, floating UI** attached to a trigger widget, Overlay fits perfectly.


# Conditional Builder

The Conditional Builder widget is a powerful tool for displaying different widgets based on a set of conditions. It evaluates a series of `ConditionalItem` children and displays the first one whose condition evaluates to `true`. This is useful for creating dynamic UIs that change based on application state, user input, or other factors.

{% embed url="<https://youtu.be/87ojech5Pyc?si=6C-WjhoTZ2HlfKUn>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=87ojech5Pyc>

### Core Concepts

* **First Match Logic**\
  Conditions are checked in order. The **first `true` condition wins**, and its widget is shown.
* **Shared Data (Data Ref)**\
  A **Data Ref** is provided at the builder level and can be used by all ConditionalItems in their conditions.
* **Active View**\
  You can manually set **Active View** to a specific index to **force** showing a particular ConditionalItem (useful for debugging or previews).

### **Data Source**

The Conditional Builder widget has a `Data Ref` property that can be used by the `ConditionalItem` children. You can input either static data or dynamic data using expressions.

### **Properties**

| Property      | Description                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------- |
| `Data Ref`    | A list of data that can be used by the `ConditionalItem` children.                                      |
| `Active View` | The index of the `ConditionalItem` to display. This is useful for debugging or forcing a specific view. |

### Children of Conditional Builder

| Children   | Description                                                                                                               |
| ---------- | ------------------------------------------------------------------------------------------------------------------------- |
| `children` | A list of `ConditionalItem` widgets. The first `ConditionalItem` whose `condition` evaluates to `true` will be displayed. |

### Default Properties

The Conditional Builder widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **Conditional Builder** when you want to:

* Switch between **loading / error / data** UIs
* Show different layouts for **logged-in vs guest** users
* Change UI based on **selected plan, mode, or step**
* Display different views based on **app state or API response**


# Expandable

The **Expandable** widget is a versatile UI component that allows you to show or hide content dynamically. It consists of a header that remains always visible and collapsible content that can be revealed or hidden with a tap. This widget is particularly useful for creating accordions, FAQ sections, collapsible forms, and any interface where space conservation is important while still providing access to detailed information on demand.

{% embed url="<https://youtu.be/PktfH9FuYuA?si=95cZnZQyuLCEOHtK>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=PktfH9FuYuA>

Expandable widgets help reduce visual clutter by allowing users to access information only when they need it, creating cleaner, more organized interfaces especially on mobile devices or complex forms.

<figure><img src="/files/EJ1UugsSrQW4aNpqX8vN" alt="A hero image illustrating an Expandable widget with collapsible content."><figcaption><p>An interactive widget for showing and hiding content dynamically with smooth animations.</p></figcaption></figure>

{% hint style="info" %}
Our Expandable widget follows Flutter's `ExpansionPanel` and `ExpansionTile` patterns, providing smooth animations, flexible content configuration, and comprehensive interaction options.
{% endhint %}

### Core Concepts

#### 1. Three Required Children Slots

The Expandable widget requires **three separate child widgets** to function properly:

* **`header`**: The always-visible part that users tap to toggle expansion.
* **`collapsedView`**: The content shown when the widget is in its collapsed state.
* **`expandedView`**: The content shown when the widget is in its expanded state.

All three children are required. The widget automatically handles the transition between collapsed and expanded views based on user interaction.

#### 2. State Management: Collapsed vs. Expanded

The Expandable widget maintains an internal state that determines which view is currently visible:

* **Collapsed State**: Shows the header and collapsedView content.
* **Expanded State**: Shows the header and expandedView content.

You can control the initial state using the `Initially Expanded` property, and users can toggle between states by tapping (depending on your tap behavior configuration). You can also bind `Initially Expanded` to expressions or variables to dynamically control the expansion state based on app logic.

#### 3. Tap Behavior Flexibility

Unlike simple toggles, Expandable provides granular control over tap interactions:

* **Tap Header to Toggle**: Most common pattern—tapping the header switches states.
* **Tap Body to Expand**: Tapping the collapsed content can expand it.
* **Tap Body to Collapse**: Tapping the expanded content can collapse it.

These options can be enabled independently, giving you complete control over the interaction model.

#### 4. Visual Feedback with Icons & Animations

Expandable provides built-in support for:

* **Expand/Collapse Icons**: Automatically swap icons based on state.
* **Icon Rotation**: Smoothly rotate icons during transitions (e.g., chevron pointing down → up).
* **Animation Duration**: Control how fast the expand/collapse animation plays.
* **InkWell Effect**: Add Material Design ripple effects to interactions.

***

### Children Slots

The Expandable widget has three **required** children slots:

<table><thead><tr><th width="180">Slot</th><th>Description</th></tr></thead><tbody><tr><td><code>header</code></td><td><strong>Required.</strong> The always-visible part of the widget, typically containing a title or label. This is what users see and tap to toggle expansion.</td></tr><tr><td><code>collapsedView</code></td><td><strong>Required.</strong> The content displayed when the widget is in its collapsed state. Often contains a brief summary, preview, or placeholder.</td></tr><tr><td><code>expandedView</code></td><td><strong>Required.</strong> The content displayed when the widget is in its expanded state. Contains the full detailed information or interactive elements.</td></tr></tbody></table>

***

### Properties

#### Active View Property

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Active View</code></td><td><strong>Dashboard Preview Only.</strong> Controls whether the widget appears in the <code>Collapsed</code> or <code>Expanded</code> state in the builder dashboard. This is purely for design preview purposes and does not affect the runtime behavior of the widget.</td></tr><tr><td><code>Initially Expanded</code></td><td>If <code>true</code>, the widget will be in the expanded state by default when the page first loads in the actual app. Default is <code>false</code> (collapsed). This is the property that controls the real initial state.</td></tr></tbody></table>

#### Tap Behavior Properties

These properties control how users can interact with the widget:

<table><thead><tr><th width="220">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Tap Header to Toggle</code></td><td>If <code>true</code>, tapping anywhere on the header will toggle between collapsed and expanded states. This is the most common interaction pattern.</td></tr><tr><td><code>Tap Body to Expand</code></td><td>If <code>true</code>, tapping on the collapsed content will expand the widget. Useful when you want the collapsed content to be interactive.</td></tr><tr><td><code>Tap Body to Collapse</code></td><td>If <code>true</code>, tapping on the expanded content will collapse the widget. Useful for "dismiss" behavior.</td></tr></tbody></table>

{% hint style="info" %}
**Tip:** You can enable multiple tap behaviors simultaneously. For example, enable both "Tap Header to Toggle" and "Tap Body to Collapse" to allow users to collapse from either location.
{% endhint %}

#### Alignment Properties

Control how content is positioned within each slot:

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Alignment</code></td><td>The alignment of the entire expandable widget within its parent container (e.g., left, center, right).</td></tr><tr><td><code>Header Alignment</code></td><td>The alignment of content within the header slot. Controls how child widgets are positioned inside the header.</td></tr><tr><td><code>Body Alignment</code></td><td>The alignment of content within the collapsed and expanded view slots.</td></tr></tbody></table>

#### Icon Properties

The Expandable widget has built-in support for state-indicating icons:

<table><thead><tr><th width="220">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Has Icon</code></td><td>If <code>true</code>, an icon will be displayed in the header to indicate the expand/collapse state.</td></tr><tr><td><code>Icon Placement</code></td><td>Where to position the icon within the header: <code>Left</code> or <code>Right</code>.</td></tr><tr><td><code>Collapsed Icon</code></td><td>The icon to display when the widget is in the collapsed state (e.g., chevron_down, add, arrow_forward).</td></tr><tr><td><code>Expanded Icon</code></td><td>The icon to display when the widget is in the expanded state (e.g., chevron_up, remove, arrow_drop_down).</td></tr><tr><td><code>Icon Size</code></td><td>The size of the icon in pixels. Default is typically 24px.</td></tr><tr><td><code>Icon Color</code></td><td>The color of the icon. Can be set from your design system colors or as a custom hex value.</td></tr><tr><td><code>Icon Padding</code></td><td>The padding around the icon to create spacing between the icon and other header content.</td></tr><tr><td><code>Icon Rotation Angle</code></td><td>The angle (in degrees) to rotate the icon when transitioning to the expanded state. Creates smooth rotation animations (e.g., 180° to flip a chevron).</td></tr></tbody></table>

{% hint style="success" %}
**Icon Best Practice:** Use consistent icon pairs across your app:

* `chevron_right` / `expand_more` for horizontal/vertical expansion
* `add` / `remove` for accordion-style interfaces
* `arrow_forward` / `arrow_drop_down` for dropdown-like behavior
  {% endhint %}

#### Style & Animation Properties

<table><thead><tr><th width="220">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Animation Duration</code></td><td>The duration of the expand and collapse animation in milliseconds. Default is typically 300ms. Lower values create snappier transitions, higher values create smoother, more deliberate animations.</td></tr><tr><td><code>Use InkWell Effect</code></td><td>If <code>true</code>, a Material Design ripple effect will be shown when the user taps the widget. Provides tactile feedback.</td></tr><tr><td><code>InkWell Border Radius</code></td><td>The corner radius for the ripple effect when InkWell is enabled. Should typically match your container's border radius for visual consistency.</td></tr></tbody></table>

***

### Use Cases

Expandable is ideal for:

* **FAQ Sections**: Display questions as headers with answers that expand on tap.
* **Accordion Menus**: Create collapsible navigation or category lists.
* **Settings Panels**: Hide advanced options until users need them.
* **Product Details**: Show basic info by default, expand for specifications.
* **Forms with Sections**: Organize long forms into collapsible sections.
* **Filter Panels**: Show/hide filter options in e-commerce or search interfaces.
* **Reading Lists**: Display article titles with expandable summaries.
* **Terms & Conditions**: Show abbreviated text with full text expansion.
* **Educational Content**: Display lesson titles with expandable content.
* **User Profiles**: Collapse sections like "About", "Skills", "Experience".

{% hint style="success" %}
**User Experience Tip:** Always provide clear visual indicators (like icons or arrows) that show whether content is expanded or collapsed. This helps users understand the widget's interactive nature.
{% endhint %}

***

### Best Practices

#### Design Guidelines

**Visual Consistency:**

* Use consistent header styling across all expandable widgets in your app
* Maintain the same icon style (filled vs outlined) throughout
* Keep animation durations uniform for predictable UX

**Content Organization:**

* Place most important information in the header
* Use collapsedView for teasers or summaries
* Reserve expandedView for detailed content or actions

**Accessibility:**

* Ensure sufficient tap target size for headers (minimum 44x44 points)
* Use clear, descriptive header text
* Provide adequate color contrast for text and icons

#### Performance Considerations

**Lazy Loading:**

* For heavy content in expandedView, consider lazy loading images or data
* Don't load all expanded content upfront if you have many expandables

**Animation Optimization:**

* Keep animation durations under 500ms for responsive feel
* Avoid animating heavy widgets; use lightweight containers

**List Performance:**

* When using multiple Expandables in a ListView, ensure only one is expanded at a time
* Use state management to track which item is expanded

#### Common Patterns

**Progressive Disclosure:** Use expandables in multi-step forms to reveal sections.

**Search & Expand:** Combine search functionality with expandables:

```
Search results → Each result is an Expandable
- Header shows title and summary
- CollapsedView shows brief preview
- ExpandedView shows full content
```

***

### Default Properties

The Expandable widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).


# Content & Display

Widgets for displaying text, images, and other visual content to users.

## Overview

Content & Display widgets are responsible for presenting information to users. These widgets handle text rendering, image display, and other visual elements that convey content.

## Categories

### Text Display

* [**Text**](/ui-building-blocks/widgets/content-display-widgets/text) - Basic text display with styling options
* [**Rich Text**](/ui-building-blocks/widgets/content-display-widgets/rich-text) - Advanced text with multiple styles and formatting

### Visual Content

* [**Image**](/ui-building-blocks/widgets/content-display-widgets/image) - Display images from various sources
* [**Icon**](/ui-building-blocks/widgets/content-display-widgets/icon) - Display icons from icon libraries
* [**Avatar**](/ui-building-blocks/widgets/content-display-widgets/avatar) - Circular user profile images

### Content Presentation

* [**Divider**](/ui-building-blocks/widgets/content-display-widgets/dividers) - Visual separators between content sections
* [**Circular Progress Bar**](/ui-building-blocks/widgets/content-display-widgets/circular-progress-bar) - Circular loading indicators
* [**Linear Progress Bar**](/ui-building-blocks/widgets/content-display-widgets/linear-progress-bar) - Horizontal progress indicators

### Interactive Display

* [**Carousel**](/ui-building-blocks/widgets/content-display-widgets/carousel) - Swipeable content galleries
* [**Timer**](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/content-display-widgets/timer.md) - Countdown or elapsed time displays


# Text

The **Text** widget is a fundamental building block for any application. It allows you to display static or dynamic text content on the screen. Whether it's a heading, a paragraph, a label, or inline text — it helps convey information clearly and effectively to users.

{% embed url="<https://www.youtube.com/watch?v=QVfpdo5IcrY>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=QVfpdo5IcrY>

#### Adding a Text Widget

The Text widget is located in the **Base Elements** section of the Widget Palette. You can drag it to your desired screen location or insert it directly via the widget tree. Once selected, the **Widget Properties Panel** appears on the right side of the screen. Use this panel to enter your desired text and customize its appearance.

### Core Concepts

Before diving into properties, it's helpful to understand two core concepts that make the Text widget powerful in Digia Studio.

#### 1. Static vs. Dynamic Text

You can use the Text widget to display both static, unchanging text and dynamic text that is bound to a data source.

* **Static Text:** Simply type the text you want to display directly into the `Text` property.
* **Dynamic Text:** Use expressions to bind the `Text` property to a variable from your app's state, an API response, or a function. This is the key to creating data-driven applications.

#### 2. Styling Strategy: Theming vs. Customizing

Consistency is key to good design. The Text widget supports two styling modes:

* **Linked (Theme):** The text's style is "linked" to your app's global `Typography` theme. This ensures all your text looks consistent. If you update the theme, all linked text widgets will update automatically.
* **Unlinked (Custom):** Use this for specific, one-off designs where you need to override the theme. This gives you full control over every style property for that specific widget.

{% hint style="success" %}
**Note:** For design consistency and easier maintenance, it is highly recommended to use theme tokens (e.g., `Headline Medium`, `Body Text Large`) rather than custom values for text styling whenever possible. Custom styling should be reserved for unique, one-off cases.
{% endhint %}

### Properties

The properties for the Text widget are organized by function. For more detailed formatting (e.g., multiple styles in one sentence), we recommend using the [Rich Text widget](/ui-building-blocks/widgets/content-display-widgets/rich-text) instead.

#### Content

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Value</code></td><td>The actual string content to display. Can be a static value or a dynamic expression.</td></tr></tbody></table>

#### Layout & Behavior

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Alignment</code></td><td>Aligns text horizontally within its container (<code>left</code>, <code>center</code>, <code>right</code>, <code>justify</code>).</td></tr><tr><td><code>Max Lines</code></td><td>Limits the number of lines shown. If empty, the text will expand as needed.</td></tr><tr><td><code>Overflow</code></td><td>Controls how text overflows when it exceeds the available space. Options include <code>clip</code>, <code>fade</code>, <code>ellipsis</code>, <code>visible</code>, <code>marquee</code>.</td></tr></tbody></table>

#### Styling

Styling is controlled via the `Text Style` property, which can be **Linked** to a theme or **Unlinked** for custom styling.

<figure><img src="/files/e9hCvsl9GWxjT4FYkXx8" alt="Visual explanation of different Box Fit properties like cover, contain, and fill."><figcaption><p>In 'Linked' mode, you select a predefined text style from your app's theme. In 'Unlinked' mode, you get granular control over font properties.</p></figcaption></figure>

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Text Style</code></td><td>The main property for styling. Choose between <strong>Linked</strong> (theme style) and <strong>Unlinked</strong> (custom).</td></tr><tr><td><code>Font Family</code></td><td>The font family used (e.g., <code>Poppins</code>, <code>Roboto</code>). Only available when <code>Text Style</code> is <strong>Unlinked</strong>.</td></tr><tr><td><code>Size</code></td><td>Font size in pixels. Only available when <code>Text Style</code> is <strong>Unlinked</strong>.</td></tr><tr><td><code>Weight</code></td><td>Font weight like <code>regular</code>, <code>bold</code>, <code>medium</code>, etc. Only available when <code>Text Style</code> is <strong>Unlinked</strong>.</td></tr><tr><td><code>Height</code></td><td>Line height multiplier (e.g., 1.5 for 150%). Only available when <code>Text Style</code> is <strong>Unlinked</strong>.</td></tr><tr><td><code>is Italic</code></td><td>Whether the text should be displayed in italic style. Only available when <code>Text Style</code> is <strong>Unlinked</strong>.</td></tr><tr><td><code>Text Color</code></td><td>The color of the text in HEX format (e.g., <code>#000000</code>).</td></tr><tr><td><code>Highlight Color</code></td><td>The background color behind the text for highlighting effects.</td></tr><tr><td><code>Text Decoration</code></td><td>Adds decorative lines to text (underline, overline, line-through).</td></tr><tr><td><code>Text Decoration Color</code></td><td>The color of the text decoration lines.</td></tr></tbody></table>

### Default Properties

The Text widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

You’ll typically use **Text** for:

* **Labels & Titles**
  * Form labels (Name, Email)
  * Section headers (Overview, Analytics, Orders)
  * Button-like captions inside other widgets
* **Dynamic Data**
  * Showing values from APIs (user name, balance, order count)
  * Displaying computed expressions (e.g., `₹${total}`)
  * Realtime values coming from state or controllers
* **Status & Feedback**
  * Empty state messages (“No data available”, “Nothing here yet”)
  * Success/error/info messages
  * Helper texts or hints below fields
* **Small Content Blocks**
  * Descriptions, help text, tooltips content, subtitles
  * Timestamp, tags, metadata under cards or list items

Basically, anywhere you need **read-only text** shown to the user, you use the Text widget.


# Rich Text

The **Rich Text** widget allows you to display text with multiple styles within a single block. Unlike the basic [Text widget](broken://pages/C9nNxThiJc2b87pM8M0Z), Rich Text is perfect for scenarios where you need to mix formatting, such as bolding a keyword, coloring a specific phrase, or making a portion of the text clickable.

{% embed url="<https://www.youtube.com/watch?v=VeQXbORTYjc>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=VeQXbORTYjc>

<figure><img src="/files/jxcjEAEJfvDOTpVOCcFT" alt="An example of a Rich Text widget with multiple styles."><figcaption><p>An example of a Rich Text widget with multiple styles in a single block.</p></figcaption></figure>

#### Adding a Rich Text Widget

The Rich Text widget is located in the **Base Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

### Core Concept: Text Spans

The Rich Text widget is composed of a list of **Text Spans**. Think of each span as an individual, mini-`Text` widget that has its own content, styling, and optional `onClick` action. By combining these spans, you can create a single, seamless block of text with varied formatting.

### Properties

The properties are divided into two main groups: properties for the entire widget and properties for each individual text span.

#### Global Properties

These properties control the layout and behavior of the entire Rich Text block.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Alignment</code></td><td>Aligns the entire text block horizontally (<code>left</code>, <code>center</code>, <code>right</code>, <code>justify</code>).</td></tr><tr><td><code>Max Lines</code></td><td>Limits the number of lines for the entire Rich Text widget. If empty, the text will expand as needed.</td></tr><tr><td><code>Overflow</code></td><td>Controls how text overflows when it exceeds the available space. Options include <code>clip</code>, <code>fade</code>, <code>ellipsis</code>, <code>visible</code>, <code>marquee</code>.</td></tr><tr><td><code>Text Style</code></td><td>A <strong>base</strong> text style applied to all spans. This can be overridden by the styling of an individual span.</td></tr></tbody></table>

#### Text Spans

This section in the properties panel is where you manage the list of individual text segments. Each span in the list has its own set of controls:

<figure><img src="/files/GqCFsLevgQuJWbv1liQc" alt="Managing Text Spans"><figcaption><p>Each span has an input for its value and an icon to edit its style.</p></figcaption></figure>

* **Value Input**: Directly edit the text content for each span in its input field. This can be static text or a dynamic expression (e.g., `Hello, ${appState.user.name}`).
* **Styling (Pencil Icon)**: Click the pencil icon to open a modal where you can customize the `Text Style` for that specific span. You can link it to a theme style or create a custom one.
* **Reordering & Deleting**: Hover over a span to reveal controls for dragging to reorder or deleting it.
* **Add New Span**: Click the "Add New" button at the bottom to add another segment to your Rich Text.
* **Interaction (On Click)**: Inside the styling modal (opened via the pencil icon), you can also add an `On Click` action. This makes a specific span interactive, which is perfect for creating inline links like "Terms of Service" or "Privacy Policy" within a sentence.

***

### Text vs. Rich Text

Choose the right widget for the job to keep your app efficient and easy to maintain.

| Feature           | Text Widget                    | Rich Text Widget                            |
| ----------------- | ------------------------------ | ------------------------------------------- |
| **Styling**       | One style for the entire block | Multiple styles in one block                |
| **Interactivity** | The entire widget is clickable | Each text span can be clickable             |
| **Use Case**      | Headings, paragraphs, labels   | "By signing up, you agree to our **Terms**" |
| **Complexity**    | Simple                         | More complex, composed of spans             |

### Default Properties

The Rich Text widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

You’d typically use **Rich Text** when:

* **Mixed-style sentences**
  * “By continuing, you agree to the **Terms & Conditions** and **Privacy Policy**.”
  * “Your balance is **₹1,250.00** and next payment is **due tomorrow**.”
* **Inline emphasis**
  * Highlight a **keyword**, amount, or username inside a longer line.
  * Show parts of a sentence in bold, italic, or different color for emphasis.
* **Link-like behavior**
  * Make part of the text **clickable** (e.g., “Forgot password?”, “Learn more”).
  * Create inline CTAs inside a paragraph instead of separate buttons.
* **Formatted messages**
  * Show **system messages**, chat messages with mentions, hashtags, or tags.
  * Display **legal or policy copy** with some parts highlighted or styled differently.
* **Multi-style labels & helpers**
  * Example: “Plan: **Pro** (billed **monthly**)”
  * Example: “**50% OFF** for the first **3 months**”

In short: whenever you need **different styles or behaviors inside one text block**, Rich Text is the right choice.


# Image

The **Image widget** is used to display images in your application. It's a versatile component that can render various image formats from different sources, with built-in support for placeholders, error states, and advanced layout control.

{% embed url="<https://www.youtube.com/watch?v=ukZoMCppxyk>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=ukZoMCppxyk>

### Core Concepts

#### 1. Image Sources: Network vs. Asset

You can load images from two primary sources:

* **Network**: Loads an image directly from a URL. This is ideal for dynamic content, like user profile pictures or images from an API.
* **Asset**: Loads an image that is part of your project's assets. For this to work, you must first upload the image in the **Settings > Local Assets** section of the dashboard. This creates a "Local Asset" that you can then select from a dropdown.

{% hint style="warning" %}
**For SDK Integrations:** When using an `Asset` image, ensure the image file is included in your Flutter project at the exact path you specified when creating the Local Asset on the dashboard.
{% endhint %}

#### 2. Supported Formats

The Image widget supports a wide range of popular formats: `png`, `jpg`, `jpeg`, `gif`, `webp`, `svg`, `avif`

***

### Properties

#### Source & Content

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Source</code></td><td>The source of the image. Can be <code>Network</code> or <code>Asset</code>.</td></tr><tr><td><code>Image URL / Asset</code></td><td>The URL for a network image or the dropdown to select a pre-uploaded asset.</td></tr><tr><td><code>Image Type</code></td><td>Specifies the image format. Options are <code>Image</code>, <code>SVG</code>,<code>Avif</code>, or <code>Auto</code>. In <strong>Auto</strong> mode, the widget automatically determines the best way to render the image based on its source.</td></tr><tr><td><code>SVG Color</code></td><td>If the image is an SVG, this property applies a solid color fill to it, ignoring the original colors within the SVG file.</td></tr></tbody></table>

#### Layout & Sizing

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Aspect Ratio</code></td><td>Constrains the widget to a specific aspect ratio (e.g., 16/9 for widescreen, 1/1 for a square). This can override the <code>Height</code> if <code>Width</code> is also set.</td></tr><tr><td><code>Fit</code></td><td>Controls how the image should be sized and positioned within its bounds if its dimensions do not match the widget's dimensions. Options include <code>None</code>, <code>Cover</code>, <code>Fill</code>, <code>Contain</code>,<code>Fit Width</code>, <code>Fit Height</code>, and <code>Scale Down</code>.</td></tr><tr><td><code>Alignment</code></td><td>Positions the image within its container if the image is smaller than the container (e.g., when using <code>fit: contain</code>).</td></tr></tbody></table>

{% hint style="info" %}
The `Width` and `Height` of the image can be controlled via the **Default Properties** section.
{% endhint %}

<figure><img src="/files/iklwTfloeJQzkLI5gWhY" alt="Visual explanation of different Box Fit properties like cover, contain, and fill."><figcaption><p>How the <code>Fit</code> property affects image rendering.</p></figcaption></figure>

<figure><img src="/files/AIwn5yTa2WaVO5ceXxPD" alt="Visual explanation of different Alignment properties like top-left, center, and bottom-right."><figcaption><p>How the <code>Alignment</code> property positions an image within its container.</p></figcaption></figure>

#### Loading & Error States

These properties enhance the user experience by providing feedback while the image is loading or if it fails to load.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Placeholder</code></td><td>The type of placeholder to show while a network image is loading. Currently, only <code>BlurHash</code> is supported.</td></tr><tr><td><code>BlurHash String</code></td><td>The BlurHash string that generates the placeholder image.</td></tr><tr><td><code>Error Image</code></td><td>A fallback image to display if the primary image fails to load. To select an error image, you must first upload it as a Local Asset in the dashboard.</td></tr></tbody></table>

{% hint style="info" %}
**Coming Soon:** We are working on adding more placeholder options, such as shimmer effects and low-resolution image previews.
{% endhint %}

***

### Default Properties

The Image widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

You’ll typically use **Image** for:

* **Branding**
  * App logo, brand mark, partner logos
  * Hero images on onboarding or home screens
* **Content Visuals**
  * Product photos in e-commerce
  * Banners, promos, and campaign creatives
  * Thumbnails for articles, videos, or podcasts
* **Context & Illustration**
  * Empty state illustrations (“No orders yet”, “No notifications”)
  * Informational graphics in guides or feature highlights
  * Icons or decorative visuals to support text
* **User-Related Media**
  * Profile pictures or avatars
  * Uploaded images (receipts, documents, screenshots)
  * Gallery or carousel views
* **Feedback & Status**
  * Success / error / warning illustrations
  * Badges or stamps (NEW, SALE, VERIFIED)


# Icon

The **Icon widget** displays graphical icons from various icon libraries. It provides a simple way to add visual elements to your application using scalable vector icons that can be customized in size and color. Icons are essential for creating intuitive user interfaces and improving visual communication.

The Icon widget supports multiple icon packs including Material Icons, Cupertino Icons, Line Icons, and FontAwesome, giving you access to thousands of professionally designed icons.

{% embed url="<https://www.youtube.com/watch?v=Tkm_TFkMp7s>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=Tkm_TFkMp7s>

### Properties

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Icon</code></td><td>The selected icon from available icon packs. Displays the icon preview and pack.key identifier.</td></tr><tr><td><code>Icon Size</code></td><td>The size of the icon in pixels. Can be a static value or dynamic expression.</td></tr><tr><td><code>Icon Color</code></td><td>The color of the icon in HEX format (e.g., <code>#000000</code>). If not specified, uses the default text color.</td></tr></tbody></table>

#### Icon Selection Interface

When you click on the Icon property, a modal opens with the following features:

**Icon Browser**

* **Icon Preview**: Live preview of the selected icon
* **Search & Browse**: Browse through different icon packs and search for specific icons
* **Icon Identification**: Selected icons are displayed with their pack and key identifier (e.g., `material.rocket`)

**Icon Management**

* **Change Icon**: Click the icon selector button to browse and select a new icon
* **Clear Icon**: Use the clear button to remove the currently selected icon
* **No Selection State**: When no icon is selected, displays "No icon selected"

#### Supported Icon Packs

The Icon widget supports the following icon libraries:

<table><thead><tr><th width="176.25390625">Icon Pack</th><th>Description</th></tr></thead><tbody><tr><td><code>Material</code></td><td>Google's Material Design icons, perfect for modern Android-style interfaces. [<a href="https://fonts.google.com/icons">Browse Icons</a>]</td></tr><tr><td><code>Cupertino</code></td><td>Apple's iOS-style icons, ideal for iOS-themed applications. [<a href="https://api.flutter.dev/flutter/cupertino/CupertinoIcons-class.html">Browse Icons</a>]</td></tr><tr><td><code>Line Icons</code></td><td>Clean, minimal line-style icons for contemporary designs. [<a href="https://icons8.com/line-awesome">Browse Icons</a>]</td></tr><tr><td><code>FontAwesome</code></td><td>Comprehensive icon library with various styles and categories. [<a href="https://fontawesome.com/icons">Browse Icons</a>]</td></tr></tbody></table>

***

### Default Properties

The Icon widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

* **Navigation**: Use directional icons for navigation buttons
* **Actions**: Represent actions with intuitive icons (save, edit, delete)
* **Status**: Show status indicators with appropriate icons
* **Categories**: Visually categorize content with relevant icons
* **Social**: Display social media icons for sharing features


# Avatar

The **Avatar widget** is used to represent users or entities, typically displaying profile pictures or initials. It provides a flexible way to show either image content or text within different shape containers, making it perfect for user profiles, contact lists, and user identification throughout your application.

{% embed url="<https://www.youtube.com/watch?v=8K3p972GeIw>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=8K3p972GeIw>

#### Adding an Avatar Widget

The Avatar widget is located in the **Base Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/4LKtr0p3x4jC122LEtqe" alt="A hero image showing different styles of the Avatar widget, including image and text fallbacks."><figcaption><p>The Avatar widget is perfect for representing users with images or initials.</p></figcaption></figure>

### Core Concept: Content Fallback

The Avatar widget is designed to be robust. It will always attempt to display an **Image** first. If the image source is not provided, is null, or fails to load, the widget will automatically fall back to displaying the **Text** content (typically user initials). This ensures your UI always shows a meaningful representation of the user.

{% hint style="info" %}
**Previewing Content in the Builder:** The properties panel includes a **`Preview State`** toggle. This is a design-time tool only; it has no effect on your running app. Use it to switch the view on the canvas between the `Image` and `Text` content while you are designing.
{% endhint %}

***

### Properties

The Avatar's properties are grouped by function.

#### Content

These properties define the primary image and the fallback text.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Image</code></td><td>The image to display in the avatar. This uses the complete <strong>Image widget</strong>, giving you access to all its properties (Source, Fit, Error Image, etc.). See the <a href="/pages/6z7S1aQEXfxif5PYzak3">Image documentation</a> for all options.</td></tr><tr><td><code>Text</code></td><td>The fallback text to display if the image is not available. This uses the complete <strong>Text widget</strong>, giving you access to all its properties (Value, Text Style, etc.). See the <a href="/pages/KG0SqVV5TzxUrLTT0yJO">Text documentation</a> for all options.</td></tr></tbody></table>

#### Shape & Styling

These properties control the avatar's container.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Shape</code></td><td>Defines the avatar's geometric shape. Options are <code>Circle</code> for round avatars or <code>Square</code> for rectangular avatars.</td></tr><tr><td><code>Background Color</code></td><td>The background color of the avatar, visible behind transparent images or as the background for the fallback text.</td></tr><tr><td><code>Radius</code></td><td>Controls the size of the avatar when <code>Shape</code> is set to <strong>Circle</strong>.</td></tr><tr><td><code>Side</code></td><td>Controls the size of the avatar by setting the side length in pixels when <code>Shape</code> is set to <strong>Square</strong>.</td></tr><tr><td><code>Corner Radius</code></td><td>Rounds the corners of the avatar when <code>Shape</code> is set to <strong>Square</strong>.</td></tr></tbody></table>

<figure><img src="/files/nkKY3YEYrkJsCX0DKQKI" alt="An illustration of the Circle and Square shapes for the Avatar widget."><figcaption><p>Choose between <code>Circle</code> and <code>Square</code> shapes to match your design.</p></figcaption></figure>

***

### Default Properties

The Avatar widget supports the **Layout** and **Interactions** sections of the [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

You’ll typically use **Avatar** for:

* **User Identity**
  * Show the signed-in user’s photo in the header or navigation bar
  * Display avatars in chat lists, comments, reviews, or activity feeds
  * Represent participants in groups, teams, or meetings
* **Fallback Initials / Icons**
  * Show user initials when no profile picture is available
  * Use generic icons for anonymous users or system accounts
* **Lists & Cards**
  * Lead visual in contact lists, member lists, or user cards
  * Compact identity marker next to names, roles, or handles
* **Brand / Entity Representation**
  * Small logo for a brand, company, or organization
  * Represent stores, merchants, or communities in lists


# Carousel

The **Carousel** widget, also known as an image slider or slideshow, is a popular UI component used to display a series of items (images, content cards, or custom widgets) in a horizontal or vertical scrollable format. Users can swipe through slides manually or let them auto-play.

Carousels are perfect for showcasing featured content, product galleries, onboarding screens, testimonials, or promotional banners within limited screen space.

{% embed url="<https://www.youtube.com/watch?v=FM9luXU-O0E>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=FM9luXU-O0E>

{% hint style="info" %}
Our Carousel widget works like Flutter's `carousel_slider` package, providing smooth transitions, auto-play capabilities, and extensive customization options for creating engaging content sliders.
{% endhint %}

{% hint style="success" %}
**User Experience Tip:** Carousels are most effective when they have 3-7 slides. Too many slides can overwhelm users, while too few may not justify the carousel format.
{% endhint %}

***

### Core Concepts

#### 1. Dynamic Children Only

The Carousel widget **requires** a data source to function. You provide a `JsonArray` of data, and Carousel automatically creates a slide for each item in the array. Each slide uses a single child widget template that you design.

This is the same pattern as ListView and GridView—Carousel is built for data-driven content.

#### 2. Viewport Fractions & Multi-Item Display

Unlike a full-screen slider, Carousel can show multiple items at once:

* **Viewport Fraction** controls how much of the viewport each slide occupies.
* A value of `1.0` means each slide fills the entire width (single item view).
* A value of `0.8` means each slide takes 80% of the width, showing portions of adjacent slides.

This "peek" effect helps users understand there's more content to explore.

#### 3. Center Page Enlargement

For added visual emphasis, you can enlarge the center (active) slide while keeping adjacent slides at normal size:

* Enable `Enlarge Center Page` to activate this effect.
* Use `Enlarge Factor` to control how much bigger the center slide appears.
* Creates a 3D-like "focus" effect that draws attention to the active slide.

***

### Data Source Property

The **Data Source** is required for the Carousel to function. It determines what slides will be displayed.

#### How to Configure the Data Source

1. In the properties panel, locate the **`Data Source`** field.
2. You can provide data in two ways:

**Option 1: Static JsonArray**

Enter a fixed JSON array directly:

```json
[
  {"image": "https://example.com/image1.jpg", "title": "Slide 1", "description": "First slide"},
  {"image": "https://example.com/image2.jpg", "title": "Slide 2", "description": "Second slide"},
  {"image": "https://example.com/image3.jpg", "title": "Slide 3", "description": "Third slide"}
]
```

This is useful for prototyping or displaying a fixed set of slides.

**Option 2: Dynamic Expression**

Bind the data source to an expression that returns a `JsonArray`:

* **From an API Response:** `${apiResponse.data.banners}`
* **From App State:** `${appState.featuredProducts}`
* **From a Variable:** `${carouselItems}`

The Carousel will automatically update whenever the data source changes.

#### Accessing Item Data with `currentItem`

Inside the child template, you have access to special variables:

* **`currentItem`**: The data for the current slide being rendered.
  * For objects: `${currentItem.image}`, `${currentItem.title}`
  * For simple values: `${currentItem}`
* **`index`**: The zero-based index of the current slide.

{% hint style="warning" %}
**Important:** The Data Source must be a `JsonArray`. If you bind it to a non-array value, the Carousel will not render any slides.
{% endhint %}

***

### Properties

#### Layout & Sizing

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Height</code></td><td>The fixed height of the carousel container. Controls how tall the carousel appears on the screen.</td></tr><tr><td><code>Width</code></td><td>The fixed width of the carousel container. If not set, it will expand to fill available width.</td></tr><tr><td><code>Aspect Ratio</code></td><td>The aspect ratio of each slide (width:height). For example, <code>16:9</code> for widescreen, <code>1:1</code> for square, <code>4:3</code> for standard.</td></tr></tbody></table>

{% hint style="warning" %}
**Important:** When a fixed `Height` is provided, the `Aspect Ratio` property has no effect. The carousel will use the specified height directly. To use aspect ratio for responsive sizing, leave the `Height` property empty or unset.
{% endhint %}

#### Scrolling Behavior

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Direction</code></td><td>The scroll direction of the carousel. Can be <code>Horizontal</code> (default) or <code>Vertical</code>.</td></tr><tr><td><code>Initial Page</code></td><td>The zero-based index of the slide to show initially. For example, <code>0</code> shows the first slide, <code>1</code> shows the second slide.</td></tr><tr><td><code>Page Snapping</code></td><td>If <code>true</code>, the carousel snaps to the nearest slide when scrolling stops. Default is <code>true</code>.</td></tr><tr><td><code>Infinite Scroll</code></td><td>If <code>true</code>, the carousel loops continuously—after the last slide, it goes back to the first. Default is <code>true</code>.</td></tr><tr><td><code>Reverse Scroll</code></td><td>If <code>true</code>, the carousel scrolls in the opposite direction.</td></tr></tbody></table>

#### Viewport & Visual Effects

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Viewport Fraction</code></td><td>The fraction of the viewport that each slide occupies. Values between <code>0</code> and <code>1</code>. <code>1.0</code> = full width, <code>0.8</code> = 80% width (shows peek of adjacent slides). Default is <code>0.8</code>.</td></tr><tr><td><code>Pad Ends</code></td><td>If <code>true</code>, adds padding to the first and last slides so they can be centered properly.</td></tr><tr><td><code>Enlarge Center Page</code></td><td>If <code>true</code>, the center (active) slide will be larger than adjacent slides, creating a focus effect.</td></tr><tr><td><code>Enlarge Factor</code></td><td>When <code>Enlarge Center Page</code> is enabled, this controls how much bigger the center slide appears. Values between <code>0</code> and <code>1</code>. Default is <code>0.3</code> (30% larger).</td></tr><tr><td><code>Keep Alive</code></td><td>If <code>true</code>, the state of each slide is preserved as it scrolls off-screen. Useful for maintaining form inputs or scroll positions within slides.</td></tr></tbody></table>

#### Auto-Play Settings

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Auto Play</code></td><td>If <code>true</code>, the carousel automatically advances to the next slide at regular intervals.</td></tr><tr><td><code>Auto Play Interval (ms)</code></td><td>The delay (in milliseconds) between auto-play transitions. For example, <code>3000</code> = 3 seconds between slides. Default is <code>4000</code>.</td></tr><tr><td><code>Animation Duration (ms)</code></td><td>The duration (in milliseconds) of the slide transition animation. For example, <code>800</code> = 0.8 seconds to slide to the next item. Default is <code>300</code>.</td></tr></tbody></table>

{% hint style="info" %}
**Auto-Play Best Practice:** Use auto-play sparingly and ensure the interval is long enough for users to read the content. Always provide manual controls (navigation dots or arrows) so users can pause or navigate manually.
{% endhint %}

***

### Page Indicator Properties

The page indicator (dots) shows users which slide is currently active and how many total slides exist.

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Show Indicator</code></td><td>If <code>true</code>, displays page indicator dots below the carousel.</td></tr><tr><td><code>Indicator Offset</code></td><td>The vertical offset (in pixels) of the indicator from the bottom of the carousel. Positive values move it up, negative values move it down.</td></tr><tr><td><code>Dot Width</code></td><td>The width of each indicator dot in pixels.</td></tr><tr><td><code>Dot Height</code></td><td>The height of each indicator dot in pixels.</td></tr><tr><td><code>Spacing</code></td><td>The horizontal spacing between indicator dots in pixels.</td></tr><tr><td><code>Dot Color</code></td><td>The color of inactive (non-active) indicator dots in HEX format.</td></tr><tr><td><code>Active Dot Color</code></td><td>The color of the active indicator dot in HEX format.</td></tr><tr><td><code>Indicator Effect</code></td><td>The animation effect for the indicator transition. Options may include <code>Worm</code>, <code>Expanding</code>, <code>Jumping</code>, <code>Slide</code>, etc.</td></tr></tbody></table>

***

### Event Handlers

The Carousel widget supports an event handler that triggers when the active slide changes:

#### On Changed

This event is triggered whenever the user swipes to a new slide or when auto-play advances to the next slide. The event provides the `index` of the newly active slide.

**Available Data:**

* **`index`**: The zero-based index of the slide that just became active. You can use this value in your actions to track which slide is currently displayed.

**Use Cases:**

* Update a custom page counter (e.g., "Slide 2 of 5")
* Track analytics for which slides users view
* Load related content based on the active slide index
* Update app state with the current slide position
* Trigger animations or effects when specific slides are reached

**How to Use:**

1. Select the Carousel widget.
2. Navigate to **Event Handlers** in the properties panel.
3. Find **On Changed** and click **+ Add Action**.
4. Add your desired action (e.g., Set State, Call API, Show Toast).
5. Use `${index}` in your action to access the new slide index.

**Example:** Set a state variable to track the current slide:

* **Action**: Set State
* **Variable**: `currentSlide`
* **Value**: `${index}`

Or display a toast with the slide number:

* **Action**: Show Toast
* **Message**: `${concat("Now viewing slide ", sum(index, 1))}`

{% hint style="info" %}
**Note:** Carousel does not support programmatic navigation via controllers or actions. All slide changes are triggered by user swipes or auto-play. Use the `On Changed` event to respond to slide transitions.
{% endhint %}

***

### Complete Setup Example

Here's a comprehensive example of setting up a Carousel for a product showcase:

#### 1. Data Source (API or Static)

**Static Example:**

```json
[
  {
    "productId": 1,
    "name": "Premium Headphones",
    "image": "https://example.com/headphones.jpg",
    "price": 299.99
  },
  {
    "productId": 2,
    "name": "Wireless Speaker",
    "image": "https://example.com/speaker.jpg",
    "price": 149.99
  },
  {
    "productId": 3,
    "name": "Smart Watch",
    "image": "https://example.com/watch.jpg",
    "price": 399.99
  }
]
```

#### 2. Carousel Configuration

* **Data Source:** Static array above or `${apiResponse.data.products}`
* **Height:** `300`
* **Aspect Ratio:** `16:9`
* **Direction:** `Horizontal`
* **Initial Page:** `0`
* **Viewport Fraction:** `0.85`
* **Enlarge Center Page:** `true`
* **Enlarge Factor:** `0.2`
* **Auto Play:** `true`
* **Auto Play Interval:** `4000` (4 seconds)
* **Animation Duration:** `600`
* **Infinite Scroll:** `true`
* **Show Indicator:** `true`
* **Dot Color:** `#CCCCCC`
* **Active Dot Color:** `#333333`

#### 3. Slide Template (Child Widget)

* **Container**
  * Padding: `16px`
  * Border Radius: `12px`
  * **Stack**
    * **Image**: `${currentItem.image}` (fills container)
    * **Positioned** (bottom gradient overlay)
      * **Column**
        * **Text**: `${currentItem.name}` (white, bold)
        * **Text**: `$${currentItem.price}` (white)

***

### Default Properties

The Carousel widget supports the **Layout** and **Appearance** sections from [Default Properties](/ui-building-blocks/widgets/default-properties). This includes:

* `Margin`
* `Background Color`
* `Border` and `Border Radius`
* `Visibility`

{% hint style="info" %}
**Note:** Padding is typically controlled by the slide template itself rather than the Carousel container. Add padding to your child widget template for consistent slide spacing.
{% endhint %}

***

### Guides

For comprehensive examples and real-world implementations, see:

{% content-ref url="<https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/guides/carousel-image-sliders.md>" %}
<https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/guides/carousel-image-sliders.md>
{% endcontent-ref %}

This guide includes:

* **Product Image Gallery** - Build professional product carousels with thumbnails and zoom
* **Onboarding Carousel** - Create interactive app tours with skip and navigation controls
* **Promotional Banners** - Implement auto-rotating marketing banners with CTAs
* **Featured Content Cards** - Design Netflix-style content showcases with peek effects
* Advanced patterns including vertical carousels, manual navigation, and parallax effects

***

### Best Practices

* **Limit the number of slides** to 3-7 items for optimal user experience.
* **Make slides tappable** by adding onClick actions to the child template to navigate to detail pages.
* **Use high-quality images** that are optimized for mobile (compressed but clear).
* **Provide alternative navigation** if using auto-play (dots, arrows, or swipe gestures).
* **Set appropriate auto-play intervals** (3-5 seconds minimum) so users can read content.
* **Use page indicators** to show users how many slides exist and their current position.
* **Test on different screen sizes** to ensure viewport fractions work well across devices.
* **Consider accessibility**: Auto-play can be disorienting for some users; provide pause controls.
* **Optimize slide templates**: Keep child widgets lightweight for smooth scrolling performance.
* **Use aspect ratios wisely**: Consistent aspect ratios create a professional, polished look.

### Use Cases

Carousel is ideal for:

* **Image Galleries**: Display product photos, portfolio images, or photo albums.
* **Featured Content**: Highlight promotions, announcements, or top stories.
* **Onboarding Screens**: Guide users through app features with tutorial slides.
* **Product Showcases**: Display product details, features, or variations.
* **Testimonials**: Rotate through customer reviews or success stories.
* **News & Articles**: Show latest news items or blog posts.
* **Promotional Banners**: Display rotating ads or special offers.
* **Before/After Comparisons**: Swipe between comparison images.


# Circular Progress Bar

{% embed url="<https://youtu.be/kQia1fwLzg8?si=Z5juhmZMRlzXwh3h>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=kQia1fwLzg8>

The **Circular Progress Bar** widget visually represents the progress of an operation in a circular form.\
It can work in two modes:

* **Determinate** – shows actual progress (e.g., 35%, 70%, 100%).
* **Indeterminate** – shows an ongoing animation when the exact progress is unknown.

This widget is useful for loading states, uploads, background tasks, and any process where you want to keep the user informed.

#### Adding a Circular Progress Bar Widget

The Circular Progress Bar widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/VdnqHkY4tpLszdXGXET2" alt="A hero image showing circular progress bars in different states and configurations."><figcaption><p>The Circular Progress Bar widget provides clear visual feedback for ongoing operations.</p></figcaption></figure>

### Core Concept

The Circular Progress Bar:

1. Draws a **circular track** (background circle).
2. Draws a **progress arc** (indicator) on top of it.
3. Uses the `type` property to decide how to behave:
   * **Determinate**: Uses `progressValue` (0–100) to show how much is completed.
   * **Indeterminate**: Ignores specific percentages and shows a continuous spinning or looping animation.

You can control:

* **How it looks** → `size`, `thickness`, `indicatorColor`, `bgColor`.
* **How it animates** → `animation`, `animateFromLastPercent`.
* **How it behaves** → `type`, `progressValue`.

### Properties

| Property                 | Description                                                                                               |
| ------------------------ | --------------------------------------------------------------------------------------------------------- |
| `type`                   | The type of progress bar: `determinate` or `indeterminate`.                                               |
| `progressValue`          | The progress value for a determinate progress bar (from **0 to 100**). Ignored in `indeterminate` mode.   |
| `size`                   | The diameter of the circular progress bar. Controls how large the circle appears.                         |
| `thickness`              | The thickness of the circular progress bar’s stroke (the width of the progress ring).                     |
| `indicatorColor`         | The color of the progress indicator (the active part of the circle).                                      |
| `bgColor`                | The background color of the progress bar’s track (the inactive circular ring).                            |
| `animation`              | If `true`, changes in `progressValue` will be animated rather than jumping abruptly.                      |
| `animateFromLastPercent` | If `true`, the progress animation starts from the **previous** value and smoothly moves to the new value. |

{% hint style="success" %}
**Performance Tip:** Use `animateFromLastPercent` with `animation = true` for smooth progress transitions (e.g., 20 → 40 → 65%) instead of jerky jumps.
{% endhint %}

## Default Properties

The Circular Progress Bar widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

The **Circular Progress Bar** is used to show **loading or progress** in a compact, circular form.\
It works well when you don’t have much horizontal space or want a more **prominent, centered indicator**.

Use **Circular Progress Bar** for:

* **General Loading States**
  * Show a spinner while a screen, modal, or section is loading
  * Indicate background operations like login, verification, or fetching data
* **Inline Status Indicators**
  * Inside cards or tiles (e.g., progress of a single download/upload)
  * Next to a label or title to show something is still in progress
* **Percentage-Based Progress**
  * Show completion percentage for:
    * File upload/download
    * Backup/restore
    * Profile or setup completion
  * Often displayed in the center of the circle as a number or icon
* **Centered Focus**
  * Full-screen or modal loader in the center of the screen to show “please wait”
  * Highlight one key task’s progress in dashboards or detail pages


# Linear Progress Bar

{% embed url="<https://youtu.be/kQia1fwLzg8?si=Z5juhmZMRlzXwh3h>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=kQia1fwLzg8>

The Linear Progress Bar widget visually represents the progress of an operation in a **horizontal bar** form.\
It can work in two modes:

* **Determinate** – shows actual progress (e.g., 35%, 70%, 100%).
* **Indeterminate** – shows a continuous animation when the exact progress is unknown.

This widget is useful for loading states, uploads, background tasks, and any process where you want to keep the user informed in a compact, horizontal way (e.g., below a button, inside a card, or at the top of the screen).

#### Adding a Linear Progress Bar Widget

The Linear Progress Bar widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

### Use Cases

The **Linear Progress Bar** shows **progress along a line**, usually from left to right.\
Use it whenever you want to **visually represent completion or loading** in a slim, unobtrusive way.

Use **Linear Progress Bar** for:

* **Loading & Fetching**
  * Show progress while downloading, uploading, or syncing data
  * Indicate that a background task (import, export, backup) is in progress
* **Step or Task Completion**
  * Display how much of a form, onboarding, or setup flow is completed
  * Show “x% complete” for profile, KYC, or configuration steps
* **Process Tracking**
  * Order status progress (e.g., Placed → Packed → Shipped → Delivered)
  * Progress for generating reports, processing payments, or applying changes

### Core Concepts

The Linear Progress Bar:

* Draws a background track (full-width bar).
* Draws a filled portion (indicator) on top of it.
* Uses the `type` property to decide how to behave:
  * **Determinate:** Uses `progressValue` (0–100) to show how much is completed.
  * **Indeterminate:** Ignores specific percentages and shows a continuous sliding or looping animation.

You can control:

* **How it looks** → `height`, `indicatorColor`, `bgColor`.
* **How it animates** → `animation`, `animateFromLastPercent`.
* **How it behaves** → `type`, `progressValue`.

### Properties

| Property                 | Description                                                                                         |
| ------------------------ | --------------------------------------------------------------------------------------------------- |
| `type`                   | The type of progress bar: determinate or indeterminate.                                             |
| `progressValue`          | The progress value for a determinate progress bar (from 0 to 100). Ignored in indeterminate mode.   |
| `height`                 | The thickness (vertical size) of the linear progress bar.                                           |
| `indicatorColor`         | The color of the progress indicator (the filled part of the bar).                                   |
| `bgColor`                | The background color of the progress bar’s track (the unfilled portion).                            |
| `animation`              | If true, changes in `progressValue` will be animated rather than jumping abruptly.                  |
| `animateFromLastPercent` | If true, the progress animation starts from the previous value and smoothly moves to the new value. |

### Default Properties

The Linear Progress Bar widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).


# Dividers

The **Styled Divider (Horizontal)** and **Styled Divider (Vertical)** widgets create a thin line to visually separate content. While they are two separate widgets in the builder, they share the same styling options. This guide covers the properties for both.

{% embed url="<https://youtu.be/JOc4ugYcv8U?si=Hk3GGA16jlavRk8d>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=JOc4ugYcv8U>

### Core Concept: Horizontal vs. Vertical

The primary difference between the two widgets is their orientation and how they are used in layouts.

* **Styled Divider (Horizontal)**: Use this to separate content vertically (e.g., between items in a `Column`).
* **Styled Divider (Vertical)**: Use this to separate content horizontally (e.g., between items in a `Row`).

<figure><img src="/files/q4fttWoEW0flWAJ85Eso" alt="A diagram showing a horizontal divider separating items in a Column, and a vertical divider separating items in a Row."><figcaption><p>Using a Horizontal Divider in a Column and a Vertical Divider in a Row.</p></figcaption></figure>

***

### Properties

The Divider's properties are grouped by function.

#### Layout & Sizing

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Thickness</code></td><td>The thickness of the divider line in pixels.</td></tr><tr><td><code>Indent</code></td><td>The amount of empty space at the beginning of the divider (left for horizontal, top for vertical).</td></tr><tr><td><code>End Indent</code></td><td>The amount of empty space at the end of the divider (right for horizontal, bottom for vertical).</td></tr><tr><td><code>Height</code></td><td>The total vertical space the widget occupies. Applicable to the <strong>Horizontal Divider</strong>.</td></tr><tr><td><code>Width</code></td><td>The total horizontal space the widget occupies. Applicable to the <strong>Vertical Divider</strong>.</td></tr></tbody></table>

<figure><img src="/files/ErjFjLc8fpDNON1ivYI0" alt="A diagram illustrating the Thickness, Indent, and End Indent properties of a divider."><figcaption><p>Visual explanation of the <code>Thickness</code>, <code>Indent</code>, and <code>End Indent</code> properties.</p></figcaption></figure>

#### Line Style

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Line Style</code></td><td>The pattern of the divider line. Options are <code>Solid</code>, <code>Dashed</code>, or <code>Dotted</code>.</td></tr><tr><td><code>Dash Pattern</code></td><td>A custom pattern for dashed lines, defined as an array of dash lengths and gap lengths (e.g., <code>[4, 2]</code> for a 4px dash followed by a 2px gap). Only available when <code>Line Style</code> is <code>Dashed</code>.</td></tr><tr><td><code>Stroke Cap</code></td><td>The style for the ends of the line segments. Options are <code>Butt</code> (flat), <code>Round</code>, or <code>Square</code>. Not applicable when <code>Line Style</code> is <code>Dotted</code>.</td></tr></tbody></table>

<figure><img src="/files/2zbfWl7KgSKWXvgy7w7g" alt="Examples of different divider line styles: Solid, Dashed, and Dotted."><figcaption><p>Examples of <code>Solid</code>, <code>Dashed</code>, and <code>Dotted</code> line styles.</p></figcaption></figure>

#### Color & Fill

You can style the divider with either a solid color or a gradient.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Color</code></td><td>The solid color of the divider.</td></tr><tr><td><code>Gradient</code></td><td>The gradient configuration for the divider. Allows for multi-color effects.</td></tr></tbody></table>

<figure><img src="/files/LIJpLhoPHMLPuBdWQcdo" alt="Examples of a divider with a solid color fill and a gradient fill."><figcaption><p>Dividers can be styled with a solid <code>Color</code> or a <code>Gradient</code>.</p></figcaption></figure>

***

### Default Properties

The Divider widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases (Horizontal & Vertical)

You’ll typically use a **Divider** when you want to separate content **visually** without using heavy borders or boxes.

**Horizontal Divider – Use Cases**

* **Between list items**
  * Order list, settings list, notifications list, profile options.
* **Section breaks in a page**
  * Split “Profile Info”, “Preferences”, “Security” sections.
* **Form grouping**
  * Separate different form groups (Personal Info vs Payment Info).
* **Summary vs details**
  * Line between a header/summary row and detailed content below.

**Vertical Divider – Use Cases**

* **Between actions in a row**
  * “Call | Message | Block” style actions.
* **Split layout**
  * Separate two panels: e.g., filters on left, results on right (in wider layouts).
* **Toolbar or header actions**
  * Visually group icons or buttons in a top bar or bottom bar.


# Markdown

The Markdown widget renders Markdown-formatted text into styled text. It supports a wide range of Markdown features, including headings, lists, links, code blocks, and more. This is a great way to display rich text content in your app without having to manually style each element.

{% embed url="<https://youtu.be/a6U6jJYgIPU?si=XAsQpH4dx7rLayem>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=a6U6jJYgIPU>

### Core Concepts

Instead of building complex rich text layouts manually, you provide a **Markdown string**, and the widget:

1. **Parses** the Markdown syntax
2. **Applies styles** based on your configuration (theme properties)
3. **Renders** it as a fully styled, interactive text view

You can control both:

* **How it behaves** → via **Markdown Settings**
* **How it looks** → via **Markdown Theme**

### Properties

#### 1. Markdown Settings

These properties control **content, behavior, and interaction** of the Markdown widget.

| Property                    | Description                                                                              |
| --------------------------- | ---------------------------------------------------------------------------------------- |
| `data`                      | The Markdown-formatted string to be rendered. This is the main content of the widget.    |
| `duration`                  | The duration of the animation when the content changes. Used when animation is enabled.  |
| `shrinkWrap`                | If `true`, the widget will shrink to fit its content instead of expanding to fill space. |
| `selectable`                | If `true`, the rendered text can be selected and copied by the user.                     |
| `animationEnabled`          | If `true`, the widget animates when the content changes (e.g., fade or transition).      |
| `onLinkTap`                 | Action to be executed when a link in the Markdown content is tapped.                     |
| `hrHeight`                  | The height (thickness) of horizontal rules (`---` or `***` lines in Markdown).           |
| `hrColor`                   | The color of horizontal rules.                                                           |
| `h1TextStyle`–`h6TextStyle` | Text styles for each heading level (`#` to `######`).                                    |
| `codeTextStyle`             | The text style for inline code (e.g., `` `code` ``).                                     |
| `pTextStyle`                | The text style used for paragraph text.                                                  |
| `linkTextStyle`             | The text style for links, often including color and underline.                           |

These settings define **what content is rendered**, how it behaves when it changes, and how basic text elements (headings, links, paragraphs, inline code) are styled.

#### 2. Markdown Theme

These properties control the **visual theme** for lists, blockquotes, and preformatted/code blocks.\
They start from `listMarginLeft` onward.

| Property           | Description                                                                                     |
| ------------------ | ----------------------------------------------------------------------------------------------- |
| `listMarginLeft`   | Left margin applied to lists (bulleted or numbered). Controls how far lists are indented.       |
| `listMarginBottom` | Bottom margin below lists. Controls spacing between a list and the next element.                |
| `blockSideColor`   | The color of the side border for blockquotes (usually a vertical bar on the left).              |
| `blockTextColor`   | The text color used inside blockquotes.                                                         |
| `blockSideWidth`   | The width (thickness) of the blockquote side border.                                            |
| `blockPadding`     | Inner padding for blockquotes. Controls the space between the border and the text.              |
| `blockMargin`      | Outer margin around blockquotes. Controls spacing between blockquotes and surrounding content.  |
| `prePadding`       | Inner padding for preformatted text/code blocks.                                                |
| `preMargin`        | Outer margin for preformatted text blocks.                                                      |
| `preColor`         | Background color for preformatted text/code blocks.                                             |
| `preBorderRadius`  | Corner radius for preformatted text blocks, used to create rounded code blocks.                 |
| `preTextStyle`     | Text style for preformatted text/code blocks (monospace fonts, size, color, etc.).              |
| `preLanguage`      | Language of the code in preformatted blocks, used for syntax highlighting (e.g., `dart`, `js`). |

These properties let you create a consistent **Markdown theme** that matches your app’s visual identity, especially for:

* Lists
* Blockquotes
* Code blocks

### Default Properties

The Markdown widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

The **Markdown** widget is used to render **rich formatted text** from Markdown input (like `# Heading`, `**bold**`, `- lists`, etc.).

Use **Markdown** when you want to:

* **Show content managed by non-developers**
  * Blog posts, help articles, FAQs, release notes
  * Content coming from CMS or backend in Markdown format
* **Display developer-friendly or docs-style text**
  * API docs, technical guides, changelogs
  * README-like sections inside your app
* **Render dynamic rich text safely**
  * User-generated descriptions, comments, or notes written in Markdown
  * Admin-configurable content (terms, policies, feature highlights)
* **Avoid building complex rich text layouts manually**
  * Quickly get headings, bold, italics, code blocks, quotes, and lists
  * Ideal for long-form text with structure and styling baked in

### Best Practices

* Use the `onLinkTap` action to handle links in your Markdown content.
* Use the text style properties to customize the appearance of your Markdown content to match your app's design.
* For large amounts of Markdown content, consider using a `SingleChildScrollView` to make it scrollable.


# Web View

The **Web View** widget displays a live web page from a given URL. It works like a **mini-browser embedded inside your app**, allowing you to show external or internal web content without leaving the app.

{% embed url="<https://youtu.be/KzEmvy7D_3Y?si=9V9L17DyBEMOUdBz>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=KzEmvy7D_3Y>

### Core Concepts

1. **Loads a URL** inside your app instead of opening the device browser.
2. **Renders full web content** (HTML, CSS, JavaScript, images, etc.).
3. Can optionally **intercept back navigation** using `interceptorBack` so that:
   * Back button first navigates **inside the Web View history**, or
   * Triggers a custom behavior (like showing a confirmation dialog),\
     instead of immediately leaving the screen.

This gives you more control over how users move inside web-based screens embedded in your app.

### Properties

| Property          | Description                                                                                                                                                                                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `url`             | The URL of the web page to display. This can be an external link (e.g., `https://example.com`) or an internal page (e.g., your own web app).                                                                                                           |
| `interceptorBack` | Controls how the back action is handled when the user presses the system back button or navigates back from this screen. Typically used to intercept back navigation inside the Web View (e.g., go back in web history instead of closing the screen). |

{% hint style="info" %}
If `interceptorBack` is enabled, you can ensure that users **don’t accidentally leave the screen** while they are still navigating between pages inside the Web View.
{% endhint %}

### Default Properties

The Web View widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **WebView** when you want to:

* **Embed existing web experiences**
  * Show an existing website, microsite, or landing page inside your app
  * Load dashboards, admin panels, or tools that already run on the web
* **Show external content you don’t want to rebuild natively**
  * Help center, documentation, blogs, or support portal
  * Legal pages like Terms & Conditions, Privacy Policy, Refund Policy
* **Integrate third-party flows**
  * Payment pages, authentication flows, or external forms
  * Partner pages, referral programs, or affiliate content
* **Render complex HTML/JS apps**
  * Interactive widgets, charts, or visualizations powered by JavaScript
  * Web-based widgets that are hard to recreate with native UI


# YouTube Player

The **YouTube Player** widget embeds a YouTube video directly inside your app. It behaves like an inline YouTube player, allowing users to watch videos without leaving the screen or opening the YouTube app separately.

You can control basic playback behaviour such as autoplay, loop, and mute state.

{% embed url="<https://youtu.be/52ODn8up7co?si=7NR-nvjAdYJfOLvP>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=52ODn8up7co>

### Core Concepts

The YouTube Player widget is designed for:

* **Embedding YouTube-hosted content** inside your app UI.
* Avoiding context switching by keeping users inside the app.
* Reusing existing video content (tutorials, promos, explainers, ads, etc.) without uploading or encoding it again.

Internally, the widget:

1. Loads a YouTube video from the given `videoUrl`.
2. Renders the player inside a rectangular area (controlled via Layout properties).
3. Applies playback behaviour based on `autoPlay`, `loop`, and `muted`.

You get a **YouTube experience**, but inside your own screens and flows.

### Properties

| Property   | Description                                                                                                                   |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `videoUrl` | The URL of the YouTube video to play. This should be a valid YouTube link (e.g., `https://www.youtube.com/watch?v=VIDEO_ID`). |
| `autoPlay` | If `true`, the video will start playing automatically when the player loads.                                                  |
| `loop`     | If `true`, the video will loop continuously and restart after it finishes.                                                    |
| `muted`    | If `true`, the video will be muted by default when playback starts.                                                           |

{% hint style="success" %}
**Performance Tip:** Use `muted = true` with `autoPlay = true` when you want videos to start silently (common in modern UX patterns).
{% endhint %}

### Default Properties

The YouTube Player widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

The **YouTube Player** widget lets you play **YouTube videos directly inside your app**, without sending users out to the YouTube app or browser.

Use **YouTube Player** when you want to:

* **Embed video content in your screens**
  * Product demos, feature walkthroughs, app tutorials
  * Brand films, ads, testimonials, launch videos
* **Educational or onboarding flows**
  * How-to videos inside a help/FAQ section
  * Onboarding lessons, course content, or training modules
* **Content & community**
  * Show your YouTube channel content inside the app
  * Play livestreams, interviews, podcasts, or event recordings
* **Marketing & engagement**
  * Embed campaign videos on offers/promotions pages
  * Use video to increase trust (reviews, case studies, success stories)


# Video Player

The **Video Player** widget is used to play local or remote video files directly inside your app. Unlike the YouTube Player, which depends on YouTube embeds, the Video Player works with **raw video URLs** (e.g., MP4 files hosted on your server or CDN).

It is ideal when you want full control over the source of the video, don't want external branding, or are not using YouTube at all.

{% embed url="<https://youtu.be/znTundKOz6Y?si=oIm2molvLt9QHz6D>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=znTundKOz6Y>

### Core Concepts

The Video Player widget is designed for:

* Playing **custom video content** hosted on your own servers, CDN, or storage.
* Building **native-feeling media experiences** without YouTube UI or branding.
* Using videos in places where full control over the source and behavior is important (e.g., onboarding, product demos, in-app stories, training content).

Internally, the widget:

* Loads a video from the given `videoUrl`.
* Renders the player inside a rectangular area controlled by layout and `aspectRatio`.
* Applies playback behavior based on `autoPlay`, `looping`, and `showControls`.

You get a native-style video experience that blends seamlessly with your app’s UI.

### Properties

| Property       | Description                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------ |
| `videoUrl`     | The URL of the video file to play (e.g., an MP4 file hosted on a server or CDN).                       |
| `showControls` | If true, playback controls (play, pause, seek, maybe fullscreen) will be displayed over the video.     |
| `aspectRatio`  | The aspect ratio of the video (e.g., 16/9, 4/3). Controls the width/height relationship of the player. |
| `autoPlay`     | If true, the video will start playing automatically when the player loads.                             |
| `looping`      | If true, the video will loop continuously and restart after it finishes.                               |

{% hint style="success" %}
**Performance Tip:** Use `autoPlay = true` only when the video is the main focus of the screen (e.g., hero video or onboarding). For feeds or lists, prefer manual play to avoid unnecessary data usage and distraction.
{% endhint %}

### Default Properties

The Video Player widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

The **Video Player** widget is used to play **local or remote video files** (MP4, etc.) directly inside your app, with controls like play/pause, seek, and fullscreen.

Use **Video Player** when you want to:

* **Show product or feature videos**
  * App/product demos
  * Feature explainers, UI walkthroughs
  * Before/after or showcase videos
* **In-app content consumption**
  * Lessons in an education app
  * Workout videos, tutorials, training modules
  * Short-form content, reels-style or landscape videos from your own CDN/storage
* **Marketing & engagement**
  * Promo clips on home/offer pages
  * Campaign stories, festival offers, launch teasers
* **User-generated or app-generated media**
  * Play videos uploaded by users (reviews, stories, posts)
  * Playback of recordings, screen captures, or generated clips


# Story

The **Story widget** lets you build immersive, Instagram-style story experiences inside your app. It shows a sequence of full-screen or card-style “stories” that users can tap through, swipe, or watch as they auto-play. This is great for feature highlights, onboarding flows, announcements, or tutorials presented in a visual, lightweight format.

{% embed url="<https://www.youtube.com/watch?v=eBUInzOEQwE>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=eBUInzOEQwE>

### Use Cases

* **Onboarding flows**
  * Introduce your app in 3–5 visual steps
  * Highlight “What you can do” with quick, snackable screens
* **Feature & product highlights**
  * Showcase new features with images + short copy
  * Display multiple product angles, USPs, or use-cases as separate story items
* **Promotions & campaigns**
  * Limited-time offers, festival campaigns, or seasonal sales
  * “Swipe through” style promo banners instead of static images
* **Announcements & release notes**
  * New version updates, changelog highlights, or important news
  * Show key changes one story at a time to avoid overwhelming text
* **Quick tutorials & tips**
  * Step-by-step mini-tutorials (“How to use X”)
  * Daily tips, growth hacks, or quick education content

### Core Concepts

1. **Story Layout (Header, Items, Footer)**
   * **Header**: Optional top area (avatar, logo, title, time).
   * **Items**: Each item is one “story screen” – can be image, video, text, buttons, or any widget.
   * **Footer**: Optional bottom area for CTAs, captions, or extra actions.
2. **Story Flow & Behaviour**
   * Stories play **one after another** (auto-advance optional).
   * User gestures: tap left = previous, tap right = next.
   * A controller manages the **current item** and lets you react with callbacks (e.g., onStart, onEnd, onChange).
3. **Indicators**
   * Small bars at the top show **how many stories** and **current position**.
   * States: completed, current, upcoming.
   * Fully customizable (colors, size, spacing, radius) to match your brand.

### Properties

#### Layout & Content

**Header / Items / Footer**

* **Header**\
  Add any widget you like (avatar, text, icons, etc.). This is optional.
* **Items**\
  Add one or more story items. Each item is a widget tree that will be shown as an individual story step.
* **Footer**\
  Optional bottom area for buttons, secondary info, links, or actions.

#### Behaviour

These properties control how the stories **play and progress**.

| Property               | Description                                                                                                                                  |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `Controller`           | Internal controller that manages the current story index and playback. Can be used in actions to programmatically change or control stories. |
| `Initial Index`        | The zero-based index of the story item that should be shown first when the widget loads.                                                     |
| `Restart on Completed` | When enabled, the story sequence restarts from the first item after the last story finishes. When disabled, playback stops at the end.       |
| `Duration`             | Time each story stays visible before automatically moving to the next one. Applies when stories are auto-playing.                            |

#### Navigation

These properties define how user gestures trigger actions.

| Property         | Description                                                                                                                |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `On Slide Down`  | Triggered when the user slides the story down. Often used to close the story or navigate back.                             |
| `On Slide Start` | Called when the user first starts viewing/interacting with the story sequence. Useful for analytics or initializing logic. |
| `On Left Tap`    | Triggered when the user taps on the left side of the story. Typically used to go to the previous story item.               |
| `On Right Tap`   | Triggered when the user taps on the right side of the story. Typically used to go to the next story item.                  |

#### Callbacks

Callbacks give you hooks into key moments in the story lifecycle.

| Property                | Description                                                                                                                                                |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `On Completed`          | Fired when the entire story sequence finishes. Useful for marking as seen, navigating away, or showing a final message.                                    |
| `On Previous Completed` | Called when a previous story group/segment completes (if you use grouped logic). Can be used for step-wise tracking.                                       |
| `On Story Changed`      | Fired every time the active story index changes. Useful for analytics, loading data for the current story, or updating other UI based on the active slide. |

#### Indicators

Indicator properties control the look and feel of the story progress bars.

| Property          | Description                                                                                                           |
| ----------------- | --------------------------------------------------------------------------------------------------------------------- |
| `Active Color`    | Color of the indicator for the currently active story item.                                                           |
| `Completed Color` | Color of indicators representing stories that have already been viewed.                                               |
| `Upcoming Color`  | Color of indicators for stories that have not yet been seen.                                                          |
| `Height`          | Thickness of each indicator bar. Smaller values give a slim line; larger values create bold bars.                     |
| `Border Radius`   | Roundness of the indicator corners. Higher values create pill-shaped bars; lower values create more rectangular ones. |
| `Horizontal Gap`  | Space between each indicator bar. Controls how tightly or loosely they are spaced.                                    |

### Default Properties

The Story widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).


# Story Video Player

The **Story Video Player** lets you add autoplaying video content inside a Story item—similar to how videos work in Instagram or Snapchat stories. It’s designed for short, snackable clips that play seamlessly as part of your Story sequence.

### Use Cases

**Feature & Product Demos**

* Show how a feature works in 5–10 seconds
* Highlight key interactions (clicks, swipes, flows) in action
* Great for complex features that are easier to show than describe

**Promotional & Campaign Videos**

* Short promo reels, teaser videos, or brand films
* Limited-time offers or festival sale clips
* “Swipe through” video stories instead of static banners

**Tutorials & How-to Clips**

* Micro-tutorials inside your story sequence
* “How to use X” shown as a quick video step
* Combine with text/caption in header/footer for context

**Announcements & Release Highlights**

* Show new UI changes via screen recordings
* Animate before/after improvements
* Use video to bring release notes to life

### Core Concepts

The Story Video Player is typically used **inside the Items** section of the Story widget. Each Story item can contain a video player configured with its own behavior.

**Video Story Item**

* Renders a video as the main content of a single Story slide
* Can be full-screen or within a card/container
* Respects the Story widget’s flow (auto-advance, indicators, etc.)

**Playback Behaviour**

* Can auto-play when the story becomes active
* Can loop continuously or stop at the end
* Can be configured to fit the available space using BoxFit options

### Properties

| Property  | Description                                                                                                   |
| --------- | ------------------------------------------------------------------------------------------------------------- |
| Video URL | The source URL of the video to play inside the story. Usually a network URL (CDN, S3, or your own server).    |
| Auto Play | When enabled, the video starts playing automatically as soon as this story item becomes active.               |
| Looping   | When enabled, the video restarts from the beginning after it finishes, creating a continuous loop.            |
| Box Fit   | Controls how the video is resized inside its container (e.g., fill, cover, contain) while maintaining layout. |

### Default Properties

The Story Video Player widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).


# Input & Forms

Widgets that enable user input and interaction with the application.

## Overview

Input & Interaction widgets allow users to provide input, make selections, and interact with your app. These widgets handle forms, buttons, and various input controls.

## Categories

### Form Inputs

* [**Text Form Field**](/ui-building-blocks/widgets/input-interaction-widgets/text-form-field) - Single-line and multi-line text input
* [**Pin Field**](/ui-building-blocks/widgets/input-interaction-widgets/pinfield) - Numeric PIN code input
* [**Range Slider**](/ui-building-blocks/widgets/input-interaction-widgets/range-slider) - Numeric range selection

### Selection Controls

* [**Check Box**](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/input-interaction-widgets/check-box.md) - Binary selection (checked/unchecked)
* [**Switch**](/ui-building-blocks/widgets/input-interaction-widgets/switch) - Toggle switch for on/off states
* [**Calendar**](/ui-building-blocks/widgets/input-interaction-widgets/calendar) - Date selection interface

### Interactive Elements

* [**Button**](/ui-building-blocks/widgets/input-interaction-widgets/button) - Action buttons with various styles
* [**State Container**](/ui-building-blocks/widgets/input-interaction-widgets/state-container) - Container that manages internal state

### Feedback & Status

* [**Timer**](/ui-building-blocks/widgets/input-interaction-widgets/timer) - Time-based interactions and displays


# Scratch Card

A **Scratch Card** is an interactive reveal widget that allows users to “scratch” an overlay layer to uncover hidden content beneath it. It is commonly used for gamification flows such as rewards, coupon reveals, mystery unlocks, onboarding surprises, or engagement campaigns.

The widget renders two layers:

* **Overlay** → The top layer that users scratch away
* **Base (Child)** → The hidden content revealed underneath

When a configurable reveal threshold is reached, the widget can automatically complete and trigger an action.

{% embed url="<https://www.youtube.com/watch?v=FYp5lN5-gWU>" %}

**Watch this on Youtube:** [**https://www.youtube.com/watch?v=FYp5lN5-gWU**](https://www.youtube.com/watch?v=FYp5lN5-gWU)

***

#### How It Works

The Scratch Card uses a brush-based interaction system. As the user drags (or taps, if enabled), portions of the overlay are cleared based on brush configuration (size, shape, opacity).

Internally, a controller tracks:

* Scratch progress (percentage revealed)
* Completion state
* Interaction state

<figure><img src="/files/KKgkCtCh2jLAzw8uqbDF" alt="Two rectangular scratch cards displayed inside a rounded light-gray container. The left card is completely unscratched with a silver textured surface, while the right card is partially scratched, revealing a golden “COUPON” label with colorful confetti and a scratch tool at the edge. The title “Scratch Card” appears below the cards."><figcaption><p>Scratch Card widget showing an unscratched state and a fully revealed reward state.</p></figcaption></figure>

When the scratched area reaches the configured percentage threshold, the widget triggers the `onScratchComplete` action.

***

### Child Structure

The Scratch Card requires **two child groups**:

* `overlay` (Required) → The scratchable top layer
* `base` (Required) → The content revealed after scratching

If either is missing, the widget renders empty.

{% hint style="warning" %}
Both `overlay` and `base` child groups are mandatory. If one is not provided, the widget will not render.
{% endhint %}

***

### Basic Usage Concept

```
ScratchCard
 ├── overlay (Image / Container / Design)
 └── base (Reward content / Coupon / Message)
```

***

### Properties

#### Layout Properties

* **height**\
  Defines the height of the scratch card.
* **width**\
  Defines the width of the scratch card.

***

#### Scratch Appearence Properties

| Property       | Type   | Default     | Description                                                                                |
| -------------- | ------ | ----------- | ------------------------------------------------------------------------------------------ |
| `brushSize`    | double | 20.0        | Controls the size of the scratch brush. Larger values remove more overlay per interaction. |
| `brushShape`   | string | circle      | Defines the brush shape. Supported values: `circle`, `square`, `star`, `heart`, `diamond`. |
| `brushColor`   | color  | transparent | Color applied to the brush stroke.                                                         |
| `brushOpacity` | double | 1.0         | Opacity of the brush stroke.                                                               |

***

#### Reveal & Completion Properties

| Property                  | Type    | Default | Description                                                                                                                               |
| ------------------------- | ------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `revealFullAtPercent`     | number  | 75      | Percentage threshold (0–100) at which the card automatically reveals fully. Example: `75` means the card completes when 75% is scratched. |
| `gridResolution`          | integer | 100     | Controls scratch detection resolution. Higher values increase accuracy but may impact performance.                                        |
| `enableProgressAnimation` | boolean | false   | Enables animation while progressing toward full reveal.                                                                                   |
| `isScratchingEnabled`     | boolean | true    | Enables or disables scratching interaction.                                                                                               |
| `enableTapToScratch`      | boolean | false   | Allows scratching via tap gestures instead of drag gestures.                                                                              |
| `enableHapticFeedback`    | boolean | false   | Enables haptic feedback during scratching interaction.                                                                                    |

{% hint style="warning" %}
**Warning:** Setting `isScratchingEnabled` to false will completely disable interaction, even if other scratch properties are configured.
{% endhint %}

{% hint style="info" %}
**Tip** For most use cases, keep `gridResolution` between 80–120. Extremely high values may impact performance on low-end devices.
{% endhint %}

***

#### Reveal Animation Properties

* **revealAnimationType**\
  Animation triggered when fully revealed. Supported values:
  * `none`
  * `fade`
  * `scale`
  * `slideup`
  * `slidedown`
  * `slideleft`
  * `slideright`
  * `bounce`
  * `zoomout`
* **animationDurationMs**\
  Duration of reveal animation in milliseconds.

{% hint style="info" %}
**Tip** Avoid combining long animation durations with high grid resolution for large scratch surfaces, as it may increase frame workload.
{% endhint %}

***

### Actions

#### onScratchComplete

Triggered once when the scratch progress reaches the configured threshold and the card is fully revealed.

This can be used to:

* Trigger navigation
* Unlock a reward
* Fire analytics events
* Update backend state
* Show a success modal

Trigger Type:\
`onScratchComplete`

{% hint style="info" %}
**Tip** `onScratchComplete` fires only once per widget lifecycle. If you need repeatable behavior, the widget must be rebuilt.
{% endhint %}

***

### Behavior Notes

* The base content remains hidden until scratching begins.
* The widget tracks progress internally using a controller.
* Completion fires only once per lifecycle.
* Performance depends on `gridResolution` and brush size.
* If scratching is disabled, the overlay remains static.

***

### Common Use Cases

* Coupon reveal campaigns
* Reward unlock mechanics
* Gamified onboarding
* Festival promotions
* E-commerce discount reveals
* Mystery box experiences

***

### Performance Considerations

For large surfaces:

* Keep `gridResolution` moderate
* Avoid excessively large brush sizes
* Use optimized images for overlay
* Avoid heavy nested layouts inside `base` content

{% hint style="success" %}
**Tip** If the scratch area covers most of the screen, prefer lightweight overlay widgets (compressed images, simple containers) to maintain smooth interaction.
{% endhint %}


# Button

The **Button widget** is a fundamental interactive element that allows users to trigger actions within your application. It provides extensive customization options for appearance, states, and behavior, making it suitable for various use cases from simple navigation to complex form submissions.

{% embed url="<https://www.youtube.com/watch?v=1YTW48viT_0>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=1YTW48viT_0>

#### Adding a Button Widget

The Button widget is located in the **Base Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/8jJPgVmqnis0wKI41yw7" alt="A hero image showing various styled buttons in an application UI."><figcaption><p>The Button widget is a versatile component for creating interactive elements.</p></figcaption></figure>

### Core Concept: Button States

A button's appearance and behavior change based on its state. Understanding these states is key to creating a good user experience.

* **Default State**: The normal, interactive state of the button. This is how it appears most of the time.
* **Disabled State**: A non-interactive state, visually indicating that the button cannot be pressed. This is controlled by the `Is Disabled` boolean property. For example, you can disable a "Submit" button until all required form fields are filled.

<figure><img src="/files/RmhfHtRqPfB8rg0yI04y" alt="A side-by-side comparison of a button in its default (enabled) and disabled states."><figcaption><p>Visual difference between the <code>Default</code> and <code>Disabled</code> states of a button.</p></figcaption></figure>

{% hint style="info" %}
**Previewing States in the Builder:** The properties panel includes a **`Button State`** toggle. This is a design-time tool only; it has no effect on your running app. Use it to switch the view on the canvas between the `Default` and `Disabled` styles while you are designing.
{% endhint %}

<figure><img src="/files/Lz47kZNCWzP9PonlrLR7" alt="A GIF showing how to use the &#x27;Button State&#x27; toggle in the properties panel to preview the disabled state."><figcaption><p>Use the <code>Button State</code> toggle to preview different states in the builder.</p></figcaption></figure>

***

### Properties

The Button's properties are grouped by function.

#### Interaction & State

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>On Click</code></td><td>Defines the action that executes when a user clicks the button. This is the most important property for making the button functional.</td></tr><tr><td><code>Is Disabled</code></td><td>A boolean (true/false) that controls the button's state. When <code>true</code>, the button will be non-interactive and use the <strong>Disabled State</strong> styling. This can be bound to an expression, e.g., <code>${not(form.isValid)}</code>.</td></tr></tbody></table>

{% hint style="warning" %}
**Important Note:** The Button widget is stateless. This means it does not manage its own disabled state internally. You are responsible for controlling the `Is Disabled` property using an external state variable (e.g., from App State or a State Container).
{% endhint %}

#### Content

These properties define what is displayed inside the button.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Text</code></td><td>The text label displayed on the button. Can be a static value or a dynamic expression.</td></tr><tr><td><code>Leading Icon</code></td><td>An icon displayed before the text. See the <a href="/pages/kA0ksMKIJAJAlUUTJ71N">Icon documentation</a> for configuration options.</td></tr><tr><td><code>Trailing Icon</code></td><td>An icon displayed after the text. See the <a href="/pages/kA0ksMKIJAJAlUUTJ71N">Icon documentation</a> for configuration options.</td></tr></tbody></table>

#### Styling

Styling is configured separately for the `Default` and `Disabled` states, allowing you to provide clear visual feedback to the user.

#### Default State Styling

These properties control the button's appearance in its normal, interactive state.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Button Color</code></td><td>The background color of the button.</td></tr><tr><td><code>Elevation</code></td><td>Creates a shadow effect to give the button depth.</td></tr><tr><td><code>Shadow Color</code></td><td>The color of the elevation shadow.</td></tr><tr><td><code>Text Style</code></td><td>Controls the font styling for the button's text. This works exactly like the <a href="/pages/C9nNxThiJc2b87pM8M0Z#styling">Text widget's styling</a> (Linked vs. Unlinked).</td></tr></tbody></table>

#### Disabled State Styling

These properties are applied when `Is Disabled` is `true`.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Button Color</code></td><td>The background color of the button when disabled. Typically a lighter or grayer version of the default color.</td></tr><tr><td><code>Text Color</code></td><td>The color of the button's text when disabled.</td></tr><tr><td><code>Icon Color</code></td><td>The color of the button's icons when disabled.</td></tr></tbody></table>

#### Shape & Layout

These properties control the button's overall shape and internal spacing.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Shape</code></td><td>Defines the button's geometric shape. Options include <code>Stadium</code>, <code>Circle</code>, and <code>RoundedRect</code>.</td></tr><tr><td><code>Border Radius</code></td><td>Controls corner rounding when <code>Shape</code> is set to <code>RoundedRect</code>.</td></tr><tr><td><code>Border Style</code></td><td>Defines the border appearance (e.g., <code>Solid</code> or <code>None</code>).</td></tr><tr><td><code>Border Color</code></td><td>Sets the color of the border.</td></tr><tr><td><code>Border Width</code></td><td>Controls the thickness of the border.</td></tr><tr><td><code>Width</code> / <code>Height</code></td><td>The dimensions of the button. Can be fixed (px) or responsive (%).</td></tr><tr><td><code>Padding</code></td><td>Internal spacing around the button's content (text and icons).</td></tr><tr><td><code>Alignment</code></td><td>Controls how the content (text and icons) is aligned within the button.</td></tr></tbody></table>

***

### Common Button Variants

The Button widget is flexible enough to create all standard button types by combining its styling properties.

* **Solid Button (Default)**: This is the standard appearance. Set a `Button Color` and a `Text Style` with a contrasting color.
* **Outline Button**: To create a button with a transparent background and a colored border, set the `Button Color` to transparent, and define the `Border Style`, `Border Color`, and `Border Width`.
* **Text Button**: For a button that looks like a simple text link, set the `Button Color` to transparent and set `Border Style` to `None`. The clickable area will still be defined by the button's `Padding` and dimensions.

<figure><img src="/files/TmFWfExHWeR2y3PDTNcj" alt="Examples of different button styles: Solid, Outline, and Text-only."><figcaption><p>Examples of Solid, Outline, and Text button variants created using the Button widget.</p></figcaption></figure>

***

### Default Properties

The Button widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

You’ll typically use **Button** for:

* **Primary Actions**
  * Submit a form (Sign Up, Log In, Save)
  * Proceed in a flow (Next, Continue, Get Started)
  * Main CTA on a screen (Checkout, Book Now, Start Free Trial)
* **Secondary / Tertiary Actions**
  * Cancel, Skip, Dismiss, Close
  * “Maybe later”, “Remind me”, “View details”
  * Less-important side actions next to the main CTA
* **Navigation**
  * Go to another screen (View All, See More, Open Settings)
  * Open modals, sheets, or overlays
  * Trigger deep links, external URLs, or app sections
* **State-Changing Actions**
  * Add to Cart, Add to Wishlist, Follow / Unfollow
  * Enable / Disable a setting
  * Start / Stop / Retry an operation
* **Contextual Quick Actions**
  * Apply filters, Refresh data, Retry on error
  * Download, Share, Copy, Edit, Delete


# Checkbox

The Checkbox widget is a visual control that allows a user to select or deselect a single option. It implements the Material Design specification for a checkbox, representing a binary choice that is typically independent of other choices (e.g., selecting multiple items in a list or toggling a setting on/off).

{% embed url="<https://youtu.be/H2OLYDApcIM?si=eRPRVXM0A6oOIE3i>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=H2OLYDApcIM>

#### Adding a Checkbox Widget

The Checkbox widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/TUtmnIDyGYOE6q8RTqxk" alt="A hero image showing various checkbox states and configurations."><figcaption><p>The Checkbox widget provides flexible binary selection controls.</p></figcaption></figure>

### Core Concepts

1. **Binary State**\
   The checkbox tracks a single **boolean value**:
   * `true` → checked / selected
   * `false` → unchecked / unselected
2. **Visual Feedback**\
   The state is shown by:
   * Background (active vs inactive)
   * Icon (checked vs unchecked)
   * Shape and border
3. **Independent Selection**\
   Each checkbox works **independently**, even if there are many in a list.\
   Users can select **any combination** of options.

### Properties

These properties define the widget's interaction, background, and overall dimensions.

| Property             | Description                                                                |
| -------------------- | -------------------------------------------------------------------------- |
| `value`              | The current state of the checkbox (true for checked, false for unchecked). |
| `size`               | The overall dimension (width/height) of the checkbox container.            |
| `activeBackground`   | Background color when the checkbox is active (value: true).                |
| `inactiveBackground` | Background color when the checkbox is inactive (value: false).             |
| `borderWidth`        | The thickness of the border when inactive.                                 |
| `shape`              | The container’s shape (e.g., rectangle or circle).                         |
| `borderRadius`       | The corner radius of the container (used for rectangle shape).             |

#### Active Icon Properties

These properties define the appearance of the icon when the `value` is `true` (checked).

| Property          | Description                                      |
| ----------------- | ------------------------------------------------ |
| `activeIcon`      | The icon displayed when the checkbox is checked. |
| `activeIconSize`  | The size of the active icon.                     |
| `activeIconColor` | The color of the active icon.                    |

#### Inactive Icon Properties

These properties define the appearance of the icon when the `value` is `false` (unchecked).

| Property            | Description                                        |
| ------------------- | -------------------------------------------------- |
| `inactiveIcon`      | The icon displayed when the checkbox is unchecked. |
| `inactiveIconSize`  | The size of the inactive icon.                     |
| `inactiveIconColor` | The color of the inactive icon.                    |

***

### **Icon Properties**

You can customize the icons used for the checked and unchecked states.

<table><thead><tr><th width="176.25390625">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Active Icon</code></td><td>The icon to display when the checkbox is checked. See <a data-mention href="https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/input-interaction-widgets/icon.md">https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/input-interaction-widgets/icon.md</a> for properties.</td></tr><tr><td><code>Inactive Icon</code></td><td>The icon to display when the checkbox is unchecked. See <a data-mention href="https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/input-interaction-widgets/icon.md">https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/input-interaction-widgets/icon.md</a> for properties.</td></tr></tbody></table>

**Value Property with Expressions**

The **Value** property is particularly powerful as it accepts both static boolean values and dynamic expressions:

* **Static Values**: Set to `true` or `false` for fixed checkbox states
* **Expressions**: Use dynamic logic to control checkbox state based on:
  * User input from other form fields
  * Application state variables
  * Conditional logic based on user selections
  * Form validation results

**Example Use Cases:**

* Form validation: `isNotEmpty(user.email) && gte(length(user.password), 8)`
* Conditional agreements: `gte(user.age, 18)`

***

### Default Properties <a href="#default-properties" id="default-properties"></a>

The Checkbox widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use a **Checkbox** when you want the user to:

* **Toggle a setting**
  * Enable/disable notifications
  * Turn features on/off (dark mode, sound, autosave)
* **Select multiple options in a list**
  * Choose multiple items (e.g., products, categories, filters)
  * Bulk-select rows in a table or list (“Select all”, “Select some”)
* **Confirm or agree**
  * “I agree to the Terms & Conditions”
  * “Remember this device” or “Save this preference”

Choose a Checkbox when the choice is **yes/no** and **doesn’t require only one option** (for that, radio buttons are better).


# Switch

The **Switch** widget is a small, interactive **toggle control** that lets users quickly turn a setting **on** or **off**.\
It represents a **binary choice** (true/false, enabled/disabled) in a compact, touch-friendly UI.

{% embed url="<https://youtu.be/x6K-jcK1AUs?si=gjiRQIANgb_wG72A>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=x6K-jcK1AUs>

#### Adding a Switch Widget

The Switch widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/qG764w4wWUJn2pe1HZ83" alt="A hero image showing a switch widget in on and off states with customizable styling."><figcaption><p>The Switch widget provides intuitive binary toggle controls for settings and preferences.</p></figcaption></figure>

### **Core Concepts**

* **Two-State Control (On/Off)**\
  The Switch has only **two states**:
  * `true` → ON
  * `false` → OFF
* **Thumb & Track**\
  Visually, the Switch has:

  * A **thumb** → small circular handle that slides left/right
  * A **track** → the background path behind the thumb

  You can style both for **active** (on) and **inactive** (off) states.
* **Enabled vs Disabled**
  * When `enabled` is `false`, the Switch:
    * Can’t be interacted with
    * Typically appears visually dimmed/disabled
  * Useful when:
    * A setting depends on another toggle
    * A feature is locked/unavailable
* **Binding to State**\
  The `value` property is usually **bound to some state or variable** in your app.\
  When the user toggles the Switch, your logic updates that state and applies the change.

### Properties

| Property             | Description                                                                                                                                                                                                                  |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`            | If `false`, the Switch is disabled and cannot be interacted with. Use this when the setting is not currently applicable or is controlled elsewhere.                                                                          |
| `value`              | A boolean that determines the current state of the Switch: `true` for ON, `false` for OFF. Usually bound to app state or a setting value.                                                                                    |
| `activeColor`        | The color of the Switch’s **thumb** when it is in the ON state. Helps visually indicate that the setting is enabled.                                                                                                         |
| `inactiveThumbColor` | The color of the Switch’s **thumb** when it is in the OFF state. Typically a neutral or subdued color.                                                                                                                       |
| `activeTrackColor`   | The color of the **track** when the Switch is ON. Often a brand or accent color.                                                                                                                                             |
| `inactiveTrackColor` | The color of the **track** when the Switch is OFF. Usually a muted/grey tone.                                                                                                                                                |
| `onChanged`          | Action or callback that is triggered whenever the user toggles the switch. Receives an object with the new value: `{ 'value': value }`. Use this to update state, save settings, or run side effects when the value changes. |

### Default Properties

The Switch widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`

**Alignment**

* `align`

**Visibility**

* `visible`

### **Use Cases**

Use a **Switch** when you want the user to:

* Enable/disable a **feature or preference**, such as:
  * Notifications on/off
  * Dark Mode on/off
  * Location access on/off
  * Auto-play videos on/off
* Control **binary settings** in:
  * Profile or app settings screens
  * Privacy & permission toggles
  * Feature flags inside experimental UIs

It’s best for **immediate, reversible changes**—where the result of toggling is clear to the user.


# Text Form Field

The **Text Form Field** widget is a versatile input field that lets users **enter and edit text**.\
It supports rich customization for **appearance, validation, behavior, and events**, making it suitable for everything from simple inputs to complex forms.

{% embed url="<https://youtu.be/JxpuQR4uxK0?si=9gNcoy0r7PF-7sU7>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=JxpuQR4uxK0>

Whenever you need **user-typed text** with control over **validation, styling, and interaction**, this widget is the default choice.

### Core Concepts

* **Input Control**
  * `initialValue`, `controller`, `enabled`, `readOnly`, `autoFocus`\
    Let you control **what the field shows**, whether it’s **editable**, and **when it gets focus**.
* **Input Behavior**
  * `obscureText`, `keyboardType`, `textInputAction`, `textAlign`, `minLines`, `maxLines`\
    Define **how the user types** (password vs normal, number vs email), how many lines it uses, and what the keyboard’s action button does.
* **Visual Styling**
  * Text, hint, label, fill color, cursor, padding + border properties for different states\
    Control **how the field looks** in normal, focused, disabled, and error states.
* **Validation & Errors**
  * `validationRules`, `regex`, `errorText`, `errorStyle`\
    Validate user input and **show clear error messages** when it’s invalid.
* **Events & Debounce**
  * `onChanged`, `onSubmit`, `debounceValue`\
    React to user input and submissions, with optional **debounced** updates for things like search or live validation.

### Properties

#### 1. Preview Mode

| Property              | Description                                                                     |
| --------------------- | ------------------------------------------------------------------------------- |
| `Field State Preview` | Preview the text field in different states (enabled, disabled, focused, error). |

#### 2. Content

| Property        | Description                                                                           |
| --------------- | ------------------------------------------------------------------------------------- |
| `Controller`    | An Text field controller variable to control the text field's value programmatically. |
| `Initial Value` | The initial text to display in the field.                                             |
| `Label Text`    | Text that "floats" above the field when it is focused.                                |
| `Hint Text`     | Placeholder text to display when the field is empty.                                  |
| `Max Length`    | The maximum number of characters allowed in the field.                                |
| `Min Lines`     | The minimum number of lines the field will occupy.                                    |
| `Max Lines`     | The maximum number of lines the field can expand to.                                  |

#### 3. Behaviour

| Property            | Description                                                                                 |
| ------------------- | ------------------------------------------------------------------------------------------- |
| `Read Only`         | If `true`, the text in the field cannot be modified by the user.                            |
| `Obscure Text`      | If `true`, the entered text will be obscured (e.g., for passwords).                         |
| `Auto Focus`        | If `true`, the text field will automatically be focused when the screen loads.              |
| `Enabled`           | If `false`, the text field is disabled.                                                     |
| `Keyboard Type`     | The type of keyboard to display (e.g., `text`, `number`, `emailAddress`).                   |
| `Text Input Action` | The action to be performed when the user presses the "enter" or "done" key on the keyboard. |
| `Text Align`        | The horizontal alignment of the text within the field.                                      |

#### 4. Actions

| Property         | Description                                                                                      |
| ---------------- | ------------------------------------------------------------------------------------------------ |
| `Debounce Delay` | The delay in milliseconds before the `onChanged` action is triggered.                            |
| `onChanged`      | An action to trigger whenever the text in the field changes.                                     |
| `onSubmit`       | An action to trigger when the user submits the field (e.g., by pressing "done" on the keyboard). |

#### 5. Colors & Padding

| Property          | Description                                   |
| ----------------- | --------------------------------------------- |
| `Fill Color`      | The background color of the text field.       |
| `Focus Color`     | The color of the field when it is focused.    |
| `Cursor Color`    | The color of the blinking cursor.             |
| `Content Padding` | The padding around the text within the field. |

#### 6. Borders

The Borders section includes a **Border Type Preview** and individual border styles for different states:

**Border Types:**

* `Underline`: Border style, border width, border color, border radius
* `Outline`: Border style, border width, border color, border radius
* `Outline Dashed`: Border style, border width, border color, border radius, stroke cap, dash pattern
* `Underline Dashed`: Border style, border width, border color, border radius, stroke cap, dash pattern

**Border States:**

* **Enabled Border**: The border style when the field is enabled
* **Disabled Border**: The border style when the field is disabled
* **Focused Border**: The border style when the field is focused
* **Focused Error Border**: The border style when the field is focused and has an error
* **Error Border**: The border style when the field has a validation error

#### 7. Text Style

| Property             | Description                                     |
| -------------------- | ----------------------------------------------- |
| `Content Text Style` | The TextStyle for the text entered by the user. |
| `Label Text Style`   | The TextStyle for the label text.               |
| `Hint Text Style`    | The TextStyle for the hint text.                |
| `Error Text Style`   | The TextStyle for the error text.               |

#### 8. Validation Rules

Validation rules allow you to add multiple validation criteria. Each validation rule has:

| Property        | Description                                                                           |
| --------------- | ------------------------------------------------------------------------------------- |
| `Type`          | The type of validation: `required`, `max length`, `min length`, or `pattern` (regex). |
| `Data`          | The validation data (e.g., max/min length value, regex pattern).                      |
| `Error Message` | The error message to display when the validation fails.                               |

#### 9. Prefix Icon Constraints

| Property     | Description                                      |
| ------------ | ------------------------------------------------ |
| `Min Width`  | The minimum width of the prefix icon container.  |
| `Max Width`  | The maximum width of the prefix icon container.  |
| `Min Height` | The minimum height of the prefix icon container. |
| `Max Height` | The maximum height of the prefix icon container. |

#### 10. Suffix Icon Constraints

| Property     | Description                                      |
| ------------ | ------------------------------------------------ |
| `Min Width`  | The minimum width of the suffix icon container.  |
| `Max Width`  | The maximum width of the suffix icon container.  |
| `Min Height` | The minimum height of the suffix icon container. |
| `Max Height` | The maximum height of the suffix icon container. |

### Children of Text Form Field

This is a leaf widget that does not support children.

### Default Properties

The Text Form Field widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`

**Alignment**

* `align`

**Visibility**

* `visible`

### Use Cases

You’ll typically use **Text Form Field** in:

* **Forms & Authentication**
  * Login / signup fields (email, password)
  * OTP backup input, username, phone number
  * Profile forms (name, address, bio)
* **Search & Filters**
  * Search bars for lists, products, or content
  * Filter inputs (e.g., min/max price, tags, keywords)
* **Multi-Line Input**
  * Feedback or support messages
  * Comments, notes, or descriptions
  * In-app messaging / short text content
* **Validated Inputs**
  * Email, phone, or custom format fields using regex
  * Inputs with min/max length, required fields, etc.


# PinField

The **Pin Field** widget is a **specialized input control** designed for entering short, fixed-length codes—usually **OTPs (One-Time Passwords)**, **PINs**, or **verification codes**.\
Instead of a single text box, it shows **multiple boxes**, one for each character, giving a clean and focused input experience.

{% embed url="<https://youtu.be/ezEUjBX98xA?si=qZbMkvuQUIk5zxww>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=ezEUjBX98xA>

#### Adding a PinField Widget

The PinField widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/trxJv6PqROdTqHt2Anoy" alt="A hero image showing a pin field widget with multiple input boxes for secure code entry."><figcaption><p>The PinField widget provides secure, focused input for PINs and verification codes.</p></figcaption></figure>

### **Core Concepts**

* **Fixed Length Input**
  * Controlled using the `length` property.
  * Ensures users enter **exactly N characters** (e.g., 4, 6 digits).
* **Per-Box UI**
  * Each character appears in its **own box**.
  * Styling is controlled via **Pin Theme Properties**—so you can:
    * Match brand design
    * Highlight focus
    * Show subtle separators
* **Security & Privacy**
  * With `obscureText` and `obscureSymbol`, you can hide the actual characters:
    * Ideal for PINs and sensitive codes
    * Shows `*` or `•` instead of the real input
* **Guided Input Flow**
  * As users type, focus moves automatically to the **next box**.
  * `autoFocus` can focus the Pin Field immediately when the screen appears, making OTP flows feel fast.
* **Event-Driven**
  * `onChanged` fires on every character change → great for live validation or enabling/disabling buttons.
  * `onCompleted` fires when **all characters are filled** → perfect to auto-submit, verify code, or move to the next step.

### Properties

| Property        | Description                                                                                                                     |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `length`        | The total number of characters in the pin/OTP. For example, `4`, `6`, etc.                                                      |
| `enabled`       | If `false`, the Pin Field is disabled and cannot be interacted with (useful when waiting for an OTP resend or while verifying). |
| `autoFocus`     | If `true`, the Pin Field will automatically gain focus when the screen loads, so users can start typing immediately.            |
| `obscureText`   | If `true`, the entered characters are visually hidden (e.g., shown as `*` or `•`) for privacy and security.                     |
| `obscureSymbol` | The character used to obscure the input (like `*`, `•`, or any symbol you prefer).                                              |

#### Pin Theme Properties

These properties define the appearance of each individual character field in the pin input.

| Property       | Description                                 |
| -------------- | ------------------------------------------- |
| `width`        | The width of each pin field box.            |
| `height`       | The height of each pin field box.           |
| `margin`       | The margin around each pin field box.       |
| `padding`      | The padding within each pin field box.      |
| `textStyle`    | The TextStyle for the entered characters.   |
| `fillColor`    | The background color of each pin field box. |
| `borderColor`  | The border color of each pin field box.     |
| `borderWidth`  | The border width of each pin field box.     |
| `borderRadius` | The corner radius of each pin field box.    |

#### Events

| Property      | Description                                                                                                                                                                                                                                                             |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onChanged`   | Triggered whenever the user types, deletes, or changes any character. Receives an object with the current `pin` value showing what has been entered so far. Useful for live validation, enabling buttons when minimum length is reached, or reacting to partial input.  |
| `onCompleted` | Triggered when **all characters are filled** (i.e., input length equals `length`). Receives an object with the complete `pin` value for processing. Perfect for auto-submitting the code, calling a verify API, or moving to the next screen without extra button taps. |

### Default Properties

The Pin Field widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`

**Alignment**

* `align`

**Visible**

* `visible`

### **Use Cases**

You’ll typically use a **Pin Field** when:

* Verifying a user’s **phone number** or **email** via OTP
* Asking users to set or enter a **PIN** for login or sensitive actions
* Implementing **2FA / security code** inputs
* Handling **transaction confirmations** (payments, withdrawals, etc.)
* Any flow where a **short, fixed-length, high-focus code** is required

Why it’s better than a normal TextField:

* Easier to **see how many digits** are required
* More **visually secure** (with obscure mode)
* Feels like the familiar OTP input from banking & fintech apps.


# Calendar

The **Calendar** widget is used to display and interact with dates in a structured, month-based or week-based view.\
It’s ideal for anything related to **scheduling, bookings, events, reminders, or date selection** inside your app.

{% embed url="<https://www.youtube.com/watch?v=Q--mDfaZwHk>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=Q--mDfaZwHk>

#### Adding a Calendar Widget

The Calendar widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/v6t8TPax8VB5X9Dtono6" alt="A hero image showing a calendar widget with date selection and event highlighting."><figcaption><p>The Calendar widget provides intuitive date selection and event visualization.</p></figcaption></figure>

### Core Concepts

To keep the Calendar powerful but flexible, its properties are grouped into **4 major sections** in the dashboard:

1. **Calendar Style**
   * Core calendar functionality and behavior
   * Date range configuration, format, and visual styling
   * Includes selection modes, highlighting, and layout options
2. **Headers Style**
   * Style the **top header** of the calendar
   * Month & year display, navigation controls, and header appearance
   * Controls text styling, alignment, colors, and spacing
3. **Days of Week Style**
   * Style the **row that shows the days of the week**
   * Weekday labels, weekend styling, and row appearance
   * Controls text styles, colors, borders, and layout
4. **Action**
   * Event handling for date selections
   * Trigger actions when users select dates or ranges

These groups make it easier to **customize the entire calendar** to match your app’s design system while keeping functionality consistent.

### Properties

#### Calendar Style

| Property                     | Description                                                                |
| ---------------------------- | -------------------------------------------------------------------------- |
| `firstDay`                   | The first date that can be selected in the calendar.                       |
| `lastDay`                    | The last date that can be selected in the calendar.                        |
| `currentDay`                 | The current date, which is often highlighted.                              |
| `focusedDay`                 | The date that is initially focused when the calendar is displayed.         |
| `startingDayOfWeek`          | The day of the week to start the calendar with (`sunday`, `monday`, etc.). |
| `calendarFormat`             | The format of the calendar (`month`, `twoWeeks`, `week`).                  |
| `rangeSelectionMode`         | The selection mode (`singleDate`, `range`).                                |
| `rangeStartDateInitialValue` | The initial value for the start date in range selection mode.              |
| `rangeEndDateInitialValue`   | The initial value for the end date in range selection mode.                |
| `rangeHighlightScale`        | The scale of the highlight for a selected date range.                      |
| `rangeHighlightColor`        | The color of the highlight for a selected date range.                      |
| `outsideDaysVisible`         | If `true`, days from the previous and next months will be visible.         |
| `isTodayHighlighted`         | If `true`, the current date will be highlighted.                           |
| `tableBorderColor`           | The color of the border around the calendar table.                         |
| `tableBorderWidth`           | The width of the border around the calendar table.                         |
| `tablePadding`               | The padding around the calendar table.                                     |
| `rowHeight`                  | The height of each row in the calendar.                                    |
| `pageJumpingEnabled`         | If `true`, allows the user to jump to a specific month or year.            |
| `shouldFillViewport`         | If `true`, the calendar will fill the entire viewport.                     |
| `weekNumbersVisible`         | If `true`, week numbers will be displayed.                                 |

#### Headers Style

| Property              | Description                                                              |
| --------------------- | ------------------------------------------------------------------------ |
| `headersVisible`      | If `true`, the header with the month and year will be visible.           |
| `shape`               | The shape of the header.                                                 |
| `color`               | The background color of the header.                                      |
| `borderColor`         | The border color of the header.                                          |
| `borderWidth`         | The border width of the header.                                          |
| `headerBorderRadius`  | The border radius of the header.                                         |
| `headerPadding`       | The padding around the header.                                           |
| `centerTitle`         | If `true`, the header title will be centered.                            |
| `textStyle`           | The TextStyle for the header title.                                      |
| `leftChevronPadding`  | The padding around the left chevron icon for navigating between months.  |
| `rightChevronPadding` | The padding around the right chevron icon for navigating between months. |

#### Days of Week Style

| Property                      | Description                                                   |
| ----------------------------- | ------------------------------------------------------------- |
| `daysOfWeekVisible`           | If `true`, the row with the days of the week will be visible. |
| `daysOfWeekHeight`            | The height of the days of the week row.                       |
| `weekdayTextStyle`            | The TextStyle for the weekday labels.                         |
| `weekendTextStyle`            | The TextStyle for the weekend labels.                         |
| `shape`                       | The shape of the days of the week row.                        |
| `color`                       | The background color of the days of the week row.             |
| `borderColor`                 | The border color of the days of the week row.                 |
| `borderWidth`                 | The border width of the days of the week row.                 |
| `daysOfWeekShapeBorderRadius` | The border radius of the days of the week row shape.          |

#### Action

| Property          | Description                                                                                                                                                                                                                                                                                                  |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `onRangeSelected` | Action triggered when a date range is selected by the user. Receives an object with `selectedRangeStart` (ISO 8601 string of the start date), `selectedRangeEnd` (ISO 8601 string of the end date), and `focusedDay` (ISO 8601 string of the currently focused day) for processing the date range selection. |

### Default Properties

The Calendar widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`

**Alignment**

* `align`

**Visible**

* `visible`

### Use Cases

You’d typically use a **Calendar widget** for:

* **Bookings & Appointments**
  * Booking a salon, doctor, class, or event slot
  * Selecting check-in/check-out dates for travel or hotels
* **Events & Schedules**
  * Showing upcoming events on specific days
  * Highlighting days with tasks, deadlines, or meetings
* **Reminders & Tracking**
  * Habit trackers, streaks, attendance
  * Marking completed days, missed days, or goals
* **Forms & Input**
  * Choosing a date of birth
  * Picking due dates or target dates

Basically, whenever the user needs to **see dates visually** and **select or understand patterns over time**, the Calendar widget fits.


# Range Slider

The **Range Slider** allows users to select a **range of values** (e.g., 100–500) between a defined **minimum and maximum**.\
It has a **track** and **two thumbs** that users can drag to adjust the start and end values.

{% embed url="<https://www.youtube.com/watch?v=zLaVt9q8Xz8>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=zLaVt9q8Xz8>

#### Adding a Range Slider Widget

The Range Slider widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/oru3TjBHcqwslTpEeEx8" alt="A hero image showing a range slider with two thumbs for selecting value ranges."><figcaption><p>The Range Slider widget enables intuitive range selection with dual thumb controls.</p></figcaption></figure>

### Core Concepts

1. **Two-Thumb Control**
   * Unlike a normal slider, the Range Slider has **two thumbs**:
     * **Start thumb** → lower value
     * **End thumb** → upper value
2. **Value Range**
   * Internally tracks:
     * **Minimum bound**
     * **Maximum bound**
     * **Current selected range** between them
3. **Visual Feedback**
   * The **selected range** is usually highlighted on the track (e.g., a filled segment between the two thumbs), helping users see the active range at a glance.
4. **Interactive Filtering / Settings**
   * Often used to **update lists, charts, or search results** as the user adjusts the range.

### Properties

| Property        | Description                                                                                                                                                                |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `min`           | The minimum value of the range.                                                                                                                                            |
| `max`           | The maximum value of the range.                                                                                                                                            |
| `division`      | The number of discrete divisions on the slider.                                                                                                                            |
| `startValue`    | The initial value of the starting thumb.                                                                                                                                   |
| `endValue`      | The initial value of the ending thumb.                                                                                                                                     |
| `activeColor`   | The color of the track between the two thumbs.                                                                                                                             |
| `inactiveColor` | The color of the track outside the selected range.                                                                                                                         |
| `thumbColor`    | The color of the draggable thumbs.                                                                                                                                         |
| `thumbRadius`   | The radius of the thumbs.                                                                                                                                                  |
| `trackHeight`   | The height of the slider track.                                                                                                                                            |
| `onChanged`     | An action to trigger when the user slides either thumb. Receives an object with `startValue` (the current start thumb value) and `endValue` (the current end thumb value). |

***

### Default Properties

The Range Slider widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use the **Range Slider** when you want the user to pick a **min–max range** instead of a single value, for example:

* **Price filters** in e-commerce (₹500 – ₹2000)
* **Age range** or **duration range** selection
* **Distance / radius** filters (2 km – 10 km)
* **Rating / score range** filters
* Any filter or setting where a **range** is more meaningful than a single number.


# Slider

The **Slider** allows users to select a **single value** within a defined range (e.g., 0–100).\
It has a track and one draggable thumb that users can slide horizontally (or vertically) to adjust the value.

Sliders are ideal for quick, touch-friendly value selection without typing.

{% embed url="<https://youtu.be/kZPDJ-qql9o?si=pqB1L0fQNeC5jhF2>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=kZPDJ-qql9o>

#### Adding a Slider Widget

The Slider widget is located in the **Form Elements** section of the Widget Palette. Once added, you can configure its properties from the **Widget Properties Panel**.

<figure><img src="/files/SxDACx1Px0yYc8v7THAc" alt="A hero image showing a slider widget with a draggable thumb for single value selection."><figcaption><p>The Slider widget provides intuitive single-value selection with smooth thumb controls.</p></figcaption></figure>

### Core Concepts

**Single-Thumb Control**

Unlike the Range Slider, the Slider has **one thumb**:

* **Thumb** → represents the current value on the track.

The user drags this thumb to increase or decrease the value.

**Value Range**

Internally, the Slider works with:

* **Minimum bound** (`min`)
* **Maximum bound** (`max`)
* **Current value** between them (`value`)

You can think of it as a controlled numeric input represented visually.

**Visual Feedback**

* The **active segment** of the track (from `min` to current value) is usually highlighted.
* The **inactive segment** (from current value to `max`) is shown in a lighter or muted color.
* The thumb clearly shows the current value position at a glance.

**Interactive Control / Settings**

Sliders often drive **live updates**:

* Adjusting a slider can update previews (e.g., font size, zoom level)
* Live filtering of results (e.g., only show items under X price/value)
* Smooth UX for quickly trying out different values without typing.

### Properties

| Property        | Description                                                                                                                                      |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `min`           | The minimum value allowed by the slider.                                                                                                         |
| `max`           | The maximum value allowed by the slider.                                                                                                         |
| `division`      | The number of discrete divisions/steps on the slider. If set, the value snaps to these.                                                          |
| `value`         | The current value of the slider thumb.                                                                                                           |
| `activeColor`   | The color of the track from `min` to the current value (filled/selected portion).                                                                |
| `inactiveColor` | The color of the track from the current value to `max` (unselected portion).                                                                     |
| `thumbColor`    | The color of the draggable thumb.                                                                                                                |
| `thumbRadius`   | The radius/size of the thumb, controlling how big it appears.                                                                                    |
| `trackHeight`   | The height/thickness of the slider track.                                                                                                        |
| `onChanged`     | An action/callback triggered whenever the user drags the thumb and the value changes. Receives an object with the current `value` of the slider. |

### Default Properties

The Slider widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use the Slider when you want the user to pick **one value**, for example:

* **Volume / brightness / opacity** controls
* **Progress or intensity** settings (e.g., difficulty level, animation speed)
* **Single-value filters** (e.g., “within 5 km”, “up to ₹1000”)
* **Percentage inputs** (0–100%) like completion, transparency, rating weight
* Any setting where a **continuous or stepped value** is meaningful and doesn’t require precise text input.


# State Container

The **State Container** is a simple widget that wraps **one child** and gives it its own **local state**.\
Use it when a part of your UI needs to manage its own state without involving the whole page or global state.

{% embed url="<https://youtu.be/RtM5l8G1rlE?si=iwURVC9A899wdncT>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=RtM5l8G1rlE>

### Core Concepts

1. **Local, Scoped State**
   * The state lives **inside** the State Container and is only available to its **child**.
   * Each State Container instance has **its own copy** of state (no sharing by default).
2. **Accessing Local State**
   * You can access local state variables directly by name: `isExpanded`, `count`, `selectedIndex`
   * Or with the container name prefix: `statecontainerName.isExpanded`
   * This allows flexible referencing based on your naming preferences
3. **State-Driven Rebuilds**
   * You read values via something like `state.count`, `state.isExpanded`, `state.selectedIndex`.
   * Use the **Set State** action to update state values and trigger UI rebuilds.
4. **Actions for State Management**
   * Use the **Set State** action to update local state variables
   * Use the **Rebuild State** action to force UI updates when needed
   * These actions work with the state container to manage local state changes
5. **Encapsulation**
   * UI logic is **packaged** with the widget that uses it.
   * You don't need to push every small boolean or counter to a page-level or global store.
6. **Ideal for Micro-Interactions**
   * Great for small, self-contained interactions:
     * Toggles → Use **Set State** action to update `isOn: not(isOn)`
     * Counters → Use **Set State** action to update `count: add(count,1)`
     * Selection → Use **Set State** action to update `selectedIndex: index`

If many widgets need the **same** state, or that state affects the **whole screen**, that's your sign to **lift the state up** out of the State Container.

### Best Practices

* Use for **small, UI-specific logic**:
  * Toggles, counters, per-card expand/collapse, local selection.
* Keep state **minimal and clear**:
  * Prefer simple keys like `isOpen`, `count`, `activeTab`.
* If multiple widgets must share the same state or it affects the whole screen,\
  move that state to a **higher-level** widget instead of a State Container.

### Properties

The State Container widget provides local state management capabilities. You can define local state variables that are scoped to the container and its child widgets.

#### Defining Local Variables

* **State Variables**: Add and configure local state variables in the State Variables section
* **Variable Types**: Support for various data types including strings, numbers, booleans, objects, and arrays
* **Initial Values**: Set initial values for each state variable
* **Scope**: Variables are only accessible within the State Container and its child widgets

Beyond the state variables, the State Container does not have specific configuration properties beyond the default layout and interaction properties.

### Actions for State Management

To manage state within a State Container, use these actions:

#### Set State Action

* **Purpose**: Update local state variables with new values
* **How to use**:
  1. Add the **Set State** action to a widget event (onClick, onChanged, etc.)
  2. Select the State Container from the State dropdown
  3. Add state variable updates in the State Updates section
  4. Optionally enable "Rebuild UI" for immediate visual updates

*Reference:* [*Set State Action*](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/actions/set-state.md)

#### Rebuild State Action

* **Purpose**: Force a UI rebuild of the State Container without changing state values
* **How to use**:
  1. Add the **Rebuild State** action to a widget event
  2. Select the State Container from the State dropdown
  3. This triggers a re-render of dependent widgets

*Reference:* [*Rebuild State Action*](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/actions/rebuild-state.md)

### Default Properties

The State Container widget supports no default property.

### Use Cases

Use **State Container** when you want:

* **Per-widget local behavior**
  * A single card that can expand/collapse without affecting others
  * A like/favorite toggle on each item in a list
  * A per-item counter (e.g., quantity selector in a cart row)
* **Isolated UI state**
  * Tabs, steps, or internal view toggles inside one section
  * Local selection in a small segment (e.g., chip group, filter section)
  * Temporary UI flags like `isLoading`, `isExpanded`, `isEditing` for one block
* **Repeated widgets with independent state**
  * Multiple cards, each with its own `isOpen`, `count`, or `selected`
  * Reusable components that should **not share** state with other instances


# Timer

The **Timer** widget is a time-based utility that lets you run **countdown** or **count-up (stopwatch)** timers inside your app. It can trigger actions at regular intervals (ticks) or when the timer completes, making it ideal for **dynamic, time-driven experiences** like quizzes, games, progress flows, and limited-time offers.

{% embed url="<https://youtu.be/OMoNGjx1r-4?si=YvMBl00aV4IqB5gE>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=OMoNGjx1r-4>

### **Core Concepts**

* **Timer Type**
  * `countDown` – Starts from a given number of seconds and decreases to zero.
  * `countUp` – Starts from a given value (usually 0) and increases over time.
* **Tick**
  * A “tick” is each point in time when the timer updates.
  * Controlled by `updateInterval` (in seconds).
  * On every tick, the widget exposes the **current time value** through `tickValue`.
* **Controller**
  * The `controller` lets you programmatically:
    * **start** the timer
    * **stop/pause** the timer
    * **reset** it back to the initial value
  * These operations can be executed using the **Control Object** action.
  * > **Note:** If a controller is provided, other properties except actions may not work as the timer is controlled programmatically.
  * This is useful when the timer’s behavior depends on user actions or other widgets (e.g., start timer when a quiz question appears).
* **Actions**
  * `onTick` – Runs repeatedly at each interval.
  * `onTimerEnd` – Runs once when the timer finishes (in countDown mode) or when you manually end it.
* **Child & tickValue**
  * The Timer has a `child` slot.
  * Inside this child, you can access **`tickValue`**, which is the **current timer value** (e.g., remaining seconds in a countdown).
  * You can access `tickValue` directly by name or with the widget name prefix: `timerName.tickValue`.
  * This allows flexible referencing and makes it easy to display the timer on-screen without extra state.

### Properties

| Property         | Description                                                                                                                                          |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `controller`     | A TimerController Variable that can be used to control the timer (e.g., start, stop, reset).                                                         |
| `duration`       | The total duration of the timer in seconds.                                                                                                          |
| `initialValue`   | The initial value of the timer. For a countdown timer, this is the number of seconds to count down from. For a stopwatch, this is the starting time. |
| `updateInterval` | The interval in seconds at which the `onTick` action is triggered.                                                                                   |
| `timerType`      | The type of timer. Can be `countDown` or `countUp`.                                                                                                  |
| `onTick`         | An action to be executed at each `updateInterval`.                                                                                                   |
| `onTimerEnd`     | An action to be executed when the timer finishes.                                                                                                    |

#### Events

| Property     | Description                                                                         |
| ------------ | ----------------------------------------------------------------------------------- |
| `onTick`     | Triggered at each `updateInterval`. Receives an object with the current tick value. |
| `onTimerEnd` | Triggered when the timer finishes. Receives an object with the final tick value.    |

***

### Default Properties

The Timer widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`

**Alignment**

* `align`

**Visibility**

* `visible`

### **Use Cases**

You can use the Timer widget in scenarios like:

* ⏳ **Countdowns**
  * Quiz timers (e.g., 30 seconds per question)
  * Flash sale or limited-time offer countdowns
  * Session expiry or logout warnings
* ⏱ **Stopwatch / Count-Up**
  * Track how long a user spends on a task or game
  * Measure response times or performance metrics
* 🔁 **Recurring UI Updates**
  * Auto-advancing slides or banners
  * Updating a progress bar every second
  * Periodic API polling (e.g., refresh status every 5 seconds)
* 🎮 **Game & Interaction Logic**
  * Trigger events after a delay (e.g., show hint after 10 seconds)
  * End a level when time runs out
  * Control animations or state changes over time


# Navigation Widgets

Widgets for navigating between different screens and managing app navigation flow.

## Overview

Navigation widgets handle movement between different parts of your app. They provide ways to switch between pages, manage navigation history, and create intuitive navigation experiences.

## Categories

### Page Navigation

* [**Page View**](/ui-building-blocks/widgets/navigation-widgets/page-view) - Swipeable page navigation
* [**Navigation Bar**](/ui-building-blocks/widgets/navigation-widgets/navigation-bar) - Bottom navigation with multiple tabs

### Tab Management

* [**Tab Bar**](/ui-building-blocks/widgets/navigation-widgets/tab-bar) - Horizontal tab selection interface
* [**Tab Controller**](/ui-building-blocks/widgets/navigation-widgets/tab-controller) - Manages tab state and navigation
* [**Tab View Content**](/ui-building-blocks/widgets/navigation-widgets/tab-view-content) - Content display for tab views

### Navigation Components

* [**Navigation Bar**](/ui-building-blocks/widgets/navigation-widgets/navigation-bar) - Bottom navigation with multiple tabs
* [**Navigation Bar (Custom)**](/ui-building-blocks/widgets/navigation-widgets/navigation-bar-custom) - Customizable navigation bars
* [**Navigation Bar Item**](/ui-building-blocks/widgets/navigation-widgets/navigation-bar-item) - Standard navigation bar items
* [**Navigation Bar Item (Custom)**](/ui-building-blocks/widgets/navigation-widgets/navigation-bar-item-custom) - Custom navigation bar items


# Navigation Bar

The Navigation Bar widget provides a persistent navigation bar at the bottom of the screen, allowing users to switch between different pages or views.

{% embed url="<https://www.youtube.com/watch?v=8Xbq4Pdax9Q>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=8Xbq4Pdax9Q>

<figure><img src="/files/hgUW90I4NIRAc95lx6rH" alt="A diagram showing the main and cross axis of a Wrap widget."><figcaption><p>Example of a Wrap widget where items wrap to a new line.</p></figcaption></figure>

### Core Concepts

1. **Tabs as Primary Destinations**\
   Each item (icon + label) represents a **top-level screen**, not a sub-page.
   * Example: *Home*, *Search*, *Orders*, *Profile*.
2. **Persistent Across Screens**\
   The Navigation Bar usually stays **visible** while switching between its tabs, giving users a stable mental model of the app’s structure.
3. **Selected vs Unselected State**
   * One item is **selected/active** (current section).
   * Others are **unselected** but tappable.
   * Visual feedback via color, icon change, or label style.
4. **Controlled by an Index / State**
   * Internally, an `activeIndex` (or similar) tells which tab is active.
   * Tapping an item updates this index and switches the visible screen.

### Properties

| Property            | Description                                                   |
| ------------------- | ------------------------------------------------------------- |
| `backgroundColor`   | The background color of the navigation bar.                   |
| `elevation`         | The z-axis elevation of the navigation bar.                   |
| `height`            | The height of the navigation bar.                             |
| `surfaceTintColor`  | The surface tint color of the navigation bar.                 |
| `indicatorColor`    | The color of the indicator that highlights the selected item. |
| `indicatorShape`    | The shape of the indicator (`circle`, `stadium`, etc.).       |
| `overlayColor`      | The color of the overlay that appears when an item is tapped. |
| `showLabels`        | If `true`, labels will be shown for the navigation items.     |
| `animationDuration` | The duration of the animation when switching between items.   |
| `borderRadius`      | The corner radius of the navigation bar.                      |
| `shadow`            | A list of shadow effects to apply to the navigation bar.      |

### Children of Navigation Bar

| Slot       | Description                                                                                     |
| ---------- | ----------------------------------------------------------------------------------------------- |
| `children` | Multiple **Navigation Bar Item** widgets that represent each tab/section in the navigation bar. |

### When to Use Navigation Bar vs Navigation Bar Custom

**Use Navigation Bar when:**

* You need a standard bottom navigation with icon + label items
* Each tab has a simple icon/image and optional text label
* You want built-in selected/unselected state styling
* Your design follows common Material Design patterns

**Use Navigation Bar Custom when:**

* You need complete control over the navigation bar layout
* You want custom shapes, backgrounds, or unique item designs
* You're implementing a floating center button or asymmetrical layout
* Your brand requires highly customized navigation styling

### Default Properties

The Navigation Bar widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Visibility**

* `visible`

### Use Cases

Use **Navigation Bar** when you want to:

* **Provide app-wide primary navigation**
  * Home, Explore, Cart, Profile, Settings, etc.
  * Quickly jump between 3–5 key sections of the app.
* **Keep core screens always accessible**
  * Make important pages just **one tap away** from anywhere.
  * Reduce back-stack mess (no need to go “back” multiple times to change section).
* **Create a familiar mobile experience**
  * Standard bottom nav like most modern apps (Instagram, YouTube, e-commerce apps).


# Navigation Bar Item

The Navigation Bar Item is a standard item for use within a Navigation Bar. It typically consists of an icon and a label, with different appearances for selected and unselected states.

### Use Cases

Use a **Navigation Bar Item** when you want to:

* **Represent a primary section**
  * Home, Explore, Search, Cart, Orders, Profile, Settings, etc.
* **Give quick, one-tap access**
  * Let users jump directly to important screens from anywhere in the app.
* **Show state of a section**
  * Badge on Cart item (e.g., 3 items)
  * Dot or highlight on Notifications when there’s something new

Each Navigation Bar Item is one “entry point” to a top-level area of the app.

### Core Concepts

1. **Icon + Label = Meaning**
   * The icon gives a quick visual cue.
   * The label clarifies the destination (e.g., “Home”, “Profile”).
   * Together they make navigation **obvious and predictable**.
2. **Active vs Inactive State**
   * One item is in **active/selected** state (current screen).
   * Others are **inactive** but tappable.
   * Visual changes (color, size, underline, or filled icon) indicate which tab is active.
3. **Linked to an Index / Route**
   * Each item maps to a specific **tab index** or **route/screen**.
   * Tapping the item:
     * Updates the active index in the Navigation Bar
     * Switches the displayed screen accordingly
4. **Optional Badges & Indicators**
   * Can show extra info (like unread count, dot, or alert) on a specific item to hint that attention is needed on that section.

### Properties

| Property   | Description                                                                                            |
| ---------- | ------------------------------------------------------------------------------------------------------ |
| `showIf`   | If `false`, this item will not be displayed in the navigation bar.                                     |
| `onSelect` | An action to perform when this item is selected. This usually involves navigating to a different page. |

#### Label Properties

| Property    | Description                                |
| ----------- | ------------------------------------------ |
| `text`      | The text of the label.                     |
| `textStyle` | The TextStyle for the label.               |
| `alignment` | The alignment of the label.                |
| `maxLines`  | The maximum number of lines for the label. |
| `overflow`  | How label overflow is handled.             |

#### Unselected State Properties

| Property          | Description                                                                     |
| ----------------- | ------------------------------------------------------------------------------- |
| `unselectedType`  | The type of content to display when the item is unselected (`icon` or `image`). |
| `unselectedIcon`  | The icon to display when unselected. See Icon for properties.                   |
| `unselectedImage` | The image to display when unselected. See Image for properties.                 |

#### Selected State Properties

| Property        | Description                                                                   |
| --------------- | ----------------------------------------------------------------------------- |
| `selectedType`  | The type of content to display when the item is selected (`icon` or `image`). |
| `selectedIcon`  | The icon to display when selected. See Icon for properties.                   |
| `selectedImage` | The image to display when selected. See Image for properties.                 |

### When to Use Navigation Bar Item vs Navigation Bar Item Custom

**Use Navigation Bar Item when:**

* You need a standard tab with icon + text label
* Selected/unselected states use different icons or images
* You want automatic state management for active/inactive appearance
* Your design follows typical navigation patterns

**Use Navigation Bar Item Custom when:**

* You need complete layout freedom for the navigation item
* You want to add badges, avatars, or complex widget combinations
* You need custom animations or interactions on tap
* Standard icon + label layout doesn't match your design needs

### Default Properties

The Navigation Bar Item widget does not have standard default properties. Its appearance is controlled by the properties listed above.


# Navigation Bar Custom

The Navigation Bar Custom provides a container for creating a completely custom navigation bar using `NavigationBarItemCustom` widgets as children.

### Use Cases

Use **Navigation Bar Custom** when you want to:

* **Build a unique bottom bar design**
  * Floating center button (like a big “+” action)
  * Curved or elevated navbar with special shapes
  * Custom backgrounds, gradients, blur, or shadows
* **Mix navigation + primary actions**
  * 2–3 tabs plus one big central action (e.g., “Scan”, “Create”, “Post”)
  * Custom layouts like left-aligned items + one highlighted CTA
* **Brand-heavy or theme-specific UI**
  * Highly branded nav for fintech, gaming, or social apps
  * Icon-only nav, text-only nav, or fully custom widgets as items

### Core Concepts

1. **You Control the Layout**
   * Instead of fixed icon+label items, you can place **any widgets** inside: icons, text, avatars, custom buttons, badges, etc.
   * You define the arrangement: equal spacing, centered button, asymmetrical layout, etc.
2. **Manual State Handling**
   * You typically manage the active tab or selected state yourself (e.g., `activeIndex`).
   * Taps on your custom items must explicitly:
     * Update the selected index
     * Trigger navigation or screen change
3. **Custom Interaction Patterns**
   * You can add:
     * Long-press behaviors
     * Double-tap shortcuts
     * Special animations on selection (scale, color change, glow)
4. **Same Role, More Freedom**
   * Functionally, it still acts as the **primary navigation** for the app.
   * Visually and structurally, you get **much more freedom** than the standard Navigation Bar.

### Properties

| Property            | Description                                                   |
| ------------------- | ------------------------------------------------------------- |
| `backgroundColor`   | The background color of the navigation bar.                   |
| `height`            | The height of the navigation bar.                             |
| `surfaceTintColor`  | The surface tint color of the navigation bar.                 |
| `indicatorColor`    | The color of the indicator that highlights the selected item. |
| `indicatorShape`    | The shape of the indicator.                                   |
| `overlayColor`      | The color of the overlay that appears when an item is tapped. |
| `animationDuration` | The duration of the animation when switching between items.   |
| `borderRadius`      | The corner radius of the navigation bar.                      |

### Children of Navigation Bar Custom

| Slot       | Description                                                                                                   |
| ---------- | ------------------------------------------------------------------------------------------------------------- |
| `children` | Multiple **Navigation Bar Item Custom** widgets that represent each custom tab/section in the navigation bar. |

### When to Use Navigation Bar vs Navigation Bar Custom

**Use Navigation Bar when:**

* You need a standard bottom navigation with icon + label items
* Each tab has a simple icon/image and optional text label
* You want built-in selected/unselected state styling
* Your design follows common Material Design patterns

**Use Navigation Bar Custom when:**

* You need complete control over the navigation bar layout
* You want custom shapes, backgrounds, or unique item designs
* You're implementing a floating center button or asymmetrical layout
* Your brand requires highly customized navigation styling

### Default Properties

The Navigation Bar Custom widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Visibility**

* `visible`


# Navigation Bar Item Custom

The Navigation Bar Item Custom allows you to create a fully custom navigation item using any widget as its child. This provides maximum flexibility for designing unique navigation bars.

### Use Cases

Use **Custom Navigation Bar Item** when you want to:

* **Design non-standard tab items**
  * Big rounded middle button (primary action like “Create”, “Scan”, “Post”)
  * Icon-only or text-only items
  * Avatar-based profile tab, or pill-shaped selected tab
* **Add rich content in a nav item**
  * Badge with count, status dot, label + subtitle
  * Animated icon, Lottie, or micro-interaction on tap
* **Match strong brand or UX patterns**
  * Gaming, fintech, or social apps with very specific nav designs
  * Highly stylized nav where standard Navigation Bar Item isn’t enough

### Core Concepts

1. **Free Layout Per Item**
   * Each custom item can be any widget tree: `Row`, `Column`, `Stack`, avatar, text, icon, etc.
   * You decide padding, shape, background, shadows, and animations.
2. **Manual Active State**
   * You typically pass in something like `isActive` or compare with an `activeIndex`.
   * Based on this, you change:
     * Colors (active vs inactive)
     * Size, background, icon style, etc.
3. **Explicit Actions & Navigation**
   * Each item handles its own `onTap` or action.
   * Tapping:
     * Updates the selected tab (index/state)
     * Navigates to the target screen or triggers a special action (e.g., open sheet, show modal).
4. **Same Purpose, Customized Experience**
   * Still represents a **primary section or key action**, just with **full visual and interaction control** compared to standard nav items.

### Properties

| Property   | Description                                                        |
| ---------- | ------------------------------------------------------------------ |
| `showIf`   | If `false`, this item will not be displayed in the navigation bar. |
| `onSelect` | An action to perform when this item is selected.                   |

### Children of Navigation Bar Item Custom

| Slot    | Description                                                                                                                                 |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `child` | A single custom child widget that represents the navigation item. Can be any widget (Row, Column, Stack, etc.) for complete design freedom. |

### When to Use Navigation Bar Item vs Navigation Bar Item Custom

**Use Navigation Bar Item when:**

* You need a standard tab with icon + text label
* Selected/unselected states use different icons or images
* You want automatic state management for active/inactive appearance
* Your design follows typical navigation patterns

**Use Navigation Bar Item Custom when:**

* You need complete layout freedom for the navigation item
* You want to add badges, avatars, or complex widget combinations
* You need custom animations or interactions on tap
* Standard icon + label layout doesn't match your design needs

### Default Properties

The Navigation Bar Item Custom widget does not have standard default properties. Its appearance is controlled by the custom child widget.


# Tab Bar

The **Tab Bar** widget displays a **horizontal row of tabs** that users can tap to switch between different sections or views.\
It’s usually used together with:

* **Tab Controller** → manages which tab is selected
* **Tab View Content** → shows the content for the selected tab

Think of it as the **navigation strip** at the top of a tabbed interface.

{% embed url="<https://www.youtube.com/watch?v=DCkob8F_pwI>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=DCkob8F_pwI>

### **Use Cases**

Use a **Tab Bar** when you want to:

* Split a screen into **multiple sections** without navigating to different pages
  * Example: `Overview`, `Details`, `Reviews` on a product page
* Provide a **quick way to switch content** in-place
  * Example: `Chats`, `Groups`, `Calls`
* Organize related content under **categories**
  * Example: `Trending`, `Latest`, `Saved`
* Build a **multi-tab dashboard**
  * Example: `Analytics`, `Reports`, `Settings`

It’s ideal when:

* All sections are **closely related**
* Users need to **switch frequently** between them
* You want **fast switching without full page transitions**

### **Core Concepts**

* **Visual Tab Strip**
  * The Tab Bar is purely the **visual + interactive row of tabs**.
  * It doesn’t store state itself; selection is usually managed by the **Tab Controller**.
* **Selected vs Unselected Tabs**
  * You can define different **templates**:
    * `selectedWidget` → how the active tab looks
    * `unselectedWidget` → how inactive tabs look
  * This lets you style active tabs with:
    * Bold text
    * Different colors
    * Icons or backgrounds
* **Scrollable vs Fixed Tabs**
  * With `tabBarScrollable.value`, the Tab Bar can:
    * Stay **fixed** (tabs share the available width), or
    * Be **scrollable horizontally** if there are many tabs.
* **Indicator & Divider**
  * **Indicator**: A line/marker showing which tab is currently selected.
    * Controlled by `indicatorColor`, `indicatorWeight`, `indicatorSize`.
  * **Divider**: A line below the Tab Bar separating it from content.
    * Controlled by `dividerColor`, `dividerHeight`.
* **Spacing & Layout**
  * `labelPadding` → Space around each tab label.
  * `tabBarPadding` → Space around the whole tab row.

### Properties

| Property                        | Description                                                                                                                                                  |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `tabBarScrollable.value`        | If `true`, the Tab Bar can scroll horizontally when there are more tabs than can fit on the screen. If `false`, tabs are distributed within available width. |
| `tabBarScrollable.tabAlignment` | Controls how tabs are aligned within the scrollable area (e.g., aligned to start, centered).                                                                 |
| `labelPadding`                  | Padding around each tab’s label (text/icon), controlling how compact or spacious each tab feels.                                                             |
| `indicatorColor`                | Color of the indicator that highlights the currently selected tab.                                                                                           |
| `indicatorWeight`               | Thickness of the indicator line (e.g., thicker for more emphasis).                                                                                           |
| `dividerColor`                  | Color of the divider line displayed below the Tab Bar.                                                                                                       |
| `dividerHeight`                 | Height/thickness of the divider line below the Tab Bar.                                                                                                      |
| `indicatorSize`                 | Defines how wide the indicator is — for example, under the whole tab or just under the label.                                                                |
| `tabBarPadding`                 | Padding applied around the entire Tab Bar area, controlling its spacing from surrounding content.                                                            |

#### Children of Tab Bar

| Slot               | Description                                                                                                                                       |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `selectedWidget`   | Widget template used for the **active/selected tab**. Use this to visually highlight the current tab (e.g., bold text, colored background, icon). |
| `unselectedWidget` | Widget template used for **inactive tabs**. Usually more subtle styling compared to the selected tab.                                             |

These templates are applied for each tab depending on its selected state, letting you create **fully custom tab designs**.

> 📚 **Learn More**: To understand the underlying Flutter implementation, see the [Flutter TabBar documentation](https://api.flutter.dev/flutter/material/TabBar-class.html).

### Default Properties

#### Layout

The Tab Bar widget supports the following layout properties:

* `width`
* `height`
* `padding`
* `margin`

#### Alignment

The Tab Bar widget supports the following alignment property:

* `align`

#### Visibility

The Tab Bar widget supports the following visibility property:

* `visible`


# Tab View Content

**Tab View Content** is the widget that **shows the actual content** for the currently selected tab.\
It works together with:

* **Tab Controller** → manages which tab is selected
* **Tab Bar** → lets the user switch tabs

Whenever the selected tab changes, Tab View Content updates to display the **corresponding screen/content**.

### **Use Cases**

You use **Tab View Content** when:

* You have multiple **sections of content** under different tabs, such as:
  * Product page → `Overview`, `Details`, `Reviews`
  * Profile → `Posts`, `About`, `Activity`
  * Dashboard → `Summary`, `Analytics`, `Logs`
* You want users to **switch between content** without leaving the screen.
* You want each tab to have:
  * Its own scrollable content
  * Its own UI/state
  * Smooth transitions between sections

It’s ideal for building **multi-tab experiences** where each tab has a distinct layout or data.

### **Core Concepts**

* **Content Area for Tabs**
  * Tab View Content is essentially the **page area below the Tab Bar**.
  * It listens to the **Tab Controller’s selected index** and shows the relevant tab’s content.
* **Scroll Behavior**
  * With `isScrollable`, you can decide if each tab’s content is scrollable vertically (e.g., long lists, forms, feeds).
* **State Preservation**
  * `keepTabsAlive` ensures each tab’s state (scroll position, form inputs, etc.) is **preserved** when you switch tabs.
  * Without it, content might rebuild/reset when you navigate away from a tab.
* **Viewport Fraction**
  * `viewportFraction` controls **how much of the screen** each tab’s page occupies.
  * Mostly useful for **paged / swipe-like layouts**, where you might show a portion of the next/previous tab for visual hints.

### Properties

| Property           | Description                                                                                                                                                                                          |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `isScrollable`     | If `true`, the content within each tab can scroll (e.g., for long lists or detailed pages). If `false`, content stays fixed within the available space.                                              |
| `keepTabsAlive`    | If `true`, the state of each tab's content is preserved when it goes off-screen. This helps keep scroll position, user input, and loaded data intact when switching between tabs.                    |
| `viewportFraction` | Defines what fraction of the viewport each tab's content should use. A value of `1.0` typically means each tab fills the full width; values less than `1.0` can show a peek of adjacent tab content. |

> 📚 **Learn More**: To understand the underlying Flutter implementation, see the [Flutter TabBarView documentation](https://api.flutter.dev/flutter/material/TabBarView-class.html).

### Default Properties

#### Layout

The Tab View Content widget supports the following layout properties:

* `width`
* `height`
* `padding`
* `margin`

#### Alignment

The Tab View Content widget supports the following alignment property:

* `align`

#### Visibility

The Tab View Content widget supports the following visibility property:

* `visible`


# Tab Controller

The **Tab Controller** is a **state management widget** that coordinates a **Tab Bar** (the row of tabs) and a **Tab View** (the content for each tab).\
It keeps track of **which tab is currently selected** and ensures that the **correct content screen** is shown for that tab.

You can think of it as the **“brain”** behind tab navigation.

### **Use Cases**

Use a **Tab Controller** whenever your screen has **multiple sections** that users can switch between using tabs, for example:

* 🛒 **E-commerce**
  * Product page with tabs like: `Overview`, `Details`, `Reviews`
* 👤 **Profile / Account**
  * Tabs such as: `Posts`, `About`, `Activity`
* 📊 **Dashboard**
  * Tabs like: `Analytics`, `Reports`, `Settings`
* 📱 **Content apps**
  * `Chats`, `Status`, `Calls`
  * `Trending`, `Latest`, `Saved`

Typical scenarios:

* One **Tab Controller** wrapping:
  * a **Tab Bar** at the top
  * a **Tab View** below containing content for each tab
* Switching tabs automatically updates the Tab View **without navigation** to new screens, making it ideal for **in-place switching**.

### **Core Concepts**

* **Selected Tab State**
  * The Tab Controller maintains **which tab is active** (by index).
  * When the user taps a tab in the Tab Bar:
    * The Tab Controller updates its **selected index**.
    * The corresponding page/content is shown in the Tab View.
* **Link Between Tab Bar & Tab View**
  * The Tab Bar handles **user input** (tap on a tab).
  * The Tab View handles **displaying content** for each tab.
  * The Tab Controller keeps them **in sync**, so they always reflect the same tab selection.
* **Tab Coordination**
  * If the selected tab changes programmatically (e.g., via action), the Tab Controller:
    * Updates the Tab Bar’s active tab.
    * Updates the Tab View to show the correct screen.
* **Consistent UX**
  * Using a Tab Controller ensures:
    * Smooth, predictable tab switching.
    * No need to manually handle which content should be visible.

### Properties

| Property       | Description                                        |
| -------------- | -------------------------------------------------- |
| `dynamicList`  | Data list used to generate tabs and their content. |
| `initialIndex` | Zero-based index of the tab selected by default.   |
| `onTabChange`  | Action triggered when the selected tab changes.    |

### Default Properties

#### Layout

The Tab Controller widget supports the following layout properties:

* `width`
* `height`
* `padding`
* `margin`

#### Alignment

The Tab Controller widget supports the following alignment property:

* `align`

#### Visibility

The Tab Controller widget supports the following visibility property:

* `visible`


# Page View

The Page View widget displays a scrollable list of pages. It is commonly used for onboarding screens, carousels, or any UI that requires full-page swiping.

{% embed url="<https://youtu.be/uHpNUKQjOI8?si=fV3y_tfpRb06ga3I>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=uHpNUKQjOI8>

### Core Concepts

1. **Page-by-Page Navigation**
   * Content is split into **discrete pages**, not continuous scroll.
   * User navigates via **swipe** or programmatic control (using a controller).
2. **PageController & Index**
   * A `PageController` manages:
     * Current page index
     * Animating to the next/previous page
   * You can sync this index with indicators, tabs, or other UI.
3. **One Layout per Page**
   * Each child is a **full layout** (could be a whole screen).
   * Perfect when each state/step deserves its **own dedicated screen**, but you still want **smooth swipe navigation**.
4. **Horizontal or Vertical**
   * Commonly horizontal (like stories or onboarding),
   * Can be vertical if your UX calls for it.

### Properties

#### 1. Page View Settings

| Property            | Description                                                        |
| ------------------- | ------------------------------------------------------------------ |
| `Data Source`       | A list of data that can be used to dynamically generate pages.     |
| `Controller`        | A PageController variable to control the currently displayed page. |
| `Initial Page`      | The index of the page to show when the widget is first displayed.  |
| `Viewport Fraction` | The fraction of the viewport that each page should occupy.         |
| `Scroll Direction`  | The direction of scrolling (`horizontal` or `vertical`).           |

#### 2. Behaviour

| Property        | Description                                                              |
| --------------- | ------------------------------------------------------------------------ |
| `Preload Page`  | If `true`, pages adjacent to the current page are preloaded.             |
| `Keep Page`     | If `true`, the state of each page is preserved as it scrolls off-screen. |
| `Allow Scroll`  | If `true`, the user can scroll between pages.                            |
| `Reverse`       | If `true`, the order of the pages is reversed.                           |
| `Pad Ends`      | If `true`, padding is added to the ends of the list of pages.            |
| `Page Snapping` | If `true`, the scroll view will snap to the nearest page.                |

#### 3. Actions

| Property        | Description                                                                                                                                                |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onPageChanged` | An action triggered when the currently displayed page changes. Receives an object with `currentItem` (the current page data) and `index` (the page index). |

### Children of Page View

| Slot       | Description                                                                                                                                                                                                                                                    |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `children` | The child widgets that represent each page in the page view. Each child has access to `currentItem` (the data for that page) and `index` (the page index). You can access these directly by name or with the PageView name prefix: `pageViewName.currentItem`. |

***

### Default Properties

The Page View widget supports the following sections of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`

**Alignment**

* `align`

**Visibility**

* `visible`

### Use Cases

The **PageView** widget lets users **swipe between full-screen pages** horizontally (or vertically). Each page is usually a complete screen or section.

Use **PageView** when you want:

* **Onboarding / Intro Screens**
  * Multiple slides explaining features of the app
  * Combined with dots/indicators to show progress (like your Digia onboarding)
* **Tabbed, swipeable content**
  * Swipe between “Overview / Details / Reviews”
  * News sections, categories, or stories that users can swipe through
* **Step-by-step flows**
  * Multi-step forms (Step 1 → Step 2 → Step 3)
  * Tutorials or walkthroughs with one step per page
* **Carousel-style full pages**
  * Full-screen banners or hero sections you can swipe
  * Feature highlights or campaigns laid out as separate pages


# Scrolling Widgets

Widgets that provide scrollable content areas and advanced scrolling behaviors.

## Overview

Scrolling widgets enable content that exceeds the screen size to be accessed through scrolling. These widgets handle various scrolling patterns and provide smooth user experiences for large content sets.

## Categories

### Basic Scrolling

* [**List View**](/ui-building-blocks/widgets/scrolling-widgets/listview) - Vertical scrolling list of items
* [**Grid View**](/ui-building-blocks/widgets/scrolling-widgets/gridview) - Scrollable grid layouts

### Advanced Scrolling

* [**Smart Scroll View**](/ui-building-blocks/widgets/scrolling-widgets/smart-scroll-view) - Advanced scrolling with custom behaviors
* [**Smart Scroll Group**](/ui-building-blocks/widgets/scrolling-widgets/smart-scroll-group) - Grouped scrolling content sections

### Scroll Components

* [**Pinned Header**](/ui-building-blocks/widgets/scrolling-widgets/pinned-header) - Sticky headers that remain visible while scrolling
* [**Refresh Indicator**](/ui-building-blocks/widgets/scrolling-widgets/refresh-indicator) - Pull-to-refresh functionality


# ListView

The **ListView** widget is a specialized layout widget designed for displaying scrollable lists efficiently. Unlike `Row` and `Column`, which can display both static and dynamic children, **ListView is exclusively for dynamic, data-driven lists**. It renders items lazily as they scroll into view, making it ideal for long or infinite lists.

{% embed url="<https://www.youtube.com/watch?v=mYZXD9Q3l8Y>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=mYZXD9Q3l8Y>

{% hint style="info" %}
The ListView widget works exactly like Flutter's `ListView.builder`. For an in-depth technical understanding, you can refer to the [ListView.builder documentation](https://api.flutter.dev/flutter/widgets/ListView/ListView.builder.html).
{% endhint %}

### Use Cases

Use **ListView** when you need a **scrollable list of widgets**, especially when the number of items can grow.

You’ll typically use **ListView** for:

* **Scrollable content lists**
  * Product lists, order history, notifications, messages
  * Settings options, menu items, FAQ entries
* **Dynamic / API-driven lists**
  * Data coming from an API, database, or backend
  * Infinite / long lists that the user can scroll through
* **Repeatable item layouts**
  * Same card design repeated for each item (e.g., blog posts, users, categories)

### Core Concepts

#### 1. Dynamic Children Only

The ListView widget **requires** a data source to function. You cannot add static children individually in the builder. Instead, you provide a `JsonArray` of data, and ListView automatically repeats a single child widget template for each item in that array.

This is fundamentally different from `Row` and `Column`, which support both static and dynamic children. ListView is purpose-built for data-driven lists.

#### 2. Single Item Type vs. Multiple Item Types

ListView can handle two types of lists:

* **Single Item Type (Uniform Lists)**: All items have the same structure and appearance. For example, a list of user profiles where each item displays a name, avatar, and bio in the same uniform layout.

  *This is the most common use case and is what you'll configure with a single child template.*
* **Multiple Item Types (Varied Lists)**: Items can have different structures. For example, a social media feed where some items are text posts, some are image posts, and some are ads—creating a varied mix of content types.

  *To build lists with varied item types, use a **Conditional Builder** as the child of the ListView. Inside the Conditional Builder, check the item type using `currentItem` and render different widgets accordingly.*

#### 3. Lazy Building & Performance

One of the key advantages of ListView is **lazy rendering**. Unlike `Row` or `Column`, which build all their children at once (even if they're off-screen), ListView only builds items as they scroll into view. This makes it highly performant for displaying hundreds or thousands of items.

{% hint style="success" %}
**Performance Tip:** For long scrollable lists, always use `ListView` instead of a scrollable `Row` or `Column` with dynamic children. ListView is optimized for this use case and will prevent performance bottlenecks.
{% endhint %}

***

### Data Source Property

The **Data Source** is the most critical property of ListView. It determines what data the list will display and how many items it will contain.

#### How to Configure the Data Source

1. In the properties panel, locate the **`Data Source`** field.
2. You can provide data in two ways:

**Option 1: Static JsonArray**

Enter a fixed JSON array directly:

```json
[
  {"name": "Apple", "price": 1.5},
  {"name": "Banana", "price": 0.8},
  {"name": "Orange", "price": 1.2}
]
```

This is useful for prototyping or displaying a small, unchanging list.

**Option 2: Dynamic Expression**

Bind the data source to an expression that returns a `JsonArray`:

* **From an API Response:** `${apiResponse.data.products}`
* **From App State:** `${appState.userList}`
* **From a Variable:** `${myListVariable}`

The ListView will automatically update whenever the data source changes.

#### Accessing Item Data with `currentItem`

Inside the child template of the ListView, you have access to a special variable called **`currentItem`**. This variable represents the data for the current item being rendered.

* **If your data is a list of objects** (e.g., `[{"name": "Apple"}, {"name": "Banana"}]`), access properties using dot notation: `${currentItem.name}`.
* **If your data is a list of simple values** (e.g., `["Apple", "Banana"]`), use `${currentItem}` directly.

You can also access the current index using `${index}`.

{% hint style="warning" %}
**Important:** The `Data Source` must always be a `JsonArray`. If you bind it to a non-array value or an invalid expression, the ListView will not render any items.
{% endhint %}

***

### Properties

#### Scrolling Behavior

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Controller</code></td><td>An optional <code>Scroll Controller</code> variable to programmatically control the scroll position. Learn how to create and use scroll controllers in the <a href="/pages/a8ZkBLioPk7BWmXQpQnj">Variables documentation</a>.</td></tr><tr><td><code>Allow Scroll</code></td><td>If <code>true</code>, the list will be scrollable. If <code>false</code>, scrolling is disabled. Default is <code>true</code>.</td></tr><tr><td><code>Scroll Direction</code></td><td>The direction in which the list scrolls. Can be <code>Vertical</code> (default) or <code>Horizontal</code>.</td></tr><tr><td><code>Reverse</code></td><td>If <code>true</code>, reverses the order in which items are displayed. For vertical lists, the first item appears at the bottom instead of the top. For horizontal lists, the first item appears on the right instead of the left. The scroll direction remains the same.</td></tr><tr><td><code>Initial Scroll Position</code></td><td>The initial position of the scroll view when the list loads. Can be <code>Start</code> (default) or <code>End</code>.</td></tr></tbody></table>

#### Layout & Sizing

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Shrink Wrap</code></td><td>If <code>true</code>, the ListView will size itself to fit its children instead of expanding to fill the available space. This is useful when nesting a ListView inside another scrollable widget, but use with caution as it can impact performance.</td></tr></tbody></table>

***

### Controller Integration

The `Controller` property allows you to programmatically control the scroll position of the ListView. This is done by creating a **Scroll Controller** variable and binding it to the ListView.

#### How to Use a Scroll Controller

1. **Create a Scroll Controller Variable**
   * Navigate to **Variables** in your project.
   * Add a new variable of type **Scroll Controller**.
   * Give it a name, such as `myScrollController`.
2. **Bind the Controller to the ListView**
   * Select the ListView widget.
   * In the `Controller` property, enter an expression referencing your variable: `${myScrollController}`.
3. **Control the Scroll Position**
   * Use the **Control Object** action to invoke methods on the controller (such as `jumpTo`, `animateTo`, etc.).
   * For a complete list of available controller methods and their usage, see the [Variables documentation](broken://pages/a8ZkBLioPk7BWmXQpQnj).

{% hint style="info" %}
**Tip:** You can use the same controller for both programmatic scrolling (via Control Object actions) and scroll-driven animations (via Animation Builder).
{% endhint %}

***

### Guides

For detailed step-by-step tutorials on common ListView patterns, see:

{% content-ref url="/pages/oSBeVceZT5MHGISVqGUq" %}
[Broken mention](broken://pages/oSBeVceZT5MHGISVqGUq)
{% endcontent-ref %}

{% content-ref url="/pages/9gFSOjPWz2WDFl8q4khk" %}
[Broken mention](broken://pages/9gFSOjPWz2WDFl8q4khk)
{% endcontent-ref %}

***

### Default Properties

The ListView widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

***

### Best Practices

* **Always provide a valid JsonArray** as the data source. ListView will not render without it.
* **Use ListView for long lists.** For short, fixed lists (fewer than 10 items), a `Column` with dynamic children may be simpler, but ListView is still recommended for consistency and future scalability.
* **Avoid nesting scrollable widgets** in the same direction (e.g., a vertical ListView inside a vertical scrollable Column). This can cause unexpected scrolling behavior. If you must nest, use `Shrink Wrap` carefully.
* **Optimize item templates.** Keep the child template as lightweight as possible to ensure smooth scrolling performance.
* **Handle empty states gracefully.** Always provide feedback when the list has no data to display.
* **Use Scroll Controllers** when you need programmatic scroll control, such as "scroll to top" buttons or scroll-driven UI changes.


# GridView

The **GridView** widget is a layout widget designed for displaying items in a scrollable, two-dimensional grid. It's perfect for photo galleries, product catalogs, dashboards, and any interface that requires items to be arranged in rows and columns.

{% embed url="<https://www.youtube.com/watch?v=jP0gh2qO3oI>" %}

Watch this on Youtube - <https://www.youtube.com/watch?v=jP0gh2qO3oI>

Unlike ListView, which displays items in a single direction, GridView arranges items both horizontally and vertically, creating a table-like structure.

{% hint style="info" %}
The GridView widget works exactly like Flutter's `GridView.builder`. For an in-depth technical understanding, you can refer to the official Flutter GridView documentation.
{% endhint %}

### Use Cases

Use **GridView** when you want to display items in a **grid layout** (rows + columns), instead of a single vertical list.

You’ll typically use **GridView** for:

* **Product & Catalog Grids**
  * E-commerce product cards
  * Category tiles (Men, Women, Electronics, etc.)
* **Image & Media Galleries**
  * Photo grids
  * Video thumbnails
  * Story/highlight tiles
* **Icon / Feature Menus**
  * “App launcher” style icons
  * Feature shortcuts on a dashboard (Orders, Wallet, Offers…)
* **Compact, Visual Collections**
  * Tags, cards, or any repeated visual item where grid makes better use of screen space than a list.

### Core Concepts

#### 1. Dynamic Children Only

The GridView widget **requires** a data source to function. You cannot add static children individually in the builder. Instead, you provide a `JsonArray` of data, and GridView automatically repeats a single child widget template for each item in that array.

This is fundamentally the same as ListView—GridView is purpose-built for data-driven grids and uses lazy rendering to efficiently display large datasets.

{% hint style="info" %}
**Note:** If you need a fixed grid layout with specific, hand-placed widgets (like a dashboard), use a **Column** with **Row** widgets inside, or use **Wrap** widget instead. GridView is designed exclusively for dynamic, data-driven content.
{% endhint %}

#### 2. Grid Structure: Rows & Columns

GridView arranges items in a grid defined by:

* **Cross Axis (Columns)**: The number of items per row, controlled by `Cross Axis Count`.
* **Main Axis (Rows)**: The vertical flow direction. Items wrap to a new row when the cross axis count is reached.

For example, with `Cross Axis Count: 3`, items are arranged in rows of 3 columns each.

#### 3. Lazy Building & Performance

When using a data source, GridView uses **lazy rendering**—it only builds grid items as they scroll into view. This makes it highly performant for displaying hundreds or thousands of items without impacting app performance.

{% hint style="success" %}
**Performance Tip:** For large grids with dynamic data, always use the Data Source property. GridView will only render visible items, keeping your app fast and responsive.
{% endhint %}

***

### Data Source Property

The **Data Source** is the most critical property of GridView. It determines what data the grid will display and how many items it will contain.

#### How to Configure the Data Source

1. In the properties panel, locate the **`Data Source`** field.
2. You can provide data in two ways:

**Option 1: Static JsonArray**

Enter a fixed JSON array directly:

```json
[
  {"name": "Product 1", "image": "url1.jpg", "price": 29.99},
  {"name": "Product 2", "image": "url2.jpg", "price": 39.99},
  {"name": "Product 3", "image": "url3.jpg", "price": 19.99}
]
```

This is useful for prototyping or displaying a small, unchanging grid.

**Option 2: Dynamic Expression**

Bind the data source to an expression that returns a `JsonArray`:

* **From an API Response:** `${apiResponse.data.products}`
* **From App State:** `${appState.galleryImages}`
* **From a Variable:** `${myGridData}`

The GridView will automatically update whenever the data source changes.

#### Accessing Item Data with `currentItem`

When using a data source, inside the child template you have access to:

* **`currentItem`**: The data for the current grid item being rendered.
  * For objects: `${currentItem.name}`, `${currentItem.price}`
  * For simple values: `${currentItem}`
* **`index`**: The zero-based index of the current item.

{% hint style="warning" %}
**Important:** When using a Data Source, it must be a `JsonArray`. If you bind it to a non-array value or an invalid expression, the GridView will not render any items.
{% endhint %}

***

### Properties

#### Grid Layout

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Cross Axis Count</code></td><td>(Required) The number of columns in the grid. This determines how many items appear per row. For example, <code>3</code> creates a 3-column grid.</td></tr><tr><td><code>Main Axis Spacing</code></td><td>The vertical space between rows in pixels. Controls the gap between items stacked vertically.</td></tr><tr><td><code>Cross Axis Spacing</code></td><td>The horizontal space between columns in pixels. Controls the gap between items placed side-by-side.</td></tr></tbody></table>

#### Scrolling Behavior

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Controller</code></td><td>An optional <code>Scroll Controller</code> variable to programmatically control the scroll position. Learn how to create and use scroll controllers in the <a href="/pages/a8ZkBLioPk7BWmXQpQnj">Variables documentation</a>.</td></tr><tr><td><code>Allow Scroll</code></td><td>If <code>true</code>, the grid will be scrollable. If <code>false</code>, scrolling is disabled. Default is <code>true</code>.</td></tr><tr><td><code>Shrink Wrap</code></td><td>If <code>true</code>, the GridView will size itself to fit its children instead of expanding to fill available space. Useful when nesting inside another scrollable widget, but use with caution as it can impact performance.</td></tr></tbody></table>

### Controller Integration

The `Controller` property allows you to programmatically control the scroll position of the GridView. This is done by creating a **Scroll Controller** variable and binding it to the GridView.

#### How to Use a Scroll Controller

1. **Create a Scroll Controller Variable**
   * Navigate to **Variables** in your project.
   * Add a new variable of type **Scroll Controller**.
   * Give it a name, such as `gridScrollController`.
2. **Bind the Controller to the GridView**
   * Select the GridView widget.
   * In the `Controller` property, enter an expression referencing your variable: `${gridScrollController}`.
3. **Control the Scroll Position**
   * Use the **Control Object** action to invoke methods on the controller (such as `jumpTo`, `animateTo`, etc.).
   * For a complete list of available controller methods and their usage, see the [Variables documentation](broken://pages/a8ZkBLioPk7BWmXQpQnj).

{% hint style="info" %}
**Tip:** You can use the same controller for both programmatic scrolling (via Control Object actions) and scroll-driven animations (via Animation Builder).
{% endhint %}

***

### Guides

For detailed step-by-step tutorials on common GridView patterns, see:

{% content-ref url="/pages/VbZ8kddjpUtQVp9aamYg" %}
[Broken mention](broken://pages/VbZ8kddjpUtQVp9aamYg)
{% endcontent-ref %}

{% content-ref url="/pages/JIRvtuYGTgcI2UCxcXST" %}
[Broken mention](broken://pages/JIRvtuYGTgcI2UCxcXST)
{% endcontent-ref %}

***

### Default Properties

The GridView widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

***

### Best Practices

* **Choose the right Cross Axis Count** for your content and screen size. Too many columns can make items too small; too few can waste space.
* **Control item sizing** through the child widget template dimensions.
* **Optimize item templates** to ensure smooth scrolling performance, especially for large grids.
* **Handle empty states** gracefully with clear messaging when no data is available.
* **Use spacing properties** to create visual breathing room between items.
* **Consider responsive design**: For different screen sizes, you might want to adjust `Cross Axis Count` dynamically.
* **Avoid nesting scrollable widgets** in the same direction to prevent scroll conflicts.


# Masonry Grid

The **Masonry Grid** widget is designed for layouts where items have **varying heights**, such as image galleries, content cards, and mixed-media feeds. Unlike a regular GridView, which maintains straight rows, Masonry Grid focuses on **filling vertical space efficiently** by stacking items in columns with different heights.

{% embed url="<https://youtu.be/xGrECzWFmdM?si=lRFCEsXzBX-GAfSh>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=xGrECzWFmdM>

This creates an organic, magazine-like layout where each column grows independently, minimizing empty gaps between items.

### Use Cases

A **Masonry Grid** is like a **Pinterest-style layout** where items are arranged in columns with **variable heights**, and they “stack” tightly without fixed row alignment.

Use **Masonry Grid** when:

* **Card Heights Vary**
  * Blog posts or articles with different text lengths
  * Product cards where some have more info/tags than others
  * Testimonial or review cards of different sizes
* **Image-Heavy Layouts**
  * Photo galleries with different image aspect ratios
  * Inspiration boards, portfolios, moodboards
  * UGC / social feeds where content size isn’t uniform
* **Pinterest-style Feeds**
  * Content discovery screens
  * Explore / inspiration pages (recipes, outfits, designs, etc.)

### Core Concepts

#### 1. Dynamic Children Only

The Masonry Grid is **data-driven**.\
You don’t manually drop multiple children inside it. Instead:

* You provide a **JsonArray** as the **Data Source**.
* You design **one child widget template**.
* Masonry Grid automatically repeats that template for each item in the array.

This is the same pattern as ListView and GridView:

* **No static, individually-placed children**
* **Only dynamic content**, generated from a data source
* Internally uses lazy building for performance

{% hint style="info" %}
Note: If you need a **fixed dashboard** layout with precise manual placement, use a `Column` + `Row`, or `Wrap` instead.\
Masonry Grid is specifically designed for dynamic, data-driven content with variable heights.
{% endhint %}

#### 2. Masonry Layout: Column-Based Flow

Masonry Grid arranges items into **columns**, not strict rows.

* **Cross Axis (Columns)**\
  The number of columns is controlled by **Cross Axis Count**.\
  For example, Cross Axis Count: 3 → 3-column masonry layout.
* **Main Axis (Vertical Growth)**\
  Items are placed in the column with the **current smallest height**.\
  This creates a **staggered**, Pinterest-like layout with minimal vertical gaps.

Key differences from GridView:

* GridView → row-based, rows are visually aligned.
* Masonry Grid → column-based, row lines are **not** aligned; each column grows at its own pace.

This makes Masonry ideal when:

* Items have **different heights** (e.g., different image aspect ratios, text lengths).
* You want a **natural, flowing** grid rather than strict, table-like rows.

#### 3. Lazy Building & Performance

Like ListView and GridView with a data source, Masonry Grid uses **lazy rendering**:

* Only items that are visible (or about to become visible) are built.
* This allows you to display **hundreds or thousands of items** smoothly.
* Scrolling remains performant even with mixed-height content.

{% hint style="success" %}
**Performance Tip:** For large masonry feeds, always bind to a **Data Source** and avoid putting heavy layouts inside each item template.
{% endhint %}

### Data Source Property

The **Data Source** defines what the Masonry Grid displays and how many items it contains.

#### How to Configure the Data Source

1. In the properties panel, locate the **Data Source** field.
2. Provide a value that evaluates to a **JsonArray**.

You can configure this in two ways:

**Option 1: Static JsonArray**

Use a fixed JSON array:

```json
[
  { "title": "Image 1", "url": "..." },
  { "title": "Image 2", "url": "..." }
]
```

Best for:

* Prototyping
* Simple demos or fixed, small sets of content

**Option 2: Dynamic Expression**

Bind the Data Source to an expression that returns a JsonArray:

* From an API response:\
  `${apiResponse.data.images}`
* From app state:\
  `${appState.galleryItems}`
* From a variable:\
  `${masonryData}`

When the underlying data changes, the Masonry Grid updates automatically.

#### Accessing Item Data with `currentItem`

Inside the item template, you can use:

* `currentItem` → The data for the current item.
* `index` → The zero-based index of the current item.

Examples:

* For objects:\
  `${currentItem.imageUrl}`, `${currentItem.title}`, `${currentItem.height}`
* For simple values:\
  `${currentItem}` (when the array contains strings, numbers, etc.)

Bind `currentItem` fields to images, text, badges, and other UI elements in your tile/card.

{% hint style="warning" %}
**Important:** The Data Source **must be a JsonArray**.\
If it’s not an array or expression is invalid, Masonry Grid will not render items.
{% endhint %}

### Properties

| Property             | Description                                                                                        |
| -------------------- | -------------------------------------------------------------------------------------------------- |
| `Data Source`        | JsonArray of items to render. Each entry becomes one masonry tile using the child widget template. |
| `Child Template`     | The single widget layout that is repeated for every item in the Data Source.                       |
| `Cross Axis Count`   | Number of **columns** in the masonry grid (e.g. 2 or 3 for mobile layouts).                        |
| `Main Axis Spacing`  | Vertical space (in pixels) between items stacked within the same column.                           |
| `Cross Axis Spacing` | Horizontal space (in pixels) between columns.                                                      |
| `Padding / Margin`   | Optional outer spacing around the entire masonry grid container.                                   |
| `Allow Scroll`       | When `true`, the grid can be scrolled by the user. When `false`, scrolling is disabled.            |
| `Shrink Wrap`        | If `true`, the grid sizes itself to fit its children instead of expanding to fill available space. |
| `Controller`         | Optional Scroll Controller variable used to programmatically control the scroll position.          |
| `Scroll Direction`   | Defines the axis along which the grid scrolls, typically vertical for masonry layouts.             |

### Controller Integration

The **Controller** property allows you to programmatically control the Masonry Grid’s scroll behavior using a **Scroll Controller** variable.

#### How to Use a Scroll Controller

1. **Create a Scroll Controller Variable**
   * Go to **Variables**.
   * Add a new variable of type **Scroll Controller**.
   * Name it, e.g. `masonryScrollController`.
2. **Bind the Controller to Masonry Grid**
   * Select the Masonry Grid widget.
   * In the **Controller** property, set:\
     `${masonryScrollController}`
3. **Control Scroll Position**
   * Use the **Control Object** action to call methods on the controller:
     * `jumpTo(...)`
     * `animateTo(...)`
     * And other supported scroll methods

For complete details on controller methods, see the **Variables documentation**.

{% hint style="info" %}
**Tip:**

The same controller can be used for:

* Programmatic scrolling
* Scroll-driven animations (e.g. fade on scroll, parallax) via Animation Builder.
  {% endhint %}

### Default Properties

The Masonry Grid widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Best Practices

* **Use Masonry for uneven heights**\
  Ideal for image galleries, cards with varying text length, and content feeds.
* **Choose Cross Axis Count carefully**
  * 2 or 3 columns for mobile
  * More columns for tablets and larger screens
* **Control item height via child**\
  Use aspect-ratio, images, or content length to define the natural height of each card.
* **Handle empty states**\
  If the Data Source is empty, show a separate empty state message or placeholder.
* **Avoid heavy layouts per item**\
  Keep your tile/card template lightweight for smooth scrolling.
* **Use spacing wisely**\
  Add enough spacing to keep the grid readable, especially with text-heavy cards.
* **Avoid nested scrolls in same direction**\
  Don’t put a vertical Masonry Grid inside another vertical scroll unless necessary and handled carefully.


# Smart Scroll View

The **Smart Scroll View** is used to make long content **scrollable intelligently**—often combining multiple scrollable areas (headers, lists, grids, sections) into **one smooth scrolling experience**.\
It can also help with things like sticky headers, collapsing areas, or coordinated scrolling.

{% embed url="<https://www.youtube.com/watch?v=HnC7rdMnt9A>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=HnC7rdMnt9A>

{% hint style="info" %}
Smart Scroll View usually works together with **Smart Scroll Group** (as its child) and **Pinned Header** (inside the group) to create advanced scrolling layouts.
{% endhint %}

### Use Cases

Use **Smart Scroll View** when you want:

* **Single smooth scroll for complex pages**
  * A screen with a banner → tabs → lists → sections, all scrolling together
  * Dashboard-style pages with multiple content blocks that should scroll as one
* **Sticky / collapsing areas**
  * A header that shrinks or sticks to the top while the user scrolls
  * Filters or tab bars that stay pinned while the content below scrolls
* **Mixed content in one scroll**
  * Text sections, images, carousels, and lists on the same page
  * Landing/marketing pages with multiple vertically stacked modules
* **Better UX than nested scrolls**
  * Avoid “scroll inside scroll” issues (e.g., ListView inside ScrollView)
  * Make scrolling feel natural and unified for the user

### Core Concepts

**Unified Scrolling**

Combines multiple child widgets (lists, grids, static sections) into one scrollable flow, so the user scrolls the entire page with a single gesture.

* Smart Scroll View is the **main scroll container**
* **Smart Scroll Group** is typically used as its child to hold all scrollable content in a structured way

**Scroll-Aware Behavior**

Can react to scroll position to:

* Pin headers or filters
* Trigger animations (e.g., fade/scale header)
* Show/hide UI (like a “Back to top” button)

When used with **Pinned Header**, Smart Scroll View ensures:

* Header stays visible when you scroll
* Content scrolls underneath the pinned area
* Transitions are smooth and coordinated

**Layout Flexibility**

Lets you mix:

* Static content (text, banners)
* Dynamic content (lists, grids)
* Special sections (carousels, cards)

All managed in a way that avoids scroll conflicts.

This is usually done by:

* Wrapping content inside a **Smart Scroll Group**
* Adding **Pinned Header** at the top of that group when you need a sticky section

#### **Data Source**

The Smart Scroll View widget has a **Data Source** property that can be used to dynamically generate children widgets. You can input either static data or dynamic data using expressions.

This is useful for:

* Creating repeated sections (cards, rows, list items)
* Binding dynamic content (from APIs, local data, etc.)
* Building complex scrollable layouts without manually duplicating widgets

### Relationship with Smart Scroll Group & Pinned Header

Smart Scroll View is designed to work closely with:

* **Smart Scroll Group (Child of Smart Scroll View)**
  * Acts as the main container for all scrollable content inside Smart Scroll View
  * Groups multiple widgets/sections into one logical scrollable block
  * Ensures that mixed content (headers, lists, banners, cards) scrolls smoothly as a single experience
* **Pinned Header (Child inside Smart Scroll Group)**
  * Placed at the top of a Smart Scroll Group
  * Stays fixed or "pinned" at the top while the rest of the content scrolls
  * Ideal for section titles, filters, tabs, or important CTAs that should always remain visible
  * See [Pinned Header documentation](/ui-building-blocks/widgets/scrolling-widgets/pinned-header) for detailed usage

{% hint style="success" %}
**Performance Tip:**

* `Smart Scroll View` = main scroll container
* `Smart Scroll Group` = scrollable content section inside it
* `Pinned Header` = sticky element inside the group that stays visible during scroll
  {% endhint %}

### **Properties**

| Property          | Description                                                           |
| ----------------- | --------------------------------------------------------------------- |
| `controller`      | An expression to control the scroll position of the view.             |
| `isReverse`       | If `true`, the scroll view scrolls in the opposite direction.         |
| `scrollDirection` | The direction in which the view scrolls (`Vertical` or `Horizontal`). |
| `allowScroll`     | If `true`, the view will be scrollable.                               |
| `dataSource`      | Data source for dynamically generating repeated child widgets.        |

> 📚 **Learn More**: To understand the underlying Flutter implementation, see the [Flutter CustomScrollView documentation](https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html).

### Supported Children

Smart Scroll View supports **all widgets** as children, but works best with sliver-based widgets for optimal performance and scrolling behavior.

**Recommended widgets for Smart Scroll View:**

* **Pinned Header** - Creates sticky headers that remain visible during scrolling
* **Smart Scroll Group** - Groups multiple scrollable sections together
* **Any other widgets** - Smart Scroll View can contain any Digia UI widgets

{% hint style="warning" %}
**Important Restrictions:**

* **Pinned Header** and **Smart Scroll Group** can only be used inside Smart Scroll View. Using them elsewhere will result in errors or unexpected behavior.
* These widgets require the sliver-based scrolling system that Smart Scroll View provides.
  {% endhint %}

### Default Properties

#### Layout

The Smart Scroll View widget supports the following layout properties:

* `width`
* `height`
* `padding`
* `margin`

#### Alignment

The Smart Scroll View widget supports the following alignment property:

* `align`

#### Visibility

The Smart Scroll View widget supports the following visibility property:

* `visible`


# Smart Scroll Group

The **Smart Scroll Group** is a **container widget** that groups multiple scrollable sections (slivers) into a single logical scrolling unit within a **Smart Scroll View**.\
It acts as the main content organizer for complex scrolling layouts.

{% embed url="<https://www.youtube.com/watch?v=HnC7rdMnt9A>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=HnC7rdMnt9A>

<figure><img src="/files/2eBJEJOohPIQE2v1OxoJ" alt="A hero image showing a refresh indicator with pull-to-refresh animation on a mobile screen." height="300"><figcaption><p>The Refresh Indicator widget provides pull-to-refresh functionality for scrollable content.</p></figcaption></figure>

{% hint style="info" %}
Smart Scroll Group works together with **Smart Scroll View** (as its parent) and **Pinned Header** (as its child) to create advanced scrolling layouts with sticky headers and coordinated scrolling.
{% endhint %}

### Core Concepts

**Sliver Grouping**

Smart Scroll Group uses Flutter's `SliverMainAxisGroup` to combine multiple slivers into a cohesive scrolling unit:

* **Slivers**: Special widgets optimized for scrolling (like `SliverList`, `SliverGrid`, `SliverAppBar`)
* **Main Axis Group**: Ensures all child slivers scroll together along the main axis
* **Unified Experience**: All content moves as one, preventing nested scroll conflicts

**Content Organization**

Typically contains:

* **Pinned Headers**: For sticky section titles or navigation
* **Scrollable Lists/Grids**: For dynamic content
* **Static Content**: Banners, cards, or other non-scrolling elements converted to slivers

**Parent-Child Relationship**

* **Parent**: Always placed inside a **Smart Scroll View**
* **Children**: Multiple slivers that should scroll together
* **Headers**: Can contain **Pinned Header** widgets for sticky behavior

### Relationship with Smart Scroll View & Pinned Header

Smart Scroll Group is designed to work closely with:

* **Smart Scroll View (Parent of Smart Scroll Group)**
  * Acts as the main scroll container that holds the Smart Scroll Group
  * Provides the overall scrolling behavior and physics
  * Manages the scroll controller and direction
* **Pinned Header (Child inside Smart Scroll Group)**
  * Placed at the top of scrollable content sections
  * Stays fixed or "pinned" at the top while other content scrolls
  * Ideal for section titles, filters, tabs, or important CTAs

{% hint style="success" %}
**Performance Tip:**

* `Smart Scroll View` = main scroll container
* `Smart Scroll Group` = groups slivers into one scrollable unit
* `Pinned Header` = sticky element that stays visible during scroll
  {% endhint %}

### Properties

Smart Scroll Group inherits properties from its parent Smart Scroll View and doesn't have additional configurable properties of its own.

> 📚 **Learn More**: To understand the underlying Flutter implementation, see the [Flutter SliverMainAxisGroup documentation](https://api.flutter.dev/flutter/widgets/SliverMainAxisGroup-class.html).

### Default Properties

#### Layout

The Smart Scroll Group widget supports the following layout properties:

* `width`
* `height`
* `padding`
* `margin`

#### Alignment

The Smart Scroll Group widget supports the following alignment property:

* `align`

#### Visibility

The Smart Scroll Group widget supports the following visibility property:

* `visible`

### Use Cases

Use **Smart Scroll Group** when you need to:

* **Group multiple scrollable sections**
  * Combine headers, lists, grids, and banners into one smooth scroll
  * Create dashboard-style layouts with multiple content blocks
* **Organize complex scrollable content**
  * Structure content with pinned headers and scrollable sections
  * Build landing pages with mixed content types
* **Create coordinated scrolling experiences**
  * Ensure all content scrolls together as one unified experience
  * Avoid "scroll inside scroll" conflicts


# Pinned Header

The **Pinned Header** widget creates a **sticky header** that remains fixed at the top of the scrollable area while the content below scrolls underneath it.\
It provides a persistent navigation or context area that stays visible during scrolling.

{% embed url="<https://www.youtube.com/watch?v=HnC7rdMnt9A>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=HnC7rdMnt9A>

<figure><img src="/files/RiUfiAOaG1O4b6EvVnrg" alt="A hero image showing a refresh indicator with pull-to-refresh animation on a mobile screen." height="300"><figcaption><p>The Refresh Indicator widget provides pull-to-refresh functionality for scrollable content.</p></figcaption></figure>

{% hint style="warning" %}
**Important**: Pinned Header **only works inside Smart Scroll View**. Using it outside of Smart Scroll View will result in an error or unexpected behavior.
{% endhint %}

### Core Concepts

**Sticky Positioning**

Pinned Header uses Flutter's sliver system to create a header that:

* **Stays fixed** at the top of the scrollable area
* **Allows content to scroll underneath** it
* **Maintains its position** regardless of scroll direction
* **Provides smooth transitions** when appearing/disappearing

**Sliver Integration**

As a sliver-based widget, Pinned Header:

* Works within `CustomScrollView` (which Smart Scroll View uses)
* Coordinates with other slivers for unified scrolling
* Handles complex scroll behaviors automatically
* Optimizes performance for large content

**Content Flexibility**

Can contain any widgets as children:

* Text titles and descriptions
* Buttons and action icons
* Custom layouts and components
* Images and branding elements

### Relationship with Smart Scroll View

Pinned Header is specifically designed to work within Smart Scroll View:

* **Parent Container**: Must be placed inside Smart Scroll View
* **Sliver Context**: Requires the sliver-based scrolling system
* **Coordination**: Works with Smart Scroll Group for complex layouts
* **Error Prevention**: Framework prevents incorrect usage

{% hint style="success" %}
**Best Practice**: Always place Pinned Header as the first child inside a Smart Scroll Group within Smart Scroll View for optimal sticky behavior.
{% endhint %}

### Properties

Pinned Header inherits properties from its parent Smart Scroll View and doesn't have additional configurable properties of its own.

> 📚 **Learn More**: To understand the underlying Flutter implementation, see the [Flutter SliverPersistentHeader documentation](https://api.flutter.dev/flutter/widgets/SliverPersistentHeader-class.html).

### Default Properties

#### Layout

The Pinned Header widget supports the following layout properties:

* `width`
* `height`
* `padding`
* `margin`

#### Alignment

The Pinned Header widget supports the following alignment property:

* `align`

#### Visibility

The Pinned Header widget supports the following visibility property:

* `visible`

### Use Cases

Use **Pinned Header** when you need:

* **Sticky section titles**
  * Chapter headers, category names, or section labels that stay visible
  * "Products", "Reviews", "Settings" headers in long content
* **Persistent navigation**
  * Tab bars or filter options that remain accessible while scrolling
  * Search bars or action buttons that shouldn't scroll away
* **Context preservation**
  * Important information that users need to reference while scrolling
  * Progress indicators or status information
* **Coordinated scrolling experiences**
  * Headers that work with scrollable content below them
  * Smooth transitions between pinned and unpinned states


# Paginated ListView

The **Paginated ListView** is a specialized list widget designed for handling large datasets by loading data in pages or chunks. Instead of loading all items at once, it fetches data incrementally as the user scrolls, providing a smooth infinite scroll experience.

This widget is essential for building feeds, search results, product listings, and any interface where the total dataset could be very large or infinite.

{% embed url="<https://youtu.be/Hr6MmvaS_PU?si=G3HtKEvO4wPIDYj2>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=Hr6MmvaS_PU>

{% hint style="info" %}
Paginated ListView automatically handles the complexity of pagination, including loading states, error handling, and triggering new page loads when the user scrolls near the end of the list.
{% endhint %}

### Use Cases

Paginated ListView is ideal for:

* **Social Media Feeds**: Load posts, comments, or notifications incrementally as users scroll.
* **E-commerce Product Listings**: Display thousands of products without loading everything upfront.
* **Search Results**: Show search results page by page, improving initial load time.
* **News Articles**: Load articles in batches for better performance.
* **User Directories**: Display large lists of users, contacts, or team members.
* **Transaction History**: Show financial transactions or order history with pagination.
* **Image Galleries**: Load images progressively to reduce initial bandwidth usage.

{% hint style="success" %}
**Performance Benefit:** By loading data in pages, you reduce initial load time, bandwidth usage, and memory consumption—especially critical for mobile apps with limited resources.
{% endhint %}

***

### How to Set Up a Paginated ListView

Setting up a Paginated ListView involves three main steps:

#### Step 1: Create a Paginated API Call

1. Navigate to the **API** section in your project.
2. Create a new API call that supports pagination.
3. Configure the API endpoint with pagination parameters (see [Pagination Variables](#pagination-variables) section below).
4. Test the API to ensure it returns paginated data correctly.

#### Step 2: Add the Paginated ListView Widget

1. Drag the **Paginated ListView** widget onto your canvas.
2. In the properties panel, select your paginated API in the **API Data Source** field.
3. Configure the pagination type and variables (explained below).

#### Step 3: Design the Item Template

1. Add a child widget to serve as the template for each list item.
2. Use `${currentItem}` to access data for each item.
3. Design your item layout (e.g., a container with text, images, buttons).

#### Step 4: Configure Loading Indicators

1. Add a `firstPageLoadingIndicator` widget (e.g., a circular progress indicator).
2. Add a `newPageLoadingIndicator` widget (e.g., a smaller loading spinner).
3. These will be shown while data is being fetched.

***

### Pagination Variables

Pagination variables control how the Paginated ListView communicates with your API to fetch successive pages of data. There are **three types of pagination** supported:

#### 1. Page-Based Pagination

In page-based pagination, you request data using a **page number**.

**How it works:**

* The API accepts a `page` parameter (e.g., `page=1`, `page=2`, `page=3`).
* Each request returns a specific page of results.
* The response typically includes the current page number and total pages.

**API Example:**

```
GET /api/products?page=1&limit=20
GET /api/products?page=2&limit=20
```

**Configuration:**

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>First Page Key</code></td><td>Expression that returns the starting page number. Typically <code>1</code>.</td></tr><tr><td><code>Next Page Key</code></td><td>Expression to extract the next page number from the API response. Example: <code>${response.body.nextPage}</code> or <code>${sum(response.body.currentPage, 1)}</code>.</td></tr><tr><td><code>Transform Items</code></td><td>Expression to extract the array of items from the response. Example: <code>${response.body.data}</code> or <code>${response.body.products}</code>.</td></tr></tbody></table>

**Example Response Structure:**

```json
{
  "currentPage": 1,
  "totalPages": 10,
  "nextPage": 2,
  "data": [
    {"id": 1, "name": "Product 1"},
    {"id": 2, "name": "Product 2"}
  ]
}
```

**When to use:** When your backend API uses page numbers and returns structured pagination metadata.

***

#### 2. Offset-Based Pagination

In offset-based pagination, you request data using an **offset** value (how many items to skip) and a **limit** (how many items to return).

**How it works:**

* The API accepts `offset` and `limit` parameters.
* `offset` tells the API how many records to skip.
* `limit` specifies how many records to return in this batch.
* You calculate the next offset by adding the limit to the current offset.

**API Example:**

```
GET /api/users?offset=0&limit=20   // First page: items 1-20
GET /api/users?offset=20&limit=20  // Second page: items 21-40
GET /api/users?offset=40&limit=20  // Third page: items 41-60
```

**Configuration:**

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>First Page Key</code></td><td>The starting offset value. Typically <code>0</code>.</td></tr><tr><td><code>Next Page Key</code></td><td>Expression to calculate the next offset. Example: <code>${sum(response.body.offset, response.body.limit)}</code> or <code>${sum(currentOffset, 20)}</code>.</td></tr><tr><td><code>Transform Items</code></td><td>Expression to extract the items array. Example: <code>${response.body.results}</code>.</td></tr></tbody></table>

**Example Response Structure:**

```json
{
  "offset": 0,
  "limit": 20,
  "total": 150,
  "results": [
    {"id": 1, "username": "user1"},
    {"id": 2, "username": "user2"}
  ]
}
```

**When to use:** Common with REST APIs and databases that support SQL-style LIMIT/OFFSET queries. Ideal for predictable datasets where you can calculate exact positions.

***

#### 3. Cursor-Based Pagination

In cursor-based pagination, you request data using a **cursor** token that points to the next set of results.

**How it works:**

* The API returns a cursor (or token) pointing to the next page.
* You pass this cursor in the next request to get the following batch.
* Cursors are typically opaque strings or tokens.
* More efficient than offset-based for large, frequently changing datasets.

**API Example:**

```
GET /api/posts?cursor=initial
GET /api/posts?cursor=eyJpZCI6MTAwfQ==
GET /api/posts?cursor=eyJpZCI6MjAwfQ==
```

**Configuration:**

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>First Page Key</code></td><td>The initial cursor value. Can be <code>null</code>, <code>""</code>, or <code>"initial"</code> depending on your API.</td></tr><tr><td><code>Next Page Key</code></td><td>Expression to extract the next cursor from the response. Example: <code>${response.body.nextCursor}</code> or <code>${response.body.pagination.next}</code>.</td></tr><tr><td><code>Transform Items</code></td><td>Expression to extract the items array. Example: <code>${response.body.items}</code>.</td></tr></tbody></table>

**Example Response Structure:**

```json
{
  "nextCursor": "eyJpZCI6MTAwfQ==",
  "hasMore": true,
  "items": [
    {"id": 50, "title": "Post Title 1"},
    {"id": 51, "title": "Post Title 2"}
  ]
}
```

**When to use:**

* Large datasets where items are frequently added/deleted (social feeds, real-time data).
* When you need consistent results even if data changes between requests.
* APIs that use cursor/token-based pagination (Facebook, Twitter, Stripe, etc.).

{% hint style="warning" %}
**Important:** The API must return `null`, `undefined`, or an empty cursor when there are no more pages. This tells the Paginated ListView to stop loading new pages.
{% endhint %}

***

### Properties

#### Data Source Configuration

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>API Data Source</code></td><td>(Required) The paginated API call to use for fetching data. This API should support pagination parameters.</td></tr><tr><td><code>Data Source</code></td><td>Optional static data or expression for testing. When using an API, this is typically not needed.</td></tr><tr><td><code>Transform Items</code></td><td>(Required) An expression that extracts the array of items from the API response. Example: <code>${response.body.data}</code>, <code>${response.body.results}</code>, or <code>${response.body.items}</code>.</td></tr></tbody></table>

#### Pagination Control

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>First Page Key</code></td><td>(Required) The initial value for the pagination parameter. For page-based: <code>1</code>. For offset-based: <code>0</code>. For cursor-based: <code>null</code> or initial token.</td></tr><tr><td><code>Next Page Key</code></td><td>(Required) Expression to extract or calculate the key for the next page from the API response. This determines what value gets sent in the next API request.</td></tr></tbody></table>

#### Scrolling Behavior

<table><thead><tr><th width="200">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Allow Scroll</code></td><td>If <code>true</code>, the list will be scrollable. Default is <code>true</code>.</td></tr><tr><td><code>Scroll Direction</code></td><td>The direction in which the list scrolls. Can be <code>Vertical</code> (default) or <code>Horizontal</code>.</td></tr><tr><td><code>Reverse</code></td><td>If <code>true</code>, reverses the order in which items are displayed. For vertical lists, the first item appears at the bottom instead of the top. For horizontal lists, the first item appears on the right instead of the left. The scroll direction remains the same.</td></tr><tr><td><code>Initial Scroll Position</code></td><td>The initial scroll position when the list loads. Can be <code>Start</code> (default) or <code>End</code>.</td></tr><tr><td><code>Shrink Wrap</code></td><td>If <code>true</code>, the list sizes itself to fit its children. Use with caution as it can impact performance.</td></tr></tbody></table>

#### Loading Indicators

<table><thead><tr><th width="250">Property</th><th>Description</th></tr></thead><tbody><tr><td><code>Show First Page Progress Indicator</code></td><td>If <code>true</code>, displays the <code>firstPageLoadingIndicator</code> widget while the initial page is loading.</td></tr><tr><td><code>Show New Page Progress Indicator</code></td><td>If <code>true</code>, displays the <code>newPageLoadingIndicator</code> widget while loading subsequent pages.</td></tr></tbody></table>

***

### Children Slots

The Paginated ListView widget has three child slots that you must configure:

#### 1. `children` (Item Template)

**Purpose:** The widget template used to render each item in the list.

**Configuration:**

* Add a single child widget (e.g., Container, Card, or custom component).
* This widget will be repeated for each item in the data.
* Use `${currentItem}` to access the data for each item.
* Use `${currentIndex}` to access the item's position in the list.

**Example:** A Container with:

* Text widget displaying `${currentItem.title}`
* Image widget showing `${currentItem.imageUrl}`
* Button with onClick action

#### 2. `firstPageLoadingIndicator`

**Purpose:** Widget displayed while the first page of data is being loaded (initial load).

**Configuration:**

* Typically a centered circular progress indicator.
* Can include loading text, skeleton screens, or placeholder content.
* Shown only on the very first load when no data is available yet.

**Example Widgets:**

* Circular Progress Indicator
* Linear Progress Bar
* Skeleton loader (multiple placeholder containers)
* Custom loading animation

#### 3. `newPageLoadingIndicator`

**Purpose:** Widget displayed at the bottom of the list while loading additional pages.

**Configuration:**

* Usually a smaller progress indicator.
* Appears at the end of the list when the user scrolls near the bottom.
* Should be subtle so it doesn't disrupt the user's scrolling experience.

**Example Widgets:**

* Small Circular Progress Indicator
* Horizontal loading bar
* Text: "Loading more..."
* Custom pagination loader

***

### Complete Setup Example

Here's a comprehensive example of setting up a Paginated ListView for a product catalog using page-based pagination:

#### 1. API Configuration

**Endpoint:** `https://api.example.com/products` **Method:** GET **Query Parameters:**

* `page`: Variable - `${pageNumber}` (integer)
* `limit`: Fixed value - `20`

#### 2. Paginated ListView Properties

* **API Data Source:** `getProducts` (your API call)
* **First Page Key:** `1`
* **Next Page Key:** `${response.body.pagination.nextPage}`
* **Transform Items:** `${response.body.data}`
* **Show First Page Progress Indicator:** `true`
* **Show New Page Progress Indicator:** `true`

#### 3. Children Configuration

**Item Template (`children`):**

* Container with padding
  * Row
    * Image: `${currentItem.imageUrl}`
    * Column
      * Text: `${currentItem.name}`
      * Text: `$${currentItem.price}`

**First Page Indicator (`firstPageLoadingIndicator`):**

* Column (centered)
  * Circular Progress Indicator
  * Text: "Loading products..."

**New Page Indicator (`newPageLoadingIndicator`):**

* Container (centered, small padding)
  * Circular Progress Indicator (smaller size)

***

### Accessing Item Data

Inside the `children` template, you have access to special variables:

<table><thead><tr><th width="180">Variable</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td><code>currentItem</code></td><td>The data object for the current list item.</td><td><code>${currentItem.name}</code>, <code>${currentItem.id}</code></td></tr><tr><td><code>currentIndex</code></td><td>The zero-based index of the current item in the list.</td><td><code>${currentIndex}</code> returns 0, 1, 2...</td></tr></tbody></table>

**For object arrays:**

```javascript
${currentItem.title}
${currentItem.user.name}
${currentItem.price}
```

**For simple arrays:**

```javascript
${currentItem}  // The value itself
```

***

### Handling End of Data

The Paginated ListView needs to know when there are no more pages to load. This is determined by the `Next Page Key` expression:

**When to stop loading:**

* When `Next Page Key` returns `null`
* When `Next Page Key` returns `undefined`
* When `Next Page Key` is empty or invalid

**Examples:**

**Page-based with hasMore flag:**

```javascript
${if(response.body.hasMore, response.body.nextPage, null)}
```

**Offset-based with total count:**

```javascript
${if(lt(sum(response.body.offset, response.body.limit), response.body.total), sum(response.body.offset, 20), null)}
```

**Cursor-based:**

```javascript
${response.body.nextCursor}  // API returns null when no more data
```

{% hint style="info" %}
Make sure your API properly signals when there are no more results by returning null for the next page/cursor, or by providing a flag like `hasMore: false`.
{% endhint %}

***

### Error Handling

When the API call fails (network error, timeout, or API error):

* The loading indicator disappears.
* The user can pull to refresh to retry.
* Already loaded items remain visible.
* Consider adding error state widgets for better UX.

**Best Practice:** Add error handling in your API call configuration and show appropriate error messages to users.

***

### Guides

For comprehensive examples and real-world implementations, see:

{% content-ref url="/pages/5DLvZ6mbyAaRiwZbXH5h" %}
[Broken mention](broken://pages/5DLvZ6mbyAaRiwZbXH5h)
{% endcontent-ref %}

This guide includes:

* **Social Media Feed** - Build infinite scroll feeds with cursor-based pagination
* **E-Commerce Product Catalog** - Create product listings with offset-based pagination
* **Search Results** - Implement search with page-based pagination
* Performance optimization tips and best practices

### Best Practices

* **Choose the right page size**: Balance between fewer requests (larger pages) and faster initial load (smaller pages). 20-50 items per page is common.
* **Show loading states clearly**: Users should always know when data is being fetched.
* **Handle errors gracefully**: Network issues are common on mobile. Provide retry mechanisms.
* **Test with slow networks**: Ensure loading indicators work properly even with slow connections.
* **Optimize item templates**: Keep item widgets lightweight for smooth scrolling performance.
* **Use cursor-based pagination** for real-time feeds where data changes frequently.
* **Implement pull-to-refresh**: Allow users to manually refresh the list (use Refresh Indicator widget).
* **Consider caching**: For offline support, cache paginated data locally.

***

### Default Properties

The Paginated ListView widget supports the **Layout** and **Appearance** sections from [Default Properties](/ui-building-blocks/widgets/default-properties).


# Refresh Indicator

{% embed url="<https://youtu.be/CrVFhq-ysl8?si=a8qPBbmDUVR24WN5>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=CrVFhq-ysl8>

The **Refresh Indicator** widget is used to trigger a **pull-to-refresh** action on scrollable content.\
When the user drags down from the top of a list or scroll view, a refresh spinner appears and an action (like an API call) is executed.

<figure><img src="/files/0Az7sqQJffaUdk1wRKIX" alt="A hero image showing a refresh indicator with pull-to-refresh animation on a mobile screen." height="300"><figcaption><p>The Refresh Indicator widget provides pull-to-refresh functionality for scrollable content.</p></figcaption></figure>

### Core Concepts

1. **Pull-to-Refresh Gesture**
   * The user **pulls down** at the top of a scrollable area.
   * When a threshold is reached, the **refresh action** is triggered (typically an API call or data reload).
2. **Loading Feedback**
   * A **spinner/indicator** is shown while the refresh is in progress.
   * Once the action completes, the indicator hides and the updated content is shown.
3. **Scroll Integration**
   * The Refresh Indicator usually wraps a **scrollable widget** (like a list or scroll view).
   * It listens to scroll gestures and only activates when the user is **at the top** of the content.
4. **Idempotent Action**
   * The refresh action is generally **safe to run multiple times** (re-fetch data, reload state) without breaking the UI, making it a friendly, repeatable user affordance.

### **Properties**

| Property           | Description                                                                                     |
| ------------------ | ----------------------------------------------------------------------------------------------- |
| `Show Indicator`   | Controls whether the refresh indicator is visible when a refresh is triggered.                  |
| `Color`            | The color of the progress indicator.                                                            |
| `Background Color` | The background color of the progress indicator.                                                 |
| `Displacement`     | The distance from the edge of the screen to the center of the progress indicator.               |
| `Edge Offset`      | The distance from the edge of the screen where the refresh indicator can be triggered.          |
| `Stroke Width`     | The thickness of the circular progress indicator's line.                                        |
| `Trigger Mode`     | How the refresh indicator is triggered. `onEdge` triggers it when the user pulls from the edge. |
| `On Refresh`       | The action to be executed when the user triggers a refresh.                                     |

### Child of Refresh Indicator

| Slot    | Description                                                                                                                        |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `child` | The single child widget that contains the scrollable content (like a ListView or ScrollView) that the refresh indicator will wrap. |

### Default Properties

The Refresh Indicator widget does not have the standard default properties. Its behavior is primarily controlled by the properties listed above.

### Use Cases

Use **Refresh Indicator** when you want the user to:

* **Manually refresh data**
  * Update a product list, feed, or timeline
  * Refresh notifications, messages, or activity logs
  * Reload dashboard stats or reports
* **Recover from stale or failed data**
  * Let users retry after an error by pulling to refresh
  * Give control when auto-refresh is not enough or not desired

Anywhere you show **scrollable, data-driven content** (ListView, GridView, Smart Scroll View, etc.), adding a Refresh Indicator improves the experience.


# Media & Async

Widgets for handling media content and asynchronous operations.

## Overview

Media & Async widgets manage content that loads asynchronously or requires special handling. These widgets provide loading states, error handling, and smooth integration of media and dynamic content.

## Categories

### Asynchronous Content

* [**Future Builder**](/ui-building-blocks/widgets/media-async-widgets/future-builder) - Builds UI based on Future results
* [**Stream Builder**](/ui-building-blocks/widgets/media-async-widgets/stream-builder) - Builds UI based on Stream data

### Media Content

* [**Lottie Animation**](/ui-building-blocks/widgets/media-async-widgets/lottie-animation) - Animated Lottie files
* [**HTML View**](/ui-building-blocks/widgets/media-async-widgets/htmlview) - Render HTML content

### Animation & Effects

* [**Animated Switcher**](/ui-building-blocks/widgets/media-async-widgets/animated-switcher) - Smooth transitions between widgets
* [**Animation Builder**](/ui-building-blocks/widgets/media-async-widgets/animation-builder) - Custom animation sequences
* [**Opacity**](/ui-building-blocks/widgets/media-async-widgets/opacity) - Fade and transparency effects


# HTML View

The **HTML View** widget renders a string of HTML content inside your app.\
It’s useful when you want to display **rich text content** that comes from a server, CMS, or external source in HTML format, without manually building UI with multiple Text widgets.

{% embed url="<https://www.youtube.com/watch?v=MOUqbzSAOAs>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=MOUqbzSAOAs>

### Core Concepts

The HTML View widget:

* Takes a **raw HTML string** from the `content` property.
* Parses it into a styled widget tree.
* Renders it as readable, formatted text inside your app.
* Allows you to **override styles** for specific tags like `<body>`, `<span>`, and `<p>` using style override properties.

This is ideal when:

* Your backend or CMS returns HTML.
* You need to show “About”, “Terms & Conditions”, “Help”, or “Blog-like” content in the app.
* You don’t want to manually convert HTML into multiple UI components.

### Properties

| Property          | Description                                                                                                                       |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `Content`         | The HTML content string and shrinkwrap setting. The content includes the HTML string and whether the widget should shrink to fit. |
| `Body Style`      | Style overrides for the `<body>` tag, including font, color, and other text styling properties.                                   |
| `Span Style`      | Style overrides for `<span>` tags, allowing customization of inline text styling.                                                 |
| `Paragraph Style` | Style overrides for `<p>` tags, controlling paragraph-level text formatting.                                                      |

### Children of HTMLView

This is a leaf widget that does not support children.

### Default Properties

The HTML View widget supports the following section of [Default Properties](/ui-building-blocks/widgets/default-properties):

**Layout**

* `width`
* `height`
* `padding`
* `margin`
* `align`

### Use Cases

The **HTML View** widget is used to render **HTML content** (like `<p>`, `<h1>`, `<a>`, `<img>`, `<ul>`, etc.) directly inside your app.

Use **HTML View** when you want to:

* **Display content from the web or CMS**
  * Blog posts, landing page sections, marketing content
  * Help center articles, FAQs, privacy policy, terms & conditions
* **Render pre-built HTML snippets**
  * Email templates, notification templates, or CMS blocks
  * Embedded descriptions from third-party tools or dashboards
* **Show rich formatted user/admin content**
  * Descriptions, announcements, or banners stored as HTML in your backend
  * Legacy content that already exists in HTML (no need to convert to Markdown or rich text manually)
* **Preview HTML-based layouts**
  * Quick preview of newsletters, web copy, or small HTML fragments inside the app


# Lottie Animation

The **Lottie Animation** widget plays vector animations from Lottie JSON files.\
It’s a powerful way to add smooth, high-quality animations to your app with **small file sizes** and **scalable graphics** that look sharp on all screen densities.

You can use it for success states, empty states, onboarding, loaders, and delightful micro-interactions throughout your app.

{% embed url="<https://www.youtube.com/watch?v=bhhS_HO3dzA>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=bhhS_HO3dzA>

### Core Concepts

The Lottie Animation widget:

* Loads a **Lottie JSON file** (vector animation) from:
  * A **network URL**, or
  * A **local asset** bundled with your app.
* Renders the animation as a widget with configurable `width`, `height`, and `fit`.
* Controls **how** and **how long** the animation plays using:
  * `animate`
  * `animationType`
  * `frameRate`

Since Lottie animations are vector-based:

* They stay **crisp and smooth** at any size.
* File sizes are much smaller than equivalent video or GIF.
* They’re ideal for modern, lightweight UI animations.

### Properties

| Property        | Description                                                                                                              |
| --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `sourceType`    | The source of the Lottie file. Can be `network` (from a URL) or `asset` (from local project files).                      |
| `lottiePath`    | The URL or asset path for the Lottie JSON file.                                                                          |
| `width`         | The width of the animation widget.                                                                                       |
| `height`        | The height of the animation widget.                                                                                      |
| `fit`           | How the animation should be inscribed into the widget's bounds (e.g., `contain`, `cover`).                               |
| `alignment`     | The alignment of the animation within its bounds.                                                                        |
| `animate`       | If `true`, the animation will play automatically.                                                                        |
| `animationType` | The playback mode: `loop` (repeats indefinitely), `once` (plays one time), or `boomerang` (plays forward then backward). |
| `frameRate`     | The frame rate at which to play the animation.                                                                           |

### Default Properties

The Lottie Animation widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **Lottie Animation** when you want to:

* **Delightful Loading & Empty States**
  * Animated loaders instead of plain spinners
  * Fun illustrations for “No data”, “No internet”, or “Success” states
* **Micro-interactions**
  * Like/heart animations on tap
  * Button press, toggle, or success tick animations
  * Animated checkmarks, confetti, or subtle icon motions
* **Onboarding & Walkthroughs**
  * Animated visuals on onboarding screens
  * Feature highlights with motion to draw attention
* **Branding & Visual Polish**
  * Logo reveals, transitions, and branded animations
  * Animated headers or backgrounds to make screens feel premium


# Future Builder

The **Future Builder** widget lets you build UI based on the result of a **Future**—that is, any **asynchronous operation** like an API call, database query, file read, or long-running computation.\
It listens to the Future, and as its state changes (loading → completed → error), the Future Builder can show **different widgets for each state**.

{% embed url="<https://youtu.be/uXSEyrUQdUw?si=9CMQcMQ0seG8cVSp>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=uXSEyrUQdUw>

### Core Concepts

**a) Future-Driven UI**\
A **Future** represents a value that will be available later (success or error).\
The Future Builder:

* Takes a Future as input
* Listens to its state
* Rebuilds its child when the Future:
  * Is waiting
  * Completes with data
  * Completes with an error

So your UI is driven directly by async state, instead of manual flags.

**b) States and UI**\
Future Builder maps **states → UI**:

* Loading → show spinner, shimmer, or placeholder
* Error → show error message / retry
* Data → show final content

You decide what to show in each case; Future Builder switches automatically as the Future resolves.

**c) Actions**\
Actions around a Future Builder usually let you:

* Trigger the Future (e.g., call API)
* React to the result (update state, store data, navigate)
* Handle errors (show message, log, offer retry)

**d) Async Controller**\
The Async Controller prevents unnecessary refetching when the Future Builder rebuilds. It caches the result and only refetches when explicitly invalidated, improving performance for expensive async operations.

**e) Child of Future Builder**\
The **child** is typically a conditional or data-aware widget that:

* Receives the current **future state** and **data**
* Chooses what to render (loading, error, data UI)

{% hint style="info" %}
This keeps the Future Builder’s role focused on:

**Listening to the Future and exposing its state**,\
while the child takes care of **how the UI looks** for each state.
{% endhint %}

### **Properties**

| Property          | Description                                                                                                                                         |
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Initial Data`    | The initial data to use while the Future is still resolving. This can be used to show cached or placeholder content before the real result arrives. |
| `AsyncController` | An Async Controller variable that manages async state and prevents unnecessary refetching. Use this to control when the Future should re-execute.   |
| `Data Source`     | Defines the **API endpoint / configuration** that the Future Builder will call to fetch data.                                                       |

### **Actions**

| Property     | Description                                                                                                                                                                                                                                                                                                                            |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `On Success` | Action triggered when the Future completes successfully. Receives an object with `futureState: 'completed'`, `futureValue` (the response data), and `response` (full API response details including statusCode, headers, etc.). Common uses: update UI state, store data, navigate to another screen, or trigger follow-up operations. |
| `On Error`   | Action triggered when the Future completes with an error. Receives an object with `futureState: 'error'`, `futureValue` (null), and `response` (error details including statusCode, headers, error message, etc.). Common uses: show an error notification, log the error, enable retry, or switch to fallback behavior.               |

### Child of Future Builder

| Slot    | Description                                                                                                                                                                                                                                                                                                                                                                                         |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `child` | The widget to build based on the state of the future. The child widget has access to the following variables: `futureState` (`'loading'`, `'error'`, `'completed'`), `futureValue` (the data or initial data), and `response` (API response details or error information). You can access these variables directly by name or with the Future Builder name prefix: `futureBuilderName.futureState`. |

#### Default Properties

The Future Builder widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **Future Builder** when your UI depends on data that arrives later, for example:

* **Fetching Data from APIs**\
  Load user profile, products, or dashboard data and:
  * Show a loader while waiting
  * Show an error UI if the call fails
  * Show the actual content when data arrives
* **Local Async Operations**
  * Read from local/secure storage
  * Load cached config or initialization data
  * Run non-blocking computations
* **One-Time Async Flows**
  * Run setup logic when the screen opens
  * Wait for token refresh or session validation
  * Do pre-loading before showing the main screen


# Stream Builder

The **StreamBuilder** widget builds its UI based on the **latest snapshot** from a **Stream**.\
It’s ideal for showing **data that changes over time**, such as real-time updates from WebSockets, Firebase, or any other continuous data source.\
Whenever the stream emits new data, the StreamBuilder **automatically rebuilds** its child.

{% embed url="<https://www.youtube.com/watch?v=0k-ImIalt60>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=0k-ImIalt60>

### Core Concepts

**a) Stream-Driven UI**

A **Stream** provides a sequence of **async values over time** (data events, errors, completion).

The **StreamBuilder**:

* Listens to the provided **Stream**
* Receives a new **snapshot** whenever:
  * New data arrives
  * An error occurs
  * The stream completes
* Rebuilds its child every time the snapshot changes

This makes the UI directly driven by **live stream events** instead of manual updates.

**b) Snapshot-Based Rendering**

The child of StreamBuilder typically reads from a **snapshot** that can include:

* Current **connection state** (waiting, active, done)
* Latest **data**
* Any **error** emitted by the stream

You can use these to:

* Show a **loading** UI when the stream is connecting / waiting
* Show an **error** UI if there’s a problem
* Show **live data** UI when values are being received

**Properties**

| Property       | Description                                                                                                                                                                 |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Initial Data` | The initial data that will be used to create the child widget before any data is received from the stream.                                                                  |
| `Controller`   | A StreamController variable or any app state variable that provides a stream to listen to.                                                                                  |
| `On Success`   | An action to be executed when the stream emits a new value. Receives an object with `streamState: 'listening'`, `streamValue` (the new data), and other stream information. |
| `On Error`     | An action to be executed when the stream emits an error. Receives an object with `streamState: 'error'`, `error` (the error details), and other stream information.         |

#### Child of StreamBuilder

| Slot    | Description                                                                                                                                                                                                                                                                                                                                                      |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `child` | The widget to be rebuilt whenever the stream emits a new value. The child has access to `streamState` (e.g., `'loading'`, `'error'`, `'listening'`, `'completed'`), `streamValue` (the latest data), and `error` (if an error occurred). You can access these variables directly by name or with the StreamBuilder name prefix: `streamBuilderName.streamState`. |

### Default Properties

The StreamBuilder widget supports only **Layout** section of [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **StreamBuilder** when you need **live / real-time** or continuously updating UI, for example:

* **Real-time feeds**
  * Live chat messages
  * Activity feeds
  * Notifications stream
* **Live data dashboards**
  * Realtime analytics or metrics
  * Stock prices, crypto prices, or counters
  * Sensor or IoT readings
* **Realtime backend updates**
  * Firebase streams (Firestore, Realtime DB)
  * WebSocket subscriptions
  * Streaming APIs or event sources

Anywhere data keeps changing over time and you want the UI to **react automatically**, StreamBuilder fits.


# Animation Builder

The Animation Builder widget is a powerful tool for creating custom animations. It listens to a `controller` (PageController or ScrollController) and rebuilds its child widget whenever the `controller`'s value changes. This allows you to create animations that are driven by scrolling or paging interactions.

{% embed url="<https://www.youtube.com/watch?v=NqFTy8HhiC8>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=NqFTy8HhiC8>

### Core Concepts

1. **Controller-Driven Rebuilds**
   * The `Controller` property accepts a **PageController or ScrollController**.
   * Whenever the controller's value changes (scroll position or page index), the **Animation Builder rebuilds its child**.
2. **Value-Based Animations**
   * Inside the child, you can access the controller's current values (scroll offset, page index) to drive animations.
   * This allows creating animations that respond to scroll or page changes.
3. **Separation of Logic & UI**
   * The controller handles **scrolling or paging behavior**.
   * The Animation Builder handles **how those changes are visualized** in the UI.

### Properties

| Property     | Description                                                                                                                                                            |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Controller` | A PageController or ScrollController variable that provides scroll or page values. When this value changes, the child widget of the Animation Builder will be rebuilt. |

#### Child of Animation Builder

| Slot    | Description                                                                                                                                                                  |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Child` | The widget to be rebuilt whenever the `controller`'s value changes. The child can access the controller's current values (scroll offset or page index) to create animations. |

### Default Properties

The Animation Builder widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **Animation Builder** when you want:

* **Scroll-based animations**
  * Animate elements as the user scrolls (fade in/out, parallax, scale changes).
* **Page-based animations**
  * Animate transitions between pages in a PageView.
* **Interactive animations**
  * Tie animations to **scroll position** or **page index** by using PageController or ScrollController values.
* **Chained / complex animations**
  * Create coordinated effects across multiple widgets based on scroll or page changes.


# Animated Switcher

The **Animated Switcher** widget provides a **smooth animated transition** between **two child widgets**.\
When the `Show First Child` (or equivalent toggle) changes, it animates from one child to the other instead of instantly swapping them.\
This is great for making state changes feel **polished and fluid**.

{% embed url="<https://www.youtube.com/watch?v=ZM1E2vqGhqQ>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=ZM1E2vqGhqQ>

<figure><img src="/files/AVwlBVhoWySlnByNqxeQ" alt="A hero image showing a switch widget in on and off states with customizable styling."><figcaption><p>The Switch widget provides intuitive binary toggle controls for settings and preferences.</p></figcaption></figure>

Any time you’re swapping **one widget for another**, Animated Switcher makes it feel smooth instead of abrupt.

{% embed url="<https://youtu.be/ZM1E2vqGhqQ?si=GzPPxVINNHCuqU-F>" %}

### Core Concepts

1. **Two Children, One Visible**
   * The Animated Switcher conceptually manages **two children**:
     * **First child**
     * **Second child**
   * A boolean-like property (e.g., `Show First Child`) controls **which one is currently visible**.
2. **Animated Transition**
   * When the visible child changes, Animated Switcher:
     * **Animates out** the old child
     * **Animates in** the new child
   * The transition can use default or configured animations (fade, scale, etc. depending on your implementation).
3. **State-Based UI Swap**
   * Rather than manually handling animations, you just:
     * Define **two states as two widgets**
     * Let Animated Switcher handle the **transition** when the state flag changes.

### Properties

| Property             | Description                                                                                                                                  |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `Animation Duration` | The duration of the animation in milliseconds. This controls how long the transition between the two children takes.                         |
| `Show First Child`   | A boolean value that determines which child is currently visible. If `true`, the first child is shown; otherwise, the second child is shown. |
| `Switch In Curve`    | The animation curve used for the incoming child during transition.                                                                           |
| `Switch Out Curve`   | The animation curve used for the outgoing child during transition.                                                                           |

### Children of Animated Switcher

| Slot          | Description                                                                                                       |
| ------------- | ----------------------------------------------------------------------------------------------------------------- |
| `firstChild`  | This is the first child of the animated switcher. When `showFirstChild` is true, this widget will be displayed.   |
| `secondChild` | This is the second child of the animated switcher. When `showFirstChild` is false, this widget will be displayed. |

### Default Properties

The Animated Switcher widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **Animated Switcher** when you want to **visually transition between two states** of a UI element, for example:

* **Loading → Content**
  * Show a loading spinner while data is fetching
  * Smoothly transition to the actual content once data is ready
* **On / Off States**
  * Toggle between “Follow” / “Following” buttons
  * Switch between active/inactive, enabled/disabled, or compact/expanded views
* **Empty State → Data State**
  * Show a “No items” placeholder
  * Animate into a list or grid when items become available
* **Mode Toggling**
  * Switch between:
    * Grid view / List view
    * Basic view / Detailed view
    * Light mode variant / Dark mode variant of an element


# Opacity

<figure><img src="/files/UbS5iMHBP8Oq9kVUdJ9p" alt="A hero image showing a switch widget in on and off states with customizable styling."><figcaption><p>The Switch widget provides intuitive binary toggle controls for settings and preferences.</p></figcaption></figure>

The `Opacity` widget in Flutter is used to control the transparency level of its child widget. It is a fundamental layout widget that allows you to visually fade or hide elements, crucial for creating subtle visual hierarchy, smooth transitions, and dynamic user interfaces.

{% embed url="<https://www.youtube.com/watch?v=gUJhjCnKvvo>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=gUJhjCnKvvo>

### Core Concepts

The `Opacity` widget works by inserting a transparent layer between its parent and child, effectively painting the child's content with the specified level of transparency.

1. Rendering vs. Interaction: The `Opacity` widget renders its child transparently, but it still occupies the same space in the layout. More importantly, the widget does not prevent its child from receiving hit-testing events (like taps or gestures) unless the opacity is set to $$ $0.0$ $$.
2. Performance Note: While simple, changing the opacity requires a save-layer operation during rendering, which can be computationally expensive if applied to very complex widgets.

### Properties

The `Opacity` widget has a minimal set of properties focused solely on transparency control and semantics.

| Property                 | Description                                                                                                                               |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `opacity`                | The transparency level of the child. `1.0` = fully visible, `0.0` = fully invisible. Must be between `0.0` and `1.0`.                     |
| `alwaysIncludeSemantics` | If `true`, the child stays in the accessibility/semantics tree even when fully transparent (`opacity = 0.0`). Helpful for screen readers. |

### Child of Opacity

| Slot    | Description                                                                                                                   |
| ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| `child` | The single child widget whose opacity will be controlled. It keeps its layout space even when partially or fully transparent. |

### Layout & Behaviour

The `Opacity` widget always takes the full size required by its `child`.

**`alwaysIncludeSemantics`**

This property is critical for accessibility.

* If `alwaysIncludeSemantics` is set to `false` (default), when `opacity` is $0.0$ , the child is invisible *and* is removed from the accessibility tree. This means screen readers will ignore the content.
* If set to `true`, even when `opacity` is $0.0$, the child's information remains in the accessibility tree, allowing screen readers to announce the content (e.g., a hidden label or image description).

#### Default Properties <a href="#default-properties" id="default-properties"></a>

The Opacity widget supports all [Default Properties](/ui-building-blocks/widgets/default-properties).

### Use Cases

Use **Opacity** when you want to:

* **Fade UI elements in/out visually**
  * Dim a background while showing a dialog or overlay
  * Fade out a button or label instead of removing it abruptly
* **Create subtle visual hierarchy**
  * Make secondary or disabled content look less prominent
  * Soften background elements behind primary content
* **Prep or transition UI states**
  * Hide something visually but keep its layout in place to avoid jumps
  * Combine with animations (or `AnimatedOpacity`) for smooth transitions
* **Accessibility-related visibility**
  * Keep content visually hidden but still accessible to screen readers (with `alwaysIncludeSemantics`)


# Default Properties

This page outlines the **Default Properties** available to widgets in Digia Studio. These properties are grouped into three main sections:

1. **Layout** – for controlling spacing, dimensions, and alignment
2. **Appearance** – for customizing the visual presentation
3. **Interactions** – for attaching user actions

Widgets may support all or only some of these sections depending on their nature. Refer to each widget’s documentation to confirm which sections apply.

***

### Layout Properties

These properties define how the widget is laid out within its parent.

| Property  | Description                                                                              |
| --------- | ---------------------------------------------------------------------------------------- |
| `width`   | Sets the fixed width of the widget. Accepts numeric or percentage values.                |
| `height`  | Sets the fixed height of the widget. Accepts numeric or percentage values.               |
| `padding` | Space **inside** the widget, between its content and border. Can be uniform or per-side. |
| `margin`  | Space **outside** the widget, between it and other widgets.                              |
| `align`   | Alignment within the parent container (e.g., `topLeft`, `center`, `bottomRight`).        |

***

### Appearance Properties

These properties control how the widget looks.

| Property             | Description                                                                          |
| -------------------- | ------------------------------------------------------------------------------------ |
| `bgColor`            | Background color of the widget in HEX format.                                        |
| `borderRadius`       | Controls the curvature of the widget’s corners. Can be a single or per-corner value. |
| `border`             | Contains all border-related styling.                                                 |
| `border.borderWidth` | Thickness of the border in pixels.                                                   |
| `border.borderColor` | Color of the border in HEX format.                                                   |
| `border.borderType`  | Pattern type of the border (`solid`, `dashed`).                                      |
| `border.strokeAlign` | Whether the border is drawn `inside`, `center`, or `outside` the widget’s bounds.    |

***

### Interactions

These properties define user-triggered actions.

| Property  | Description                                                                                                       |
| --------- | ----------------------------------------------------------------------------------------------------------------- |
| `onClick` | Action to be triggered when the widget is tapped or clicked. Supports navigation, state changes, animations, etc. |

***

Use these properties to control layout, appearance, and interactivity consistently across widgets in your application.

For examples and usage, refer back to each individual widget’s documentation.


# Widget Commonalities

While working with widgets, you may find some features or properties that are common across various widgets. This page will guide you on how to implement these common functionalities or modify properties that are uniformly applicable to multiple widgets.

## Widget Default Properties

### 1. Visible

Cannot make up your mind if you want to keep the Widget or not? Use this handy option to turn off the visibility of the Widget, and take better decisions with and without the Widget.

### 2. Widget Alignment

Use this option to align the position of the Widget, you can choose from 9 options: Top Left, Top Center, Top Right, Center Left, Center, Center Right, Bottom Left, Bottom Center and Bottom Right.

### 3. Styling Properties

#### Padding

Padding is the empty space around the outer side of the widget. You can add values on specific sides, Left, Top, Right and Bottom.

#### Margin

Margin is the outer space around the box. You can customize values on specific sides, Left, Top, Right and Bottom.

<figure><img src="/files/b8sDvzonQyuKeg6qgyBD" alt=""><figcaption><p>Illustration for Padding, Border and Margin</p></figcaption></figure>

#### Background Color

Want to set the background color for your widget? You can choose from default Theme Colors, or Custom Colors, or choose using HEX Values and Opacity.

#### Alignment

Use this option to align the position of the Widget, you can choose from 9 options: Top Left, Top Center, Top Right, Center Left, Center, Center Right, Bottom Left, Bottom Center and Bottom Right.

***

## Adding border

To add a border to any widget:\
First choose the Widget, go to Default Properties, and customize the below properties to add a border.

#### Border Style

You can choose a **Solid** Border Style, or None.

#### Border Width

Define the width of the Border using this property.

#### Border Color

Change the color of your border using this property. Choose from default theme colors, or custom colors using HEX values and opacity.

#### Border Radius

To create a rounded border, use this property. Customize border radius values for top-left, top-right, bottom-right and bottom-left.

***

#### Width

If you want your widget to be set to a fixed width on the screen, use this property. You can enter a value in either Pixels (PX), or in Percentage (%) for responsiveness.

#### Height

Want to set your widget to a fixed height? Use this property. Enter a value either in Pixels (PX), or in Percentage (%).

### 4. Event Handlers

Read more about adding Event Handlers [here](/logic-and-interaction/event-handlers).

***

## Text Span Style Properties

This contains customizations for your text.

#### Font Token

You can choose from the preset Typography, or set custom Fonts from the [Typography ](/ui-building-blocks/design-system/typography)screen. The font size can be chosen quickly with this.

#### Custom Values

By turning this toggle ON, you can create a custom font for your text, by choosing the **Font Family**, **Font Weight**, **Font Style** and **Line Height**.

1. Font Family\
   Choose from Nunito, Roboto, Poppins and Inter.
2. Font Weight\
   Options available are Thin (100), Extra Light (200), Light (300), Regular (400), Medium (500), Semi Bold (600), Bold (700), Extra Bold (800) and Black.
3. Font Style\
   Turn the toggle ON to change the text from Normal to *Italic*.
4. Font Weight\
   If you want to set the font's weight manually, you can enter a value here.
5. Line Height\
   The *line*-*height* property sets the height of a line box. It's commonly used to set the distance between lines of text.

#### Text Color

Choose the color you want to display your text with.

#### Text Background Color

Want to set the background color of the text? With this option, the color will only be applied on the background of the text.

#### Text Decoration

Choose from various options, Line Underneath, Line Above and Line Through.

#### Text Decoration Color

Customize the color for the Text Decoration.

#### Text Decoration Style

Choose how you want your Text Decoration to appear, Dashed, Dotted, Double or Solid.

***

## Set Max Lines

When you have a long text that won't fit in a single line, it will start from the new line. This is an optional maximum number of lines for the text to span, wrapping if necessary. If the text exceeds the given number of lines, it will be truncated.

To set the max lines, move to the Widget Properties panel -> enter the **Max Lines** value.

***

## Set Text Overflow

This deals with how overflowing text should be handled. There are 4 options present:

1. clip → Clips the overflowing text to fix its container.
2. fade → Fades the overflowing text to transparent.
3. ellipsis → Use an ellipsis to indicate that the text has overflowed.
4. visible → Render overflowing text outside of its container.

***

## Set Text Alignment

This helps in aligning the Text horizontally. There are 4 options present:

1. start -> Aligns the text on the leading edge of the container.
2. end -> Aligns the text on the trailing edge of the container.
3. center -> Aligns the text in the center of the container.
4. justify -> Stretches lines of text that end with a soft line break to fill the width of the container.

***

## Changing Image type

The most common type is the Image Type of Network.

Here's how you can change the Image Type:

1. Under Widget Properties (on the right side of your screen), scroll down to **Image** **Source** section.
2. Find the **Network** property for Image Type and change it to Blurhash or Assets.
3. For Blurhash:
   1. First generate the BlurHash string for your image.
   2. Enter the BlurHash string in the text field and click Done.
   3. Refresh to see your image.

{% hint style="info" %}
Learn more about using BlurHash images [here](https://blurha.sh/).
{% endhint %}

4. For Asset images, you need to first upload the images you want in your project.
   1. Navigate to Settings, go to Media Assets and select **Upload Media**.
   2. After uploading your image, you can go back to the Builder Tool, and select the Image widget. Under Image Source, select Asset and choose your image.

***

## Progress Bar Customizations

### Background Color

This is the Color of the track being filled by the indicator. You can choose from default Theme Colors, or Custom Colors, or choose using HEX Values and Opacity.

### Indicator Color

This is the progress indicator's color. You can customize it to whatever you want.

### Animation Duration

You can set the duration for the animation to complete here. Value entered is in milliseconds.

### Animation End Length

You can set the Animation End Length here.

### Border Radius

This refers to the border radius of both the indicator and the track. You can provide a value in Pixels to give the indicator and track a border radius.

### Curve (Animation)

You can choose from 40+ Curve styles.

{% hint style="info" %}
You can view the various Curve styles [here](https://api.flutter.dev/flutter/animation/Curves-class.html).
{% endhint %}

***


# Event System

For every widget, custom Events can be defined. Various options are present, which are described in detail below:

### Call Rest Api

To add an Event which calls some REST API on clicking it, use this option:

1. Select a Widget to call REST API from.
2. Select the Action as **Call Rest Api**
3. Select the API ID to whatever API you want to be called.
4. Confirm by pressing Done.

### Go Back

If you want to configure custom navigation on your app, you can add this Event.

1. Select a Widget to add navigation, and navigate to Default Properties -> Event Handlers.
2. Select the Action as **Go Back**.
3. Confirm by pressing Done.
4. Now, users can press on the widget and navigate to the previous screen.

{% embed url="<https://www.loom.com/share/40271152d85f4d1ebfd48c2c736e5872?sid=6bd1d4dc-fab5-46bf-9299-94516b5452c4>" %}

### Open Url

If you want to open a URL from within your app:

1. Select the Widget from which you want to open the URL.
2. Select the Action as **Open Url**.
3. Enter the URL, or fetch it from an API Call.
4. Select the LaunchMode.
   1. Platform Default\
      This option leaves the decision of how to launch the URL to the platform implementation.
   2. WebView\
      This option loads the URL in an in-app web view (e.g., Android WebView).
   3. External Application\
      This option passes the URL to the OS to be handled by another application.
   4. External (Non-Browser)\
      This option passes the URL to the OS to be handled by another non-browser application.

{% embed url="<https://www.loom.com/share/1ce7c88433b64160b17163f270848362?sid=83915fcf-b6b0-4475-b739-7c9a53730bf8>" %}

### Go to Page

If you want to configure custom navigation on your app, you can add this Event as follows:

1. Select a Widget to add navigation, and navigate to Default Properties -> Event Handlers.
2. Select the Action as **Go to Page**.
3. Choose the page you want to navigate to from the Dropdown.
4. Confirm by pressing Done.
5. Now, users can press on the widget and navigate to the chosen screen.

{% embed url="<https://www.loom.com/share/9346a6bba64f4004bad7e62d285e6112?sid=88a18da6-1ae3-4584-9b84-01cdc134c295>" %}

### Set Local Storage

If you want to save something on Local Storage, you can modify this Event:

1. Select a Widget to Set Local Storage in.
2. Select the Action as **Set Local Storage**.
3. Choose the Method as **Set** or **Clear**.
4. If you choose **Set**, you can enter the `key` and `value` you want to set.
5. Confirm by pressing Done.

### Rebuild Page

This Event can help in force rebuilding a Page:

1. Select a Widget on clicking which the page will be rebuilt.
2. Select the Action as **Rebuild Page**.
3. Confirm by pressing Done.

{% embed url="<https://www.loom.com/share/ddbc255dc36347cea9bac13285a5c32f?sid=6685b0cb-4ced-4696-b20d-e8c5f2a0bce1>" %}


# Action Catalog

Actions define the behavior of the app in response to user interactions with the app's elements or widgets. These actions can be triggered by various user gestures (or touch), such as tapping on a button, selecting an option from a dropdown list, or submitting form, on page load.

Actions can be simple or complex, depending on the app's requirements. Simple actions might include displaying a message, navigating to a new screen, or updating the value of a variable. Complex actions might involve making an API call or integrating with other third-party services using custom actions.

By defining actions in response to user interactions, you can create more engaging and intuitive user experiences.

## Available Actions

| Action                                                                                                                       | Category         | Description                                                        |
| ---------------------------------------------------------------------------------------------------------------------------- | ---------------- | ------------------------------------------------------------------ |
| [**Call External Method**](/logic-and-interaction/actions/call-external-method)                                              | API & Data       | Execute methods from external libraries or custom integrations     |
| [**Call REST API**](/logic-and-interaction/actions/call-rest-api)                                                            | API & Data       | Trigger pre-configured API calls with success/error handling       |
| [**Control Drawer**](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/actions/control_drawer.md) | UI & Interaction | Open, close, or toggle navigation drawer state                     |
| [**Control Navigation Bar**](/logic-and-interaction/actions/control-navigation-bar)                                          | UI & Interaction | Modify navigation bar appearance and behavior                      |
| [**Control Object**](/logic-and-interaction/actions/control-object)                                                          | UI & Interaction | Interact with controllable widget instances                        |
| [**Copy to Clipboard**](/logic-and-interaction/actions/copy-to-clipboard)                                                    | File & Media     | Copy text content to device clipboard                              |
| [**Delay**](/logic-and-interaction/actions/delay)                                                                            | Timing & Events  | Pause action execution for specified duration                      |
| [**Execute Callback**](/logic-and-interaction/actions/execute-callback)                                                      | API & Data       | Invoke custom callback functions with arguments                    |
| [**File Picker**](/logic-and-interaction/actions/file-picker)                                                                | File & Media     | Allow users to select files from device storage                    |
| [**Fire Event**](/logic-and-interaction/actions/fire-event)                                                                  | Timing & Events  | Trigger custom events for component communication                  |
| [**Go To Page**](/logic-and-interaction/actions/go-to-page)                                                                  | Navigation       | Navigate to different pages with data passing and stack management |
| [**Image Picker**](/logic-and-interaction/actions/image-picker)                                                              | File & Media     | Enable camera or gallery image selection                           |
| [**Open Dialog**](/logic-and-interaction/actions/open-dialog)                                                                | UI & Interaction | Display modal dialogs with custom content                          |
| [**Open URL**](/logic-and-interaction/actions/open-url)                                                                      | UI & Interaction | Launch external URLs in browser or system apps                     |
| [**Pop**](/logic-and-interaction/actions/pop)                                                                                | Navigation       | Return to previous page with optional result data                  |
| [**Pop Until**](/logic-and-interaction/actions/pop-until)                                                                    | Navigation       | Navigate back through stack until reaching specific route          |
| [**Rebuild State**](/logic-and-interaction/actions/rebuild-state)                                                            | State Management | Force UI rebuild without changing state values                     |
| [**Set App State**](/logic-and-interaction/actions/set-app-state)                                                            | State Management | Update global application state variables                          |
| [**Set State**](/logic-and-interaction/actions/set-state)                                                                    | State Management | Modify local state in components, pages, or containers             |
| [**Share**](/logic-and-interaction/actions/share)                                                                            | File & Media     | Share content via system sharing capabilities                      |
| [**Show Bottom Sheet**](/logic-and-interaction/actions/show-bottom-sheet)                                                    | UI & Interaction | Display bottom sheet modals with custom content                    |
| [**Toast**](/logic-and-interaction/actions/toast)                                                                            | UI & Interaction | Show temporary notification messages                               |
| [**Upload**](/logic-and-interaction/actions/upload)                                                                          | File & Media     | Upload files to configured storage endpoints                       |

## Action Categories

### 🔄 State Management

Actions for managing application state and triggering UI updates.

### 🧭 Navigation

Actions for moving between pages and managing navigation stack.

### 🌐 API & Data

Actions for communicating with external services and handling data operations.

### 🎨 UI & Interaction

Actions for controlling user interface elements and user feedback.

### 📁 File & Media

Actions for handling file operations, media selection, and sharing.

### ⏱️ Timing & Events

Actions for controlling timing and triggering custom events.

## How To add a Action

1. Select the widget from the Widget Panel where you want to add the action.
2. Locate the **'On Click'** menu in the Properties Panel inside the Widget's Default Properties.
3. Tap on the **'+'** icon next to the **'On Click'** menu.
4. Choose the desired action from the dropdown menu.


# Toast

{% embed url="<https://youtu.be/zl7ZAsgPghQ?si=DSyhfVTjWoNpKog->" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=zl7ZAsgPghQ>

The **Show Toast** action displays a temporary, customizable notification message to provide user feedback. Toasts appear as floating overlays that automatically disappear after a specified duration, making them ideal for non-intrusive confirmations, alerts, or status updates.

<figure><img src="/files/UFnkWqdGcwpozyAO08JW" alt="Call External Method action configuration showing message name and payload fields"><figcaption><p>Toast Action</p></figcaption></figure>

***

#### ✅ Common Use Cases

* Showing success messages after form submissions
* Confirming actions like "Item saved" or "Copied to clipboard"
* Displaying error messages or warnings
* Providing feedback after API calls or data operations
* Alerting users about background processes

***

#### ⚙️ Default Behavior

By default:

| Behavior        | Description                                              |
| --------------- | -------------------------------------------------------- |
| **Duration**    | Toast displays for 2 seconds before auto-dismissing      |
| **Position**    | Appears at the bottom center of the screen               |
| **Appearance**  | Black background with white text, rounded corners        |
| **Size**        | Auto-sized based on content (customizable)               |
| **Interaction** | Non-interactive - cannot be tapped or dismissed manually |

***

#### 🛠️ How to Use

1. Add the action to a widget event (e.g., button tap, form submission)
2. Choose **Show Toast** from the action list
3. Set the `message` text to display
4. Optionally customize `duration` and `style` properties

***

#### 📦 Properties

| Property   | Type                | Required | Description                              |
| ---------- | ------------------- | -------- | ---------------------------------------- |
| `message`  | Expression (String) | ✅        | The text content to display in the toast |
| `duration` | Expression (Number) | ❌        | Display duration in seconds (default: 2) |
| `style`    | Object              | ❌        | Visual styling configuration             |

***

#### 🎨 Style Configuration

The `style` object supports extensive customization:

| Style Property | Type   | Description                                                                                                                                                                              | Default         |
| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
| `bgColor`      | String | Background color (hex code or color name)                                                                                                                                                | `"#000000"`     |
| `borderRadius` | String | Corner radius (comma-separated: `topLeft,topRight,bottomRight,bottomLeft`)                                                                                                               | `"12,12,12,12"` |
| `height`       | Number | Toast height in pixels                                                                                                                                                                   | Auto-sized      |
| `width`        | Number | Toast width in pixels                                                                                                                                                                    | Auto-sized      |
| `padding`      | String | Inner spacing (comma-separated: `left,top,right,bottom`)                                                                                                                                 | `"24,12,24,12"` |
| `margin`       | String | Outer spacing (same format as padding)                                                                                                                                                   | None            |
| `alignment`    | String | alignment within toast                                                                                                                                                                   | `"center"`      |
| `textStyle`    | Object | Text styling (see [Text Style Properties](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/building-ui/widgets/basic-widgets/text.md#text-style-properties)) | White text      |

***

#### 💡 Examples

**Basic Success Message:**

```javascript
// message: "Data saved successfully!"
// duration: 2
// style: {}
```

**Error Toast with Custom Styling:**

```javascript
// message: "Failed to save data. Please try again."
// duration: 3
// style: {
//   "bgColor": "#dc3545",
//   "borderRadius": "8,8,8,8",
//   "textStyle": {
//     "color": "#ffffff",
//     "fontSize": 14,
//     "fontWeight": "500"
//   }
// }
```

**Dynamic Message from State:**

```javascript
// message: appState.lastActionMessage
// duration: 2
```

**API Response Feedback:**

```javascript
// message: if(isNull(jsonGet(response.body, 'message')), 'Operation completed', jsonGet(response.body, 'message'))
// duration: 2
```

**Custom Styled Confirmation:**

```javascript
// message: "Welcome back!"
// style: {
//   "bgColor": "#28a745",
//   "borderRadius": "20,20,20,20",
//   "padding": "32,16,32,16",
//   "textStyle": {
//     "fontSize": 16,
//     "fontWeight": "600"
//   }
// }
```

{% embed url="<https://digiaacademy.portal.trainn.co/share/toast-examples>" %}


# Copy to Clipboard

{% embed url="<https://youtu.be/iypmU5492OQ?si=I9qTrLrs-XPyRiGe>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=iypmU5492OQ>

The **Copy to Clipboard** action copies text content to the device's clipboard, making it available for pasting in other apps or fields. This is commonly used for sharing codes, links, or generated content.

***

***

#### 📦 Properties

| Property  | Type                | Required | Description                           |
| --------- | ------------------- | -------- | ------------------------------------- |
| `message` | Expression (String) | ✅        | The text content to copy to clipboard |

#### ✅ Common Use Cases

* Copying referral codes, promo codes, or invite links
* Copying generated passwords or tokens
* Copying text from form fields for reuse
* Sharing user IDs, transaction IDs, or confirmation codes
* Copying dynamic content from API responses

***

#### ⚙️ Default Behavior

By default:

| Behavior                   | Description                                                    |
| -------------------------- | -------------------------------------------------------------- |
| **Toast Notification**     | Shows "Copied to Clipboard!" success message (dashboard only)  |
| **Error Handling**         | Shows "Failed to copy to clipboard." on error (dashboard only) |
| **Empty Message Handling** | Gracefully handles null/empty messages without error           |
| **Platform Support**       | Works on all platforms supported by Flutter                    |

***

#### 🛠️ How to Use

1. Add the action to a widget event (e.g., button tap, text selection)
2. Choose **Copy to Clipboard** from the action list
3. Set the `message` property to the text you want to copy

<figure><img src="/files/w04ZiZE74xAhUtpfVoKW" alt="Call External Method action configuration showing message name and payload fields"><figcaption><p>Call External Method action configuration in Digia Studio</p></figcaption></figure>

***


# Call Rest API

The **Call REST API** action allows you to trigger a pre-configured API call directly from your app. It is typically used to send or retrieve data from a remote server based on user actions or events.

Refer to [Define API Calls](broken://pages/KXlJNRsMXnx5Dzegsqjn) on how to define and then use.

{% embed url="<https://www.youtube.com/watch?v=afWKuKP0Fow>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=afWKuKP0Fow>

***

#### ✅ Common Use Cases

* Submitting a form to a backend service
* Fetching dynamic data to update the UI
* Sending user input to an external system

***

#### ⚙️ Default Behavior

By default:

| Behavior                     | Description                                                                                                                              |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| **Data Source**              | The API call is executed using the selected `API Call`                                                                                   |
| **Success / Error Handling** | If `On Success` or `On Error` flows are configured, they are triggered conditionally based on the **response** and **success condition** |
| **Visual Feedback**          | No loading or error UI is shown automatically → use actions like **Show Toast** or **Show Loading** for user feedback                    |

***

#### 📦 Properties

| Property            | Type                 | Required | Description                                                     |
| ------------------- | -------------------- | -------- | --------------------------------------------------------------- |
| `API Call`          | Dropdown             | ✅        | Select the pre-configured API call to execute                   |
| `Success Condition` | Expression (Boolean) | ❌        | Optional expression to determine if the API call was successful |
| `On Success`        | Action Flow          | ❌        | Actions to execute when the API call succeeds                   |
| `On Error`          | Action Flow          | ❌        | Actions to execute when the API call fails                      |

***

#### 📦 How to use

<figure><img src="/files/qmbnBwpy1wXtW1HG3Gwo" alt="Call External Method action configuration showing message name and payload fields"><figcaption><p>Call External Method action configuration in Digia Studio</p></figcaption></figure>

1. Add the action to a widget (e.g. on form submission or button click)
2. Choose **Call REST API** from the action list
3. Select the desired `API Call`
4. (Optional) Configure a **success condition** expression to determine success/failure
5. (Optional) Configure **On Success** and **On Error** flows based on the API outcome

***

#### 📦 Response Payload (Available in Expressions)

When the API call completes, the response is made available as a `response` variable with the following fields:

| Field        | Description                                                              |
| ------------ | ------------------------------------------------------------------------ |
| `body`       | The response body data                                                   |
| `statusCode` | The HTTP status code of the API response                                 |
| `headers`    | The response headers as a map                                            |
| `requestObj` | Details about the request (URL, method, headers, data, query parameters) |
| `error`      | Error message (if any) - `null` for successful responses                 |

You can access these fields in expressions using `response.body`, `response.statusCode`, etc.

***

#### 🎯 Success Condition

The **success condition** is an optional expression that determines whether the API call is considered successful. If not configured, all responses are treated as successful.

**Example expressions:**

* `isEqual(response.statusCode, 200)` - Success only on HTTP 200
* `and(gte(response.statusCode, 200), lt(response.statusCode, 300))` - Success on 2xx status codes
* `isEqual(jsonGet(response.body, 'success'), true)` - Success based on response body content

***

#### 💡 Examples

**Basic API Call with Response Handling:**

* Select "getUserData" as the API Call
* Add Set App State action in On Success to store `response.body`

**Conditional Success Based on Response:**

* Select "submitForm" as the API Call
* Set success condition: `and(isEqual(response.statusCode, 200), isEqual(jsonGet(response.body, 'status'), 'success'))`
* Add Show Toast action in On Success with success message
* Add Show Toast action in On Error with dynamic error message

**Error Handling in On Error Flow:**

* Select "updateProfile" as the API Call
* Add Show Toast action in On Error with error message

***

#### 🔗 Related Documentation

* [Setting up API Calls](broken://pages/kcZ74Q5CK596WD1ntuVO) - How to configure API calls for use with this action
* [Create API Calls](broken://pages/K4LZEVuvKE6GXbu6apLH) - Creating and managing API call configurations
* [Show Toast](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/actions/show-toast.md) - Display user feedback messages
* [Set App State](/logic-and-interaction/actions/set-app-state) - Update application state with API response data

***


# Delay

The **Delay** action introduces a pause in action execution, allowing you to control timing between operations. This is essential for creating smooth user experiences, coordinating animations, or pacing sequential operations.

{% embed url="<https://www.youtube.com/watch?v=SqXkDwIdBhg>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=SqXkDwIdBhg>

***

#### 📦 Properties

| Property       | Type                | Required | Description                    |
| -------------- | ------------------- | -------- | ------------------------------ |
| `durationInMs` | Expression (Number) | ❌        | Delay duration in milliseconds |

***

#### ✅ Common Use Cases

* Adding pauses between UI transitions or animations
* Delaying toast notifications to allow visual feedback to complete
* Creating staggered effects in action sequences
* Waiting for user attention before proceeding with next steps
* Coordinating with external services or API rate limits

***

#### ⚙️ Default Behavior

By default:

| Behavior               | Description                                              |
| ---------------------- | -------------------------------------------------------- |
| **Duration Handling**  | If no duration is specified, delay completes immediately |
| **Execution Blocking** | Subsequent actions wait for the delay to complete        |
| **UI Responsiveness**  | App remains responsive during delay (non-blocking UI)    |
| **Precision**          | Delay duration is in milliseconds with 1ms precision     |

***

#### 🛠️ How to Use

1. Insert the **Delay** action between other actions in a sequence
2. Set the `durationInMs` to the desired wait time in milliseconds
3. Add subsequent actions that should execute after the delay

<figure><img src="/files/oeEiW0tLS97CwD2e2SEd" alt="Copy Slugs"><figcaption><p>Copy Slug</p></figcaption></figure>

***


# Open URL

{% embed url="<https://youtu.be/QxCkMp_n5JA?si=4zsLcUC9QQHYhAcT>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=QxCkMp_n5JA>

The **Open URL** action launches external URLs using the device's default browser or in-app web views. This enables seamless integration with web content, external services, and third-party applications.

***

#### 📦 Properties

| Property     | Type                | Required | Description                                  |
| ------------ | ------------------- | -------- | -------------------------------------------- |
| `url`        | Expression (String) | ✅        | The URL to open (must be valid format)       |
| `launchMode` | String              | ❌        | How to open the URL (see launch modes below) |

***

#### ✅ Common Use Cases

* Opening help documentation or FAQ pages
* Linking to social media profiles or marketing pages
* Accessing external product pages or support portals
* Integrating with payment gateways or authentication services
* Sharing links to articles, videos, or resources

***

#### ⚙️ Default Behavior

By default:

| Behavior                 | Description                                           |
| ------------------------ | ----------------------------------------------------- |
| **Launch Mode**          | Uses platform default (typically external browser)    |
| **URL Validation**       | Validates URL format before attempting to open        |
| **Error Handling**       | Throws errors for invalid URLs or unsupported schemes |
| **Platform Integration** | Leverages device capabilities for URL handling        |

***

#### 🛠️ How to Use

<figure><img src="/files/tohSJ04KXh1MnrVW8TTI" alt="Copy Slugs"><figcaption><p>Copy Slug</p></figcaption></figure>

1. Add the action to a widget event (e.g., button tap, link click)
2. Choose **Open URL** from the action list
3. Set the `url` property to the target web address
4. Optionally configure `launchMode` for specific opening behavior

***

#### 🌐 Launch Modes

<figure><img src="/files/u8UqgTwHavIE3qNi5P4U" alt="Copy Slugs"><figcaption><p>Copy Slug</p></figcaption></figure>

| Mode                               | Description                           | Use Case                   |
| ---------------------------------- | ------------------------------------- | -------------------------- |
| `platformDefault`                  | Uses device's default URL handler     | Standard web links         |
| `inAppWebView` / `inApp`           | Opens in embedded web view within app | Keep users in your app     |
| `externalApplication` / `external` | Opens in external browser/app         | Full browser experience    |
| `externalNonBrowserApplication`    | Opens in external non-browser app     | Deep linking to other apps |

***

{% embed url="<https://digiaacademy.portal.trainn.co/share/open-url-examples>" %}


# Pop

{% embed url="<https://youtu.be/S2y8sSdRk_o?si=IbJVS4cMRecHArer>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=S2y8sSdRk_o>

The **Pop Page** action navigates backward in the app's navigation stack, closing the current page/screen and returning to the previous one. This is the standard way to implement "back" functionality in mobile apps.

***

#### 📦 Properties

| Property | Type             | Required | Description                                               |
| -------- | ---------------- | -------- | --------------------------------------------------------- |
| `maybe`  | Boolean          | ❌        | If `true`, safely attempts to pop without throwing errors |
| `result` | Expression (Any) | ❌        | Data to pass back to the previous screen                  |

***

#### ✅ Common Use Cases

* Closing detail screens and returning to list views
* Dismissing modal dialogs or bottom sheets
* Navigating back after completing forms or tasks
* Implementing cancel/back buttons in workflows
* Returning from settings or configuration screens

***

#### ⚙️ Default Behavior

By default:

| Behavior              | Description                                                  |
| --------------------- | ------------------------------------------------------------ |
| **Navigation Safety** | Uses standard `Navigator.pop()` - throws error if cannot pop |
| **Result Passing**    | No result data is passed back to the previous screen         |
| **Stack Management**  | Removes current route from navigation stack                  |
| **Animation**         | Uses platform default back transition animation              |

***

#### 🛠️ How to Use

<figure><img src="/files/GTgA8OvbGoNPSOLWpu2c" alt="Copy Slugs"><figcaption><p>Copy Slug</p></figcaption></figure>

1. Add the action to a widget event (e.g., back button, cancel button)
2. Choose **Pop Page** from the action list
3. Optionally configure `maybe` for safe popping or `result` to pass data back

***

#### 🔄 Result Handling

When popping with a `result`, the data is passed back to the previous screen. This is commonly used with the **Go To Page** action's `Expect Result` and `onResult` properties.

**Result Structure:**

```javascript
{
  "data": <your-result-value>
}
```

***

{% embed url="<https://digiaacademy.portal.trainn.co/share/pop-examples>" %}

***

#### 🔗 Related Documentation

* [Go To Page](/logic-and-interaction/actions/go-to-page) - Navigate to pages with result handling
* [Finding Page/Component Slugs](https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/platform-overview/builder-tool/finding-slugs.md) - Understanding page identifiers for navigation

***

*Asset Placeholder: Tutorial video demonstrating back navigation and result passing in Digia Studio*


# Pop Until

The **Pop Until** action navigates backward through the navigation stack until reaching a specified route. This enables jumping back multiple levels in the navigation hierarchy with a single action, regardless of stack depth.

{% embed url="<https://www.youtube.com/watch?v=0iQoE1a5LZc>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=0iQoE1a5LZc>

***

#### 📦 Properties

| Property              | Type   | Required | Description                          |
| --------------------- | ------ | -------- | ------------------------------------ |
| `routeNameToPopUntil` | String | ❌        | Route name to pop back to (optional) |

***

**Digia Page Route Format:** When popping back to a Digia Studio page, append `'duiPageRoute-'` prefix to the page slug:

* **Digia Page**: If your page slug is `"user-profile-xCMB7s"`, use `"duiPageRoute-user-profile-xCMB7s"`
* **Normal Routes**: Use the route name as-is without prefix

This prefix is required for Digia Studio pages to ensure proper route resolution in the navigation stack.

***

#### ✅ Common Use Cases

* Returning to home screen or main dashboard from deep navigation
* Implementing "back to main menu" functionality
* Resetting navigation state after complex workflows
* Creating emergency exit paths from nested screens
* Implementing breadcrumb-style navigation

***

#### ⚙️ Default Behavior

By default:

| Behavior               | Description                                        |
| ---------------------- | -------------------------------------------------- |
| **Route Matching**     | Pops until exact route name match is found         |
| **Stack Preservation** | Maintains routes above the target route            |
| **Fallback Behavior**  | If no route name specified, performs single pop    |
| **Error Handling**     | No error if target route not found (stops at root) |

***

#### 🛠️ How to Use

<figure><img src="/files/AFKzfRgA6AWKDFscr51T" alt="Copy Slugs"><figcaption><p>Copy Slug</p></figcaption></figure>

1. Add the action to a widget event (e.g., home button, cancel workflow)
2. Choose **Pop Until** from the action list
3. Set the `routeNameToPopUntil` to the target route name
4. Leave empty for single-level back navigation

***


# Call External Method

The Call External Method action enables communication from Digia UI pages to native Flutter code. This action sends messages through the MessageBus to trigger native functionality or platform-specific operations. The payload supports any valid JSON data structure.

{% embed url="<https://www.youtube.com/watch?v=Fbu_W3O40x4>" %}

Watch this on Youtube: <https://www.youtube.com/watch?v=Fbu_W3O40x4>

## Properties

| Property  | Type     | Required | Description                                                                                                                                                                       |
| --------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`    | `string` | Yes      | The message name/channel to send to native code.                                                                                                                                  |
| `payload` | `object` | No       | Optional JSON object to send as parameters to the native handler. Individual property values can contain dynamic expressions, but the payload itself must be an object structure. |

## Examples

All payload data is automatically converted to JSON format before being sent to native code. The payload must be a JSON object where individual property values can contain dynamic expressions. Direct dynamic expressions for the entire payload are not supported.

### Basic Message Sending

<figure><img src="/files/Gvaj9jUkoYOJp0v7MWiC" alt="Call External Method action configuration showing message name and payload fields"><figcaption><p>Call External Method action configuration in Digia Studio</p></figcaption></figure>

***

Sends a message named "login" with user data to native code.

> **Note:** You cannot use dynamic expressions for both `name` and `payload` simultaneously. The payload must be a JSON object where individual property values can contain dynamic expressions, not a direct dynamic expression.

## Use Cases

* **Native API Integration**: Call device APIs not available in the UI framework
* **Platform-Specific Features**: Trigger camera, sensors, or hardware functionality
* **Analytics Tracking**: Send custom events to native analytics handlers
* **Third-Party Integration**: Communicate with Flutter packages from Digia Studio
* **Custom Processing**: Pass data to native code for specialized operations

## Default Behavior

By default:

| Behavior             | Description                                          |
| -------------------- | ---------------------------------------------------- |
| **Message Delivery** | Sends message immediately through MessageBus         |
| **Asynchronous**     | Action completes without waiting for native response |
| **No Feedback**      | No built-in UI feedback or confirmation              |
| **Handler Required** | Native code must implement DigiaMessageHandlerMixin  |

## How to Use

<figure><img src="/files/ZxiZC4m26KWj42s2qBd4" alt="Call External Method action configuration showing message name and payload fields"><figcaption><p>Call External Method action configuration in Digia Studio</p></figcaption></figure>

1. Attach the action to a widget event (button tap, form submission, etc.)
2. Select **Call External Method** from the action list
3. Specify the `name` that native code will listen for
4. Optionally provide `payload` data to send to the native handler

//TODO : Add gif

## Implementation Details

The action uses Flutter's MessageBus to send messages to native code. The payload is automatically JSON-serialized before transmission. Native widgets must implement `DigiaMessageHandlerMixin` to receive and handle these messages.

**Limitations:**

* You cannot use dynamic expressions for both `name` and `payload` simultaneously
* The payload must be a JSON object where individual property values can contain dynamic expressions
* Direct dynamic expressions like `"{{formData}}"` are not supported for payload

Example native implementation:

```dart
class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> with DigiaMessageHandlerMixin {
  @override
  void initState() {
    super.initState();
    addMessageHandler('login', _handleCustomAction);
  }

  void _handleCustomAction(Message message) {
    print('Received message with payload: ${message.payload}');
  }
}
```

Messages are sent asynchronously and the action completes immediately after sending, without waiting for native code response.

## Related Actions

* [Execute Callback](/logic-and-interaction/actions/execute-callback) - Call predefined callback functions
* [Fire Event](/logic-and-interaction/actions/fire-event) - Trigger analytics events
* [Set State](/logic-and-interaction/actions/set-state) - Update application state

***

*Asset Placeholder: Tutorial video demonstrating native method calls and MessageBus integration in Digia Studio*




---

[Next Page](/llms-full.txt/1)

