Fluxy

Premium Widget Suite

High-quality, pre-styled widgets for modern Flutter apps.

Premium Widget Suite

Fluxy v0.1.7 introduces a suite of "Premium" widgets designed to handle common UI patterns with minimal configuration and built-in reactivity.

FxAvatar

A versatile avatar system with smart fallback logic. If an image fails to load or is not provided, it falls back to a string label or a custom widget.

Configuration

  • Image: Remote URL via the image property.
  • Fallback Label: Pass a string to fallback. It automatically extracts and capitalizes the first two characters.
  • Custom Fallback: Use fallbackWidget for icons or complex placeholders.
  • Shapes: Supports circle (default), square, and rounded.
  • Style: Pass an FxStyle directly.
  • ClassName: Apply shared styles via CSS-like class names.
  • Responsive: Pass an FxResponsiveStyle for adaptive looks.
FxAvatar(
  image: "https://avatar.iran.liara.run/public",
  fallback: "Jane Doe", // Displays "JA"
  size: FxAvatarSize.lg,
  shape: FxAvatarShape.rounded,
)

FxBadge

Wraps any widget with a highly customizable notification overlay.

  1. Custom: Passing a widget to content.

Layout-Aware Features

New in 0.1.6, FxBadge supports style, className, and responsive directly in the constructor, and respects Structural Recursion when used inside layout widgets.

FxBadge(
  label: "New",
  color: Colors.green,
  offset: const Offset(10, -10),
  child: Fx.box().square(50).bg(Colors.blue),
)

FxDropdown<T>

An Overlay-based selective UI that provides a modern, "web-like" select experience. It uses a CompositedTransformFollower to ensure the menu follows the trigger widget even during scrolls or animations.

Implementation Checklist

  • Atomic Binding: It is mandatory to provide either a value or a signal.
  • Custom Labels: Use itemLabel to define how each item is converted to text.
  • Custom Builders: Use itemBuilder for complex item layouts.
  • Dual Styling: Control the trigger button with style and the overlay menu with dropdownStyle.
  • Adaptive: Use the responsive parameter to change column counts or styles per breakpoint.
final selectedCity = flux("New York");

FxDropdown<String>(
  signal: selectedCity, // Two-way binding
  items: ["New York", "London", "Tokyo", "Berlin"],
  placeholder: "Select a city",
  
  // Custom Label Shortcut
  itemLabel: (city) => city.toUpperCase(),
  
  // Custom Trigger Styling
  style: FxStyle(
    backgroundColor: Colors.grey.withValues(alpha: 0.1),
    borderRadius: BorderRadius.circular(8),
    padding: const EdgeInsets.all(12),
  ),
  
  // Custom Menu Styling
  dropdownStyle: FxStyle(
    backgroundColor: Colors.white,
    boxShadow: [BoxShadow(color: Colors.black12, blurRadius: 10)],
  ),
  
  onChanged: (val) => print("Selected: $val"),
)

Complex Item Builder

You can render custom widgets for each dropdown item:

FxDropdown<User>(
  signal: currentUser,
  items: users,
  itemBuilder: (user) => Fx.row()
    .children([
      FxAvatar(image: user.avatar, size: FxAvatarSize.sm),
      Fx.text(user.name).ml(8),
    ]),
)

FxBottomBar

A pill-style, animated navigation bar with physics-based selection tracking. It provides a premium, "springy" feel out of the box.

FxBottomBar(
  selectedIndex: currentTab,
  items: [
    FxBottomBarItem(icon: Icons.home, label: "Home"),
    FxBottomBarItem(icon: Icons.search, label: "Search"),
    FxBottomBarItem(icon: Icons.person, label: "Profile"),
  ],
  onTap: (index) => currentTab.value = index,
)

FxTabScaffold (Parallel Navigation)

The FxTabScaffold is a high-level widget for building complex tab-based apps with parallel navigation stacks. This means each tab maintains its own navigation history.

final currentTab = flux(0);

FxTabScaffold(
  currentIndex: currentTab,
  tabs: [
    FxTabItem(
      label: "Home",
      icon: Icons.home,
      initialRoute: "/",
      routes: homeRoutes,
    ),
    FxTabItem(
      label: "Search",
      icon: Icons.search,
      initialRoute: "/discover",
      routes: searchRoutes,
    ),
  ],
)
  • When you navigate within the "Home" tab, the "Search" tab's state is preserved.
  • Use Fluxy.to("/some-path", scope: "Home") to navigate within a specific tab's stack.

FxButton

A fully responsive, theme-aware button component with multiple variants and fluent modifiers.

Basic Usage

Fx.button("Click Me", onTap: () => print("Clicked"))

Atomic Interaction API (New in 0.1.7)

You can now turn any String or Widget into a button directly using Buttonizers:

"Save".primaryBtn(onTap: () => save())
"Cancel".outlineBtn(onTap: () => back())
myIcon.btn(onTap: () => search()) // FxButtonVariant.none

Custom Content Injection

Buttons are now content-first. Use .withChild() for complex layouts:

