Add support for Material 3 `Divider` and `VerticalDivider` (#112378)

diff --git a/dev/tools/gen_defaults/bin/gen_defaults.dart b/dev/tools/gen_defaults/bin/gen_defaults.dart
index ef1f32a..00c6cd7 100644
--- a/dev/tools/gen_defaults/bin/gen_defaults.dart
+++ b/dev/tools/gen_defaults/bin/gen_defaults.dart
@@ -24,6 +24,7 @@
 import 'package:gen_defaults/card_template.dart';
 import 'package:gen_defaults/checkbox_template.dart';
 import 'package:gen_defaults/dialog_template.dart';
+import 'package:gen_defaults/divider_template.dart';
 import 'package:gen_defaults/fab_template.dart';
 import 'package:gen_defaults/filter_chip_template.dart';
 import 'package:gen_defaults/icon_button_template.dart';
@@ -65,6 +66,7 @@
     'date_picker_docked.json',
     'date_picker_modal.json',
     'dialog.json',
+    'divider.json',
     'dialog_fullscreen.json',
     'elevation.json',
     'fab_extended_primary.json',
@@ -121,6 +123,7 @@
   CardTemplate('Card', '$materialLib/card.dart', tokens).updateFile();
   CheckboxTemplate('Checkbox', '$materialLib/checkbox.dart', tokens).updateFile();
   DialogTemplate('Dialog', '$materialLib/dialog.dart', tokens).updateFile();
+  DividerTemplate('Divider', '$materialLib/divider.dart', tokens).updateFile();
   FABTemplate('FAB', '$materialLib/floating_action_button.dart', tokens).updateFile();
   FilterChipTemplate('ChoiceChip', '$materialLib/choice_chip.dart', tokens).updateFile();
   FilterChipTemplate('FilterChip', '$materialLib/filter_chip.dart', tokens).updateFile();
diff --git a/dev/tools/gen_defaults/lib/divider_template.dart b/dev/tools/gen_defaults/lib/divider_template.dart
new file mode 100644
index 0000000..2028dcb
--- /dev/null
+++ b/dev/tools/gen_defaults/lib/divider_template.dart
@@ -0,0 +1,24 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'template.dart';
+
+class DividerTemplate extends TokenTemplate {
+  const DividerTemplate(super.blockName, super.fileName, super.tokens, {
+    super.colorSchemePrefix = '_colors.',
+    super.textThemePrefix = '_textTheme.'
+  });
+
+  @override
+  String generate() => '''
+class _${blockName}DefaultsM3 extends DividerThemeData {
+  _${blockName}DefaultsM3(this.context) : super(thickness: ${tokens["md.comp.divider.thickness"]});
+
+  final BuildContext context;
+  late final ColorScheme _colors = Theme.of(context).colorScheme;
+
+  @override Color? get color => ${componentColor("md.comp.divider")};
+}
+''';
+}
diff --git a/examples/api/lib/material/divider/divider.0.dart b/examples/api/lib/material/divider/divider.0.dart
index 5912c1f..6672379 100644
--- a/examples/api/lib/material/divider/divider.0.dart
+++ b/examples/api/lib/material/divider/divider.0.dart
@@ -11,22 +11,19 @@
 class MyApp extends StatelessWidget {
   const MyApp({super.key});
 
-  static const String _title = 'Flutter Code Sample';
-
   @override
   Widget build(BuildContext context) {
     return MaterialApp(
-      title: _title,
       home: Scaffold(
-        appBar: AppBar(title: const Text(_title)),
-        body: const MyStatelessWidget(),
+        appBar: AppBar(title: const Text('Divider Sample')),
+        body: const DividerExample(),
       ),
     );
   }
 }
 
-class MyStatelessWidget extends StatelessWidget {
-  const MyStatelessWidget({super.key});
+class DividerExample extends StatelessWidget {
+  const DividerExample({super.key});
 
   @override
   Widget build(BuildContext context) {
diff --git a/examples/api/lib/material/divider/divider.1.dart b/examples/api/lib/material/divider/divider.1.dart
new file mode 100644
index 0000000..708e642
--- /dev/null
+++ b/examples/api/lib/material/divider/divider.1.dart
@@ -0,0 +1,52 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// Flutter code sample for [Divider].
+
+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(
+      theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
+      home: Scaffold(
+        appBar: AppBar(title: const Text('Divider Sample')),
+        body: const DividerExample(),
+      ),
+    );
+  }
+}
+
+class DividerExample extends StatelessWidget {
+  const DividerExample({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Center(
+      child: Padding(
+        padding: const EdgeInsets.all(16.0),
+        child: Column(
+          children: const <Widget>[
+            Expanded(
+              child: Card(
+                child: SizedBox.expand(),
+              ),
+            ),
+            Divider(),
+            Expanded(
+              child: Card(
+                child: SizedBox.expand(),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/examples/api/lib/material/divider/vertical_divider.0.dart b/examples/api/lib/material/divider/vertical_divider.0.dart
index 0a9a5cb..2bb5ad1 100644
--- a/examples/api/lib/material/divider/vertical_divider.0.dart
+++ b/examples/api/lib/material/divider/vertical_divider.0.dart
@@ -11,22 +11,19 @@
 class MyApp extends StatelessWidget {
   const MyApp({super.key});
 
-  static const String _title = 'Flutter Code Sample';
-
   @override
   Widget build(BuildContext context) {
     return MaterialApp(
-      title: _title,
       home: Scaffold(
-        appBar: AppBar(title: const Text(_title)),
-        body: const MyStatelessWidget(),
+        appBar: AppBar(title: const Text('VerticalDivider Sample')),
+        body: const DividerExample(),
       ),
     );
   }
 }
 
-class MyStatelessWidget extends StatelessWidget {
-  const MyStatelessWidget({super.key});
+class DividerExample extends StatelessWidget {
+  const DividerExample({super.key});
 
   @override
   Widget build(BuildContext context) {
diff --git a/examples/api/lib/material/divider/vertical_divider.1.dart b/examples/api/lib/material/divider/vertical_divider.1.dart
new file mode 100644
index 0000000..47a7b54
--- /dev/null
+++ b/examples/api/lib/material/divider/vertical_divider.1.dart
@@ -0,0 +1,52 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// Flutter code sample for [Divider].
+
+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(
+      theme: ThemeData(colorSchemeSeed: const Color(0xff6750a4), useMaterial3: true),
+      home: Scaffold(
+        appBar: AppBar(title: const Text('Divider Sample')),
+        body: const DividerExample(),
+      ),
+    );
+  }
+}
+
+class DividerExample extends StatelessWidget {
+  const DividerExample({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return Center(
+      child: Padding(
+        padding: const EdgeInsets.all(16.0),
+        child: Row(
+          children: const <Widget>[
+            Expanded(
+              child: Card(
+                child: SizedBox.expand(),
+              ),
+            ),
+            VerticalDivider(),
+            Expanded(
+              child: Card(
+                child: SizedBox.expand(),
+              ),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+}
diff --git a/examples/api/test/material/divider/divider.0_test.dart b/examples/api/test/material/divider/divider.0_test.dart
new file mode 100644
index 0000000..825f0cb
--- /dev/null
+++ b/examples/api/test/material/divider/divider.0_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_api_samples/material/divider/divider.0.dart' as example;
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  testWidgets('Horizontal Divider', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const MaterialApp(
+        home: Scaffold(
+          body: example.MyApp(),
+        ),
+      ),
+    );
+
+    expect(find.byType(Divider), findsOneWidget);
+
+    // Divider is positioned horizintally.
+    final Offset container = tester.getBottomLeft(find.byType(Container).first);
+    expect(container.dy, tester.getTopLeft(find.byType(Divider)).dy);
+
+    final Offset subheader = tester.getTopLeft(find.text('Subheader'));
+    expect(subheader.dy, tester.getBottomLeft(find.byType(Divider)).dy);
+  });
+}
diff --git a/examples/api/test/material/divider/divider.1_test.dart b/examples/api/test/material/divider/divider.1_test.dart
new file mode 100644
index 0000000..a0cedbb
--- /dev/null
+++ b/examples/api/test/material/divider/divider.1_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_api_samples/material/divider/divider.1.dart' as example;
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  testWidgets('Horizontal Divider', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const MaterialApp(
+        home: Scaffold(
+          body: example.MyApp(),
+        ),
+      ),
+    );
+
+    expect(find.byType(Divider), findsOneWidget);
+
+    // Divider is positioned horizontally.
+    Offset card = tester.getBottomLeft(find.byType(Card).first);
+    expect(card.dy, tester.getTopLeft(find.byType(Divider)).dy);
+
+    card = tester.getTopLeft(find.byType(Card).last);
+    expect(card.dy, tester.getBottomLeft(find.byType(Divider)).dy);
+  });
+}
diff --git a/examples/api/test/material/divider/vertical_divider.0_test.dart b/examples/api/test/material/divider/vertical_divider.0_test.dart
new file mode 100644
index 0000000..63c7513
--- /dev/null
+++ b/examples/api/test/material/divider/vertical_divider.0_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_api_samples/material/divider/vertical_divider.0.dart' as example;
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  testWidgets('Vertical Divider', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const MaterialApp(
+        home: Scaffold(
+          body: example.MyApp(),
+        ),
+      ),
+    );
+
+    expect(find.byType(VerticalDivider), findsOneWidget);
+
+    // Divider is positioned horizintally.
+    Offset expanded = tester.getTopRight(find.byType(Expanded).first);
+    expect(expanded.dx, tester.getTopLeft(find.byType(VerticalDivider)).dx);
+
+    expanded = tester.getTopLeft(find.byType(Expanded).last);
+    expect(expanded.dx, tester.getTopRight(find.byType(VerticalDivider)).dx);
+  });
+}
diff --git a/examples/api/test/material/divider/vertical_divider.1_test.dart b/examples/api/test/material/divider/vertical_divider.1_test.dart
new file mode 100644
index 0000000..8840fee
--- /dev/null
+++ b/examples/api/test/material/divider/vertical_divider.1_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_api_samples/material/divider/vertical_divider.1.dart' as example;
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  testWidgets('Vertical Divider', (WidgetTester tester) async {
+    await tester.pumpWidget(
+      const MaterialApp(
+        home: Scaffold(
+          body: example.MyApp(),
+        ),
+      ),
+    );
+
+    expect(find.byType(VerticalDivider), findsOneWidget);
+
+    // Divider is positioned vertically.
+    Offset card = tester.getTopRight(find.byType(Card).first);
+    expect(card.dx, tester.getTopLeft(find.byType(VerticalDivider)).dx);
+
+    card = tester.getTopLeft(find.byType(Card).last);
+    expect(card.dx, tester.getTopRight(find.byType(VerticalDivider)).dx);
+  });
+}
diff --git a/packages/flutter/lib/src/material/divider.dart b/packages/flutter/lib/src/material/divider.dart
index 44b3f66..c3f30f4 100644
--- a/packages/flutter/lib/src/material/divider.dart
+++ b/packages/flutter/lib/src/material/divider.dart
@@ -4,6 +4,7 @@
 
 import 'package:flutter/widgets.dart';
 
+import 'color_scheme.dart';
 import 'divider_theme.dart';
 import 'theme.dart';
 
@@ -34,6 +35,13 @@
 /// ** See code in examples/api/lib/material/divider/divider.0.dart **
 /// {@end-tool}
 ///
+/// {@tool dartpad}
+/// This sample shows the creation of [Divider] widget, as described in:
+/// https://m3.material.io/components/divider/overview
+///
+/// ** See code in examples/api/lib/material/divider/divider.1.dart **
+/// {@end-tool}
+///
 /// See also:
 ///
 ///  * [PopupMenuDivider], which is the equivalent but for popup menus.
@@ -154,11 +162,14 @@
 
   @override
   Widget build(BuildContext context) {
+    final ThemeData theme = Theme.of(context);
     final DividerThemeData dividerTheme = DividerTheme.of(context);
+    final DividerThemeData defaults = theme.useMaterial3 ? _DividerDefaultsM3(context) : const _DividerDefaultsM2();
     final double height = this.height ?? dividerTheme.space ?? 16.0;
-    final double thickness = this.thickness ?? dividerTheme.thickness ?? 0.0;
+    final double thickness = this.thickness ?? dividerTheme.thickness ?? defaults.thickness!;
     final double indent = this.indent ?? dividerTheme.indent ?? 0.0;
     final double endIndent = this.endIndent ?? dividerTheme.endIndent ?? 0.0;
+    final Color? color = this.color ?? defaults.color;
 
     return SizedBox(
       height: height,
@@ -195,6 +206,13 @@
 /// ** See code in examples/api/lib/material/divider/vertical_divider.0.dart **
 /// {@end-tool}
 ///
+/// {@tool dartpad}
+/// This sample shows the creation of [VerticalDivider] widget, as described in:
+/// https://m3.material.io/components/divider/overview
+///
+/// ** See code in examples/api/lib/material/divider/vertical_divider.1.dart **
+/// {@end-tool}
+///
 /// See also:
 ///
 ///  * [ListView.separated], which can be used to generate vertical dividers.
@@ -264,11 +282,14 @@
 
   @override
   Widget build(BuildContext context) {
+    final ThemeData theme = Theme.of(context);
     final DividerThemeData dividerTheme = DividerTheme.of(context);
+    final DividerThemeData defaults = theme.useMaterial3 ? _DividerDefaultsM3(context) : const _DividerDefaultsM2();
     final double width = this.width ?? dividerTheme.space ?? 16.0;
-    final double thickness = this.thickness ?? dividerTheme.thickness ?? 0.0;
+    final double thickness = this.thickness ?? dividerTheme.thickness ?? defaults.thickness!;
     final double indent = this.indent ?? dividerTheme.indent ?? 0.0;
     final double endIndent = this.endIndent ?? dividerTheme.endIndent ?? 0.0;
+    final Color? color = this.color ?? defaults.color;
 
     return SizedBox(
       width: width,
@@ -286,3 +307,27 @@
     );
   }
 }
+
+class _DividerDefaultsM2 extends DividerThemeData {
+  const _DividerDefaultsM2() : super(thickness: 0.0);
+}
+
+// BEGIN GENERATED TOKEN PROPERTIES - Divider
+
+// Do not edit by hand. The code between the "BEGIN GENERATED" and
+// "END GENERATED" comments are generated from data in the Material
+// Design token database by the script:
+//   dev/tools/gen_defaults/bin/gen_defaults.dart.
+
+// Token database version: v0_132
+
+class _DividerDefaultsM3 extends DividerThemeData {
+  _DividerDefaultsM3(this.context) : super(thickness: 1.0);
+
+  final BuildContext context;
+  late final ColorScheme _colors = Theme.of(context).colorScheme;
+
+  @override Color? get color => _colors.outlineVariant;
+}
+
+// END GENERATED TOKEN PROPERTIES - Divider
diff --git a/packages/flutter/test/material/divider_theme_test.dart b/packages/flutter/test/material/divider_theme_test.dart
index 4d34e28..909c9e4 100644
--- a/packages/flutter/test/material/divider_theme_test.dart
+++ b/packages/flutter/test/material/divider_theme_test.dart
@@ -59,8 +59,9 @@
 
   group('Horizontal Divider', () {
     testWidgets('Passing no DividerThemeData returns defaults', (WidgetTester tester) async {
-      await tester.pumpWidget(const MaterialApp(
-        home: Scaffold(
+      await tester.pumpWidget( MaterialApp(
+        theme: ThemeData(useMaterial3: true),
+        home: const Scaffold(
           body: Divider(),
         ),
       ));
@@ -70,10 +71,10 @@
 
       final Container container = tester.widget(find.byType(Container));
       final BoxDecoration decoration = container.decoration! as BoxDecoration;
-      expect(decoration.border!.bottom.width, 0.0);
+      expect(decoration.border!.bottom.width, 1.0);
 
       final ThemeData theme = ThemeData();
-      expect(decoration.border!.bottom.color, theme.dividerColor);
+      expect(decoration.border!.bottom.color, theme.colorScheme.outlineVariant);
 
       final Rect dividerRect = tester.getRect(find.byType(Divider));
       final Rect lineRect = tester.getRect(find.byType(DecoratedBox));
@@ -142,8 +143,9 @@
 
   group('Vertical Divider', () {
     testWidgets('Passing no DividerThemeData returns defaults', (WidgetTester tester) async {
-      await tester.pumpWidget(const MaterialApp(
-        home: Scaffold(
+      await tester.pumpWidget(MaterialApp(
+        theme: ThemeData(useMaterial3: true),
+        home: const Scaffold(
           body: VerticalDivider(),
         ),
       ));
@@ -154,10 +156,10 @@
       final Container container = tester.widget(find.byType(Container));
       final BoxDecoration decoration = container.decoration! as BoxDecoration;
       final Border border = decoration.border! as Border;
-      expect(border.left.width, 0.0);
+      expect(border.left.width, 1.0);
 
       final ThemeData theme = ThemeData();
-      expect(border.left.color, theme.dividerColor);
+      expect(border.left.color, theme.colorScheme.outlineVariant);
 
       final Rect dividerRect = tester.getRect(find.byType(VerticalDivider));
       final Rect lineRect = tester.getRect(find.byType(DecoratedBox));
@@ -225,6 +227,62 @@
       expect(lineRect.bottom, dividerRect.bottom - endIndent);
     });
   });
+
+  group('Material 2', () {
+    // Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
+    // is turned on by default, these tests can be removed.
+
+    group('Horizontal Divider', () {
+      testWidgets('Passing no DividerThemeData returns defaults', (WidgetTester tester) async {
+        await tester.pumpWidget(const MaterialApp(
+          home: Scaffold(
+            body: Divider(),
+          ),
+        ));
+
+        final RenderBox box = tester.firstRenderObject(find.byType(Divider));
+        expect(box.size.height, 16.0);
+
+        final Container container = tester.widget(find.byType(Container));
+        final BoxDecoration decoration = container.decoration! as BoxDecoration;
+        expect(decoration.border!.bottom.width, 0.0);
+
+        final ThemeData theme = ThemeData();
+        expect(decoration.border!.bottom.color, theme.dividerColor);
+
+        final Rect dividerRect = tester.getRect(find.byType(Divider));
+        final Rect lineRect = tester.getRect(find.byType(DecoratedBox));
+        expect(lineRect.left, dividerRect.left);
+        expect(lineRect.right, dividerRect.right);
+      });
+    });
+
+    group('Vertical Divider', () {
+      testWidgets('Passing no DividerThemeData returns defaults', (WidgetTester tester) async {
+        await tester.pumpWidget(const MaterialApp(
+          home: Scaffold(
+            body: VerticalDivider(),
+          ),
+        ));
+
+        final RenderBox box = tester.firstRenderObject(find.byType(VerticalDivider));
+        expect(box.size.width, 16.0);
+
+        final Container container = tester.widget(find.byType(Container));
+        final BoxDecoration decoration = container.decoration! as BoxDecoration;
+        final Border border = decoration.border! as Border;
+        expect(border.left.width, 0.0);
+
+        final ThemeData theme = ThemeData();
+        expect(border.left.color, theme.dividerColor);
+
+        final Rect dividerRect = tester.getRect(find.byType(VerticalDivider));
+        final Rect lineRect = tester.getRect(find.byType(DecoratedBox));
+        expect(lineRect.top, dividerRect.top);
+        expect(lineRect.bottom, dividerRect.bottom);
+      });
+    });
+  });
 }
 
 DividerThemeData _dividerTheme() {