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.

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.

Our Expandable widget follows Flutter's ExpansionPanel and ExpansionTile patterns, providing smooth animations, flexible content configuration, and comprehensive interaction options.

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".

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:

Slot
Description

header

Required. The always-visible part of the widget, typically containing a title or label. This is what users see and tap to toggle expansion.

collapsedView

Required. The content displayed when the widget is in its collapsed state. Often contains a brief summary, preview, or placeholder.

expandedView

Required. The content displayed when the widget is in its expanded state. Contains the full detailed information or interactive elements.


Properties

Active View Property

Property
Description

Active View

Dashboard Preview Only. Controls whether the widget appears in the Collapsed or Expanded state in the builder dashboard. This is purely for design preview purposes and does not affect the runtime behavior of the widget.

Initially Expanded

If true, the widget will be in the expanded state by default when the page first loads in the actual app. Default is false (collapsed). This is the property that controls the real initial state.

Tap Behavior Properties

These properties control how users can interact with the widget:

Property
Description

Tap Header to Toggle

If true, tapping anywhere on the header will toggle between collapsed and expanded states. This is the most common interaction pattern.

Tap Body to Expand

If true, tapping on the collapsed content will expand the widget. Useful when you want the collapsed content to be interactive.

Tap Body to Collapse

If true, tapping on the expanded content will collapse the widget. Useful for "dismiss" behavior.

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.

Alignment Properties

Control how content is positioned within each slot:

Property
Description

Alignment

The alignment of the entire expandable widget within its parent container (e.g., left, center, right).

Header Alignment

The alignment of content within the header slot. Controls how child widgets are positioned inside the header.

Body Alignment

The alignment of content within the collapsed and expanded view slots.

Icon Properties

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

Property
Description

Has Icon

If true, an icon will be displayed in the header to indicate the expand/collapse state.

Icon Placement

Where to position the icon within the header: Left or Right.

Collapsed Icon

The icon to display when the widget is in the collapsed state (e.g., chevron_down, add, arrow_forward).

Expanded Icon

The icon to display when the widget is in the expanded state (e.g., chevron_up, remove, arrow_drop_down).

Icon Size

The size of the icon in pixels. Default is typically 24px.

Icon Color

The color of the icon. Can be set from your design system colors or as a custom hex value.

Icon Padding

The padding around the icon to create spacing between the icon and other header content.

Icon Rotation Angle

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).

Style & Animation Properties

Property
Description

Animation Duration

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.

Use InkWell Effect

If true, a Material Design ripple effect will be shown when the user taps the widget. Provides tactile feedback.

InkWell Border Radius

The corner radius for the ripple effect when InkWell is enabled. Should typically match your container's border radius for visual consistency.


Building an Expandable Widget

Example 1: Simple FAQ Item

Create a basic FAQ item with a question header and answer content:

Setup:

  1. Add an Expandable widget to your page

  2. Set Initially Expanded to false

  3. Enable Tap Header to Toggle

  4. Enable Has Icon and set icon placement to Right

Header Slot:

Row
├─ Text: "What is Digia Studio?" (flex: 1)
└─ (Icon handled automatically by Expandable properties)

CollapsedView Slot:

SizedBox (height: 0)  // Empty collapsed state

ExpandedView Slot:

Padding (all: 16)
└─ Text: "Digia Studio is a server-driven UI platform..."
   └─ Style: bodyMedium, grey color

Properties Configuration:

  • Collapsed Icon: chevron_right

  • Expanded Icon: expand_more

  • Icon Rotation Angle: 90

  • Animation Duration: 300


Example 2: Product Details with Preview

Show product summary when collapsed, full details when expanded:

Setup:

  1. Add Expandable widget

  2. Set Initially Expanded to false

  3. Enable Tap Header to Toggle and Tap Body to Expand

Header Slot:

Row (mainAxisAlignment: spaceBetween)
├─ Column (crossAxisAlignment: start)
│  ├─ Text: "Premium Wireless Headphones"
│  └─ Text: "$299.99" (style: bold, primaryColor)
└─ (Icon managed by widget)

CollapsedView Slot:

Padding (left: 16, right: 16, bottom: 8)
└─ Text: "High-quality audio with noise cancellation..."
   └─ maxLines: 2
   └─ overflow: ellipsis
   └─ color: grey

ExpandedView Slot:

Column
├─ Image (product photo)
├─ Padding
│  └─ Column
│     ├─ Text: "Product Description"
│     ├─ Text: "Full product description here..."
│     ├─ SizedBox (height: 16)
│     ├─ Text: "Features"
│     ├─ Column
│     │  ├─ Row: "• 40-hour battery life"
│     │  ├─ Row: "• Active noise cancellation"
│     │  └─ Row: "• Wireless charging"
│     └─ Button: "Add to Cart"

Properties:

  • Collapsed Icon: add_circle_outline

  • Expanded Icon: remove_circle_outline

  • Icon Color: primaryColor

  • Use InkWell Effect: true


Example 3: Form Section with Conditional Expansion

Advanced settings that expand based on user selection:

Header Slot:

Container (backgroundColor: lightGrey, padding: 12)
└─ Row
   ├─ Icon: settings
   ├─ SizedBox (width: 8)
   └─ Text: "Advanced Settings"

CollapsedView Slot:

Container (padding: 16)
└─ Text: "Click to configure advanced options"
   └─ style: italic, grey

ExpandedView Slot:

Container (padding: 16, backgroundColor: white)
└─ Column
   ├─ TextFormField (label: "API Timeout")
   ├─ SizedBox (height: 12)
   ├─ Row
   │  ├─ Text: "Enable Debug Mode"
   │  └─ Switch
   ├─ SizedBox (height: 12)
   ├─ TextFormField (label: "Log Level")
   └─ Button: "Save Settings"

Properties:

  • Initially Expanded: ${appState.isAdvancedUser}

  • Tap Header to Toggle: true

  • Animation Duration: 400


Event Handling

While Expandable doesn't have explicit event handlers like onExpanded, you can respond to state changes in several ways:

1. Binding to Initially Expanded

You can bind the Initially Expanded property to a state variable to dynamically control expansion:

Initially Expanded: ${expandState.isExpanded}

Then use this state variable to control the expansion state from other parts of your app or based on conditions.

2. Using Wrapper Events

Add tap handlers by wrapping the Expandable widget:

Widget with onClick
├─ onClick: Set State (track expansion analytics)
└─ Expandable

You can wrap the Expandable in any widget that supports onClick or other event handlers to track when users interact with it.


Guides

For comprehensive examples and real-world implementations, see:

https://github.com/Digia-Technology-Private-Limited/digiaDocs/blob/main/docs/guides/expandable-accordion-patterns.md

This guide includes:

  • FAQ Section - Build interactive question-and-answer interfaces with accordion behavior

  • Product Details Accordion - Create e-commerce product pages with expandable specifications

  • Settings Panel - Organize complex settings with nested expandable sections

  • Advanced patterns including nested expandables, loading states, and state management

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

Accordion (One-at-a-Time): Create a system where only one expandable is open at a time:

Store current expanded index in state
When expandable is tapped:
  - Close previously expanded item
  - Open current item
  - Update state with new index

Progressive Disclosure: Use expandables in multi-step forms to reveal sections as users progress:

Step 1 Header: "Personal Information" - Initially Expanded: true
Step 2 Header: "Address Details" - Initially Expanded: false
Step 3 Header: "Payment Information" - Initially Expanded: false

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.

Last updated