File Uploaders
Ported from HyperUI’s File Uploaders — see Attribution.
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 _uploadIconSvg = '''<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="M7.5 7.5h-.75A2.25 2.25 0 0 0 4.5 9.75v7.5a2.25 2.25 0 0 0 2.25 2.25h7.5a2.25 2.25 0 0 0 2.25-2.25v-7.5a2.25 2.25 0 0 0-2.25-2.25h-.75m0-3-3-3m0 0-3 3m3-3v11.25m6-2.25h.75a2.25 2.25 0 0 1 2.25 2.25v7.5a2.25 2.25 0 0 1-2.25 2.25h-7.5a2.25 2.25 0 0 1-2.25-2.25v-.75"/></svg>''';
class FileUploaders1Example extends StatelessWidget { const FileUploaders1Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-md p-6', child: Style( 'block rounded border border-gray-300 bg-white p-4 text-gray-900 shadow-sm sm:p-6 dark:border-gray-700 dark:bg-gray-900 dark:text-white', children: [ Style( 'flex items-center justify-center gap-4', children: [ const Style( 'font-medium dark:text-white', child: Text('Upload your file(s)'), ), Style('size-6', child: CurrentColorIcon(_uploadIconSvg)), ], ), const Style('sr-only', child: SizedBox.shrink()), ], ), ); }}<label for="File" class="block rounded border border-gray-300 p-4 text-gray-900 shadow-sm sm:p-6"> <div class="flex items-center justify-center gap-4"> <span class="font-medium"> Upload your file(s) </span>
<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="size-6" > <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 7.5h-.75A2.25 2.25 0 0 0 4.5 9.75v7.5a2.25 2.25 0 0 0 2.25 2.25h7.5a2.25 2.25 0 0 0 2.25-2.25v-7.5a2.25 2.25 0 0 0-2.25-2.25h-.75m0-3-3-3m0 0-3 3m3-3v11.25m6-2.25h.75a2.25 2.25 0 0 1 2.25 2.25v7.5a2.25 2.25 0 0 1-2.25 2.25h-7.5a2.25 2.25 0 0 1-2.25-2.25v-.75" /> </svg> </div>
<input multiple type="file" id="File" class="sr-only" /></label>Base with button
Section titled “Base with button”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 _uploadIconSvg = '''<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="M7.5 7.5h-.75A2.25 2.25 0 0 0 4.5 9.75v7.5a2.25 2.25 0 0 0 2.25 2.25h7.5a2.25 2.25 0 0 0 2.25-2.25v-7.5a2.25 2.25 0 0 0-2.25-2.25h-.75m0-3-3-3m0 0-3 3m3-3v11.25m6-2.25h.75a2.25 2.25 0 0 1 2.25 2.25v7.5a2.25 2.25 0 0 1-2.25 2.25h-7.5a2.25 2.25 0 0 1-2.25-2.25v-.75"/></svg>''';
class FileUploaders2Example extends StatelessWidget { const FileUploaders2Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-md p-6', child: Style( 'flex flex-col items-center rounded border border-gray-300 bg-white p-4 text-gray-900 shadow-sm sm:p-6 dark:border-gray-700 dark:bg-gray-900 dark:text-white', children: [ Style('size-6', child: CurrentColorIcon(_uploadIconSvg)), const Style( 'mt-4 font-medium dark:text-white', child: Text('Upload your file(s)'), ), const Style( 'mt-2 inline-block rounded border border-gray-200 bg-gray-50 px-3 py-1.5 text-center text-xs font-medium text-gray-700 shadow-sm hover:bg-gray-100 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700', child: Text('Browse files'), ), const Style('sr-only', child: SizedBox.shrink()), ], ), ); }}<label for="File" class="flex flex-col items-center rounded border border-gray-300 p-4 text-gray-900 shadow-sm sm:p-6"> <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="size-6" > <path stroke-linecap="round" stroke-linejoin="round" d="M7.5 7.5h-.75A2.25 2.25 0 0 0 4.5 9.75v7.5a2.25 2.25 0 0 0 2.25 2.25h7.5a2.25 2.25 0 0 0 2.25-2.25v-7.5a2.25 2.25 0 0 0-2.25-2.25h-.75m0-3-3-3m0 0-3 3m3-3v11.25m6-2.25h.75a2.25 2.25 0 0 1 2.25 2.25v7.5a2.25 2.25 0 0 1-2.25 2.25h-7.5a2.25 2.25 0 0 1-2.25-2.25v-.75" /> </svg>
<span class="mt-4 font-medium"> Upload your file(s) </span>
<span class="mt-2 inline-block rounded border border-gray-200 bg-gray-50 px-3 py-1.5 text-center text-xs font-medium text-gray-700 shadow-sm hover:bg-gray-100" > Browse files </span>
<input multiple type="file" id="File" class="sr-only" /></label>