init
This commit is contained in:
commit
d205277cdd
182 changed files with 22978 additions and 0 deletions
91
lib/widgets/hairline_panel.dart
Normal file
91
lib/widgets/hairline_panel.dart
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/tokens.dart';
|
||||
|
||||
/// A thin-stroked panel with its title label sitting *on* the top border —
|
||||
/// Ratune's signature container ("Album Art", "Queue (127)", "Lyrics",
|
||||
/// "Visualizer"). Recreated with the fieldset trick: draw a full 1px border,
|
||||
/// then overlay the title with a background that occludes the segment behind
|
||||
/// it, so the label appears to break the line.
|
||||
class HairlinePanel extends StatelessWidget {
|
||||
const HairlinePanel({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.child,
|
||||
this.trailing,
|
||||
this.active = false,
|
||||
this.padding = const EdgeInsets.all(RatuneSpacing.lg),
|
||||
this.backgroundColor = RatuneColors.background,
|
||||
});
|
||||
|
||||
/// Panel label, e.g. "Queue". Rendered uppercase-ish in mono.
|
||||
final String title;
|
||||
|
||||
/// Optional trailing bit of the label, e.g. "(127)" — dimmed.
|
||||
final String? trailing;
|
||||
|
||||
/// Panel content.
|
||||
final Widget child;
|
||||
|
||||
/// When focused, the border and title tint toward the accent.
|
||||
final bool active;
|
||||
|
||||
final EdgeInsetsGeometry padding;
|
||||
|
||||
/// Color painted behind the title to "cut" the border. Must match whatever
|
||||
/// sits behind this panel (the canvas by default).
|
||||
final Color backgroundColor;
|
||||
|
||||
static const double _titleStraddle = 8;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final borderColor =
|
||||
active ? RatuneColors.borderActive : RatuneColors.border;
|
||||
final titleColor =
|
||||
active ? Theme.of(context).colorScheme.primary : RatuneColors.dimmed;
|
||||
|
||||
return Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(top: _titleStraddle),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: borderColor, width: 1),
|
||||
),
|
||||
child: Padding(padding: padding, child: child),
|
||||
),
|
||||
Positioned(
|
||||
left: RatuneSpacing.lg,
|
||||
top: 0,
|
||||
child: Container(
|
||||
color: backgroundColor,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: RatuneSpacing.md,
|
||||
),
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: title,
|
||||
style: TextStyle(
|
||||
color: titleColor,
|
||||
fontWeight: FontWeight.w700,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
if (trailing != null)
|
||||
TextSpan(
|
||||
text: ' $trailing',
|
||||
style: const TextStyle(color: RatuneColors.dimmed),
|
||||
),
|
||||
],
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelMedium,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue