Redesign previous chain box with rounded top, flat bottom, and gradient effect

- Move previous chain box to sit directly on top of current post
- Add rounded top corners with flat bottom for visual flow
- Implement gradient from darker top to lighter bottom
- Add subtle top border for better visual separation
- Update arrow icon styling with background container
- Remove spacing between previous chain and focus post
This commit is contained in:
Patrick Britton 2026-02-01 13:36:02 -06:00
parent 681b5b85f9
commit 1cc6d22f20

View file

@ -496,39 +496,47 @@ class _KineticThreadWidgetState extends ConsumerState<KineticThreadWidget>
} }
Widget _buildPreviousChainJump(ThreadNode parentNode) { Widget _buildPreviousChainJump(ThreadNode parentNode) {
return Padding( return Container(
padding: const EdgeInsets.fromLTRB(16, 12, 16, 6), margin: const EdgeInsets.fromLTRB(16, 0, 16, 0),
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
if (_layerStack.length > 1) { if (_layerStack.length > 1) {
_scrubToLayer(_layerStack.length - 2); _scrubToLayer(_layerStack.length - 2);
} }
}, },
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
child: Container( child: Container(
width: double.infinity, width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.5), // Rounded top corners, flat bottom
borderRadius: BorderRadius.circular(16), borderRadius: const BorderRadius.only(
border: Border.all( topLeft: Radius.circular(20),
color: AppTheme.navyBlue.withValues(alpha: 0.12), topRight: Radius.circular(20),
),
boxShadow: [
BoxShadow(
color: AppTheme.navyBlue.withValues(alpha: 0.06),
blurRadius: 16,
offset: const Offset(0, 6),
), ),
// Gradient from darker top to lighter bottom
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
AppTheme.navyBlue.withValues(alpha: 0.15), // Darker at top
AppTheme.navyBlue.withValues(alpha: 0.08), // Lighter at bottom
Colors.transparent, // Fade to transparent
], ],
stops: const [0.0, 0.7, 1.0],
), ),
// Subtle border at the top
border: Border(
top: BorderSide(
color: AppTheme.brightNavy.withValues(alpha: 0.3),
width: 1,
),
),
),
child: Container(
padding: const EdgeInsets.fromLTRB(16, 14, 16, 8),
child: Row( child: Row(
children: [ children: [
_buildMiniAvatar(parentNode), _buildMiniAvatar(parentNode),
const SizedBox(width: 10), const SizedBox(width: 12),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -536,17 +544,17 @@ class _KineticThreadWidgetState extends ConsumerState<KineticThreadWidget>
Text( Text(
'Previous chain', 'Previous chain',
style: GoogleFonts.inter( style: GoogleFonts.inter(
color: AppTheme.textSecondary, color: AppTheme.textSecondary.withValues(alpha: 0.8),
fontSize: 11, fontSize: 10,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
letterSpacing: 0.4, letterSpacing: 0.5,
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 3),
Text( Text(
parentNode.post.author?.displayName ?? 'Anonymous', parentNode.post.author?.displayName ?? 'Anonymous',
style: GoogleFonts.inter( style: GoogleFonts.inter(
color: AppTheme.navyBlue.withValues(alpha: 0.85), color: AppTheme.navyBlue.withValues(alpha: 0.9),
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
@ -557,27 +565,33 @@ class _KineticThreadWidgetState extends ConsumerState<KineticThreadWidget>
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter( style: GoogleFonts.inter(
color: AppTheme.navyText.withValues(alpha: 0.7), color: AppTheme.navyText.withValues(alpha: 0.75),
fontSize: 12, fontSize: 12,
height: 1.4, height: 1.3,
), ),
), ),
], ],
), ),
), ),
const SizedBox(width: 8), const SizedBox(width: 8),
Icon( Container(
padding: const EdgeInsets.all(6),
decoration: BoxDecoration(
color: AppTheme.brightNavy.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
Icons.arrow_upward, Icons.arrow_upward,
size: 18, size: 16,
color: AppTheme.brightNavy, color: AppTheme.brightNavy.withValues(alpha: 0.8),
),
), ),
], ],
), ),
), ),
), ),
), ),
), ).animate().fadeIn(duration: 220.ms).slideY(begin: -0.08, end: 0);
).animate().fadeIn(duration: 220.ms).slideY(begin: -0.1, end: 0);
} }
Widget _buildMiniAvatar(ThreadNode node) { Widget _buildMiniAvatar(ThreadNode node) {
final avatarUrl = node.post.author?.avatarUrl; final avatarUrl = node.post.author?.avatarUrl;
@ -629,7 +643,7 @@ class _KineticThreadWidgetState extends ConsumerState<KineticThreadWidget>
return Hero( return Hero(
tag: 'thread_post_${node.post.id}', tag: 'thread_post_${node.post.id}',
child: Container( child: Container(
margin: const EdgeInsets.fromLTRB(16, 6, 16, 10), margin: const EdgeInsets.fromLTRB(16, 0, 16, 10),
decoration: BoxDecoration( decoration: BoxDecoration(
color: AppTheme.cardSurface, color: AppTheme.cardSurface,
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),