)]}'
{
  "commit": "07ca92a69eae5f17f463bc1ca8c48aa5ffda15bf",
  "tree": "169b7570822417a250a449f461f23c7f450459c3",
  "parents": [
    "bf735d7058bc510fbf9fd8377a2f2382ecb900e3"
  ],
  "author": {
    "name": "auto-submit[bot]",
    "email": "98614782+auto-submit[bot]@users.noreply.github.com",
    "time": "Thu Feb 01 21:11:26 2024 +0000"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Thu Feb 01 21:11:26 2024 +0000"
  },
  "message": "Reverts \"Added ButtonStyle.foregroundBuilder and ButtonStyle.backgroundBuilder\" (#142748)\n\nReverts flutter/flutter#141818\nInitiated by: XilaiZhang\nThis change reverts the following previous change:\nOriginal Description:\nFixes https://github.com/flutter/flutter/issues/139456, https://github.com/flutter/flutter/issues/130335, https://github.com/flutter/flutter/issues/89563.\r\n\r\nTwo new properties have been added to ButtonStyle to make it possible to insert arbitrary state-dependent widgets in a button\u0027s background or foreground. These properties can be specified for an individual button, using the style parameter, or for all buttons using a button theme\u0027s style parameter.\r\n\r\nThe new ButtonStyle properties are `backgroundBuilder` and `foregroundBuilder` and their (function) types are:\r\n\r\n```dart\r\ntypedef ButtonLayerBuilder \u003d Widget Function(\r\n  BuildContext context,\r\n  Set\u003cMaterialState\u003e states,\r\n  Widget? child\r\n);\r\n```\r\n\r\nThe new builder functions are called whenever the button is built and the `states` parameter communicates the pressed/hovered/etc state fo the button.\r\n\r\n## `backgroundBuilder`\r\n\r\nCreates a widget that becomes the child of the button\u0027s Material and whose child is the rest of the button, including the button\u0027s `child` parameter.  By default the returned widget is clipped to the Material\u0027s ButtonStyle.shape.\r\n\r\nThe `backgroundBuilder` can be used to add a gradient to the button\u0027s background. Here\u0027s an example that creates a yellow/orange gradient background:\r\n\r\n![opaque-gradient-bg](https://github.com/flutter/flutter/assets/1377460/80df8368-e7cf-49ef-aee7-2776a573644c)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    backgroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      return DecoratedBox(\r\n        decoration: BoxDecoration(\r\n          gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nBecause the background widget becomes the child of the button\u0027s Material, if it\u0027s opaque (as it is in this case) then it obscures the overlay highlights which are painted on the button\u0027s Material. To ensure that the highlights show through one can decorate the background with an `Ink` widget.  This version also overrides the overlay color to be (shades of) red, because that makes the highlights look a little nicer with the yellow/orange background.\r\n\r\n![ink-gradient-bg](https://github.com/flutter/flutter/assets/1377460/68a49733-f30e-44a1-a948-dc8cc95e1716)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    overlayColor: Colors.red,\r\n    backgroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      return Ink(\r\n        decoration: BoxDecoration(\r\n          gradient: LinearGradient(colors: [Colors.orange, Colors.yellow]),\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nNow the button\u0027s overlay highlights are painted on the Ink widget. An Ink widget isn\u0027t needed if the background is sufficiently translucent. This version of the example creates a translucent backround widget. \r\n\r\n![translucent-graident-bg](https://github.com/flutter/flutter/assets/1377460/3b016e1f-200a-4d07-8111-e20d29f18014)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    overlayColor: Colors.red,\r\n    backgroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      return DecoratedBox(\r\n        decoration: BoxDecoration(\r\n          gradient: LinearGradient(colors: [\r\n            Colors.orange.withOpacity(0.5),\r\n            Colors.yellow.withOpacity(0.5),\r\n          ]),\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nOne can also decorate the background with an image. In this example, the button\u0027s background is an burlap texture image. The foreground color has been changed to black to make the button\u0027s text a little clearer relative to the mottled brown backround.\r\n\r\n![burlap-bg](https://github.com/flutter/flutter/assets/1377460/f2f61ab1-10d9-43a4-bd63-beecdce33b45)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    foregroundColor: Colors.black,\r\n    backgroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      return Ink(\r\n        decoration: BoxDecoration(\r\n          image: DecorationImage(\r\n            image: NetworkImage(burlapUrl),\r\n            fit: BoxFit.cover,\r\n          ),\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nThe background widget can depend on the `states` parameter. In this example the blue/orange gradient flips horizontally when the button is hovered/pressed.\r\n\r\n![gradient-flip](https://github.com/flutter/flutter/assets/1377460/c6c6fe26-ae47-445b-b82d-4605d9583bd8)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    backgroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      final Color color1 \u003d Colors.blue.withOpacity(0.5);\r\n      final Color color2 \u003d Colors.orange.withOpacity(0.5);\r\n      return DecoratedBox(\r\n        decoration: BoxDecoration(\r\n          gradient: LinearGradient(\r\n            colors: switch (states.contains(MaterialState.hovered)) {\r\n              true \u003d\u003e \u003cColor\u003e[color1, color2],\r\n              false \u003d\u003e \u003cColor\u003e[color2, color1],\r\n            },\r\n          ),\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nThe preceeding examples have not included a BoxDecoration border because ButtonStyle already supports `ButtonStyle.shape` and `ButtonStyle.side` parameters that can be uesd to define state-dependent borders. Borders defined with the ButtonStyle side parameter match the button\u0027s shape. To add a border that changes color when the button is hovered or pressed, one must specify the side property using `copyWith`, since there\u0027s no `styleFrom` shorthand for this case.\r\n\r\n![border-gradient-bg](https://github.com/flutter/flutter/assets/1377460/63cffcd3-0dcf-4eb1-aed5-d14adf1e57f6)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    foregroundColor: Colors.indigo,\r\n    backgroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      final Color color1 \u003d Colors.blue.withOpacity(0.5);\r\n      final Color color2 \u003d Colors.orange.withOpacity(0.5);\r\n      return DecoratedBox(\r\n        decoration: BoxDecoration(\r\n          gradient: LinearGradient(\r\n            colors: switch (states.contains(MaterialState.hovered)) {\r\n              true \u003d\u003e \u003cColor\u003e[color1, color2],\r\n              false \u003d\u003e \u003cColor\u003e[color2, color1],\r\n            },\r\n          ),\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ).copyWith(\r\n    side: MaterialStateProperty.resolveWith\u003cBorderSide?\u003e((Set\u003cMaterialState\u003e states) {\r\n      if (states.contains(MaterialState.hovered)) {\r\n        return BorderSide(width: 3, color: Colors.yellow);\r\n      }\r\n      return null; // defer to the default\r\n    }),\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nAlthough all of the examples have created a ButtonStyle locally and only applied it to one button, they could have configured the `ThemeData.textButtonTheme` instead and applied the style to all TextButtons. And, of course, all of this works for all of the ButtonStyleButton classes, not just TextButton.\r\n\r\n## `foregroundBuilder`\r\n\r\nCreates a Widget that contains the button\u0027s child parameter. The returned widget is clipped by the button\u0027s [ButtonStyle.shape] inset by the button\u0027s [ButtonStyle.padding] and aligned by the button\u0027s [ButtonStyle.alignment].\r\n\r\nThe `foregroundBuilder` can be used to wrap the button\u0027s child, e.g. with a border or a `ShaderMask` or as a state-dependent substitute for the child.\r\n\r\nThis example adds a border that\u0027s just applied to the child. The border only appears when the button is hovered/pressed.\r\n\r\n![border-fg](https://github.com/flutter/flutter/assets/1377460/687a3245-fe68-4983-a04e-5fcc77f8aa21)\r\n\r\n```dart\r\nElevatedButton(\r\n  onPressed: () {},\r\n  style: ElevatedButton.styleFrom(\r\n    foregroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      final ColorScheme colorScheme \u003d Theme.of(context).colorScheme;\r\n      return DecoratedBox(\r\n        decoration: BoxDecoration(\r\n          border: states.contains(MaterialState.hovered)\r\n            ? Border(bottom: BorderSide(color: colorScheme.primary))\r\n            : Border(), // essentially \"no border\"\r\n        ),\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027Text Button\u0027),\r\n)\r\n```\r\n\r\nThe foregroundBuilder can be used with `ShaderMask` to change the way the button\u0027s child is rendered. In this example the ShaderMask\u0027s gradient causes the button\u0027s child to fade out on top.\r\n\r\n![shader_mask_fg](https://github.com/flutter/flutter/assets/1377460/54010f24-e65d-4551-ae58-712135df3d8d)\r\n\r\n```dart\r\nElevatedButton(\r\n  onPressed: () { },\r\n  style: ElevatedButton.styleFrom(\r\n    foregroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      final ColorScheme colorScheme \u003d Theme.of(context).colorScheme;\r\n      return ShaderMask(\r\n        shaderCallback: (Rect bounds) {\r\n          return LinearGradient(\r\n            begin: Alignment.bottomCenter,\r\n            end: Alignment.topCenter,\r\n            colors: \u003cColor\u003e[\r\n              colorScheme.primary,\r\n              colorScheme.primaryContainer,\r\n            ],\r\n          ).createShader(bounds);\r\n        },\r\n        blendMode: BlendMode.srcATop,\r\n        child: child,\r\n      );\r\n    },\r\n  ),\r\n  child:  const Text(\u0027Elevated Button\u0027),\r\n)\r\n```\r\n\r\nA commonly requested configuration for butttons has the developer provide images, one for pressed/hovered/normal state. You can use the foregroundBuilder to create a button that fades between a normal image and another image when the button is pressed. In this case the foregroundBuilder doesn\u0027t use the child it\u0027s passed, even though we\u0027ve provided the required TextButton child parameter.\r\n\r\n![image-button](https://github.com/flutter/flutter/assets/1377460/f5b1a22f-43ce-4be3-8e70-06de4c958380)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    foregroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      final String url \u003d states.contains(MaterialState.pressed) ? smiley2Url : smiley1Url;\r\n      return AnimatedContainer(\r\n        width: 100,\r\n        height: 100,\r\n        duration: Duration(milliseconds: 300),\r\n        decoration: BoxDecoration(\r\n          image: DecorationImage(\r\n            image: NetworkImage(url),\r\n            fit: BoxFit.contain,\r\n          ),\r\n        ),\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027No Child\u0027),\r\n)\r\n```\r\n\r\nIn this example the button\u0027s default overlay appears when the button is hovered and pressed. Another image can be used to indicate the hovered state and the default overlay can be defeated by specifying `Colors.transparent` for the `overlayColor`:\r\n\r\n![image-per-state](https://github.com/flutter/flutter/assets/1377460/7ab9da2f-f661-4374-b395-c2e0c7c4cf13)\r\n\r\n```dart\r\nTextButton(\r\n  onPressed: () {},\r\n  style: TextButton.styleFrom(\r\n    overlayColor: Colors.transparent,\r\n    foregroundBuilder: (BuildContext context, Set\u003cMaterialState\u003e states, Widget? child) {\r\n      String url \u003d states.contains(MaterialState.hovered) ? smiley3Url : smiley1Url;\r\n      if (states.contains(MaterialState.pressed)) {\r\n        url \u003d smiley2Url;\r\n      }\r\n      return AnimatedContainer(\r\n        width: 100,\r\n        height: 100,\r\n        duration: Duration(milliseconds: 300),\r\n        decoration: BoxDecoration(\r\n          image: DecorationImage(\r\n            image: NetworkImage(url),\r\n            fit: BoxFit.contain,\r\n          ),\r\n        ),\r\n      );\r\n    },\r\n  ),\r\n  child: Text(\u0027No Child\u0027),\r\n)\r\n```",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "41e4554649a0b4585ebef249fc633eb2a847cedc",
      "old_mode": 33188,
      "old_path": "dev/bots/check_code_samples.dart",
      "new_id": "8d947f57a4dfa62ab3c4fdda5d045950e0d1b41d",
      "new_mode": 33188,
      "new_path": "dev/bots/check_code_samples.dart"
    },
    {
      "type": "modify",
      "old_id": "0f7f0209289ae756096188a6395b61e03af809c5",
      "old_mode": 33188,
      "old_path": "examples/api/lib/material/text_button/text_button.0.dart",
      "new_id": "98fa6bc770e69e6b25fc52e69a7451a26cd1cde8",
      "new_mode": 33188,
      "new_path": "examples/api/lib/material/text_button/text_button.0.dart"
    },
    {
      "type": "delete",
      "old_id": "e6a13b9dc3ac35bfd602d4dc0cfc4434ae0fa271",
      "old_mode": 33188,
      "old_path": "examples/api/test/material/text_button/text_button.0_test.dart",
      "new_id": "0000000000000000000000000000000000000000",
      "new_mode": 0,
      "new_path": "/dev/null"
    },
    {
      "type": "modify",
      "old_id": "d2c7dffca003b05b40e1b177501bc80c05c9d372",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/button_style.dart",
      "new_id": "701071dff48c3b57b2e1e26ed6bd89f305f24c4b",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/button_style.dart"
    },
    {
      "type": "modify",
      "old_id": "5b35eb583cd87a4aeae5bbc9cda307eaec4cc5e3",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/button_style_button.dart",
      "new_id": "e51d5a17172fbbe8e2a4a733b2d444aa2838c69d",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/button_style_button.dart"
    },
    {
      "type": "modify",
      "old_id": "802a482ea7077bb73025c75ec0e3293a82cd104f",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/elevated_button.dart",
      "new_id": "ca0e85baa5720c49c865e38b2cc10e788ec1f006",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/elevated_button.dart"
    },
    {
      "type": "modify",
      "old_id": "d2a9c6cfd43f461d5bbf13c2cf386ba6d51491ca",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/filled_button.dart",
      "new_id": "463322e364008fcdda8494d6c012a2fa84b6a867",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/filled_button.dart"
    },
    {
      "type": "modify",
      "old_id": "c1d23d622c7b4554616b820bfe800d9ef75b50ca",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/material_state.dart",
      "new_id": "59d5dfcb71ee9612c74508237a90b701092a8304",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/material_state.dart"
    },
    {
      "type": "modify",
      "old_id": "abba6a7e0582fa94717dda3270c4f9c899095168",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/outlined_button.dart",
      "new_id": "fbc3fcf01d2bc0113ddcf1966ce4c3502d7e6243",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/outlined_button.dart"
    },
    {
      "type": "modify",
      "old_id": "325e1d3312d7d0441ce3f29c7c98b5e74c904a33",
      "old_mode": 33188,
      "old_path": "packages/flutter/lib/src/material/text_button.dart",
      "new_id": "7efa8c473ae4476328804d78778fa5ca478a3fd2",
      "new_mode": 33188,
      "new_path": "packages/flutter/lib/src/material/text_button.dart"
    },
    {
      "type": "modify",
      "old_id": "de0c35584429dc6e2b9500d4d4e6a81c0a91240c",
      "old_mode": 33188,
      "old_path": "packages/flutter/test/material/button_style_test.dart",
      "new_id": "2244c2940a72d77abe9faafda91fad93e24d591b",
      "new_mode": 33188,
      "new_path": "packages/flutter/test/material/button_style_test.dart"
    },
    {
      "type": "modify",
      "old_id": "e7f1a6e68c9e5fdfe94ec4046b0267b1a0f4e935",
      "old_mode": 33188,
      "old_path": "packages/flutter/test/material/elevated_button_test.dart",
      "new_id": "bf5e69e5f35d33c9a3784e9cde16df2f4f5ec22f",
      "new_mode": 33188,
      "new_path": "packages/flutter/test/material/elevated_button_test.dart"
    },
    {
      "type": "modify",
      "old_id": "535d8ba52f8d9fd6fb22c409e5f6ec99e01010d7",
      "old_mode": 33188,
      "old_path": "packages/flutter/test/material/filled_button_test.dart",
      "new_id": "a7524fa8fac41f844bc5e41af3307e274ec0cf83",
      "new_mode": 33188,
      "new_path": "packages/flutter/test/material/filled_button_test.dart"
    },
    {
      "type": "modify",
      "old_id": "eec865318156862998d3123add47fd2dc08c4baf",
      "old_mode": 33188,
      "old_path": "packages/flutter/test/material/outlined_button_test.dart",
      "new_id": "b45ad9ad416bcb39c14de58655f96ca97e998ee1",
      "new_mode": 33188,
      "new_path": "packages/flutter/test/material/outlined_button_test.dart"
    },
    {
      "type": "modify",
      "old_id": "fc86ae3aef952b4eb1b6d526a9067b7ad47889e0",
      "old_mode": 33188,
      "old_path": "packages/flutter/test/material/text_button_test.dart",
      "new_id": "9747790ed3c001bf046c16a18ac9896ebedaf0d0",
      "new_mode": 33188,
      "new_path": "packages/flutter/test/material/text_button_test.dart"
    },
    {
      "type": "modify",
      "old_id": "c80ee7a82ae97a77e5b0fb8d5d8aa3f6c747d939",
      "old_mode": 33188,
      "old_path": "packages/flutter/test/material/text_button_theme_test.dart",
      "new_id": "473e0a64473e7f7357b8f6b783a4a544557781bb",
      "new_mode": 33188,
      "new_path": "packages/flutter/test/material/text_button_theme_test.dart"
    }
  ]
}
