Empty States
Ported from HyperUI’s Empty States — see Attribution.
Create first item
Section titled “Create first item”Includes a dark: variant — toggle the site theme (top right) to preview it.
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)); }}
const _emptyStateIconSvg = '''<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 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z"/></svg>''';
class EmptyStates1Example extends StatelessWidget { const EmptyStates1Example({super.key});
@override Widget build(BuildContext context) { return Style( 'flex min-h-screen items-center justify-center p-6', child: Style( 'max-w-md text-center', children: [ const Style( 'mx-auto size-20 text-gray-400 dark:text-gray-500', child: CurrentColorIcon(_emptyStateIconSvg), ), const Style( 'mt-6 text-2xl font-bold text-gray-900 dark:text-white', child: Text('No items found'), ), const Style( 'mt-4 text-pretty text-gray-700 dark:text-gray-200', child: Text( 'Get started by creating your first item. It only takes a few seconds.', ), ), const Style( 'mt-6 block w-full rounded-lg bg-indigo-600 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-indigo-700', child: Text('Create Item'), ), Style( 'mt-6 text-sm text-gray-700 dark:text-gray-200', child: Center( child: Row( textDirection: TextDirection.ltr, mainAxisSize: MainAxisSize.min, children: const [ Style( 'underline hover:text-gray-900 dark:hover:text-white', cursor: SystemMouseCursors.click, child: Text('Learn how'), ), Text(' or '), Style( 'underline hover:text-gray-900 dark:hover:text-white', cursor: SystemMouseCursors.click, child: Text('view examples'), ), ], ), ), ), ], ), ); }}<div class="max-w-md text-center"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mx-auto size-20 text-gray-400" > <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" /> </svg>
<h2 class="mt-6 text-2xl font-bold text-gray-900">No items found</h2>
<p class="mt-4 text-pretty text-gray-700"> Get started by creating your first item. It only takes a few seconds. </p>
<button type="button" class="mt-6 block w-full rounded-lg bg-indigo-600 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-indigo-700" > Create Item </button>
<p class="mt-6 text-sm text-gray-700"> <a href="#" class="underline hover:text-gray-900">Learn how</a> or <a href="#" class="underline hover:text-gray-900">view examples</a> </p></div>Import or create
Section titled “Import or create”Includes a dark: variant — toggle the site theme (top right) to preview it.
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)); }}
const _emptyStateIconSvg = '''<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="M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75m16.5 0c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125"/></svg>''';
class EmptyStates2Example extends StatelessWidget { const EmptyStates2Example({super.key});
@override Widget build(BuildContext context) { return Style( 'flex min-h-screen items-center justify-center p-6', child: Style( 'max-w-md text-center', children: const [ Style( 'mx-auto size-20 text-gray-400 dark:text-gray-500', child: CurrentColorIcon(_emptyStateIconSvg), ), Style( 'mt-6 text-2xl font-bold text-gray-900 dark:text-white', child: Text('No data to display'), ), Style( 'mt-4 text-pretty text-gray-700 dark:text-gray-200', child: Text( 'Get started by creating your first item. It only takes a few seconds.', ), ), Style( 'mt-6 space-y-3', children: [ Style( 'block w-full rounded-lg bg-indigo-600 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-indigo-700', child: Text('Import Data'), ), Style( 'block w-full rounded-lg border border-gray-300 px-6 py-3 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50 dark:border-gray-600 dark:text-white dark:hover:bg-gray-800/50', child: Text('Create New'), ), ], ), Style( 'mt-6 text-sm text-gray-700 dark:text-gray-200', child: Text('Supported formats: CSV, JSON'), ), ], ), ); }}<div class="max-w-md text-center"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mx-auto size-20 text-gray-400" > <path stroke-linecap="round" stroke-linejoin="round" d="M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75m16.5 0c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125" /> </svg>
<h2 class="mt-6 text-2xl font-bold text-gray-900">No data to display</h2>
<p class="mt-4 text-pretty text-gray-700"> Get started by creating your first item. It only takes a few seconds. </p>
<div class="mt-6 space-y-3"> <button class="block w-full rounded-lg bg-indigo-600 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-indigo-700" > Import Data </button>
<button class="block w-full rounded-lg border border-gray-300 px-6 py-3 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50" > Create New </button> </div>
<p class="mt-6 text-sm text-gray-700">Supported formats: CSV, JSON</p></div>Upload data
Section titled “Upload data”Includes a dark: variant — toggle the site theme (top right) to preview it.
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)); }}
const _emptyStateIconSvg = '''<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="M9 8.25H7.5a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 0 0 2.25 2.25h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25H15m0-3-3-3m0 0-3 3m3-3V15"/></svg>''';
class EmptyStates3Example extends StatelessWidget { const EmptyStates3Example({super.key});
@override Widget build(BuildContext context) { return Style( 'flex min-h-screen items-center justify-center p-6', child: Style( 'max-w-md text-center', children: const [ Style( 'mx-auto size-20 text-gray-400 dark:text-gray-500', child: CurrentColorIcon(_emptyStateIconSvg), ), Style( 'mt-6 text-2xl font-bold text-gray-900 dark:text-white', child: Text('Upload your files'), ), Style( 'mt-4 text-pretty text-gray-700 dark:text-gray-200', child: Text( 'Drag and drop files here or click to browse your computer.', ), ), Style( 'mt-6 block rounded-lg border-2 border-dashed border-gray-300 p-6 transition-colors hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-gray-800/50', children: [ Style( 'text-sm font-semibold text-indigo-600 dark:text-indigo-500', display: DisplayType.inline, child: Text('Choose files'), ), Style('sr-only', child: SizedBox.shrink()), ], ), Style( 'mt-6 text-sm text-gray-700 dark:text-gray-200', child: Text( 'Maximum file size: 10MB. Supported formats: PDF, DOCX, XLSX', ), ), ], ), ); }}<div class="max-w-md text-center"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mx-auto size-20 text-gray-400" > <path stroke-linecap="round" stroke-linejoin="round" d="M9 8.25H7.5a2.25 2.25 0 0 0-2.25 2.25v9a2.25 2.25 0 0 0 2.25 2.25h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25H15m0-3-3-3m0 0-3 3m3-3V15" /> </svg>
<h2 class="mt-6 text-2xl font-bold text-gray-900">Upload your files</h2>
<p class="mt-4 text-pretty text-gray-700"> Drag and drop files here or click to browse your computer. </p>
<label for="files" class="mt-6 block rounded-lg border-2 border-dashed border-gray-300 p-6 transition-colors hover:bg-gray-50" > <span class="text-sm font-semibold text-indigo-600"> Choose files </span>
<input type="file" id="files" class="sr-only" /> </label>
<p class="mt-6 text-sm text-gray-700"> Maximum file size: 10MB. Supported formats: PDF, DOCX, XLSX </p></div>Get started
Section titled “Get started”Includes a dark: variant — toggle the site theme (top right) to preview it.
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)); }}
const _emptyStateIconSvg = '''<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="m3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75Z"/></svg>''';
class EmptyStates4Example extends StatelessWidget { const EmptyStates4Example({super.key});
@override Widget build(BuildContext context) { return Style( 'flex min-h-screen items-center justify-center p-6', child: Style( 'max-w-md text-center', children: const [ Style( 'mx-auto size-20 text-gray-400 dark:text-gray-500', child: CurrentColorIcon(_emptyStateIconSvg), ), Style( 'mt-6 text-2xl font-bold text-gray-900 dark:text-white', child: Text('Get started in seconds'), ), Style( 'mt-4 text-pretty text-gray-700 dark:text-gray-200', child: Text('Complete these quick steps to set up your workspace.'), ), Style( 'mt-6 space-y-2 text-left', children: [ Style( 'flex items-center gap-2', children: [ Style( 'grid size-6 shrink-0 place-content-center rounded-full bg-indigo-600 text-sm font-medium text-white', child: Text('1'), ), Style( 'text-sm text-gray-700 dark:text-gray-200', display: DisplayType.inline, child: Text('Create your first project'), ), ], ), Style( 'flex items-center gap-2', children: [ Style( 'grid size-6 shrink-0 place-content-center rounded-full bg-indigo-600 text-sm font-medium text-white', child: Text('2'), ), Style( 'text-sm text-gray-700 dark:text-gray-200', display: DisplayType.inline, child: Text('Invite team members'), ), ], ), Style( 'flex items-center gap-2', children: [ Style( 'grid size-6 shrink-0 place-content-center rounded-full bg-indigo-600 text-sm font-medium text-white', child: Text('3'), ), Style( 'text-sm text-gray-700 dark:text-gray-200', display: DisplayType.inline, child: Text('Start collaborating'), ), ], ), ], ), Style( 'mt-6 block w-full rounded-lg bg-indigo-600 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-indigo-700', child: Text('Create Project'), ), ], ), ); }}<div class="max-w-md text-center"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mx-auto size-20 text-gray-400" > <path stroke-linecap="round" stroke-linejoin="round" d="m3.75 13.5 10.5-11.25L12 10.5h8.25L9.75 21.75 12 13.5H3.75Z" /> </svg>
<h2 class="mt-6 text-2xl font-bold text-gray-900">Get started in seconds</h2>
<p class="mt-4 text-pretty text-gray-700"> Complete these quick steps to set up your workspace. </p>
<ol class="mt-6 space-y-2 text-left"> <li class="flex items-center gap-2"> <span class="grid size-6 shrink-0 place-content-center rounded-full bg-indigo-600 text-sm font-medium text-white" > 1 </span>
<span class="text-sm text-gray-700">Create your first project</span> </li>
<li class="flex items-center gap-2"> <span class="grid size-6 shrink-0 place-content-center rounded-full bg-indigo-600 text-sm font-medium text-white" > 2 </span>
<span class="text-sm text-gray-700">Invite team members</span> </li>
<li class="flex items-center gap-2"> <span class="grid size-6 shrink-0 place-content-center rounded-full bg-indigo-600 text-sm font-medium text-white" > 3 </span>
<span class="text-sm text-gray-700">Start collaborating</span> </li> </ol>
<button class="mt-6 block w-full rounded-lg bg-indigo-600 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-indigo-700" > Create Project </button></div>No results found
Section titled “No results found”Includes a dark: variant — toggle the site theme (top right) to preview it.
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)); }}
const _emptyStateIconSvg = '''<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="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Zm3.75 11.625a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z"/></svg>''';
class EmptyStates5Example extends StatelessWidget { const EmptyStates5Example({super.key});
@override Widget build(BuildContext context) { return Style( 'flex min-h-screen items-center justify-center p-6', child: Style( 'max-w-md text-center', children: [ const Style( 'mx-auto size-20 text-gray-400 dark:text-gray-500', child: CurrentColorIcon(_emptyStateIconSvg), ), const Style( 'mt-6 text-2xl font-bold text-gray-900 dark:text-white', child: Text('No results found'), ), const Style( 'mt-4 text-pretty text-gray-700 dark:text-gray-200', child: Text( "Try adjusting your search or filters to find what you're looking for.", ), ), Style( 'mt-6 space-y-2', children: [ Style( 'w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:text-white', child: const TextField( decoration: InputDecoration( hintText: 'Search again...', border: InputBorder.none, isDense: true, contentPadding: EdgeInsets.zero, ), ), ), const Style( 'block w-full rounded-lg border border-gray-300 px-6 py-3 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50 dark:border-gray-600 dark:text-white dark:hover:bg-gray-800', child: Text('Clear filters'), ), ], ), Style( 'mt-6 text-sm text-gray-700 dark:text-gray-200', child: Center( child: Row( textDirection: TextDirection.ltr, mainAxisSize: MainAxisSize.min, children: const [ Style( 'underline transition-colors hover:text-gray-900 dark:hover:text-white', cursor: SystemMouseCursors.click, child: Text('Contact support'), ), Text(' if you need help'), ], ), ), ), ], ), ); }}<div class="max-w-md text-center"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="mx-auto size-20 text-gray-400" > <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m5.231 13.481L15 17.25m-4.5-15H5.625c-.621 0-1.125.504-1.125 1.125v16.5c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Zm3.75 11.625a2.625 2.625 0 1 1-5.25 0 2.625 2.625 0 0 1 5.25 0Z" /> </svg>
<h2 class="mt-6 text-2xl font-bold text-gray-900">No results found</h2>
<p class="mt-4 text-pretty text-gray-700"> Try adjusting your search or filters to find what you're looking for. </p>
<div class="mt-6 space-y-2"> <input type="text" placeholder="Search again..." class="w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" />
<button class="block w-full rounded-lg border border-gray-300 px-6 py-3 text-sm font-medium text-gray-900 transition-colors hover:bg-gray-50" > Clear filters </button> </div>
<p class="mt-6 text-sm text-gray-700"> <a href="#" class="underline transition-colors hover:text-gray-900">Contact support</a> if you need help </p></div>