skills/material3-expressive-flutter/references/components/buttons.md

88 lines
2.8 KiB
Markdown

# Common Buttons - M3 Expressive
## Overview
Common buttons (Elevated, Filled, Tonal, Outlined, Text) are updated in M3 Expressive with larger sizes, fuller rounding, and more tactile feedback.
## Button Types
| Type | Use Case | Expressive Enhancement |
|------|----------|------------------------|
| **Filled** | Highest importance actions | Full rounding (`StadiumBorder`), high contrast |
| **Filled Tonal** | Secondary importance | Softer color interaction, tonal balance |
| **Elevated** | High importance with depth | Subtle shadows, expressive elevation shifts |
| **Outlined** | Medium importance, less visual weight | Crisp outlines, clear states |
| **Text** | Lowest importance, inline actions | Emphasized text weights |
## Implementation in Flutter
### 1. High-Emphasis Expressive Button
```dart
FilledButton(
style: FilledButton.styleFrom(
minimumSize: const Size(0, 56), // Larger height
shape: const StadiumBorder(), // Full rounding
),
onPressed: () {},
child: const Text('Primary Action'),
)
```
### 2. Springy Tonal Button
```dart
class SpringyTonalButton extends StatefulWidget {
final String label;
final VoidCallback onPressed;
const SpringyTonalButton({super.key, required this.label, required this.onPressed});
@override
State<SpringyTonalButton> createState() => _SpringyTonalButtonState();
}
class _SpringyTonalButtonState extends State<SpringyTonalButton> {
bool _isPressed = false;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (_) => setState(() => _isPressed = true),
onTapUp: (_) {
setState(() => _isPressed = false);
widget.onPressed();
},
onTapCancel: () => setState(() => _isPressed = false),
child: AnimatedScale(
scale: _isPressed ? 0.95 : 1.0,
duration: const Duration(milliseconds: 100),
child: FilledButton.tonal(
onPressed: null, // Managed by GestureDetector for animation
style: FilledButton.styleFrom(
disabledBackgroundColor: Theme.of(context).colorScheme.secondaryContainer,
disabledForegroundColor: Theme.of(context).colorScheme.onSecondaryContainer,
shape: const StadiumBorder(),
),
child: Text(widget.label),
),
),
);
}
}
```
## Best Practices
1. **Size-Based Hierarchy**: Reserve large buttons for primary calls to action.
2. **Standard heights**: 40dp (Small), 48dp (Regular), 56dp (Large).
3. **Pill-shaped as Default**: Prefer `StadiumBorder` for most buttons in M3E.
4. **Micro-interactions**: Use `InkWell` or custom scale animations for tactile feedback.
## Related
- [Icon Buttons](icon-buttons.md)
- [Split Buttons](split-buttons.md)
- [Button Groups](button-groups.md)
- [Motion Guide](../motion-guide.md)