---
title: Session Replay - Flutter
description: Learn how to integrate and configure Session Replay capabilities in your Flutter app with the CSQ SDK
lastUpdated: 18 February 2026
source_url:
  html: https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/session-replay/
  md: https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/session-replay/index.md
---

Session Replay enables replaying real sessions to observe how users interact with your product, by capturing screen content - including text and images - as users navigate your mobile app. For more details, see [Introduction to Session Replay for Apps ↗](https://support.contentsquare.com/hc/en-us/articles/37271667148561-Introduction-to-Session-Replay-for-Apps) in the Help Center.

## Starter guide

### Prerequisites

#### Update to latest SDK version

In order to enable Session Replay in your app and get the most stable version, it is required to [upgrade the SDK](https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/#install-the-sdk) to its latest version.

#### Implement screen tracking

Ensure screen tracking is implemented, since Session Replay collection starts at the first screenview event. See [Track screens](https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/track-screens/).

#### Handle User consent

Ensure user consent is handled for Contentsquare data collection, especially if you're implementing the SDK for the first time. See [Privacy](https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/privacy/) section.

Note

Mandatory data collection settings are configured by Contentsquare in your project parameters. [Learn more about Data collection configurations ↗](https://support.contentsquare.com/hc/en-us/articles/37271667148561-Introduction-to-Session-Replay-for-Apps) on the Help Center.

### Configure Session Replay masking

#### Masking behavior

By default, the CSQ SDK is configured to mask all content displayed on the user interface (UI) to prevent unnecessary data collection. For more details, see what a fully masked screen looks like in [Masking mechanisms](#masking-mechanisms).

**For testing purposes**, use this setup:

* Either unmasking all the content by setting the [default masking](#default-masking) status to false.
* Or unmasking most content with the [Text and Image unmasking configuration ↗](https://support.contentsquare.com/hc/en-us/articles/37271682878353-Data-masking-in-Session-Replay-Mobile-Apps) in your Console parameters.

**For more granular control in deployment mode**, you can use the [Text and Image unmasking configuration ↗](https://support.contentsquare.com/hc/en-us/articles/37271682878353-Data-masking-in-Session-Replay-Mobile-Apps) in your Console parameters in combination with [SDK public masking APIs](#public-masking-apis) to fine-tune exactly which elements remain masked.

Warning

Always keep sensitive data masked to ensure compliance with privacy regulations and to protect users' personal data.

### Configure Event-Triggered Replays (optional)

If Event-Triggered Replays is included in your contract, you can set up ETR events to enable specific screen and session collection in Session Replay. See [Event-Triggered Replays (ETR)](#event-triggered-replays-etr).

### Configure Webviews (optional)

If your mobile app includes Webviews, specific implementation steps are required to ensure they are properly reflected in Session Replay:

* Implement [Webview tracking](https://docs.contentsquare.com/en/webview-tracking-tag/)
* Handle [personal data within WebViews](https://docs.contentsquare.com/en/webview-tracking-tag/session-replay/#personal-data-handling)

### Test your setup

#### Enable Session Replay on your device

If the Session Replay sampling rate is less than 100%, only a portion of sessions are collected. To ensure data collection on your device for testing and debugging purposes, you can force it from the In-app Features settings by following these steps:

1. [Enable in-app features](https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/in-app-features/)
2. Open in-app features settings with a long press on the screenshot button
3. Under "Session Replay", toggle "Enable Session Replay" on
4. Kill the app
5. Upon restarting the app, a new session will start with Session Replay enabled.

##### iOS example

![](https://docs.contentsquare.com/_astro/ios-enable-sr-2.0sYFDfbq.gif)

#### How do I know if Session Replay is enabled?

There are 2 places where you can verify if Session Replay is enabled:

**In the logs:** The log `Session Recording is starting` will confirm that Session Replay is enabled.

**In in-app features settings:** Below the "Enable (will start at next app start) *(see below [Access the replay](#access-the-replay))*, you will either see:

* `No replay link available` which means Session Replay is not running for the current session
* `Get Replay link` which means Session Replay is running for the current session

#### Access the Replay

The session can be accessed by tapping on `Get replay link` button from the in-app features settings:

![](https://docs.contentsquare.com/_astro/ios-get-replay-link.tN1tVH-m_Z1EodDY.webp)

The replay will be **available within 5 minutes**. Only the *concluded* screen views are processed, and we identify a screenview has *concluded* when we begin receiving data for the subsequent screenview or if the session has ended. This means that you will be able to replay your session up to the previous screenview if the session is still ongoing.

## Personal Data Masking

The Session Replay feature replays every interaction of your users with your app. To respect the user’s right to privacy, the CSQ SDK:

* Masks everything by default
* Allows you to control which part of the user interface is collected via our [Masking rules](#masking-rules)

Warning

When using Contentsquare with Flutter, if you decide to use unmasked elements leading to collection of new data or use already collected data but for a different purpose, it is up to you to update your app’s privacy documentation accordingly. Here are some common examples of data collected via un-masked session Replay: Search history, Purchase history, Advertising data, etc. See [Types of data and purpose](https://docs.contentsquare.com/en/csq-sdk-flutter/experience-analytics/privacy/) already described in the Contentsquare iOS SDK Privacy Manifest.

**Important:** Contentsquare is not intended nor designed to collect sensitive personal data (such as health, financial, racial data). It is the customer’s responsibility not to send any sensitive personal data to Contentsquare.

### Masking mechanisms

Masking depends on the type of element:

* **Images**: A blurred representation is sent in place of the original content.
* **SVG images**: A blurred representation is sent in place of the original content.
* **CustomPaint**: custom-made `CustomPaint` elements are not collected. Instead, a blurred representation is sent in place of the original content. [Framework specific decorative `CustomPaint`](#unmaskable-framework-specific-custompaint-classes) that do not contain sensitive data are still collected.
* **Text**: Replaced by \* (asterisk) characters, matching the original character count. Whitespace characters (spaces, tabs, line breaks) are preserved. For instance, `the lazy fox` is collected as `*** **** ***`. All other visual properties (text color, background color, alignment, etc.) are collected.
* **TextFields**: Same as Text
* **TextField with `obscureText`**: Both the obscured text and the briefly revealed character are replaced by • (bullet).
* **Other types**: no specific data is collected but visual properties are collected.
* **Icons**: Single characters belonging to the Private Use Area `U+E000..U+F8FF` are collected.

If you believe a particular element might disclose personal data through any of these properties, you must mask it using one of the methods outlined below. A reliable method to assess how a view is rendered in a replay is to navigate to the desired view with the CS SDK active, then use the [quick replay link](#access-the-replay).

#### Masking example

Here's an illustration of a masked view:

`Original` -> `Replay fully unmasked` -> `Replay fully masked`

![](https://docs.contentsquare.com/_astro/flutter-sr-masking-example_from_3_19.CrHM_fsR_Z1obhya.webp)

### Masking rules

Masking rules can be applied in two ways:

1. **Through remote masking configuration in the CSQ Console (for admin users):** These configurations are managed directly in the Console and take effect for all sessions as soon as the app is restarted or brought to the foreground. See [How to customize masking rules from the Data Masking tab ↗](https://support.contentsquare.com/hc/en-us/articles/37271848716561-How-to-customize-masking-rules-from-the-Data-Masking-tab-Apps) on the Help Center.
2. **Using public masking APIs in the SDK (for mobile application developers):** These configurations require developer implementation and will be applied only after the mobile app has gone through its release cycle.

Masking rules set via the CSQ Console or the public APIs are applied according to different priorities, as described below. The SDK determines whether a view is masked by evaluating the rules in the order specified below. Once a rule is triggered, the state is set, and subsequent rules are not applied:

When using `CSQMask` and `CSQMaskingConfig`, it's essential to understand the priority of masking rules in the widget tree. The masking rules specified in a `CSQMask` widget will affect its descendants, and if nested scopes are used, the innermost (closest) scope takes precedence.

Once a rule is triggered, the state is set, and subsequent rules are not applied:

| Rule | Configured via |
| - | - |
| 1. The app or plugin version is fully masked | [Data Masking tab in the CSQ Console ↗](https://support.contentsquare.com/hc/en-us/articles/37271848716561-How-to-customize-masking-rules-from-the-Data-Masking-tab-Apps) |
| 1. Remote Text or Image masking is defined | [Data Masking tab in the CSQ Console ↗](https://support.contentsquare.com/hc/en-us/articles/37271848716561-How-to-customize-masking-rules-from-the-Data-Masking-tab-Apps) |
| 1. The `CSQMaskingConfig` object provided to the `start()` method sets the masking rules for the entire app. | API |
| 1. The `CSQMaskingConfig` object provided to a `CSQMask` widget sets the masking rules for its child and descendants. | API |
| 1. Remote Text or Image unmasking is defined | [Data Masking tab in the CSQ Console ↗](https://support.contentsquare.com/hc/en-us/articles/37271848716561-How-to-customize-masking-rules-from-the-Data-Masking-tab-Apps) |
| 1. Otherwise the widget remains masked except for `CustomPaints` and `SvgImages` | default |

### Public Masking APIs

#### Default masking

By default all images, text and Text fields will be masked. SVGs and CustomPaints are not masked.

#### Masking/Un-masking in Flutter

`CSQMask` is a Flutter widget that applies specified masking rules to its descendant widgets. This can be used when you want to mask sensitive information during Session Replays, such as user data or private texts.

`CSQMaskingConfig` is a class that determines what type of content should be masked during Session Replays. You can customize the masking behavior by setting the masking options for texts, text fields, and images.

#### Handle masking

In order to mask or unmask content, wrap the desired widget(s) with the `CSQMask` widget and provide a `CSQMaskingConfig` object to configure the masking rules.

Here's an example of how to use `CSQMask`:

```dart
import 'package:contentsquare/csq.dart';


CSQMask(
  maskingConfig: CSQMaskingConfig.maskAll(),
  child: const Text('Hello world'),
);
```

In this example, `CSQMaskingConfig.maskAll()` is used to mask the `Text` widget.

You can also use nested `CSQMask` widgets to apply different masking rules to different parts of your widget tree. Here's an example:

```dart
import 'package:contentsquare/csq.dart';


CSQMask(
  maskingConfig: CSQMaskingConfig.maskAll(),
  child: Column(
    children: [
      const Text('This text will be masked'),
      CSQMask(
        maskingConfig: CSQMaskingConfig(maskTexts: false),
        child: Text('This text will NOT be masked'),
      ),
    ],
  ),
);
```

In this example, the first `Text` widget will be masked, while the second one will not be masked due to the `maskTexts: false` option in the nested `CSQMask`.

#### How to use `CSQMaskingConfig`

`CSQMaskingConfig` allows you to configure the masking behavior for different types of content:

* `maskTexts`: If set to `true`, any widget that creates a `RenderParagraph` (example: `Text`, `RichText`) will be masked.
* `maskTextFields`: If set to `true`, any widget that creates a `RenderEditable` (example: `TextFormField`, `TextField`) will be masked.
* `maskImages`: If set to `true`, any widget that creates an image (example: `Image`, `BoxDecoration.image`) will be masked.
* `maskSvgImages`: If set to `true`, any widget that creates an SVG image through `flutter_svg` will be masked.
* `maskCustomPaints`: If set to `true`, any custom-made widget that creates a `CustomPaint` will be masked. [Framework specific decorative `CustomPaint`](#unmaskable-framework-specific-custompaint-classes) not containing any sensitive data are not masked.
* `maskCharts`: If set to `true`, any widget that creates a chart using the [`fl_chart` ↗](https://pub.dev/packages/fl_chart) package will be masked.

You can create a custom `CSQMaskingConfig` object by using the constructor:

```dart
import 'package:contentsquare/csq.dart';


const CSQMaskingConfig({
  bool? maskTexts,
  bool? maskImages,
  bool? maskTextFields,
  bool? maskSvgImages,
  bool? maskCharts,
  bool? maskCustomPaints,
})
```

For easier readability and convenience, you can use the following factory constructors:

* `CSQMaskingConfig.maskAll()`: Returns a `CSQMaskingConfig` object with all values set to `true`, meaning everything will be masked.
* `CSQMaskingConfig.unMaskAll()`: Returns a `CSQMaskingConfig` object with all values set to `false`, meaning nothing will be masked.

If any masking parameter is omitted in the `CSQMaskingConfig` object, its value is inherited from the nearest `SessionMaskingScope` widget in the widget tree.

Note

By default, CSQ masks all types of content (texts, text fields, and images) except the SVG images and CustomPaints during Session Replays. It achieves this by providing a default `CSQMaskingConfig` object if none is specified. The default configuration masks everything, ensuring that sensitive information is protected. However, you can override the default masking behavior by providing your own `CSQMaskingConfig` object when calling the `start()` method. This allows you to customize the masking rules for your app according to your requirements.

Note

If you did not include any sensitive content in `CustomPaint`s or SVG images, prefer to use `CSQMaskingConfig` with `maskCustomPaints` and `maskSvgImages` set to false, to avoid unnecessary masking and guarantee the best Session Replay fidelity.

## Event-Triggered Replays (ETR)

Event-Triggered Replays (ETR) is an add-on feature that allows you to selectively collect specific screens or sessions for Session Replay, based on predefined custom events. Once configured, ETR events can be used to filter specific replays, or view these events as they happen in the player event stream.

To enable ETR, contact your CSM or Implementation Manager. For more information, see [Event-Triggered Replays ↗](https://support.contentsquare.com/hc/en-us/articles/4412027865874) in the Help Center.

Note

When ETR is enabled, the SDK collects data for the entire session even if none of the ETR methods described below are called. After collection, only the sessions or screens that match the global replay sampling rate or are associated with ETR events are retained.

As a result, you may notice a network activity during all sessions, regardless of whether ETR has been triggered or not.

Warning

To protect end-user personal data, ensure that appropriate masking configurations are applied to all screens even the ones that are not associated with ETR events.

### Trigger Replay for the Session

Use the following function to trigger Session Replay for the entire current session, with the parameter `name` as "ETR event".

```dart
import 'package:contentsquare/csq.dart';


await CSQ().triggerReplayForCurrentSession(name: name)
```

### Trigger Replay for the Screen

Use the following function to trigger Session Replay for the entire current screen, with the parameter `name` as "ETR event".

```dart
import 'package:contentsquare/csq.dart';


await CSQ().triggerReplayForCurrentScreen(name: name)
```

## Advanced features for Experience Monitoring

Note

This feature is part of [Experience Monitoring ↗](https://contentsquare.com/platform/experience-monitoring/), which is only available on Enterprise plans or as an add-on to Pro plans. Contact your Customer Success Manager or [sales ↗](https://contentsquare.com/request-a-demo/) to learn more.

### Send user identifier

Contentsquare provides the ability to search for session(s) associated with a specific visitor, based on an identifier: email, phone number, customer ID… As these values are typically personal data, from the moment the SDK is collecting the `User Identifier`, we immediately encode the value using a hashing algorithm so that the information is hidden and can never be accessed.

Use the following code to send a user identifier:

```dart
import 'package:contentsquare/csq.dart';


await CSQ().sendUserIdentifier(userIdentifier: 'the_neo@one.com');
```

When called, the native SDK will log:

```plaintext
CSLIB ℹ️ Info: User identifier hashed sent {value}
```

### Sending a user identifier for each session

You may consider sending the user identifier for each session. Although triggering the user identifier at app launch will cover most cases, it may not be adequate in all scenarios. For instance, a session might start when the app is brought to the foreground after being in the background for more than 30 minutes. For further details, refer to the [Session definition](https://docs.contentsquare.com/en/csq-sdk-ios/experience-analytics/data-collection/#session-definition) section. That is why we also recommend sending the user identifier every time the app enters foreground.

### Limitations

* User identifier max length is 100 characters (if the limit is exceeded, the user identifier will not be handled and you will see an error message in the native Console/Logcat)
* Only the first 15 user identifiers per view will be processed on server side
* The SDK will trim and lowercase user identifier
* User identifier event are not visible in `LogVisualizer`

## Session Replay Quality

### Quality Levels

Session Replay is designed by reconstructing the app's tree structure from selected frames. To minimize performance impact during a session, different quality levels are dynamically applied. Each quality level determines whether certain styles are preserved or omitted while maintaining the overall screen structure and appearance.

#### High Quality Level

![](https://docs.contentsquare.com/_astro/hq_sr.ClkWayQ9_2gfzly.webp)

At this level, all supported styles are captured every 200ms, provided a new frame is available. This ensures a comprehensive reproduction of the session's visual fidelity.

#### Low Quality Level

This level captures supported styles only when user interaction ceases, such as during screen scrolling. images are reduced to their average color representation.

### Quality Level Adjustment

Our plugin continuously monitors its performance while running. Upon detecting a performance issue, the quality level is automatically reduced to mitigate any potential impact on the application. The quality level may increase when navigating to a new screen, provided the performance issue is resolved.

Quality levels are visibly indicated in the Session Player event stream. ![](https://docs.contentsquare.com/_astro/quality_change_sr.DL4WAey__Z1ACTs0.webp)

## Integrations

Contentsquare provides the ability to retrieve the link of the replay to be attached to other vendors such as Voice of Customer or Crash reporting tools.

### Get current replay Link

Generate a link to the replay of the current session. This link can be pushed to any internal or 3rd-party tool as a custom property/variable. For instance, you can add the replay link to:

* Each user request sent to your customer service tool
* Each user voting in your Voice of Customer tool
* Each user session in your App Performance, Observability tool
* ...

Note

The replay link can also be accessed from the in-app features settings. See [Access the Replay](#access-the-replay)

Warning

For the API to return a valid replay link, the session has to be tracked (included in tracked users and not opted-out) and a first screenview event has to be sent before it's called, since Session Replay only starts after the first screenview event.

#### Function signature

You can listen for the replay link that is part of `Metadata` changes using the following function:

```dart
import 'package:contentsquare/csq.dart';


CSQ().metadata.onChange(void Function(Metadata metadata) handler);
```

#### Parameters

`void Function(Metadata metadata) handler`: A callback function that receives the updated `Metadata` object, which contains the `sessionReplayUrl` property.

#### Key Features

* Real-Time Updates: The callback is triggered every time there is a change in the `Metadata` object. If during the method call current `metadata` is available, the callback will be triggered immediately.

* Single Callback Registration: Only one callback can be active at a time. If the API is called multiple times, the most recent callback registration overrides the previous one.

* `onChange` returns a `StreamSubscription<Metadata>` object that can be used to manage the subscription.

Use the following code to retrieve a Session Replay link each time it changes:

```dart
import 'package:contentsquare/csq.dart';


CSQ().metadata.onChange(_onCSQMetadataChanged);


void _onCSQMetadataChanged(Metadata metadata) {
  final sessionReplayUrl = metadata.sessionReplayUrl;
  print('Session Replay URL: $sessionReplayUrl');
}
```

To unregister the current callback, cancel the `StreamSubscription`:

```dart
import 'package:contentsquare/csq.dart';


StreamSubscription<Metadata>? _csqMetadataSubscription;


_csqMetadataSubscription = CSQ().metadata.onChange(_onCSQMetadataChanged);


_csqMetadataSubscription?.cancel();
```

When a new link is available, the SDK will also log:

```plaintext
CSLIB: SessionReplay link: https://app.contentsquare.com/quick-playback/index.html?pid={projectId}&uu={userId}&sn={sessionNumber}&recordingType=cs
```

Warning

You can only have one callback at a time. Calling this API multiple times will override the previous callback.

The replay will be **available within 5 minutes**. Only the "ended screen views" are processed *(we know a screenview is ended when we start receiving data for the next screenview)*. This means that you will be able to replay the session up to the previous screenview if the session is still running.

## How Session Replay works

### Initialization

Sessions can be collected for Session Replay if the Session Replay feature has been enabled for your project and the session matches the collection criteria.

The following conditions will have an impact on which sessions will be collected:

* **User consent**: The users have provided their **consent** (if required)
* **Collection rate**: The session is **designated for collection** (see [Collection Rate](#collection-rate))
* **Compatibility**: The **OS version** is supported.
* **App version**: The **app version** is not included in the block list (see [App Version Block List](#app-version-block-list))

Note

When Session Replay is disabled, no content specific to Session Replay is collected. Additionally, be aware that standard Contentsquare analytics tracking remains unaffected by this.

#### Collection Rate

Session Replay collection is based on a percentage of the total sessions. By default Session Replay collection is disabled.

During the early access phase, the percentage of collected sessions will be set to 1% at the beginning. It will then be adjusted based on:

* The traffic on your app
* The volume of collected sessions set in the contract

#### Compatibility

See the [Compatibility matrix](https://docs.contentsquare.com/en/flutter/compatibility/#compatibility-matrix).

#### App Version Block List

The Contentsquare team can include versions of your app in the block list to prevent Session Replay from initiating on these versions. This functionality proves valuable when a problem is identified on a particular version of your app, such as a situation where masking for Personal Data was not implemented. By employing this feature, Session Replay can continue to operate on other app versions, particularly those with necessary fixes implemented.

### Collection

The SDK monitors the application lifecycle events and the view hierarchy, capturing Session Replay data based on app behavior, screen content, and user interaction. These events are initially stored locally and later sent to our servers in batches. Subsequently, we aggregate this data to generate actionable visual insights in our Web Application, facilitating your ability to gather insights.

Tip

Session collection begins when the first screenview event is triggered.

### Network and Storage

By default, Session Replay data can be sent over **cellular network**. However, if your app's context or user preferences necessitate minimal impact on cellular data usage, you can opt to disable data transmission over cellular networks entirely. Once disabled, data will only be sent when the device is connected to Wi-Fi.

To make this adjustment in your project's configuration, contact your Contentsquare representative.

#### Storage

Before being sent, data is stored in local files on disk up to 30MB on iOS and 20MB on Android. If the limit is reached, Session Replay is halted. It will resume at the next app launch once the SDK can transmit the data.

### Requests

The maximum request size is 1 MByte.

#### iOS

Requests are sent:

* Every 10 seconds
* At app hide
* When [Replay Link API](#access-the-replay) is called

#### Android

Requests are sent:

* On screen change
* When [Replay Link API](#access-the-replay) is called

## Performance impact

We always strive to be non-intrusive, and transparent to the developers of the client app. We apply this rule on the performance as well. These are the technical specifics we can share on performance, if you have any questions feel free to reach out to us.

### Performance impact mitigation

Most operations related to Session Collection are performed on background threads, for the impact on the main thread to be minimal.

We also set up mechanisms that adapts and stop the Session Collection if we detect the feature is using too much memory.

We defined our network strategy to have the lesser impact on CPU and battery of the users devices. We measure these impacts, using Apple Dev Tools, for each release of our SDK.

Session Collection will also stop if we use up to 30Mbytes of local storage.

### Performance Benchmarks

We have conducted performance tests on the SDK to ensure that it has a minimal impact on the app's performance. The tests were conducted on a variety of devices and operating systems to ensure that the SDK performs well across different platforms. These tests use the [Flutter Gallery ↗](https://github.com/flutter/gallery) app as a reference and simulate an intensive normal user interaction with the app during 60 seconds (scrolling, tapping, etc.) using the Session Replay feature.

#### iOS

For iPhone 14 with iOS 16.3

| Metric | Value |
| - | - |
| CPU Usage Delta | < 3% |
| Memory Usage Delta | < 2% |
| Network Usage | < 80kb |

#### Android

For Pixel 6 with Android 13

| Metric | Value |
| - | - |
| CPU Usage Delta | < 25% |
| Memory Usage Delta | < 20% |
| Network Usage | < 80kb |

## Known limitations

* Images set by `Ink.image` are not currently supported.
* Custom shapes are sent as rectangles.
* Blur style is not supported when the app is [obfuscated ↗](https://docs.flutter.dev/deployment/obfuscate).
* In the event stream of the Session Replay, a tapped element is displayed as `unknown` if it has a transparent parent.
* In debug mode, the stability and performance of the Session Replay feature are not guaranteed. Moreover, hot restart and hot reload may introduce unexpected issues. For a reliable and high-performing Session Replay experience, use release or profile builds.
* Masking applied to parent widgets does not apply to the [Draggable.feedback ↗](https://api.flutter.dev/flutter/widgets/Draggable/feedback.html) widget. To ensure proper masking while dragging, wrap the Draggable.feedback widget within its own `CSQMask`.

## Unmaskable Framework specific `CustomPaint` classes

* `CupertinoActivityIndicator`
* `CupertinoTextSelectionToolbar`
* `BottomNavigationBar`
* `DatePickerDialog`
* `DropdownButton`
* `InputDecorator`
* `PhysicalShape`
* `LinearProgressIndicator`
* `CircularProgressIndicator`
* `Stepper`
* `TabBar`
* `TextSelectionToolbar`
* `AnimatedIcon`
* `GridPaper`
* `GlowingOverscrollIndicator`
* `Placeholder`
