Toggles
Ported from HyperUI’s Toggles — see Attribution.
Includes a dark: variant — toggle the site theme (top right) to preview it.
class Toggles1Example extends StatefulWidget { const Toggles1Example({super.key});
@override State<Toggles1Example> createState() => _Toggles1ExampleState();}
class _Toggles1ExampleState extends State<Toggles1Example> { var _checked = false;
@override Widget build(BuildContext context) { return Style( 'flex justify-center p-6', child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _checked = !_checked), child: Style( 'relative block h-8 w-14 rounded-full bg-gray-300 transition-colors [-webkit-tap-highlight-color:transparent] has-checked:bg-green-500 dark:bg-gray-600 dark:has-checked:bg-green-600', cursor: SystemMouseCursors.click, children: [ Style('peer sr-only', checked: _checked, child: const SizedBox.shrink()), const Style( 'absolute inset-y-0 start-0 m-1 size-6 rounded-full bg-white transition-[inset-inline-start] peer-checked:start-6 dark:bg-gray-900', ), ], ), ), ); }}<label for="AcceptConditions" class="relative block h-8 w-14 rounded-full bg-gray-300 transition-colors [-webkit-tap-highlight-color:transparent] has-checked:bg-green-500"> <input type="checkbox" id="AcceptConditions" class="peer sr-only" />
<span class="absolute inset-y-0 start-0 m-1 size-6 rounded-full bg-white transition-[inset-inline-start] peer-checked:start-6" ></span></label>Base with icon
Section titled “Base with icon”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)); }}
class Toggles2Example extends StatefulWidget { const Toggles2Example({super.key});
static const _xSvg = '''<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="M6 18 18 6M6 6l12 12"/></svg>''';
static const _checkSvg = '''<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="m4.5 12.75 6 6 9-13.5"/></svg>''';
@override State<Toggles2Example> createState() => _Toggles2ExampleState();}
class _Toggles2ExampleState extends State<Toggles2Example> { var _checked = false;
@override Widget build(BuildContext context) { return Style( 'flex justify-center p-6', child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _checked = !_checked), child: Style( 'group relative block h-8 w-14 rounded-full bg-gray-300 transition-colors [-webkit-tap-highlight-color:transparent] has-checked:bg-green-500', cursor: SystemMouseCursors.click, children: [ Style('peer sr-only', checked: _checked, child: const SizedBox.shrink()), Style( 'absolute inset-y-0 start-0 m-1 grid size-6 place-content-center rounded-full bg-white text-gray-700 transition-[inset-inline-start] peer-checked:start-6 peer-checked:*:first:hidden *:last:hidden peer-checked:*:last:block', children: [ Style('size-4', child: CurrentColorIcon(Toggles2Example._xSvg)), Style('size-4', child: CurrentColorIcon(Toggles2Example._checkSvg)), ], ), ], ), ), ); }}<label for="AcceptConditions" class="group relative block h-8 w-14 rounded-full bg-gray-300 transition-colors [-webkit-tap-highlight-color:transparent] has-checked:bg-green-500"> <input type="checkbox" id="AcceptConditions" class="peer sr-only" />
<span class="absolute inset-y-0 start-0 m-1 grid size-6 place-content-center rounded-full bg-white text-gray-700 transition-[inset-inline-start] peer-checked:start-6 peer-checked:*:first:hidden *:last:hidden peer-checked:*:last:block" > <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-4" > <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" /> </svg>
<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-4" > <path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" /> </svg> </span></label>Material
Section titled “Material”Includes a dark: variant — toggle the site theme (top right) to preview it.
class Toggles3Example extends StatefulWidget { const Toggles3Example({super.key});
@override State<Toggles3Example> createState() => _Toggles3ExampleState();}
class _Toggles3ExampleState extends State<Toggles3Example> { var _checked = false;
@override Widget build(BuildContext context) { return Style( 'flex justify-center p-6', child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _checked = !_checked), child: Style( 'relative block h-8 w-12 [-webkit-tap-highlight-color:transparent]', cursor: SystemMouseCursors.click, children: [ Style('peer sr-only', checked: _checked, child: const SizedBox.shrink()), const Style('absolute inset-0 m-auto h-2 rounded-full bg-gray-300 dark:bg-gray-600'), const Style( 'absolute inset-y-0 start-0 m-auto size-6 rounded-full bg-gray-500 transition-[inset-inline-start] peer-checked:start-6 peer-checked:*:scale-0 dark:bg-gray-400', child: Style( 'absolute inset-0 m-auto size-4 rounded-full bg-gray-200 transition-transform dark:bg-gray-700', ), ), ], ), ), ); }}<label for="AcceptConditions" class="relative block h-8 w-12 [-webkit-tap-highlight-color:transparent]"> <input type="checkbox" id="AcceptConditions" class="peer sr-only" />
<span class="absolute inset-0 m-auto h-2 rounded-full bg-gray-300"></span>
<span class="absolute inset-y-0 start-0 m-auto size-6 rounded-full bg-gray-500 transition-[inset-inline-start] peer-checked:start-6 peer-checked:*:scale-0" > <span class="absolute inset-0 m-auto size-4 rounded-full bg-gray-200 transition-transform"> </span> </span></label>Includes a dark: variant — toggle the site theme (top right) to preview it.
class Toggles4Example extends StatefulWidget { const Toggles4Example({super.key});
@override State<Toggles4Example> createState() => _Toggles4ExampleState();}
class _Toggles4ExampleState extends State<Toggles4Example> { var _checked = false;
@override Widget build(BuildContext context) { return Style( 'flex justify-center p-6', child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => setState(() => _checked = !_checked), child: Style( 'relative block h-8 w-14 rounded-full bg-gray-300 transition-colors [-webkit-tap-highlight-color:transparent] has-checked:bg-blue-500 dark:bg-gray-600 dark:has-checked:bg-blue-600', cursor: SystemMouseCursors.click, children: [ Style('peer sr-only', checked: _checked, child: const SizedBox.shrink()), const Style( 'absolute inset-y-0 start-0 m-1 size-6 rounded-full bg-gray-300 ring-[6px] ring-white transition-all ring-inset peer-checked:start-8 peer-checked:w-2 peer-checked:bg-white peer-checked:ring-transparent dark:bg-gray-600 dark:ring-gray-900 dark:peer-checked:bg-gray-900', ), ], ), ), ); }}<label for="AcceptConditions" class="relative block h-8 w-14 rounded-full bg-gray-300 transition-colors [-webkit-tap-highlight-color:transparent] has-checked:bg-blue-500"> <input type="checkbox" id="AcceptConditions" class="peer sr-only" />
<span class="absolute inset-y-0 start-0 m-1 size-6 rounded-full bg-gray-300 ring-[6px] ring-white transition-all ring-inset peer-checked:start-8 peer-checked:w-2 peer-checked:bg-white peer-checked:ring-transparent" > </span></label>