promotion_card 1.0.0
promotion_card: ^1.0.0 copied to clipboard
A flexible Flutter widget for promotion cards with built-in variants, RTL-aware overlay positioning, and Material 3 theme extension support.
promotion_card #
A flexible, themeable Flutter widget for building promotion cards with built-in support for multiple visual variants, stacked overlays, and Material 3 theme extensions.
Features #
- Four built-in variants —
primary,soft,imageHero, andminimal - Composable layout — leading icon/widget, title, description, body, trailing action, and a stacked overlay slot
- RTL-aware — uses
PositionedDirectionaland directional arrow icons throughout - Three-layer theming — variant defaults → app-wide
ThemeExtension→ per-widget overrides - Background flexibility — solid color, gradient, or
DecorationImage - Auto trailing arrow — generated automatically when
onTapis provided - Material 3 compatible —
PromotionCardThemeDataimplementsThemeExtension
Getting started #
Add the package to your pubspec.yaml:
dependencies:
promotion_card: ^1.0.0
Then run:
flutter pub get
Import it in your Dart code:
import 'package:promotion_card/promotion_card.dart';
Usage #
Minimal example #
PromotionCard(
title: Text('Summer Sale', style: Theme.of(context).textTheme.titleMedium),
body: Padding(
padding: const EdgeInsets.all(16),
child: Text('Up to 50% off selected items.'),
),
)
With a leading icon, description, and tap action #
PromotionCard(
leading: const Icon(Icons.local_offer, color: Colors.white),
title: Text('Exclusive Offer'),
description: Text('Valid until end of month'),
body: Padding(
padding: const EdgeInsets.all(16),
child: Text('Get 3 months free on any annual plan.'),
),
onTap: () => Navigator.pushNamed(context, '/promo'),
style: PromotionCardStyle(
backgroundColor: Colors.deepPurple,
borderRadius: BorderRadius.circular(16),
arrowColor: Colors.white,
),
)
Variants #
Use the variant parameter to switch between visual presets defined in your theme.
PromotionCard(
variant: PromotionCardVariant.soft,
title: Text('New Arrivals'),
body: /* ... */,
)
| Variant | Description |
|---|---|
primary |
Default high-emphasis card |
soft |
Subtle, low-contrast styling |
imageHero |
Image-prominent layout |
minimal |
Bare-bones, content-first |
Variant visual defaults (colors, leading widget, overlay) are configured through PromotionCardThemeData — see Theme integration below.
Style overrides #
Use PromotionCardStyle to override any style property on a single card without touching your theme.
PromotionCard(
title: Text('Flash Deal'),
body: /* ... */,
style: PromotionCardStyle(
gradient: LinearGradient(
colors: [Colors.orange, Colors.deepOrange],
),
borderRadius: BorderRadius.circular(12),
padding: EdgeInsetsDirectional.fromSTEB(20, 16, 12, 16),
),
)
PromotionCardStyle properties #
| Property | Type | Default | Description |
|---|---|---|---|
backgroundColor |
Color? |
— | Solid background color |
gradient |
Gradient? |
— | Background gradient (overrides backgroundColor) |
backgroundImage |
DecorationImage? |
— | Background image |
padding |
EdgeInsetsGeometry? |
EdgeInsetsDirectional.all(16) |
Inner padding for the header area |
borderRadius |
BorderRadiusGeometry? |
BorderRadius.zero |
Corner rounding |
arrowColor |
Color? |
colorScheme.onSurface |
Color of the auto-generated trailing arrow |
leadingWidth |
double? |
40 |
Width of the leading widget slot |
leadingHeight |
double? |
40 |
Height of the leading widget slot |
leadingEndPadding |
double? |
8 |
Space between leading widget and title |
showOverlay |
bool? |
auto | Force overlay on/off; auto-detected from overlay presence when null |
overlayPosition |
PromotionCardOverlayPosition? |
— | Position of the stacked overlay |
Stacked overlay #
The overlay slot renders a widget on top of the card shell using PositionedDirectional. Useful for decorative images, badges, or ribbons.
PromotionCard(
title: Text('Refer a Friend'),
body: /* ... */,
overlay: Image.asset('assets/gift_box.png'),
style: PromotionCardStyle(
overlayPosition: PromotionCardOverlayPosition(
end: 0,
bottom: 0,
width: 80,
height: 80,
),
),
)
PromotionCardOverlayPosition properties #
| Property | Type | Description |
|---|---|---|
top |
double? |
Distance from top |
bottom |
double? |
Distance from bottom |
start |
double? |
Distance from the start edge (RTL-aware) |
end |
double? |
Distance from the end edge (RTL-aware) |
width |
double? |
Fixed width for the overlay widget |
height |
double? |
Fixed height for the overlay widget |
Theme integration #
Register PromotionCardThemeData as a Material 3 ThemeExtension to define per-variant defaults app-wide. Individual PromotionCard widgets inherit these defaults and can still override them via style, leading, overlay, and trailing.
MaterialApp(
theme: ThemeData(
extensions: [
PromotionCardThemeData(
variants: {
PromotionCardVariant.primary: PromotionCardVariantData(
leading: const Icon(Icons.bolt, color: Colors.white),
style: PromotionCardStyle(
backgroundColor: Colors.indigo,
borderRadius: BorderRadius.circular(16),
arrowColor: Colors.white,
),
),
PromotionCardVariant.soft: PromotionCardVariantData(
style: PromotionCardStyle(
backgroundColor: Color(0xFFF0F4FF),
borderRadius: BorderRadius.circular(12),
),
),
PromotionCardVariant.imageHero: PromotionCardVariantData(
style: PromotionCardStyle(
backgroundImage: DecorationImage(
image: AssetImage('assets/hero_bg.jpg'),
fit: BoxFit.cover,
),
borderRadius: BorderRadius.circular(20),
),
),
PromotionCardVariant.minimal: PromotionCardVariantData(
style: PromotionCardStyle(
padding: EdgeInsetsDirectional.all(12),
),
),
},
),
],
),
home: MyHomePage(),
)
Once registered, all PromotionCard widgets in the subtree inherit the configured defaults without any additional setup.
API reference #
PromotionCard #
| Parameter | Type | Required | Description |
|---|---|---|---|
title |
Widget |
Yes | Header title widget |
body |
Widget |
Yes | Main content area below the header |
description |
Widget? |
No | Subtitle displayed below the title |
onTap |
VoidCallback? |
No | Tap handler; auto-generates a trailing arrow icon when set |
variant |
PromotionCardVariant |
No | Visual preset (primary by default) |
style |
PromotionCardStyle? |
No | Per-widget style overrides |
theme |
PromotionCardThemeData? |
No | Explicit theme; falls back to ThemeExtension then defaults |
leading |
Widget? |
No | Leading slot widget (overrides variant default) |
overlay |
Widget? |
No | Stacked overlay widget (overrides variant default) |
trailing |
Widget? |
No | Trailing slot widget (overrides auto arrow) |
PromotionCardThemeData #
| Method | Description |
|---|---|
PromotionCardThemeData({variants}) |
Constructor; pass a map of variant → variant data |
resolve(variant) |
Returns the PromotionCardVariantData for a given variant |
fallback(context) |
Returns neutral defaults derived from the current color scheme |
copyWith({variants}) |
Creates a modified copy |
PromotionCardVariantData #
| Property | Type | Description |
|---|---|---|
leading |
Widget? |
Default leading widget for this variant |
overlay |
Widget? |
Default overlay widget for this variant |
style |
PromotionCardStyle |
Style defaults for this variant |
| Method | Description |
|---|---|
mergeWidgets({leading, overlay}) |
Returns a copy with the given widgets, falling back to existing values |
Customization hierarchy #
Style and widget resolution follows a most-specific-wins order:
Variant defaults (PromotionCardThemeData)
↓ merged with
App ThemeExtension (or fallback)
↓ overridden by
Per-widget style / leading / overlay / trailing parameters
Contributing #
Contributions, bug reports, and feature requests are welcome. Please open an issue or submit a pull request on GitHub.
License #
MIT — see LICENSE for details.