Should you have copyWith/merge on Widget?

I’m trying to create a design system, which a button can have a custom variant, and depending on that variant it’ll have a corresponding default text style, which could be overridden if needed. For example

class MyText extends StatelessWidget{
  final String text;
  final MyFontSize fontSize;
  ...

  MyText copyWith({MyFontSize? fontSize}) { 
  ...
  }
}

class MyButton extends StatelessWidget {
  final MyText text;
  final MytButtonVariant variant;

  build() {
    final text = this.text.merge(
        fontSize: _fontSizeFromVariant(variant)
      );
    return ElevatedButton(child: text, ...)
  }
}

My colleague makes the argument that we should move the MyFontSize & all the other params into an object, MyTextStyle, and the MyButton will take in String text & MyTextStyle style as the params, and perform copyWith/merge on the MyTextStyle, similar to how the Text widget and the TextStyle.

The main difference between MyButton and ElevatedButton is it doesn’t take in any widget, but only MyText, so it justifies for the unusual copyWith in Widget.

What do you think?

I’m more inclined to go with your colleague’s argument as it is closer to what you’re actually doing: modifying the text style shown in the button.

Now if you need just the text widget as a part of your design system, I would use your approach.

yea we only use the MyText widget in the button, as it’s a constraint from our designer

I would still go with the suggestion to perform the copyWith/merge on MyTextStyle.

1 Like