Skip to content
HyperUI for Flutter requires the Style package — this site itself ships no pub package.

Cards

Ported from HyperUI’s Cards — see Attribution.

Title, author, avatar, excerpt, published date and reading time

Section titled “Title, author, avatar, excerpt, published date and reading time”
class CurrentColorIcon extends StatelessWidget
implements StyleReplacedElementWrapper {
const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override
Widget build(BuildContext context) {
final color = IconTheme.of(context).color ?? const Color(0xFF000000);
return SvgPicture.string(svg, theme: SvgTheme(currentColor: color));
}
}
class Cards1Example extends StatelessWidget {
const Cards1Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1633332755192-727a05c4013d?auto=format&fit=crop&q=80&w=1160';
static const _calendarSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5"/></svg>''';
static const _clockSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"/></svg>''';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'block rounded-md border border-gray-300 p-4 shadow-sm sm:p-6',
cursor: SystemMouseCursors.click,
children: [
Style(
'sm:flex sm:justify-between sm:gap-4 lg:gap-6',
children: [
Style(
'sm:order-last sm:shrink-0',
child: Style(
'size-16 rounded-full object-cover sm:size-18',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
),
Style(
'mt-4 sm:mt-0',
children: const [
Style(
'text-lg font-medium text-pretty text-gray-900',
child: Text('How I built my first website with Nuxt, Tailwind CSS and Vercel'),
),
Style('mt-1 text-sm text-gray-700', child: Text('By John Doe')),
Style(
'mt-4 line-clamp-2 text-sm text-pretty text-gray-700',
child: Text(
'Lorem ipsum dolor sit, amet consectetur adipisicing elit. At velit illum provident a, '
'ipsa maiores deleniti consectetur nobis et eaque.',
),
),
],
),
],
),
Style(
'mt-6 flex gap-4 lg:gap-6',
children: [
Style(
'flex items-center gap-2',
children: [
Style(
'text-gray-700',
children: [
const Style('sr-only', child: Text('Published on')),
Style('size-5', child: CurrentColorIcon(_calendarSvg)),
],
),
const Style('text-xs text-gray-700', child: Text('31/06/2025')),
],
),
Style(
'flex items-center gap-2',
children: [
Style(
'text-gray-700',
children: [
const Style('sr-only', child: Text('Reading time')),
Style('size-5', child: CurrentColorIcon(_clockSvg)),
],
),
const Style('text-xs text-gray-700', child: Text('12 minutes')),
],
),
],
),
],
),
);
}
}
class Cards2Example extends StatelessWidget {
const Cards2Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1605721911519-3dfeb3be25e7?auto=format&fit=crop&q=80&w=1160';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'block',
cursor: SystemMouseCursors.click,
children: [
Style(
'h-64 w-full object-cover sm:h-80 lg:h-96',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
const Style(
'mt-4 text-lg font-bold text-gray-900 sm:text-xl',
child: Text('Lorem, ipsum dolor.'),
),
const Style(
'mt-2 max-w-sm text-gray-700',
child: Text(
'Lorem ipsum dolor sit amet consectetur, adipisicing elit. Magni reiciendis sequi ipsam '
'incidunt.',
),
),
],
),
);
}
}
class Cards3Example extends StatelessWidget {
const Cards3Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1603871165848-0aa92c869fa1?auto=format&fit=crop&q=80&w=1160';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'group relative block bg-black',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-0 h-full w-full object-cover opacity-75 transition-opacity group-hover:opacity-50',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
Style(
'relative p-4 sm:p-6 lg:p-8',
children: [
const Style(
'text-sm font-medium tracking-widest text-pink-500 uppercase',
child: Text('Developer'),
),
const Style(
'text-xl font-bold text-white sm:text-2xl',
child: Text('Tony Wayne'),
),
Style(
'mt-32 sm:mt-48 lg:mt-64',
child: const Style(
'translate-y-8 transform opacity-0 transition-all group-hover:translate-y-0 group-hover:opacity-100',
child: Style(
'text-sm text-white',
child: Text(
'Lorem ipsum dolor, sit amet consectetur adipisicing elit. Omnis perferendis hic '
'asperiores quibusdam quidem voluptates doloremque reiciendis nostrum harum. '
'Repudiandae?',
),
),
),
),
],
),
],
),
);
}
}
class Cards4Example extends StatelessWidget {
const Cards4Example({super.key});
static const _compassSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>''';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'group relative block h-64 sm:h-80 lg:h-96',
cursor: SystemMouseCursors.click,
children: [
const Style('absolute inset-0 border-2 border-dashed border-black'),
Style(
'relative flex h-full transform items-end border-2 border-black bg-white transition-transform group-hover:-translate-x-2 group-hover:-translate-y-2',
children: [
Style(
'px-4 pb-4 transition-opacity group-hover:absolute group-hover:opacity-0 sm:px-6 sm:pb-4 lg:px-8 lg:pb-8',
children: [
Style(
'size-10 sm:size-12',
child: SvgPicture.string(
_compassSvg,
theme: SvgTheme(
currentColor:
IconTheme.of(context).color ??
const Color(0xFF000000),
),
),
),
const Style(
'mt-4 text-xl font-medium sm:text-2xl',
child: Text('Go around the world'),
),
],
),
Style(
'absolute p-4 opacity-0 transition-opacity group-hover:relative group-hover:opacity-100 sm:p-6 lg:p-8',
children: const [
Style(
'mt-4 text-xl font-medium sm:text-2xl',
child: Text('Go around the world'),
),
Style(
'mt-4 text-sm sm:text-base',
child: Text(
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Cupiditate, praesentium '
'voluptatem omnis atque culpa repellendus.',
),
),
Style('mt-8 font-bold', child: Text('Read more')),
],
),
],
),
],
),
);
}
}

Bordered with Image, Price, Content and Details

Section titled “Bordered with Image, Price, Content and Details”
class CurrentColorIcon extends StatelessWidget
implements StyleReplacedElementWrapper {
const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override
Widget build(BuildContext context) {
final color = IconTheme.of(context).color ?? const Color(0xFF000000);
return SvgPicture.string(svg, theme: SvgTheme(currentColor: color));
}
}
class Cards5Example extends StatelessWidget {
const Cards5Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1613545325278-f24b0cae1224?auto=format&fit=crop&q=80&w=1160';
static const _parkingSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 14v3m4-3v3m4-3v3M3 21h18M3 10h18M3 7l9-4 9 4M4 10h16v11H4V10z"/></svg>''';
static const _bathroomSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z"/></svg>''';
static const _bedroomSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>''';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'block rounded-lg p-4 shadow-xs shadow-indigo-100',
cursor: SystemMouseCursors.click,
children: [
Style(
'h-56 w-full rounded-md object-cover',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
Style(
'mt-2',
children: [
const Style('sr-only', child: Text('Price')),
const Style('text-sm text-gray-500', child: Text(r'$240,000')),
const Style('sr-only', child: Text('Address')),
const Style('font-medium', child: Text('123 Wallaby Avenue, Park Road')),
Style(
'mt-6 flex items-center gap-8 text-xs',
children: [
Style(
'sm:inline-flex sm:shrink-0 sm:items-center sm:gap-2',
children: [
Style(
'size-4 text-indigo-700',
child: CurrentColorIcon(_parkingSvg),
),
Style(
'mt-1.5 sm:mt-0',
children: const [
Style('text-gray-500', child: Text('Parking')),
Style('font-medium', child: Text('2 spaces')),
],
),
],
),
Style(
'sm:inline-flex sm:shrink-0 sm:items-center sm:gap-2',
children: [
Style(
'size-4 text-indigo-700',
child: CurrentColorIcon(_bathroomSvg),
),
Style(
'mt-1.5 sm:mt-0',
children: const [
Style('text-gray-500', child: Text('Bathroom')),
Style('font-medium', child: Text('2 rooms')),
],
),
],
),
Style(
'sm:inline-flex sm:shrink-0 sm:items-center sm:gap-2',
children: [
Style(
'size-4 text-indigo-700',
child: CurrentColorIcon(_bedroomSvg),
),
Style(
'mt-1.5 sm:mt-0',
children: const [
Style('text-gray-500', child: Text('Bedroom')),
Style('font-medium', child: Text('4 rooms')),
],
),
],
),
],
),
],
),
],
),
);
}
}

Image, Name, with Social Links and Project Links

Section titled “Image, Name, with Social Links and Project Links”
class Cards6Example extends StatelessWidget {
const Cards6Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1614644147724-2d4785d69962?auto=format&fit=crop&q=80&w=1160';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'rounded-xl border border-gray-700 bg-gray-800 p-4',
children: [
Style(
'flex items-center gap-4',
children: [
Style(
'size-16 rounded-full object-cover',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Style('text-lg font-medium text-white', child: Text('Claire Mac')),
Style(
'flow-root',
child: Style(
'-m-1 flex flex-wrap',
children: [
Style(
'p-1 leading-none',
child: Style(
'text-xs font-medium text-gray-300',
cursor: SystemMouseCursors.click,
child: const Text('Twitter'),
),
),
Style(
'p-1 leading-none',
child: Style(
'text-xs font-medium text-gray-300',
cursor: SystemMouseCursors.click,
child: const Text('GitHub'),
),
),
Style(
'p-1 leading-none',
child: Style(
'text-xs font-medium text-gray-300',
cursor: SystemMouseCursors.click,
child: const Text('Website'),
),
),
],
),
),
],
),
],
),
Style(
'mt-4 space-y-2',
children: [
Style(
'block h-full rounded-lg border border-gray-700 p-4 hover:border-pink-600',
cursor: SystemMouseCursors.click,
children: const [
Style('font-medium text-white', child: Text('Project A')),
Style(
'mt-1 text-xs font-medium text-gray-300',
child: Text(
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Maxime consequuntur '
'deleniti, unde ab ut in!',
),
),
],
),
Style(
'block h-full rounded-lg border border-gray-700 p-4 hover:border-pink-600',
cursor: SystemMouseCursors.click,
children: const [
Style('font-medium text-white', child: Text('Project B')),
Style(
'mt-1 text-xs font-medium text-gray-300',
child: Text(
'Lorem ipsum dolor sit amet consectetur adipisicing elit. Sapiente cumque saepe sit.',
),
),
],
),
],
),
],
),
);
}
}
class Cards7Example extends StatelessWidget {
const Cards7Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1588515724527-074a7a56616c?auto=format&fit=crop&q=80&w=1160';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
child: Style(
'block',
cursor: SystemMouseCursors.click,
children: [
Style(
'h-56 w-full rounded-se-3xl rounded-es-3xl object-cover sm:h-64 lg:h-72',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
Style(
'mt-4 sm:flex sm:items-center sm:justify-center sm:gap-4',
children: const [
Style('font-medium', child: Text('Company Name')),
Style('hidden sm:block sm:h-px sm:w-8 sm:bg-yellow-500'),
Style('mt-0.5 opacity-50 sm:mt-0', child: Text('Branding / Signage')),
],
),
],
),
);
}
}
class CurrentColorIcon extends StatelessWidget
implements StyleReplacedElementWrapper {
const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override
Widget build(BuildContext context) {
final color = IconTheme.of(context).color ?? const Color(0xFF000000);
return SvgPicture.string(svg, theme: SvgTheme(currentColor: color));
}
}
class Cards8Example extends StatelessWidget {
const Cards8Example({super.key});
static const _clockSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>''';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-3xl p-6',
child: Style(
'rounded-xl bg-white p-4 ring-3 ring-indigo-50 sm:p-6 lg:p-8',
child: Style(
'flex items-start sm:gap-8',
children: [
Style(
'hidden sm:grid sm:size-20 sm:shrink-0 sm:place-content-center sm:rounded-full sm:border-2 sm:border-indigo-500',
child: Style(
'flex items-center gap-1',
children: const [
Style('h-8 w-0.5 rounded-full bg-indigo-500'),
Style('h-6 w-0.5 rounded-full bg-indigo-500'),
Style('h-4 w-0.5 rounded-full bg-indigo-500'),
Style('h-6 w-0.5 rounded-full bg-indigo-500'),
Style('h-8 w-0.5 rounded-full bg-indigo-500'),
],
),
),
Style.empty(
children: [
const Style(
'rounded-sm border border-indigo-500 bg-indigo-500 px-3 py-1.5 text-[10px] font-medium text-white',
display: DisplayType.inline,
child: Text('Episode #101'),
),
Style(
'mt-4 text-lg font-medium sm:text-xl',
child: Style(
'hover:underline',
cursor: SystemMouseCursors.click,
child: const Text('Some Interesting Podcast Title'),
),
),
const Style(
'mt-1 text-sm text-gray-700',
child: Text(
'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ipsam nulla amet '
'voluptatum sit rerum, atque, quo culpa ut necessitatibus eius suscipit eum '
'accusamus, aperiam voluptas exercitationem facere aliquid fuga. Sint.',
),
),
Style(
'mt-4 sm:flex sm:items-center sm:gap-2',
children: [
Style(
'flex items-center gap-1 text-gray-500',
children: [
Style('size-4', child: CurrentColorIcon(_clockSvg)),
const Style('text-xs font-medium', child: Text('48:32 minutes')),
],
),
const Style('hidden sm:block', child: Text('·')),
Style(
'mt-2 text-xs font-medium text-gray-500 sm:mt-0',
child: Row(
textDirection: TextDirection.ltr,
mainAxisSize: MainAxisSize.min,
children: [
const Text('Featuring-3 '),
Style(
'underline hover:text-gray-700',
cursor: SystemMouseCursors.click,
child: const Text('Barry'),
),
const Text(', '),
Style(
'underline hover:text-gray-700',
cursor: SystemMouseCursors.click,
child: const Text('Sandra'),
),
const Text(' and '),
Style(
'underline hover:text-gray-700',
cursor: SystemMouseCursors.click,
child: const Text('August'),
),
],
),
),
],
),
],
),
],
),
),
);
}
}
class CurrentColorIcon extends StatelessWidget
implements StyleReplacedElementWrapper {
const CurrentColorIcon(this.svg, {super.key});
final String svg;
@override
Widget build(BuildContext context) {
final color = IconTheme.of(context).color ?? const Color(0xFF000000);
return SvgPicture.string(svg, theme: SvgTheme(currentColor: color));
}
}
class Cards9Example extends StatelessWidget {
const Cards9Example({super.key});
static const _photoUrl =
'https://images.unsplash.com/photo-1570295999919-56ceb5ecca61?auto=format&fit=crop&q=80&w=1160';
static const _chatSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"/></svg>''';
static const _checkBadgeSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"/></svg>''';
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-3xl p-6',
child: Style(
'rounded-xl border-2 border-gray-100 bg-white',
children: [
Style(
'flex items-start gap-4 p-4 sm:p-6 lg:p-8',
children: [
Style(
'block shrink-0',
cursor: SystemMouseCursors.click,
child: Style(
'size-14 rounded-lg object-cover',
child: Image.network(_photoUrl, fit: BoxFit.cover),
),
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Style(
'font-medium sm:text-lg',
child: Style(
'hover:underline',
cursor: SystemMouseCursors.click,
child: const Text('Question about Rendering'),
),
),
const Style(
'line-clamp-2 text-sm text-gray-700',
child: Text(
'Lorem ipsum dolor, sit amet consectetur adipisicing elit. Accusamus, accusantium '
'temporibus iure delectus ut totam natus nesciunt ex? Ducimus, enim.',
),
),
Style(
'mt-2 sm:flex sm:items-center sm:gap-2',
children: [
Style(
'flex items-center gap-1 text-gray-500',
children: [
Style('size-4', child: CurrentColorIcon(_chatSvg)),
const Style('text-xs', child: Text('14 comments')),
],
),
const Style('hidden sm:block', child: Text('·')),
Style(
'hidden sm:block sm:text-xs sm:text-gray-500',
child: Row(
textDirection: TextDirection.ltr,
mainAxisSize: MainAxisSize.min,
children: [
const Text('Posted by '),
Style(
'font-medium underline hover:text-gray-700',
cursor: SystemMouseCursors.click,
child: const Text('John'),
),
],
),
),
],
),
],
),
],
),
Style(
'flex justify-end',
child: Style(
'-me-0.5 -mb-0.5 inline-flex items-center gap-1 rounded-ss-xl rounded-ee-xl bg-green-600 px-3 py-1.5 text-white',
children: [
Style('size-4', child: CurrentColorIcon(_checkBadgeSvg)),
const Style(
'text-[10px] font-medium sm:text-xs',
display: DisplayType.inline,
child: Text('Solved!'),
),
],
),
),
],
),
);
}
}