flek_select 0.5.0 copy "flek_select: ^0.5.0" to clipboard
flek_select: ^0.5.0 copied to clipboard

A customizable Flutter select widget library with Select dropdown and ToggleButtonGroup components. Features flexible overlay options and tree-shakable exports.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flek_select/select.dart';
import 'package:flek_select/select_option.dart';
import 'package:flek_select/toggle_button_group.dart';
import 'package:tappable/tappable.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'flek_select Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const ExamplePage(),
    );
  }
}

class ExamplePage extends StatefulWidget {
  const ExamplePage({super.key});

  @override
  State<ExamplePage> createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;

  // Select state
  String? _selectedLanguage;
  String? _selectedCountryCustom;

  // Toggle button state
  String? _selectedSize;
  String? _selectedColorCustom;

  // Option lists
  final _languageOptions = [
    SelectOption<String, void>(text: 'English', value: 'en'),
    SelectOption<String, void>(text: 'Spanish', value: 'es'),
    SelectOption<String, void>(text: 'French', value: 'fr'),
    SelectOption<String, void>(text: 'German', value: 'de'),
  ];

  final _countryOptions = [
    SelectOption<String, void>(text: 'United States', value: 'us'),
    SelectOption<String, void>(text: 'Canada', value: 'ca'),
    SelectOption<String, void>(text: 'United Kingdom', value: 'uk'),
    SelectOption<String, void>(text: 'Australia', value: 'au'),
  ];

  final _sizeOptions = [
    SelectOption<String, void>(text: 'S', value: 's'),
    SelectOption<String, void>(text: 'M', value: 'm'),
    SelectOption<String, void>(text: 'L', value: 'l'),
    SelectOption<String, void>(text: 'XL', value: 'xl'),
  ];

