recipe_card_stack 0.0.2 copy "recipe_card_stack: ^0.0.2" to clipboard
recipe_card_stack: ^0.0.2 copied to clipboard

A smooth, swipeable stacked-card widget with visible tabs, infinite looping, tap-to-focus selection, and fully customizable card UI. Perfect for recipes, flashcards, and index-style card layouts.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:recipe_card_stack/recipe_card_stack.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: Color(0xFFE0E0E0),
        body: Center(
          child: SizedBox(width: 320, height: 480, child: RecipeStackDemo()),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final recipes = <DemoRecipe>[
      const DemoRecipe(
        title: 'Banana Cake',
        description: 'Soft, moist banana cake with vanilla.',
        serves: '8',
        prepTime: '15 min',
        cookTime: '35 min',
        color: Color(0xFFFFF7E6),
      ),
      const DemoRecipe(
        title: 'Chocolate Cake',
        description: 'Rich and fudgy chocolate layers.',
        serves: '10',
        prepTime: '20 min',
        cookTime: '30 min',
        color: Color(0xFFFFEFEF),
      ),
      const DemoRecipe(
        title: 'Vanilla Cupcakes',
        description: 'Light vanilla cupcakes with buttercream.',
        serves: '12',
        prepTime: '15 min',
        cookTime: '18 min',
        color: Color(0xFFFFF9F0),
      ),
      const DemoRecipe(
        title: 'Carrot Cake',
        description: 'Spiced carrot cake with cream cheese frosting.',
        serves: '8',
        prepTime: '25 min',
        cookTime: '40 min',
        color: Color(0xFFF7FFF2),
      ),
    ];

    return InfiniteSwipeCardStack<DemoRecipe>(
      items: recipes,
      maxVisibleCards: 4,
      scaleGap: 0.05,
      verticalGap: 70.0,
      cardBuilder: (context, recipe, index, isFrontCard) {
        return DemoRecipeCard(recipe: recipe, isFrontCard: isFrontCard);
      },
      onSwipe: (index, direction, recipe) {
        debugPrint('Swiped ${recipe.title} to $direction');
      },
    );
  }
}

class DemoRecipe {
  final String title;
  final String description;
  final String serves;
  final String prepTime;
  final String cookTime;
  final Color color;

  const DemoRecipe({
    required this.title,
    required this.description,
    required this.serves,
    required this.prepTime,
    required this.cookTime,
    required this.color,
  });
}

class DemoRecipeCard extends StatelessWidget {
  final DemoRecipe recipe;
  final bool isFrontCard;

  const DemoRecipeCard({
    super.key,
    required this.recipe,
    required this.isFrontCard,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 360,
      decoration: BoxDecoration(
        color: recipe.color,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: Colors.black, width: 2),
      ),
      child: AnimatedSwitcher(
        duration: const Duration(milliseconds: 220),
        switchInCurve: Curves.easeOut,
        switchOutCurve: Curves.easeOut,
        transitionBuilder: (child, animation) {
          return FadeTransition(opacity: animation, child: child);
        },
        child: isFrontCard
            ? _buildFrontLayout(key: const ValueKey('front'))
            : _buildBackLayout(key: const ValueKey('back')),
      ),
    );
  }

  Widget _buildFrontLayout({required Key key}) {
    return Padding(
      key: key,
      padding: const EdgeInsets.all(16.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Center(
            child: Text(
              recipe.title,
              style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
          ),
          const SizedBox(height: 16),
          Text(recipe.description, style: const TextStyle(fontSize: 16)),
          const SizedBox(height: 16),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                "Serves: ${recipe.serves}",
                style: const TextStyle(fontSize: 16),
              ),
              Text(
                "Prep: ${recipe.prepTime}",
                style: const TextStyle(fontSize: 16),
              ),
              Text(
                "Cook: ${recipe.cookTime}",
                style: const TextStyle(fontSize: 16),
              ),
            ],
          ),
          const Spacer(),
          Align(
            alignment: Alignment.bottomRight,
            child: Text(
              "Read Recipe",
              style: TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.w500,
                decoration: TextDecoration.underline,
                color: Colors.black.withOpacity(0.8),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildBackLayout({required Key key}) {
    return Stack(
      key: key,
      children: [
        Positioned.fill(child: Container(color: recipe.color)),
        Align(
          alignment: Alignment.bottomLeft,
          child: Container(
            width: double.infinity,
            color: Colors.black.withOpacity(0.25),
            padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
            child: Text(
              recipe.title,
              style: const TextStyle(
                fontSize: 16,
                color: Colors.white,
                fontWeight: FontWeight.bold,
              ),
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
            ),
          ),
        ),
      ],
    );
  }
}
2
likes
0
points
52
downloads

Publisher

unverified uploader

Weekly Downloads

A smooth, swipeable stacked-card widget with visible tabs, infinite looping, tap-to-focus selection, and fully customizable card UI. Perfect for recipes, flashcards, and index-style card layouts.

Repository (GitHub)
View/report issues

Topics

#cards #swipe #stack #ui #selector

License

unknown (license)

Dependencies

flutter

More

Packages that depend on recipe_card_stack