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

Polls

Ported from HyperUI’s Polls — see Attribution.

Includes a dark: variant — toggle the site theme (top right) to preview it.

class Polls1Example extends StatefulWidget {
const Polls1Example({super.key});
@override
State<Polls1Example> createState() => _Polls1ExampleState();
}
class _Polls1ExampleState extends State<Polls1Example> {
var _selected = -1;
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8',
children: [
const Style(
'max-w-prose',
children: [
Style(
'text-2xl font-semibold text-gray-900 sm:text-3xl dark:text-white',
child: Text('Where should we go for lunch?'),
),
Style(
'mt-4 text-pretty text-gray-700 dark:text-gray-200',
child: Text(
'Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe maiores '
'exercitationem id soluta eaque harum eligendi distinctio sapiente esse ad! Sit '
'expedita eos quam numquam ea, assumenda officiis minus ut!',
),
),
],
),
Style(
'mt-6 space-y-4',
child: Style(
'space-y-4',
children: [
const Style('sr-only', child: Text('Select an option')),
Style(
'flex items-center gap-4',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 0),
child: LayoutBuilder(
builder: (context, constraints) {
final barWidth = constraints.maxWidth * 0.45;
return Style(
'relative block flex-1 overflow-hidden rounded border border-gray-300 px-4 py-2 shadow-sm dark:border-gray-600 dark:bg-gray-900 dark:text-white',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-y-0 left-0 rounded bg-gray-100 dark:bg-gray-800',
child: SizedBox(width: barWidth),
),
Style(
'relative flex items-center gap-4',
children: [
Style(
'size-5 border-gray-300 shadow-sm dark:border-gray-600',
formControl: true,
formControlRadio: true,
checked: _selected == 0,
),
const Style(
'font-medium text-gray-900 dark:text-white',
child: Text('Option 1'),
),
],
),
],
);
},
),
),
const Style(
'text-gray-700 dark:text-gray-200',
child: Text('45%'),
),
],
),
Style(
'flex items-center gap-4',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 1),
child: LayoutBuilder(
builder: (context, constraints) {
final barWidth = constraints.maxWidth * 0.25;
return Style(
'relative block flex-1 overflow-hidden rounded border border-gray-300 px-4 py-2 shadow-sm dark:border-gray-600 dark:bg-gray-900 dark:text-white',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-y-0 left-0 rounded bg-gray-100 dark:bg-gray-800',
child: SizedBox(width: barWidth),
),
Style(
'relative flex items-center gap-4',
children: [
Style(
'size-5 border-gray-300 shadow-sm dark:border-gray-600',
formControl: true,
formControlRadio: true,
checked: _selected == 1,
),
const Style(
'font-medium text-gray-900 dark:text-white',
child: Text('Option 2'),
),
],
),
],
);
},
),
),
const Style(
'text-gray-700 dark:text-gray-200',
child: Text('25%'),
),
],
),
Style(
'flex items-center gap-4',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 2),
child: LayoutBuilder(
builder: (context, constraints) {
final barWidth = constraints.maxWidth * 0.30;
return Style(
'relative block flex-1 overflow-hidden rounded border border-gray-300 px-4 py-2 shadow-sm dark:border-gray-600 dark:bg-gray-900 dark:text-white',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-y-0 left-0 rounded bg-gray-100 dark:bg-gray-800',
child: SizedBox(width: barWidth),
),
Style(
'relative flex items-center gap-4',
children: [
Style(
'size-5 border-gray-300 shadow-sm dark:border-gray-600',
formControl: true,
formControlRadio: true,
checked: _selected == 2,
),
const Style(
'font-medium text-gray-900 dark:text-white',
child: Text('Option 3'),
),
],
),
],
);
},
),
),
const Style(
'text-gray-700 dark:text-gray-200',
child: Text('30%'),
),
],
),
],
),
),
const Style(
'mt-4 text-sm text-gray-700 dark:text-gray-200',
child: Text('Ends on October 31, 2025'),
),
],
);
}
}

Includes a dark: variant — toggle the site theme (top right) to preview it.

