Inputs
Ported from HyperUI’s Inputs — see Attribution.
Includes a dark: variant — toggle the site theme (top right) to preview it.
class NeobrutalismInputs1Example extends StatelessWidget { const NeobrutalismInputs1Example({super.key});
@override Widget build(BuildContext context) { final isSmUp = MediaQuery.sizeOf(context).width >= 640; final fontSize = isSmUp ? 14.0 : 16.0; final lineHeight = isSmUp ? 20.0 : 24.0; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); final isDark = Theme.of(context).brightness == Brightness.dark;
return Style( 'mx-auto max-w-sm p-6', child: Style( 'text-black dark:text-white', display: DisplayType.block, children: [ const Style( 'text-sm font-semibold', display: DisplayType.inline, child: Text('Email'), ), Style( 'mt-0.5 w-full border-2 border-black bg-white shadow-[4px_4px_0_0] shadow-black focus:ring-2 focus:ring-yellow-300 sm:text-sm dark:border-white dark:bg-gray-900 dark:shadow-white dark:focus:ring-yellow-600', child: TextFormField( keyboardType: TextInputType.emailAddress, style: baseStyle.copyWith( fontSize: fontSize, height: lineHeight / fontSize, color: isDark ? Colors.white : Colors.black, ), ), ), ], ), ); }}<label for="Email" class="text-black"> <span class="text-sm font-semibold"> Email </span>
<input type="email" id="Email" class="mt-0.5 w-full border-2 border-black bg-white shadow-[4px_4px_0_0] shadow-black focus:ring-2 focus:ring-yellow-300 sm:text-sm" /></label>Base with icon
Section titled “Base with icon”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 _searchSvg = '''<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor"><path fill-rule="evenodd" d="M11.89 4.111a5.5 5.5 0 1 0 0 7.778.75.75 0 1 1 1.06 1.061A7 7 0 1 1 15 8a2.5 2.5 0 0 1-4.083 1.935A3.5 3.5 0 1 1 11.5 8a1 1 0 0 0 2 0 5.48 5.48 0 0 0-1.61-3.889ZM10 8a2 2 0 1 0-4 0 2 2 0 0 0 4 0Z" clip-rule="evenodd"/></svg>''';
class NeobrutalismInputs2Example extends StatelessWidget { const NeobrutalismInputs2Example({super.key});
@override Widget build(BuildContext context) { final isSmUp = MediaQuery.sizeOf(context).width >= 640; final fontSize = isSmUp ? 14.0 : 16.0; final lineHeight = isSmUp ? 20.0 : 24.0; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); final isDark = Theme.of(context).brightness == Brightness.dark;
return Style( 'mx-auto max-w-sm p-6', child: Style( 'text-black dark:text-white', display: DisplayType.block, children: [ const Style( 'text-sm font-semibold', display: DisplayType.inline, child: Text('Email'), ), Style( 'relative mt-0.5', children: [ Style( 'w-full border-2 border-black bg-white pe-8 shadow-[4px_4px_0_0] shadow-black focus:ring-2 focus:ring-yellow-300 sm:text-sm dark:border-white dark:bg-gray-900 dark:shadow-white dark:focus:ring-yellow-600', child: TextFormField( keyboardType: TextInputType.emailAddress, style: baseStyle.copyWith( fontSize: fontSize, height: lineHeight / fontSize, color: isDark ? Colors.white : Colors.black, ), ), ), Style( 'absolute top-1 right-1 grid size-8 place-content-center bg-black text-white dark:bg-white dark:text-gray-900', child: Style('size-4', child: CurrentColorIcon(_searchSvg)), ), ], ), ], ), ); }}<label for="Email" class="text-black"> <span class="text-sm font-semibold"> Email </span>
<div class="relative mt-0.5"> <input type="email" id="Email" class="w-full border-2 border-black bg-white pe-8 shadow-[4px_4px_0_0] shadow-black focus:ring-2 focus:ring-yellow-300 sm:text-sm" />
<span class="absolute top-1 right-1 grid size-8 place-content-center bg-black text-white"> <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4" > <path fill-rule="evenodd" d="M11.89 4.111a5.5 5.5 0 1 0 0 7.778.75.75 0 1 1 1.06 1.061A7 7 0 1 1 15 8a2.5 2.5 0 0 1-4.083 1.935A3.5 3.5 0 1 1 11.5 8a1 1 0 0 0 2 0 5.48 5.48 0 0 0-1.61-3.889ZM10 8a2 2 0 1 0-4 0 2 2 0 0 0 4 0Z" clip-rule="evenodd" /> </svg> </span> </div></label>Search
Section titled “Search”Includes a dark: variant — toggle the site theme (top right) to preview it.
class NeobrutalismInputs3Example extends StatelessWidget { const NeobrutalismInputs3Example({super.key});
@override Widget build(BuildContext context) { final isSmUp = MediaQuery.sizeOf(context).width >= 640; final fontSize = isSmUp ? 14.0 : 16.0; final lineHeight = isSmUp ? 20.0 : 24.0; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); final isDark = Theme.of(context).brightness == Brightness.dark;
return Style( 'mx-auto max-w-sm p-6', children: [ const Style('sr-only', child: Text('Search')), Style( 'flex border-2 border-black shadow-[4px_4px_0_0] shadow-black focus-within:ring-2 focus-within:ring-yellow-300 dark:border-white dark:shadow-white dark:focus-within:ring-yellow-600', children: [ Style( 'w-full border-none bg-white text-black focus:ring-0 sm:text-sm dark:bg-gray-900 dark:text-white', child: SizedBox( height: lineHeight, child: TextFormField( keyboardType: TextInputType.text, decoration: const InputDecoration( isCollapsed: true, contentPadding: EdgeInsets.zero, border: InputBorder.none, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, disabledBorder: InputBorder.none, errorBorder: InputBorder.none, focusedErrorBorder: InputBorder.none, ), style: baseStyle.copyWith( fontSize: fontSize, height: lineHeight / fontSize, color: isDark ? Colors.white : Colors.black, ), ), ), ), const Style( 'bg-yellow-300 px-4 py-2 text-xs/none font-bold tracking-wide uppercase hover:bg-yellow-400 focus:bg-yellow-400 focus:outline-0 dark:bg-yellow-600 dark:hover:bg-yellow-500 dark:focus:bg-yellow-500', child: Text('Search'), ), ], ), ], ); }}<label for="Search"> <span class="sr-only"> Search </span>
<div class="flex border-2 border-black shadow-[4px_4px_0_0] shadow-black focus-within:ring-2 focus-within:ring-yellow-300" > <input type="search" id="Search" class="w-full border-none bg-white text-black focus:ring-0 sm:text-sm" />
<button type="submit" class="bg-yellow-300 px-4 py-2 text-xs/none font-bold tracking-wide uppercase hover:bg-yellow-400 focus:bg-yellow-400 focus:outline-0" > Search </button> </div></label>