Files
SpotiFLAC-Mobile/lib/widgets/app_shape.dart
T

71 lines
1.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:material_3_expressive/material_3_expressive.dart';
import 'package:spotiflac_android/theme/mornye_theme.dart';
/// Expressive shapes used across the Material theme.
abstract final class AppShapes {
/// Artist portraits, from list thumbnails to profile headers.
static const artist = M3EShapeKind.cookie9Sided;
/// Decorative badges behind empty-state and branding glyphs.
static const badge = M3EShapeKind.softBurst;
static const brand = M3EShapeKind.cookie12Sided;
}
/// Clips [child] to an expressive [kind] on the Material theme.
///
/// Mornye keeps its own geometry: [fallbackRadius], or an oval when null.
class AppShapeClip extends StatelessWidget {
const AppShapeClip({
super.key,
required this.kind,
required this.child,
this.fallbackRadius,
});
final M3EShapeKind kind;
final BorderRadius? fallbackRadius;
final Widget child;
@override
Widget build(BuildContext context) {
if (!context.isMornye) {
return ClipPath(clipper: M3EShapeClipper(kind), child: child);
}
final fallbackRadius = this.fallbackRadius;
return fallbackRadius == null
? ClipOval(child: child)
: ClipRRect(borderRadius: fallbackRadius, child: child);
}
}
/// A filled expressive [kind] behind a centered icon or logo.
///
/// Mornye draws the same fill as a circle.
class AppShapeBadge extends StatelessWidget {
const AppShapeBadge({
super.key,
required this.kind,
required this.size,
required this.color,
required this.child,
});
final M3EShapeKind kind;
final double size;
final Color color;
final Widget child;
@override
Widget build(BuildContext context) => SizedBox.square(
dimension: size,
child: AppShapeClip(
kind: kind,
child: ColoredBox(
color: color,
child: Center(child: child),
),
),
);
}