Search code examples
flutterdartoopsolid-principles

How to manage more than 1 type(accent) of button properly?


I hope somebody can explain me some kind of solution:) I've been working on app UI using Flutter and there are 2 types of a button in that app design on Figma, each has its accent (there're 3 for now), which just define the button's heigth.

Those 2 types of button and accents

So those buttons have different emphasis over the app and I need to somehow manage it following the best coding practices.

Well for now I simply created enum, which contains accent variation:

enum ButtonAccent {
  primary,
  secondary,
  tertiary,
}

class FilledButton extends StatelessWidget {
  final String text;
  final IconData icon;
  final Color backgroundColor;
  final Color foregroundColor;
// defines a button height following Figma design. By default 'buttonAccent = ButtonAccent.tertiary', which sets 'heigth = 46'
  final ButtonAccent buttonAccent;
  final VoidCallback onPressed;

  const FilledButton(
      {super.key,
      required this.text,
      required this.icon,
      this.backgroundColor = ColorConstants.kCallToAction,
      this.foregroundColor = ColorConstants.kText,
      this.buttonAccent = ButtonAccent.tertiary,
      required this.onPressed});
// method that checks accent
  double _buttonHeigthFromAccent() => buttonAccent == ButtonAccent.primary
      ? 72.0
      : buttonAccent == ButtonAccent.secondary
          ? 60.0
          : buttonAccent == ButtonAccent.tertiary
              ? 48.0
              : throw Exception('Wrong ButtonAccent value');

  @override
  Widget build(BuildContext context) {
    return ElevatedButton.icon(
      onPressed: onPressed,
      style: ElevatedButton.styleFrom(
          minimumSize: Size(double.infinity, _buttonHeigthFromAccent()),
          backgroundColor: backgroundColor,
          foregroundColor: foregroundColor,
          textStyle: const TextStyle(color: ColorConstants.kText),
          shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(20.0))),
      icon: Icon(icon),
      label: Text(text),
    );
  }
}

Then my FilledButton contains method that checks the accents passed via constuctor and returning the proper heigth. But! There're plenty of cons in my opinion:

  1. if we consider to change not just height of a button but style in general (color, shape etc), it will lead us to overwrite the whole button implementation and ButtonAccent enum;
  2. not sure that all principles of SOLID are met;
  3. I put _buttonHeigthFromAccent() in both CustomOutlinedButton and FilledButton (added the code of FilledButton only as it doesn't differ much) which is bad idea as well;

I think it would be better to create an abstract class (interface) so I could implement it for my needs. However I am not sure about it, it can be just extra, pointless work


Solution

  • You can use enhanced enum, it is comes by default from v2.17.0

    enum ButtonAccent {
      primary(72.0),
      secondary(60.0),
      tertiary(48.0);
    
      const ButtonAccent(this.size);
      final double size;
    }
    

    And use the size like

     minimumSize: Size(double.infinity, buttonAccent.size),