Contact Forms
Ported from HyperUI’s Contact Forms — see Attribution.
Includes a dark: variant — toggle the site theme (top right) to preview it.
class ContactForms1Example extends StatelessWidget { const ContactForms1Example({super.key});
@override Widget build(BuildContext context) { return Style( 'p-6', child: Style( 'mx-auto max-w-md space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6 dark:border-gray-600 dark:bg-gray-800', children: [ Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Name'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField(context, hintText: 'Your name'), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Email'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField( context, hintText: 'Your email', keyboardType: TextInputType.emailAddress, ), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Message'), ), Style( 'mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:text-white', child: Builder( builder: (context) => _buildField(context, hintText: 'Your message', maxLines: 4, minLines: 4), ), ), ], ), Style( 'block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600 dark:hover:bg-indigo-700 dark:hover:text-white', child: const Text('Send Message'), ), ], ), ); }}
Widget _buildField( BuildContext context, { required String hintText, TextInputType? keyboardType, int? maxLines, int? minLines,}) { final isDark = Theme.of(context).brightness == Brightness.dark; final borderColor = isDark ? tailwindColors['gray']![600]! : tailwindColors['gray']![300]!; final border = OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor), ); final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return TextFormField( keyboardType: keyboardType, maxLines: maxLines, minLines: minLines, style: baseStyle.copyWith( color: isDark ? Colors.white : Colors.black, letterSpacing: 0, ), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: tailwindColors['gray']![500], letterSpacing: 0), isDense: true, filled: true, fillColor: isDark ? tailwindColors['gray']![900] : Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9), border: border, enabledBorder: border, focusedBorder: border, ), );}<form action="#" class="mx-auto max-w-md space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6"> <div> <label class="block text-sm font-medium text-gray-900" for="name">Name</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="name" type="text" placeholder="Your name" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="email">Email</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="email" type="email" placeholder="Your email" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="message">Message</label>
<textarea class="mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="message" rows="4" placeholder="Your message" ></textarea> </div>
<button class="block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600" type="submit" > Send Message </button></form>Base with triage
Section titled “Base with triage”Includes a dark: variant — toggle the site theme (top right) to preview it.
class ContactForms2Example extends StatelessWidget { const ContactForms2Example({super.key});
static const _subjectOptions = <String, String>{ '': 'Select a subject', 'general-inquiry': 'General Inquiry', 'support': 'Support', 'feedback': 'Feedback', };
static const _priorityOptions = <String, String>{ '': 'Select a priority', 'low': 'Low', 'medium': 'Medium', 'high': 'High', };
@override Widget build(BuildContext context) { return Style( 'p-6', child: Style( 'mx-auto max-w-md space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6 dark:border-gray-600 dark:bg-gray-800', children: [ Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Name'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField(context, hintText: 'Your name'), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Email'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField( context, hintText: 'Your email', keyboardType: TextInputType.emailAddress, ), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Subject'), ), Style( 'mt-1 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: Builder(builder: (context) => _buildSelect(context, _subjectOptions)), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Priority'), ), Style( 'mt-1 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: Builder(builder: (context) => _buildSelect(context, _priorityOptions)), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Message'), ), Style( 'mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:text-white', child: Builder( builder: (context) => _buildField(context, hintText: 'Your message', maxLines: 4, minLines: 4), ), ), ], ), Style( 'block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600 dark:hover:bg-indigo-700 dark:hover:text-white', child: const Text('Send Message'), ), ], ), ); }}
const _chevronSvg = '''<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20"><path stroke="#6b7280" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M6 8l4 4 4-4"/></svg>''';
OutlineInputBorder _fieldBorder(bool isDark) { final borderColor = isDark ? tailwindColors['gray']![600]! : tailwindColors['gray']![300]!; return OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor), );}
Widget _buildField( BuildContext context, { required String hintText, TextInputType? keyboardType, int? maxLines, int? minLines,}) { final isDark = Theme.of(context).brightness == Brightness.dark; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return TextFormField( keyboardType: keyboardType, maxLines: maxLines, minLines: minLines, style: baseStyle.copyWith( color: isDark ? Colors.white : Colors.black, letterSpacing: 0, ), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: tailwindColors['gray']![500], letterSpacing: 0), isDense: true, filled: true, fillColor: isDark ? tailwindColors['gray']![900] : Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9), border: _fieldBorder(isDark), enabledBorder: _fieldBorder(isDark), focusedBorder: _fieldBorder(isDark), ), );}
Widget _buildSelect(BuildContext context, Map<String, String> options) { final isDark = Theme.of(context).brightness == Brightness.dark; final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); final textColor = isDark ? Colors.white : tailwindColors['gray']![900]!; return Stack( children: [ DropdownButtonFormField<String>( initialValue: '', isExpanded: true, itemHeight: null, icon: const SizedBox.shrink(), style: baseStyle.copyWith(color: textColor, letterSpacing: 0), decoration: InputDecoration( isDense: true, filled: true, fillColor: isDark ? tailwindColors['gray']![900] : Colors.white, contentPadding: const EdgeInsets.fromLTRB(12, 8, 40, 8), border: _fieldBorder(isDark), enabledBorder: _fieldBorder(isDark), focusedBorder: _fieldBorder(isDark), ), items: [ for (final entry in options.entries) DropdownMenuItem(value: entry.key, child: Text(entry.value)), ], onChanged: (_) {}, ), Positioned.fill( child: IgnorePointer( child: Align( alignment: Alignment.centerRight, child: Padding( padding: const EdgeInsets.only(right: 8), child: SvgPicture.string(_chevronSvg, width: 24, height: 24), ), ), ), ), ], );}<form action="#" class="mx-auto max-w-md space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6"> <div> <label class="block text-sm font-medium text-gray-900" for="name">Name</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="name" type="text" placeholder="Your name" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="email">Email</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="email" type="email" placeholder="Your email" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="subject">Subject</label>
<select class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="subject" > <option value="">Select a subject</option> <option value="general-inquiry">General Inquiry</option> <option value="support">Support</option> <option value="feedback">Feedback</option> </select> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="priority">Priority</label>
<select class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="priority" > <option value="">Select a priority</option> <option value="low">Low</option> <option value="medium">Medium</option> <option value="high">High</option> </select> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="message">Message</label>
<textarea class="mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="message" rows="4" placeholder="Your message" ></textarea> </div>
<button class="block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600" type="submit" > Send Message </button></form>Base with checkboxes
Section titled “Base with checkboxes”Includes a dark: variant — toggle the site theme (top right) to preview it.
class ContactForms3Example extends StatefulWidget { const ContactForms3Example({super.key});
@override State<ContactForms3Example> createState() => _ContactForms3ExampleState();}
class _ContactForms3ExampleState extends State<ContactForms3Example> { var _generalInquiry = false; var _support = false; var _feedback = false; var _other = false;
@override Widget build(BuildContext context) { return Style( 'p-6', child: Style( 'mx-auto max-w-md space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6 dark:border-gray-600 dark:bg-gray-800', children: [ Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Name'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField(context, hintText: 'Your name'), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Email'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField( context, hintText: 'Your email', keyboardType: TextInputType.emailAddress, ), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Inquiry'), ), Style( 'mt-2 space-y-2', children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _generalInquiry = !_generalInquiry), child: Style( 'flex items-center gap-2', cursor: SystemMouseCursors.click, children: [ Style( 'size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900 dark:text-white', formControl: true, checked: _generalInquiry, ), const Style( 'block text-sm text-gray-900 dark:text-white', child: Text('General Inquiry'), ), ], ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _support = !_support), child: Style( 'flex items-center gap-2', cursor: SystemMouseCursors.click, children: [ Style( 'size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900 dark:text-white', formControl: true, checked: _support, ), const Style( 'block text-sm text-gray-900 dark:text-white', child: Text('Support'), ), ], ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _feedback = !_feedback), child: Style( 'flex items-center gap-2', cursor: SystemMouseCursors.click, children: [ Style( 'size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900 dark:text-white', formControl: true, checked: _feedback, ), const Style( 'block text-sm text-gray-900 dark:text-white', child: Text('Feedback'), ), ], ), ), GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _other = !_other), child: Style( 'flex items-center gap-2', cursor: SystemMouseCursors.click, children: [ Style( 'size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900 dark:text-white', formControl: true, checked: _other, ), const Style( 'block text-sm text-gray-900 dark:text-white', child: Text('Other'), ), ], ), ), ], ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Message'), ), Style( 'mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:text-white', child: Builder( builder: (context) => _buildField(context, hintText: 'Your message', maxLines: 4, minLines: 4), ), ), ], ), Style( 'block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600 dark:hover:bg-indigo-700 dark:hover:text-white', child: const Text('Send Message'), ), ], ), ); }}
Widget _buildField( BuildContext context, { required String hintText, TextInputType? keyboardType, int? maxLines, int? minLines,}) { final isDark = Theme.of(context).brightness == Brightness.dark; final borderColor = isDark ? tailwindColors['gray']![600]! : tailwindColors['gray']![300]!; final border = OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor), ); final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return TextFormField( keyboardType: keyboardType, maxLines: maxLines, minLines: minLines, style: baseStyle.copyWith( color: isDark ? Colors.white : Colors.black, letterSpacing: 0, ), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: tailwindColors['gray']![500], letterSpacing: 0), isDense: true, filled: true, fillColor: isDark ? tailwindColors['gray']![900] : Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9), border: border, enabledBorder: border, focusedBorder: border, ), );}<form action="#" class="mx-auto max-w-md space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6"> <div> <label class="block text-sm font-medium text-gray-900" for="name">Name</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="name" type="text" placeholder="Your name" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="email">Email</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="email" type="email" placeholder="Your email" /> </div>
<fieldset> <legend class="block text-sm font-medium text-gray-900">Inquiry</legend>
<div class="mt-2 space-y-2"> <div class="flex items-center gap-2"> <input class="size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" id="general-inquiry" type="checkbox" name="inquiry-type" value="general-inquiry" />
<label class="block text-sm text-gray-900" for="general-inquiry">General Inquiry</label> </div>
<div class="flex items-center gap-2"> <input class="size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" id="support" type="checkbox" name="inquiry-type" value="support" />
<label class="block text-sm text-gray-900" for="support">Support</label> </div>
<div class="flex items-center gap-2"> <input class="size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" id="feedback" type="checkbox" name="inquiry-type" value="feedback" />
<label class="block text-sm text-gray-900" for="feedback">Feedback</label> </div>
<div class="flex items-center gap-2"> <input class="size-5 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" id="other" type="checkbox" name="inquiry-type" value="other" />
<label class="block text-sm text-gray-900" for="other">Other</label> </div> </div> </fieldset>
<div> <label class="block text-sm font-medium text-gray-900" for="message">Message</label>
<textarea class="mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="message" rows="4" placeholder="Your message" ></textarea> </div>
<button class="block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600" type="submit" > Send Message </button></form>Includes a dark: variant — toggle the site theme (top right) to preview it.
class ContactForms4Example extends StatelessWidget { const ContactForms4Example({super.key});
@override Widget build(BuildContext context) { return Style( 'p-6', child: Style( 'mx-auto grid max-w-lg grid-cols-1 gap-4 rounded-lg border border-gray-300 bg-gray-100 p-6 sm:grid-cols-2 dark:border-gray-600 dark:bg-gray-800', children: [ Style( 'md:col-span-2', children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Name'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField(context, hintText: 'Your name'), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Email'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField( context, hintText: 'Your email', keyboardType: TextInputType.emailAddress, ), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Phone'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField(context, hintText: 'Your phone', keyboardType: TextInputType.phone), ), ), ], ), Style( 'md:col-span-2', children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Message'), ), Style( 'mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:text-white', child: Builder( builder: (context) => _buildField(context, hintText: 'Your message', maxLines: 4, minLines: 4), ), ), ], ), Style( 'md:col-span-2', child: Style( 'block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600 dark:hover:bg-indigo-700 dark:hover:text-white', child: const Text('Send Message'), ), ), ], ), ); }}
Widget _buildField( BuildContext context, { required String hintText, TextInputType? keyboardType, int? maxLines, int? minLines,}) { final isDark = Theme.of(context).brightness == Brightness.dark; final borderColor = isDark ? tailwindColors['gray']![600]! : tailwindColors['gray']![300]!; final border = OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor), ); final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return TextFormField( keyboardType: keyboardType, maxLines: maxLines, minLines: minLines, style: baseStyle.copyWith( color: isDark ? Colors.white : Colors.black, letterSpacing: 0, ), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: tailwindColors['gray']![500], letterSpacing: 0), isDense: true, filled: true, fillColor: isDark ? tailwindColors['gray']![900] : Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9), border: border, enabledBorder: border, focusedBorder: border, ), );}<form action="#" class="mx-auto grid max-w-lg grid-cols-1 gap-4 rounded-lg border border-gray-300 bg-gray-100 p-6 sm:grid-cols-2"> <div class="md:col-span-2"> <label class="block text-sm font-medium text-gray-900" for="name">Name</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="name" type="text" placeholder="Your name" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="email">Email</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="email" type="email" placeholder="Your email" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="phone">Phone</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="phone" type="tel" placeholder="Your phone" /> </div>
<div class="md:col-span-2"> <label class="block text-sm font-medium text-gray-900" for="message">Message</label>
<textarea class="mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="message" rows="4" placeholder="Your message" ></textarea> </div>
<div class="md:col-span-2"> <button class="block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600" type="submit" > Send Message </button> </div></form>Side-by-side form with description
Section titled “Side-by-side form with description”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 _phoneSvg = '''<svg aria-hidden="true" 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="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3"/></svg>''';
const _envelopeSvg = '''<svg aria-hidden="true" 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="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75"/></svg>''';
const _locationSvg = '''<svg aria-hidden="true" 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="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"/></svg>''';
class ContactForms5Example extends StatelessWidget { const ContactForms5Example({super.key});
@override Widget build(BuildContext context) { return Style( 'mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8', child: Style( 'grid grid-cols-1 gap-8 md:grid-cols-2', children: [ Style( 'md:py-4', children: [ const Style( 'text-2xl font-bold text-gray-900 sm:text-3xl dark:text-white', child: Text('Get in touch'), ), const Style( 'mt-4 text-pretty text-gray-700 dark:text-gray-200', child: Text( 'Lorem, ipsum dolor sit amet consectetur adipisicing elit. Sed voluptas delectus alias magni velit! Dicta corrupti dignissimos dolor consequatur illum tempore consectetur hic a cupiditate sunt quam, earum nisi aperiam.', ), ), Style( 'mt-6 space-y-3', children: [ Style.empty( children: [ const Style('sr-only', child: Text('Phone number')), Style( 'grid grid-cols-[24px_1fr] items-center gap-2 text-gray-700 dark:text-gray-200', children: [ Style('size-5', child: CurrentColorIcon(_phoneSvg)), const Style( 'font-medium', child: Text('+1 (555) 123-4567'), ), ], ), ], ), Style.empty( children: [ const Style('sr-only', child: Text('Email')), Style( 'grid grid-cols-[24px_1fr] items-center gap-2 text-gray-700 dark:text-gray-200', children: [ Style('size-5', child: CurrentColorIcon(_envelopeSvg)), const Style( 'font-medium', child: Text('info@example.com'), ), ], ), ], ), Style.empty( children: [ const Style('sr-only', child: Text('Location')), Style( 'grid grid-cols-[24px_1fr] items-center gap-2 text-gray-700 dark:text-gray-200', children: [ Style('size-5', child: CurrentColorIcon(_locationSvg)), const Style( 'font-medium', child: Text('123 Main St, Anytown, USA'), ), ], ), ], ), ], ), ], ), Style( 'space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6 dark:border-gray-600 dark:bg-gray-800', children: [ Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Name'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField(context, hintText: 'Your name'), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Email'), ), Style( 'mt-1 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: Builder( builder: (context) => _buildField( context, hintText: 'Your email', keyboardType: TextInputType.emailAddress, ), ), ), ], ), Style.empty( children: [ const Style( 'block text-sm font-medium text-gray-900 dark:text-white', child: Text('Message'), ), Style( 'mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:text-white', child: Builder( builder: (context) => _buildField(context, hintText: 'Your message', maxLines: 4, minLines: 4), ), ), ], ), Style( 'block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600 dark:hover:bg-indigo-700 dark:hover:text-white', child: const Text('Send Message'), ), ], ), ], ), ); }}
Widget _buildField( BuildContext context, { required String hintText, TextInputType? keyboardType, int? maxLines, int? minLines,}) { final isDark = Theme.of(context).brightness == Brightness.dark; final borderColor = isDark ? tailwindColors['gray']![600]! : tailwindColors['gray']![300]!; final border = OutlineInputBorder( borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: borderColor), ); final baseStyle = Theme.of(context).textTheme.bodyLarge ?? const TextStyle(); return TextFormField( keyboardType: keyboardType, maxLines: maxLines, minLines: minLines, style: baseStyle.copyWith( color: isDark ? Colors.white : Colors.black, letterSpacing: 0, ), decoration: InputDecoration( hintText: hintText, hintStyle: TextStyle(color: tailwindColors['gray']![500], letterSpacing: 0), isDense: true, filled: true, fillColor: isDark ? tailwindColors['gray']![900] : Colors.white, contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 9), border: border, enabledBorder: border, focusedBorder: border, ), );}<div class="mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"> <div class="grid grid-cols-1 gap-8 md:grid-cols-2"> <div class="md:py-4"> <h2 class="text-2xl font-bold text-gray-900 sm:text-3xl">Get in touch</h2>
<p class="mt-4 text-pretty text-gray-700"> Lorem, ipsum dolor sit amet consectetur adipisicing elit. Sed voluptas delectus alias magni velit! Dicta corrupti dignissimos dolor consequatur illum tempore consectetur hic a cupiditate sunt quam, earum nisi aperiam. </p>
<dl class="mt-6 space-y-3"> <div> <dt class="sr-only">Phone number</dt>
<dd class="grid grid-cols-[24px_1fr] items-center gap-2 text-gray-700"> <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-5" > <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 1.5H8.25A2.25 2.25 0 0 0 6 3.75v16.5a2.25 2.25 0 0 0 2.25 2.25h7.5A2.25 2.25 0 0 0 18 20.25V3.75a2.25 2.25 0 0 0-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 18.75h3" /> </svg>
<span class="font-medium">+1 (555) 123-4567</span> </dd> </div>
<div> <dt class="sr-only">Email</dt>
<dd class="grid grid-cols-[24px_1fr] items-center gap-2 text-gray-700"> <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-5" > <path stroke-linecap="round" stroke-linejoin="round" d="M21.75 6.75v10.5a2.25 2.25 0 0 1-2.25 2.25h-15a2.25 2.25 0 0 1-2.25-2.25V6.75m19.5 0A2.25 2.25 0 0 0 19.5 4.5h-15a2.25 2.25 0 0 0-2.25 2.25m19.5 0v.243a2.25 2.25 0 0 1-1.07 1.916l-7.5 4.615a2.25 2.25 0 0 1-2.36 0L3.32 8.91a2.25 2.25 0 0 1-1.07-1.916V6.75" /> </svg>
<span class="font-medium">info@example.com</span> </dd> </div>
<div> <dt class="sr-only">Location</dt>
<dd class="grid grid-cols-[24px_1fr] items-center gap-2 text-gray-700"> <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-5" > <path stroke-linecap="round" stroke-linejoin="round" d="m2.25 12 8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" /> </svg>
<span class="font-medium">123 Main St, Anytown, USA</span> </dd> </div> </dl> </div>
<form action="#" class="space-y-4 rounded-lg border border-gray-300 bg-gray-100 p-6"> <div> <label class="block text-sm font-medium text-gray-900" for="name">Name</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="name" type="text" placeholder="Your name" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="email">Email</label>
<input class="mt-1 w-full rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="email" type="email" placeholder="Your email" /> </div>
<div> <label class="block text-sm font-medium text-gray-900" for="message">Message</label>
<textarea class="mt-1 w-full resize-none rounded-lg border-gray-300 focus:border-indigo-500 focus:outline-none" id="message" rows="4" placeholder="Your message" ></textarea> </div>
<button class="block w-full rounded-lg border border-indigo-600 bg-indigo-600 px-12 py-3 text-sm font-medium text-white transition-colors hover:bg-transparent hover:text-indigo-600" type="submit" > Send Message </button> </form> </div></div>