Fx.button("Loading")
  .withChild(
    Fx.row().children([
      Fx.loader.shimmer().square(20),
      Fx.text("Processing...").ml(8),
    ])
  )

Interaction-Only Primitive

Use Fx.btn() to create custom interactive elements (like cards or list items) that utilize the framework's internal hover, focus, and pressed logic without any default styling.

Fx.btn(
  onTap: () => navigate(),
  child: MyCustomCard(),
)

Variants

Fluxy supports a wide range of semantic variants:

  • Fx.primaryButton("Label"): Default primary action (Blue).
  • Fx.secondaryButton("Label"): Secondary action (Slate).
  • Fx.textButton("Label"): Text-only button.
  • .danger: Red variant for destructive actions.
  • .success: Green variant for positive actions.
  • .warning: Amber variant for warnings.
  • .outline: Transparent background with border.
  • .ghost: Transparent background, hover effect only.
Fx.button("Delete").danger
Fx.button("Save").success
Fx.button("Cancel").outline

Sizes

Available in xs, sm, md (default), lg, and xl.

Fx.button("Tiny").sizeXs()
Fx.button("Large Action").sizeLg()

Fluent Modifiers

Chain modifiers to customize appearance and behavior instantly:

  • .rounded: Makes the button fully rounded (pill shape).
  • .square: Removes rounding.
  • .loading(bool): Shows a loading spinner and disables interaction.
  • .withIcon(Widget): Adds a leading icon.
  • .withTrailing(Widget): Adds a trailing icon.
  • .fullWidth(): Expands to fill available width.
  • .shadowSm(), .shadowMd(), .shadowLg(): Adds elevation.
Fx.button("Continue")
  .primary
  .sizeLg()
  .rounded
  .withIcon(Icon(Icons.arrow_forward))
  .fullWidth()
  .shadowMd()
  .onTap(() {
    // Action
  })

Advanced Layouts (New in 0.1.3)

Fluxy provides powerful layout primitives for building responsive interfaces.

FxLayout

The Fx.layout builder provides semantic targeting for different screen sizes.

Fx.layout(
  mobile: (context) => MobileView(),
  desktop: (context) => DesktopView(),
);

FxGrid

A responsive grid system that uses FxStyle for column control.

Fx.grid(
  gap: 16,
  children: myItems.map((item) => ItemCard(item)).toList(),
  // Mobile: 1 Column
  style: FxStyle(gridCols: 1), 
  // Tablet: 2 Cols, Desktop: 4 Cols
  responsive: FxResponsiveStyle(
    md: FxStyle(gridCols: 2),
    lg: FxStyle(gridCols: 4),
  ),
)

Data Display

FxTable

A premium data table with built-in scrolling, sticky headers, and hover effects.

Fx.table<User>(
  data: users,
  columns: [
    FxTableColumn(
      header: "Name", 
      cellBuilder: (user) => Fx.text(user.name).bold(),
    ),
    FxTableColumn(
      header: "Status", 
      cellBuilder: (user) => FxBadge(label: user.status, color: Colors.blue),
    ),
  ],
  striped: true,
  onRowTap: () => print("Row tapped"),
  style: FxStyle(padding: 20), // Direct styling supported
)

Collections (New in 0.1.4)

Fluxy v0.1.4 introduces performant ways to handle large datasets with reactive builders.

Fx.list()

Similar to ListView.builder, the Fx.list() helper provides a fluent way to build lazy-loading lists that are automatically reactive.

Fx.list(
  itemCount: 100,
  itemBuilder: (context, index) => Fx.text("Item $index").p(16),
)

Forms & Validation

Fluxy v0.1.4 features a complete reactive form system. For a detailed guide on validation rules and smart UX features, see the Forms & Inputs page.

Quick Example

// Define fields with rules
final email = fluxField("").required().email();
final password = fluxField("").required().minLength(8);

// Group into a form (optional)
final loginForm = fluxForm({
  "email": email,
  "password": password,
});

FxInput & FxForm

Use specialized widgets that automatically bind to these reactive fields.

Fx.form(
  child: Fx.column().children([
    Fx.input(
      signal: email, 
      placeholder: "Email Address",
    ),
    Fx.password(
      signal: password,
      placeholder: "Password",
    ),
    Fx.button("Login", onTap: () {
      if (loginForm.validate()) {
        // Proceed with login
      }
    }).mt(16),
  ]),
)

Interactive Form Controls

Fx.checkbox & Fx.switcher

Small, reactive toggles that bind directly to Signal<bool>.

final isToggled = flux(false);

Fx.checkbox(
  signal: isToggled,
  label: "Accept Terms",
)

Fx.switcher(signal: isToggled)

Feedback & Overlays

Fluxy includes responsive feedback mechanisms that adapt to the device form factor. For v0.1.6, we recommend using the new Context-Free API.

See the full Feedback & Overlays documentation for details on Fx.toast, Fx.loader, and Fx.dialog.

Usage in DSL

All premium widgets are also available via the Fx namespace for a consistent development experience, and can be styled using the new Proxy-based DSL:

Fx.avatar(image: "...")
  .shadow.md // Proxy syntax getter
;

On this page