class Polls2Example extends StatefulWidget {
const Polls2Example({super.key});
@override
State<Polls2Example> createState() => _Polls2ExampleState();
}
class _Polls2ExampleState extends State<Polls2Example> {
var _selected = -1;
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8',
children: [
const Style(
'max-w-prose',
children: [
Style(
'text-2xl font-semibold text-gray-900 sm:text-3xl dark:text-white',
child: Text('Where should we go for lunch?'),
),
Style(
'mt-4 text-pretty text-gray-700 dark:text-gray-200',
child: Text(
'Lorem ipsum dolor sit, amet consectetur adipisicing elit. Saepe maiores '
'exercitationem id soluta eaque harum eligendi distinctio sapiente esse ad! Sit '
'expedita eos quam numquam ea, assumenda officiis minus ut!',
),
),
],
),
Style(
'mt-6 space-y-4',
child: Style(
'space-y-4',
children: [
const Style('sr-only', child: Text('Select an option')),
Style(
'flex items-center gap-4',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 0),
child: LayoutBuilder(
builder: (context, constraints) {
final barWidth = constraints.maxWidth * 0.45;
return Style(
'relative block flex-1 overflow-hidden rounded border border-gray-300 px-4 py-2 shadow-sm dark:border-gray-600',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-y-0 left-0 rounded bg-gray-100 dark:bg-gray-800',
child: SizedBox(width: barWidth),
),
Style(
'relative flex items-center gap-4',
children: [
Style(
'size-5 rounded border-gray-300 shadow-sm dark:border-gray-600',
formControl: true,
checked: _selected == 0,
),
const Style(
'font-medium text-gray-900 dark:text-white',
child: Text('Option 1'),
),
],
),
],
);
},
),
),
const Style(
'text-gray-700 dark:text-gray-200',
child: Text('45%'),
),
],
),
Style(
'flex items-center gap-4',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 1),
child: LayoutBuilder(
builder: (context, constraints) {
final barWidth = constraints.maxWidth * 0.25;
return Style(
'relative block flex-1 overflow-hidden rounded border border-gray-300 px-4 py-2 shadow-sm dark:border-gray-600',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-y-0 left-0 rounded bg-gray-100 dark:bg-gray-800',
child: SizedBox(width: barWidth),
),
Style(
'relative flex items-center gap-4',
children: [
Style(
'size-5 rounded border-gray-300 shadow-sm dark:border-gray-600',
formControl: true,
checked: _selected == 1,
),
const Style(
'font-medium text-gray-900 dark:text-white',
child: Text('Option 2'),
),
],
),
],
);
},
),
),
const Style(
'text-gray-700 dark:text-gray-200',
child: Text('25%'),
),
],
),
Style(
'flex items-center gap-4',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 2),
child: LayoutBuilder(
builder: (context, constraints) {
final barWidth = constraints.maxWidth * 0.30;
return Style(
'relative block flex-1 overflow-hidden rounded border border-gray-300 px-4 py-2 shadow-sm dark:border-gray-600',
cursor: SystemMouseCursors.click,
children: [
Style(
'absolute inset-y-0 left-0 rounded bg-gray-100 dark:bg-gray-800',
child: SizedBox(width: barWidth),
),
Style(
'relative flex items-center gap-4',
children: [
Style(
'size-5 rounded border-gray-300 shadow-sm dark:border-gray-600',
formControl: true,
checked: _selected == 2,
),
const Style(
'font-medium text-gray-900 dark:text-white',
child: Text('Option 3'),
),
],
),
],
);
},
),
),
const Style(
'text-gray-700 dark:text-gray-200',
child: Text('30%'),
),
],
),
],
),
),
const Style(
'mt-4 text-sm text-gray-700 dark:text-gray-200',
child: Text('Ends on October 31, 2025'),
),
],
);
}
}

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 _outlineStarSvg =
'''<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="M11.48 3.499a.562.562 0 0 1 1.04 0l2.125 5.111a.563.563 0 0 0 .475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 0 0-.182.557l1.285 5.385a.562.562 0 0 1-.84.61l-4.725-2.885a.562.562 0 0 0-.586 0L6.982 20.54a.562.562 0 0 1-.84-.61l1.285-5.386a.562.562 0 0 0-.182-.557l-4.204-3.602a.562.562 0 0 1 .321-.988l5.518-.442a.563.563 0 0 0 .475-.345L11.48 3.5Z"/></svg>''';
const _solidStarSvg =
'''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path fill-rule="evenodd" d="M10.788 3.21c.448-1.077 1.976-1.077 2.424 0l2.082 5.006 5.404.434c1.164.093 1.636 1.545.749 2.305l-4.117 3.527 1.257 5.273c.271 1.136-.964 2.033-1.96 1.425L12 18.354 7.373 21.18c-.996.608-2.231-.29-1.96-1.425l1.257-5.273-4.117-3.527c-.887-.76-.415-2.212.749-2.305l5.404-.434 2.082-5.005Z" clip-rule="evenodd"/></svg>''';
class Polls3Example extends StatefulWidget {
const Polls3Example({super.key});
@override
State<Polls3Example> createState() => _Polls3ExampleState();
}
class _Polls3ExampleState extends State<Polls3Example> {
var _rating = 0;
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-md p-6',
children: [
const Style('sr-only', child: Text('Leave a rating')),
Style(
'flex flex-row-reverse items-center justify-end gap-1',
children: [
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _rating = 5),
child: Style(
'text-gray-900 hover:text-yellow-500 dark:text-white hover:[&~label]:text-yellow-500',
cursor: SystemMouseCursors.click,
children: [
Style('peer sr-only', checked: _rating >= 5, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('5 Stars')),
const Style(
'block size-6 peer-checked:hidden',
child: CurrentColorIcon(_outlineStarSvg),
),
const Style(
'hidden size-6 text-yellow-500 peer-checked:block',
child: CurrentColorIcon(_solidStarSvg),
),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _rating = 4),
child: Style(
'text-gray-900 hover:text-yellow-500 dark:text-white hover:[&~label]:text-yellow-500',
cursor: SystemMouseCursors.click,
children: [
Style('peer sr-only', checked: _rating >= 4, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('4 Stars')),
const Style(
'block size-6 peer-checked:hidden',
child: CurrentColorIcon(_outlineStarSvg),
),
const Style(
'hidden size-6 text-yellow-500 peer-checked:block',
child: CurrentColorIcon(_solidStarSvg),
),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _rating = 3),
child: Style(
'text-gray-900 hover:text-yellow-500 dark:text-white hover:[&~label]:text-yellow-500',
cursor: SystemMouseCursors.click,
children: [
Style('peer sr-only', checked: _rating >= 3, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('3 Stars')),
const Style(
'block size-6 peer-checked:hidden',
child: CurrentColorIcon(_outlineStarSvg),
),
const Style(
'hidden size-6 text-yellow-500 peer-checked:block',
child: CurrentColorIcon(_solidStarSvg),
),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _rating = 2),
child: Style(
'text-gray-900 hover:text-yellow-500 dark:text-white hover:[&~label]:text-yellow-500',
cursor: SystemMouseCursors.click,
children: [
Style('peer sr-only', checked: _rating >= 2, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('2 Stars')),
const Style(
'block size-6 peer-checked:hidden',
child: CurrentColorIcon(_outlineStarSvg),
),
const Style(
'hidden size-6 text-yellow-500 peer-checked:block',
child: CurrentColorIcon(_solidStarSvg),
),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _rating = 1),
child: Style(
'text-gray-900 hover:text-yellow-500 dark:text-white hover:[&~label]:text-yellow-500',
cursor: SystemMouseCursors.click,
children: [
Style('peer sr-only', checked: _rating >= 1, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('1 Star')),
const Style(
'block size-6 peer-checked:hidden',
child: CurrentColorIcon(_outlineStarSvg),
),
const Style(
'hidden size-6 text-yellow-500 peer-checked:block',
child: CurrentColorIcon(_solidStarSvg),
),
],
),
),
],
),
],
);
}
}