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,88 +496,102 @@ 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( child: Container(
borderRadius: BorderRadius.circular(16), width: double.infinity,
child: BackdropFilter( decoration: BoxDecoration(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8), // Rounded top corners, flat bottom
child: Container( borderRadius: const BorderRadius.only(
width: double.infinity, topLeft: Radius.circular(20),
padding: const EdgeInsets.all(12), topRight: Radius.circular(20),
decoration: BoxDecoration( ),
color: Colors.white.withValues(alpha: 0.5), // Gradient from darker top to lighter bottom
borderRadius: BorderRadius.circular(16), gradient: LinearGradient(
border: Border.all( begin: Alignment.topCenter,
color: AppTheme.navyBlue.withValues(alpha: 0.12), 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(
children: [
_buildMiniAvatar(parentNode),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Previous chain',
style: GoogleFonts.inter(
color: AppTheme.textSecondary.withValues(alpha: 0.8),
fontSize: 10,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
),
const SizedBox(height: 3),
Text(
parentNode.post.author?.displayName ?? 'Anonymous',
style: GoogleFonts.inter(
color: AppTheme.navyBlue.withValues(alpha: 0.9),
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 2),
Text(
parentNode.post.body,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
color: AppTheme.navyText.withValues(alpha: 0.75),
fontSize: 12,
height: 1.3,
),
),
],
),
), ),
boxShadow: [ const SizedBox(width: 8),
BoxShadow( Container(
color: AppTheme.navyBlue.withValues(alpha: 0.06), padding: const EdgeInsets.all(6),
blurRadius: 16, decoration: BoxDecoration(
offset: const Offset(0, 6), color: AppTheme.brightNavy.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
), ),
], child: Icon(
),
child: Row(
children: [
_buildMiniAvatar(parentNode),
const SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Previous chain',
style: GoogleFonts.inter(
color: AppTheme.textSecondary,
fontSize: 11,
fontWeight: FontWeight.w600,
letterSpacing: 0.4,
),
),
const SizedBox(height: 4),
Text(
parentNode.post.author?.displayName ?? 'Anonymous',
style: GoogleFonts.inter(
color: AppTheme.navyBlue.withValues(alpha: 0.85),
fontSize: 12,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 2),
Text(
parentNode.post.body,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.inter(
color: AppTheme.navyText.withValues(alpha: 0.7),
fontSize: 12,
height: 1.4,
),
),
],
),
),
const SizedBox(width: 8),
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.1, end: 0); ).animate().fadeIn(duration: 220.ms).slideY(begin: -0.08, 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),