Skip to content

Commit

Permalink
feat(UI/UX): declutter the search interface
Browse files Browse the repository at this point in the history
  • Loading branch information
casimir committed Nov 28, 2024
1 parent 80e655a commit 14c07db
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 55 deletions.
2 changes: 1 addition & 1 deletion lib/pages/articles/listing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class _ListingPageState extends ConsumerState<ListingPage> {
Widget build(BuildContext context) {
ref.watch(wStorageProvider);

final headerColor = Theme.of(context).colorScheme.surfaceContainer;
final headerColor = Theme.of(context).colorScheme.surfaceContainerLow;

return Scaffold(
body: SafeArea(
Expand Down
121 changes: 67 additions & 54 deletions lib/pages/articles/search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,25 @@ import '../../widgets/async/text.dart';
import '../../widgets/selectors.dart';

class SearchFilters extends ConsumerWidget {
const SearchFilters({super.key});
const SearchFilters({super.key, this.indent});

// A widget that is prepended and appended to the filters list.
final Widget? indent;

@override
Widget build(BuildContext context, WidgetRef ref) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(children: [
if (indent != null) indent!,
_buildState(context, ref),
C.spacers.horizontalComponent,
_buildStarred(context, ref),
C.spacers.horizontalComponent,
_buildTags(context, ref),
C.spacers.horizontalComponent,
_buildDomains(context, ref),
if (indent != null) indent!,
]),
);
}
Expand Down Expand Up @@ -151,54 +156,58 @@ class SearchBarWithFilters<T> extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
return Container(
color: backgroundColor,
child: PaddedGroup(
padding: C.paddings.group.copyWith(bottom: kSpacingInGroup),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: kSpacingInGroup),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SearchBar(
hintText: context.L.filters_searchbarHint,
leading: const Padding(
padding: EdgeInsets.only(left: 8.0),
child: Icon(Icons.search),
),
trailing: [
AText(
builder: (context) async {
final count = await ref
.watch(wStorageProvider.notifier)
.count(ref.watch(queryProvider));
return count.toString();
},
style: TextStyle(
color: Theme.of(context).colorScheme.onSurfaceVariant,
Padding(
padding: const EdgeInsets.symmetric(horizontal: kSpacingInGroup),
child: Row(
children: [
_buildTextMode(context, ref),
C.spacers.horizontalComponent,
Flexible(
child: SearchBar(
hintText: context.L.filters_searchbarHint,
trailing: [
AText(
builder: (context) async {
final count = await ref
.watch(wStorageProvider.notifier)
.count(ref.watch(queryProvider));
return count.toString();
},
style: TextStyle(
color:
Theme.of(context).colorScheme.onSurfaceVariant,
),
),
C.spacers.horizontalComponent,
],
onChanged: (value) {
if (value.isEmpty) {
ref.read(queryProvider.notifier).clearText();
} else {
ref
.read(queryProvider.notifier)
.overrideWith(WQuery(text: value));
}
},
elevation: WidgetStateProperty.all(0.0),
shape: const WidgetStatePropertyAll(
ContinuousRectangleBorder(
// Freely inspired by the FilterChip shape (height / 4)
borderRadius: BorderRadius.all(Radius.circular(14.0)),
)),
),
),
),
_buildTextMode(context, ref),
if (menu != null) menu!,
],
onChanged: (value) {
if (value.isEmpty) {
ref.read(queryProvider.notifier).clearText();
} else {
ref
.read(queryProvider.notifier)
.overrideWith(WQuery(text: value));
}
},
elevation: WidgetStateProperty.all(0.0),
backgroundColor: WidgetStateProperty.all(
Theme.of(context).colorScheme.surface),
side: WidgetStatePropertyAll(
BorderSide(color: Theme.of(context).colorScheme.onSurface),
if (menu != null) ...[C.spacers.horizontalComponent, menu!]
],
),
shape: const WidgetStatePropertyAll(ContinuousRectangleBorder(
// Freely inspired by the FilterChip shape (height / 4)
borderRadius: BorderRadius.all(Radius.circular(14.0)),
)),
),
C.spacers.verticalComponent,
const SearchFilters(),
SearchFilters(indent: C.spacers.horizontalContent),
],
),
),
Expand All @@ -217,17 +226,17 @@ class SearchBarWithFilters<T> extends ConsumerWidget {
DropdownMenuEntry(
value: SearchTextMode.all,
label: context.L.filters_searchModeAll,
leadingIcon: const Icon(Icons.text_fields),
leadingIcon: iconFromTextMode(SearchTextMode.all),
),
DropdownMenuEntry(
value: SearchTextMode.title,
label: context.L.filters_searchModeTitle,
leadingIcon: const Icon(Icons.title),
leadingIcon: iconFromTextMode(SearchTextMode.title),
),
DropdownMenuEntry(
value: SearchTextMode.content,
label: context.L.filters_searchModeContent,
leadingIcon: const Icon(Icons.article),
leadingIcon: iconFromTextMode(SearchTextMode.content),
),
],
initial: textMode ?? SearchTextMode.all,
Expand All @@ -238,14 +247,18 @@ class SearchBarWithFilters<T> extends ConsumerWidget {
}
}

final iconData = switch (textMode ?? SearchTextMode.all) {
SearchTextMode.all => Icons.text_fields,
SearchTextMode.title => Icons.title,
SearchTextMode.content => Icons.article,
};
return IconButton(
icon: Icon(iconData),
onPressed: onTap,
);
final iconData = iconFromTextMode(textMode);
return textMode == null || textMode == SearchTextMode.all
? IconButton(icon: iconData, onPressed: onTap)
: IconButton.filledTonal(icon: iconData, onPressed: onTap);
}
}

Icon iconFromTextMode(SearchTextMode? textMode) {
final iconData = switch (textMode ?? SearchTextMode.all) {
SearchTextMode.all => Icons.manage_search_outlined,
SearchTextMode.title => Icons.title_outlined,
SearchTextMode.content => Icons.article_outlined,
};
return Icon(iconData);
}

0 comments on commit 14c07db

Please sign in to comment.