Skip to content

Commit

Permalink
Reland "Fix Chip.shape's side is not used when provided in Material…
Browse files Browse the repository at this point in the history
… 3" (#133856)

fixes [Chip border side color not working in Material3](flutter/flutter#132922)
Relands flutter/flutter#132941 with an updated fix and a regression test.

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(useMaterial3: true),
      home: const Example(),
    );
  }
}

class Example extends StatelessWidget {
  const Example({super.key});

  @OverRide
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Chips'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            const RawChip(
              shape: RoundedRectangleBorder(
                side: BorderSide(color: Colors.amber),
              ),
              side: BorderSide(color: Colors.red),
              label: Text('RawChip'),
            ),
            const Chip(
              shape: RoundedRectangleBorder(
                side: BorderSide(color: Colors.amber),
              ),
              side: BorderSide(color: Colors.red),
              label: Text('Chip'),
            ),
            ActionChip(
              shape: const RoundedRectangleBorder(
                side: BorderSide(color: Colors.amber),
              ),
              side: const BorderSide(color: Colors.red),
              label: const Text('ActionChip'),
              onPressed: () {},
            ),
            FilterChip(
              shape: const RoundedRectangleBorder(
                side: BorderSide(color: Colors.amber),
              ),
              side: const BorderSide(color: Colors.red),
              label: const Text('FilterChip'),
              onSelected: (value) {},
            ),
            ChoiceChip(
              shape: const RoundedRectangleBorder(
                side: BorderSide(color: Colors.amber),
              ),
              side: const BorderSide(color: Colors.red),
              label: const Text('ChoiceChip'),
              selected: false,
              onSelected: (value) {},
            ),
            InputChip(
              shape: const RoundedRectangleBorder(
                side: BorderSide(color: Colors.amber),
              ),
              side: const BorderSide(color: Colors.red),
              label: const Text('InputChip'),
              onSelected: (value) {},
            ),
          ],
        ),
      ),
    );
  }
}
```

</details>

<img src="https://github.com/flutter/flutter/assets/48603081/f713fd84-cf9a-4e52-8cdb-5faba63d8e91" height="450" /> <img src="https://github.com/flutter/flutter/assets/48603081/a142efc7-041e-4e6e-87cf-e6c4ebe735f3" height="450" />

<img src="https://github.com/flutter/flutter/assets/48603081/377df55b-499f-403f-96c5-0be0334795dc" height="450" /> <img src="https://github.com/flutter/flutter/assets/48603081/731a2752-7822-4605-8e9c-db0a71dd6f08" height="450" />
  • Loading branch information
TahaTesser authored Sep 7, 2023
1 parent 83c2427 commit ded8b8e
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 3 deletions.
14 changes: 11 additions & 3 deletions packages/flutter/lib/src/material/chip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -992,13 +992,21 @@ class _RawChipState extends State<RawChip> with MaterialStateMixin, TickerProvid

OutlinedBorder _getShape(ThemeData theme, ChipThemeData chipTheme, ChipThemeData chipDefaults) {
final BorderSide? resolvedSide = MaterialStateProperty.resolveAs<BorderSide?>(widget.side, materialStates)
?? MaterialStateProperty.resolveAs<BorderSide?>(chipTheme.side, materialStates)
?? MaterialStateProperty.resolveAs<BorderSide?>(chipDefaults.side, materialStates);
?? MaterialStateProperty.resolveAs<BorderSide?>(chipTheme.side, materialStates);
final OutlinedBorder resolvedShape = MaterialStateProperty.resolveAs<OutlinedBorder?>(widget.shape, materialStates)
?? MaterialStateProperty.resolveAs<OutlinedBorder?>(chipTheme.shape, materialStates)
?? MaterialStateProperty.resolveAs<OutlinedBorder?>(chipDefaults.shape, materialStates)
// TODO(tahatesser): Remove this fallback when Material 2 is deprecated.
?? const StadiumBorder();
return resolvedShape.copyWith(side: resolvedSide);
// If the side is provided, shape uses the provided side.
if (resolvedSide != null) {
return resolvedShape.copyWith(side: resolvedSide);
}
// If the side is not provided and the shape's side is not [BorderSide.none],
// then the shape's side is used. Otherwise, the default side is used.
return resolvedShape.side != BorderSide.none
? resolvedShape
: resolvedShape.copyWith(side: chipDefaults.side);
}

Color? resolveColor({
Expand Down
79 changes: 79 additions & 0 deletions packages/flutter/test/material/chip_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3503,6 +3503,85 @@ void main() {
expect(calledDelete, isTrue);
});

// This is a regression test for https://github.com/flutter/flutter/pull/133615.
testWidgets('Material3 - Custom shape without provided side uses default side', (WidgetTester tester) async {
final ThemeData theme = ThemeData(useMaterial3: true);
await tester.pumpWidget(
MaterialApp(
theme: theme,
home: const Material(
child: Center(
child: RawChip(
// No side provided.
shape: StadiumBorder(),
label: Text('RawChip'),
),
),
),
),
);

// Chip should have the default side.
expect(
getMaterial(tester).shape,
StadiumBorder(side: BorderSide(color: theme.colorScheme.outline)),
);
});

testWidgets("Material3 - RawChip.shape's side is used when provided", (WidgetTester tester) async {
Widget buildChip({ OutlinedBorder? shape, BorderSide? side }) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Material(
child: Center(
child: RawChip(
shape: shape,
side: side,
label: const Text('RawChip'),
),
),
),
);
}

// Test [RawChip.shape] with a side.
await tester.pumpWidget(buildChip(
shape: const RoundedRectangleBorder(
side: BorderSide(color: Color(0xffff00ff)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
)),
);

// Chip should have the provided shape and the side from [RawChip.shape].
expect(
getMaterial(tester).shape,
const RoundedRectangleBorder(
side: BorderSide(color: Color(0xffff00ff)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
);

// Test [RawChip.shape] with a side and [RawChip.side].
await tester.pumpWidget(buildChip(
shape: const RoundedRectangleBorder(
side: BorderSide(color: Color(0xffff00ff)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
side: const BorderSide(color: Color(0xfffff000))),
);
await tester.pumpAndSettle();

// Chip use shape from [RawChip.shape] and the side from [RawChip.side].
// [RawChip.shape]'s side should be ignored.
expect(
getMaterial(tester).shape,
const RoundedRectangleBorder(
side: BorderSide(color: Color(0xfffff000)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
);
});

group('Material 2', () {
// These tests are only relevant for Material 2. Once Material 2
// support is deprecated and the APIs are removed, these tests
Expand Down
58 changes: 58 additions & 0 deletions packages/flutter/test/material/chip_theme_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,64 @@ void main() {
)),
);
});

testWidgets("Material3 - RawChip.shape's side is used when provided", (WidgetTester tester) async {
Widget buildChip({ OutlinedBorder? shape, BorderSide? side }) {
return MaterialApp(
theme: ThemeData(
useMaterial3: true,
chipTheme: ChipThemeData(
shape: shape,
side: side,
),
),
home: const Material(
child: Center(
child: RawChip(
label: Text('RawChip'),
),
),
),
);
}

// Test [RawChip.shape] with a side.
await tester.pumpWidget(buildChip(
shape: const RoundedRectangleBorder(
side: BorderSide(color: Color(0xffff00ff)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
)),
);

// Chip should have the provided shape and the side from [RawChip.shape].
expect(
getMaterial(tester).shape,
const RoundedRectangleBorder(
side: BorderSide(color: Color(0xffff00ff)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
);

// Test [RawChip.shape] with a side and [RawChip.side].
await tester.pumpWidget(buildChip(
shape: const RoundedRectangleBorder(
side: BorderSide(color: Color(0xffff00ff)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
side: const BorderSide(color: Color(0xfffff000))),
);
await tester.pumpAndSettle();

// Chip use shape from [RawChip.shape] and the side from [RawChip.side].
// [RawChip.shape]'s side should be ignored.
expect(
getMaterial(tester).shape,
const RoundedRectangleBorder(
side: BorderSide(color: Color(0xfffff000)),
borderRadius: BorderRadius.all(Radius.circular(7.0)),
),
);
});
}

class _MaterialStateOutlinedBorder extends StadiumBorder implements MaterialStateOutlinedBorder {
Expand Down

0 comments on commit ded8b8e

Please sign in to comment.