Claude Code Plugins

Community-maintained marketplace

Feedback

Flutter UI patterns including layouts, Material 3 components, and responsive design. Use when building screens, creating reusable widgets, or implementing responsive layouts.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name flutter-ui
description Flutter UI patterns including layouts, Material 3 components, and responsive design. Use when building screens, creating reusable widgets, or implementing responsive layouts.

Flutter UI Building

Widget Decision

Need Widget
Vertical list Column (few) or ListView (many)
Horizontal list Row (few) or ListView.horizontal (many)
Overlapping widgets Stack + Positioned
Grid GridView.builder
Spacing/sizing SizedBox (preferred) or Container
Decorations (shadow, border) Container with BoxDecoration

Detailed Guides

Topic Guide Use When
Layouts layouts.md Row, Column, Stack, Flex patterns
Material 3 material-components.md Scaffold, AppBar, Cards, Buttons
Responsive responsive.md LayoutBuilder, MediaQuery, adaptive

Essential Patterns

Standard Widget Structure

class ProductCard extends StatelessWidget {
  const ProductCard({
    super.key,
    required this.product,
    this.onTap,
  });

  final Product product;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    
    return Card(
      child: InkWell(
        onTap: onTap,
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(product.name, style: theme.textTheme.titleMedium),
              const SizedBox(height: 8),
              Text(product.description, style: theme.textTheme.bodyMedium),
            ],
          ),
        ),
      ),
    );
  }
}

Use const Constructors

// ✅ Widget cached, never rebuilds
const SizedBox(height: 16)
const Icon(Icons.home)
const Text('Static text')

// ❌ Recreated every build
SizedBox(height: 16)
Icon(Icons.home)

SizedBox vs Container

// ✅ SizedBox for spacing (lighter)
const SizedBox(height: 16)
const SizedBox(width: 8)
SizedBox(width: 100, height: 100, child: widget)

// ✅ Container for decoration
Container(
  padding: const EdgeInsets.all(16),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(8),
    boxShadow: [BoxShadow(...)],
  ),
  child: widget,
)

Keys for Lists

// ✅ Use keys when list items can reorder
ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) {
    return ListTile(
      key: ValueKey(items[index].id),  // Unique, stable key
      title: Text(items[index].name),
    );
  },
)

Layout Quick Reference

Expand vs Flexible

Row(
  children: [
    Expanded(child: Text('Takes remaining space')),     // flex: 1, fit: tight
    Flexible(child: Text('Takes needed space, can shrink')),  // fit: loose
    const SizedBox(width: 100),  // Fixed width
  ],
)

Stack Positioning

Stack(
  children: [
    // Background (fills entire stack)
    Positioned.fill(child: Image.asset('bg.png', fit: BoxFit.cover)),
    
    // Top-right corner
    Positioned(top: 16, right: 16, child: CloseButton()),
    
    // Centered
    Center(child: Text('Centered content')),
    
    // Bottom, full width
    Positioned(left: 0, right: 0, bottom: 0, child: BottomBar()),
  ],
)

Theme Usage

// Access theme
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final textTheme = theme.textTheme;

// Use theme values
Text('Title', style: textTheme.headlineMedium)
Container(color: colorScheme.primaryContainer)
Icon(Icons.star, color: colorScheme.primary)

Common Patterns

Loading State

Widget build(BuildContext context) {
  if (isLoading) {
    return const Center(child: CircularProgressIndicator());
  }
  
  if (error != null) {
    return Center(child: Text('Error: $error'));
  }
  
  return ContentWidget(data: data);
}

Pull to Refresh

RefreshIndicator(
  onRefresh: () async {
    await viewModel.refresh();
  },
  child: ListView.builder(...),
)

Safe Area

Scaffold(
  body: SafeArea(
    child: Column(
      children: [...],
    ),
  ),
)