Data Presentation

Card

A flexible container component that displays content with an optional title, subtitle, and child widget. Cards are commonly used to group related information and actions.

  dart run forui snippet create card
1class CardExample extends StatelessWidget {
2 @override
3 Widget build(BuildContext _) => Card(
4 title: const Text('Notifications'),
5 subtitle: const Text('You have 3 unread messages.'),
6 child: FButton(onPress: () {}, child: const Text('Mark all as read')),
7 );
8}
9
10class Card extends StatelessWidget {
11 final Widget title;
12 final Widget subtitle;
13 final Widget child;
14 const Card({
15 required this.title,
16 required this.subtitle,
17 required this.child,
18 super.key,
19 });
20 @override
21 Widget build(BuildContext context) {
22 final style = context.theme.cardStyle;
23 return FCard(
24 style: style,
25 child: Padding(
26 padding: style.padding,
27 child: Column(
28 crossAxisAlignment: .start,
29 mainAxisSize: .min,
30 children: [
31 DefaultTextStyle.merge(
32 textHeightBehavior: const TextHeightBehavior(
33 applyHeightToFirstAscent: false,
34 applyHeightToLastDescent: false,
35 ),
36 style: style.titleTextStyle,
37 child: title,
38 ),
39 const SizedBox(height: 2),
40 DefaultTextStyle.merge(
41 textHeightBehavior: const TextHeightBehavior(
42 applyHeightToFirstAscent: false,
43 applyHeightToLastDescent: false,
44 ),
45 style: style.subtitleTextStyle,
46 child: subtitle,
47 ),
48 const SizedBox(height: 6),
49 child,
50 ],
51 ),
52 ),
53 );
54 }
55}
56

CLI

To generate a specific style for customization:

dart run forui style create card

Usage

FCard(...)

1FCard(
2 style: const .delta(decoration: .shapeDelta(color: Color(0xFFFFFFFF))),
3 clipBehavior: .none,
4 builder: (context, style, child) => child!,
5 child: const Text('Content'),
6)

Examples

Title

  dart run forui snippet create title-card
1class TitleCardExample extends StatelessWidget {
2 @override
3 Widget build(BuildContext _) => const TitleCard(
4 title: Text('Notifications'),
5 subtitle: Text('You have 3 unread messages.'),
6 );
7}
8
9class TitleCard extends StatelessWidget {
10 final Widget title;
11 final Widget subtitle;
12 const TitleCard({required this.title, required this.subtitle, super.key});
13 @override
14 Widget build(BuildContext context) {
15 final style = context.theme.cardStyle;
16 return FCard(
17 style: style,
18 child: Padding(
19 padding: style.padding,
20 child: Column(
21 crossAxisAlignment: .start,
22 mainAxisSize: .min,
23 children: [
24 DefaultTextStyle.merge(
25 textHeightBehavior: const TextHeightBehavior(
26 applyHeightToFirstAscent: false,
27 applyHeightToLastDescent: false,
28 ),
29 style: style.titleTextStyle,
30 child: title,
31 ),
32 const SizedBox(height: 2),
33 DefaultTextStyle.merge(
34 textHeightBehavior: const TextHeightBehavior(
35 applyHeightToFirstAscent: false,
36 applyHeightToLastDescent: false,
37 ),
38 style: style.subtitleTextStyle,
39 child: subtitle,
40 ),
41 ],
42 ),
43 ),
44 );
45 }
46}
47

Media

  dart run forui snippet create media-card
1class MediaCardExample extends StatelessWidget {
2 @override
3 Widget build(BuildContext _) => MediaCard(
4 image: Container(
5 decoration: BoxDecoration(
6 image: DecorationImage(
7 image: AssetImage(path('avatar.png')),
8 fit: .cover,
9 ),
10 ),
11 height: 200,
12 ),
13 title: const Text('Gratitude'),
14 subtitle: const Text(
15 'The quality of being thankful; readiness to show appreciation for and to return kindness.',
16 ),
17 child: FButton(onPress: () {}, child: const Text('Read more')),
18 );
19}
20
21class MediaCard extends StatelessWidget {
22 final Widget image;
23 final Widget title;
24 final Widget subtitle;
25 final Widget child;
26 const MediaCard({
27 required this.image,
28 required this.title,
29 required this.subtitle,
30 required this.child,
31 super.key,
32 });
33 @override
34 Widget build(BuildContext context) {
35 final style = context.theme.cardStyle;
36 return FCard(
37 style: style,
38 child: Padding(
39 padding: style.padding,
40 child: Column(
41 crossAxisAlignment: .start,
42 mainAxisSize: .min,
43 children: [
44 ClipPath(
45 clipper: ShapeBorderClipper(
46 shape: RoundedSuperellipseBorder(
47 borderRadius: context.theme.style.borderRadius.lg,
48 ),
49 ),
50 child: image,
51 ),
52 const SizedBox(height: 24),
53 DefaultTextStyle.merge(
54 textHeightBehavior: const TextHeightBehavior(
55 applyHeightToFirstAscent: false,
56 applyHeightToLastDescent: false,
57 ),
58 style: style.titleTextStyle,
59 child: title,
60 ),
61 const SizedBox(height: 2),
62 DefaultTextStyle.merge(
63 textHeightBehavior: const TextHeightBehavior(
64 applyHeightToFirstAscent: false,
65 applyHeightToLastDescent: false,
66 ),
67 style: style.subtitleTextStyle,
68 child: subtitle,
69 ),
70 const SizedBox(height: 6),
71 child,
72 ],
73 ),
74 ),
75 );
76 }
77}
78

On this page