/* * Copyright (c) 2024-2026 Fabian Freund. * * This file is part of WebLibre * (see https://weblibre.eu). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ import 'package:flutter/material.dart'; class SlidingPillToggle extends StatelessWidget { final int selectedIndex; final List labels; final ValueChanged onChanged; const SlidingPillToggle({ super.key, required this.selectedIndex, required this.labels, required this.onChanged, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final colorScheme = theme.colorScheme; final disableAnimations = MediaQuery.disableAnimationsOf(context); return Container( height: 36, decoration: BoxDecoration( color: colorScheme.surfaceContainerHighest, borderRadius: BorderRadius.circular(18), ), child: Stack( children: [ AnimatedAlign( alignment: Alignment( -1.0 + (2.0 * selectedIndex / (labels.length - 1)), 0.0, ), duration: disableAnimations ? Duration.zero : const Duration(milliseconds: 250), curve: Curves.easeOutCubic, child: FractionallySizedBox( widthFactor: 1.0 / labels.length, child: Container( decoration: BoxDecoration( color: colorScheme.primary, borderRadius: BorderRadius.circular(18), ), ), ), ), Row( children: [ for (var i = 0; i < labels.length; i++) Expanded( child: GestureDetector( behavior: HitTestBehavior.opaque, onTap: () => onChanged(i), child: Center( child: Text( labels[i], style: theme.textTheme.labelMedium?.copyWith( color: i == selectedIndex ? colorScheme.onPrimary : colorScheme.onSurfaceVariant, fontWeight: i == selectedIndex ? FontWeight.w600 : FontWeight.normal, ), ), ), ), ), ], ), ], ), ); } }