  final _colorOptions = [
    SelectOption<String, void>(text: 'Red', value: 'red'),
    SelectOption<String, void>(text: 'Blue', value: 'blue'),
    SelectOption<String, void>(text: 'Green', value: 'green'),
  ];

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: 2, vsync: this);
  }

  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('flek_select v0.5.0'),
        bottom: TabBar(
          controller: _tabController,
          tabs: const [
            Tab(text: 'Select'),
            Tab(text: 'ToggleButtonGroup'),
          ],
        ),
      ),
      body: TabBarView(
        controller: _tabController,
        children: [
          _buildSelectTab(),
          _buildToggleButtonGroupTab(),
        ],
      ),
    );
  }

  Widget _buildSelectTab() {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _buildSectionTitle('1. Basic Select (Default)'),
          const SizedBox(height: 8),
          const Text(
            'Uses GestureDetector by default (no visual feedback)',
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
          const SizedBox(height: 8),
          Select<String, void>(
            inputLabel: 'Language',
            options: _languageOptions,
            value: _selectedLanguage,
            onChange: (value) => setState(() => _selectedLanguage = value),
          ),
          const SizedBox(height: 32),
          _buildSectionTitle('2. Select with Custom Input Builder + Tappable'),
          const SizedBox(height: 8),
          const Text(
            'Custom inputBuilder using Tappable for touch feedback',
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
          const SizedBox(height: 8),
          Select<String, void>(
            options: _countryOptions,
            value: _selectedCountryCustom,
            onChange: (value) =>
                setState(() => _selectedCountryCustom = value),
            inputBuilder: (context, selectedOption, isDisabled, onOpenSelectPopup) {
              return Tappable(
                onTap: isDisabled ? null : onOpenSelectPopup,
                borderRadius: BorderRadius.circular(12),
                child: Container(
                  padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
                  decoration: BoxDecoration(
                    color: Colors.blue.shade50,
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(color: Colors.blue.shade200),
                  ),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        selectedOption?.text ?? 'Select a country',
                        style: TextStyle(
                          color: selectedOption != null
                              ? Colors.blue.shade900
                              : Colors.blue.shade400,
                        ),
                      ),
                      Icon(
                        Icons.keyboard_arrow_down,
                        color: Colors.blue.shade600,
                      ),
                    ],
                  ),
                ),
              );
            },
            backdropBuilder: (context, onCloseSelectPopup) {
              return Tappable(
                onTap: onCloseSelectPopup,
                child: Container(color: Colors.black54),
              );
            },
          ),
          const SizedBox(height: 32),
          _buildSectionTitle('3. Select with InkWell (Material Ripple)'),
          const SizedBox(height: 8),
          const Text(
            'Custom inputBuilder using InkWell for Material feedback',
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
          const SizedBox(height: 8),
          Select<String, void>(
            inputLabel: 'Language (InkWell)',
            options: _languageOptions,
            value: _selectedLanguage,
            onChange: (value) => setState(() => _selectedLanguage = value),
            inputBuilder: (context, selectedOption, isDisabled, onOpenSelectPopup) {
              return Material(
                color: Colors.transparent,
                child: InkWell(
                  onTap: isDisabled ? null : onOpenSelectPopup,
                  borderRadius: BorderRadius.circular(8),
                  child: Container(
                    padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
                    decoration: BoxDecoration(
                      color: Colors.white10,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          selectedOption?.text ?? 'Select...',
                          style: const TextStyle(color: Colors.grey),
                        ),
                        const Icon(Icons.arrow_drop_down, color: Colors.grey),
                      ],
                    ),
                  ),
                ),
              );
            },
          ),
        ],
      ),
    );
  }

  Widget _buildToggleButtonGroupTab() {
    return SingleChildScrollView(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          _buildSectionTitle('1. Basic ToggleButtonGroup (Default)'),
          const SizedBox(height: 8),
          const Text(
            'Uses GestureDetector by default (no visual feedback)',
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
          const SizedBox(height: 8),
          ToggleButtonGroup<String, void>(
            options: _sizeOptions,
            value: _selectedSize,
            onChange: (value) => setState(() => _selectedSize = value),
          ),
          const SizedBox(height: 32),
          _buildSectionTitle('2. ToggleButtonGroup with Custom Builder + Tappable'),
          const SizedBox(height: 8),
          const Text(
            'Custom buttonBuilder using Tappable for touch feedback',
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
          const SizedBox(height: 8),
          ToggleButtonGroup<String, void>(
            options: _colorOptions,
            value: _selectedColorCustom,
            onChange: (value) => setState(() => _selectedColorCustom = value),
            buttonBuilder: (context, option, isActive, onSelect) {
              return Tappable(
                onTap: onSelect,
                borderRadius: BorderRadius.circular(20),
                child: Container(
                  padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
                  decoration: BoxDecoration(
                    color: isActive ? _getColor(option.value) : Colors.grey.shade100,
                    borderRadius: BorderRadius.circular(20),
                    border: Border.all(
                      color: isActive ? _getColor(option.value) : Colors.grey.shade300,
                      width: 2,
                    ),
                  ),
                  child: Text(
                    option.text,
                    style: TextStyle(
                      color: isActive ? Colors.white : Colors.black87,
                      fontWeight: isActive ? FontWeight.bold : FontWeight.normal,
                    ),
                  ),
                ),
              );
            },
          ),
          const SizedBox(height: 32),
          _buildSectionTitle('3. ToggleButtonGroup with InkWell'),
          const SizedBox(height: 8),
          const Text(
            'Custom buttonBuilder using InkWell for Material feedback',
            style: TextStyle(color: Colors.grey, fontSize: 12),
          ),
          const SizedBox(height: 8),
          ToggleButtonGroup<String, void>(
            options: _sizeOptions,
            value: _selectedSize,
            onChange: (value) => setState(() => _selectedSize = value),
            buttonBuilder: (context, option, isActive, onSelect) {
              return Material(
                color: Colors.transparent,
                child: InkWell(
                  onTap: onSelect,
                  borderRadius: BorderRadius.circular(8),
                  child: Container(
                    padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
                    decoration: BoxDecoration(
                      color: isActive ? Colors.blue : Colors.grey.shade200,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Text(
                      option.text,
                      style: TextStyle(
                        color: isActive ? Colors.white : Colors.black87,
                        fontWeight: isActive ? FontWeight.w600 : FontWeight.w400,
                      ),
                    ),
                  ),
                ),
              );
            },
          ),
        ],
      ),
    );
  }

  Color _getColor(String? value) {
    switch (value) {
      case 'red':
        return Colors.red;
      case 'blue':
        return Colors.blue;
      case 'green':
        return Colors.green;
      default:
        return Colors.grey;
    }
  }

  Widget _buildSectionTitle(String title) {
    return Text(
      title,
      style: Theme.of(context).textTheme.titleMedium?.copyWith(
            fontWeight: FontWeight.bold,
          ),
    );
  }
}
2
likes
150
points
150
downloads

Publisher

unverified uploader

Weekly Downloads

A customizable Flutter select widget library with Select dropdown and ToggleButtonGroup components. Features flexible overlay options and tree-shakable exports.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flek_select