feat(ux): edge fades hint that filter rows scroll horizontally

Chips clipped at the viewport edge with no cue that more filters exist.
New reusable EdgeFade widget (ShaderMask + dstIn) fades an edge only
while content remains beyond it, driven by scroll metrics; RTL mirrors
via Directionality. Applied to the inventory filter bar, market filter
bar and calendar month strip.
This commit is contained in:
vjrj 2026-07-11 07:14:19 +02:00
parent a461106dbf
commit 4ebfdca2fd
5 changed files with 262 additions and 46 deletions

View file

@ -12,6 +12,7 @@ import '../services/social_connection.dart';
import '../services/social_service.dart';
import '../services/social_settings.dart';
import '../state/offers_cubit.dart';
import 'edge_fade.dart';
import 'market_widgets.dart';
import 'theme.dart';
@ -514,24 +515,26 @@ class _MarketFilterBar extends StatelessWidget {
),
];
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: Row(
children: [
for (final chip in chips)
Padding(
padding: const EdgeInsetsDirectional.only(end: 8),
child: chip,
),
if (state.hasActiveFilter)
TextButton.icon(
key: const Key('market.filter.clear'),
onPressed: cubit.clearFilters,
icon: const Icon(Icons.clear, size: 18),
label: Text(t.inventory.clearFilters),
),
],
return EdgeFade(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
child: Row(
children: [
for (final chip in chips)
Padding(
padding: const EdgeInsetsDirectional.only(end: 8),
child: chip,
),
if (state.hasActiveFilter)
TextButton.icon(
key: const Key('market.filter.clear'),
onPressed: cubit.clearFilters,
icon: const Icon(Icons.clear, size: 18),
label: Text(t.inventory.clearFilters),
),
],
),
),
);
}