arch-atlas

Search result view ui done

Presentation (Building the UI)

15:29

Summary

Construct the UI for the search feature by composing a custom text field and a scrollable results list. Extract the text field into a dedicated CustomSearchTextField widget with tailored input decorations, including outline borders and a magnifying glass suffix icon controlled by an Opacity widget. Reuse previously built list view items to display search results, ensuring the list is wrapped in an Expanded widget to properly occupy the available vertical space while maintaining scrollability independent of the parent layout.

Key Ideas

  • Modularizing form inputs by extracting a customized TextField into a standalone StatelessWidget for better maintainability.
  • Customizing InputDecoration using OutlineInputBorder to explicitly define both enabledBorder and focusedBorder states.
  • Utilizing the Opacity widget to soften the visual presence of UI elements like the suffix icon without altering the core color palette.
  • Reusing existing UI components (like BookListViewItem) within new contexts (SearchResultListView) to maintain design consistency and reduce code duplication.
  • Managing layout constraints in Column layouts by wrapping scrollable children (ListView) in Expanded widgets to prevent infinite height errors.
  • Adjusting ScrollPhysics contextually: removing NeverScrollableScrollPhysics when a ListView becomes the primary scrolling area rather than being embedded inside a broader custom scroll view.

Code Snippets

Custom Search Text Fielddart
class CustomSearchTextField extends StatelessWidget {
  const CustomSearchTextField({super.key});

  @override
  Widget build(BuildContext context) {
    return TextField(
      decoration: InputDecoration(
        enabledBorder: buildOutlineInputBorder(),
        focusedBorder: buildOutlineInputBorder(),
        hintText: 'Search',
        suffixIcon: IconButton(
          onPressed: () {},
          icon: const Opacity(
            opacity: .8,
            child: Icon(
              FontAwesomeIcons.magnifyingGlass,
              size: 22,
            ),
          ),
        ),
      ),
    );
  }

  OutlineInputBorder buildOutlineInputBorder() {
    return OutlineInputBorder(
      borderSide: const BorderSide(
        color: Colors.white,
      ),
      borderRadius: BorderRadius.circular(12),
    );
  }
}
Search Result List Viewdart
class SearchResultListView extends StatelessWidget {
  const SearchResultListView({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      padding: EdgeInsets.zero,
      itemCount: 10,
      itemBuilder: (context, index) {
        return const Padding(
          padding: EdgeInsets.symmetric(vertical: 10),
          child: BookListViewItem(),
        );
      },
    );
  }
}
Navigating to Search Viewdart
IconButton(
  onPressed: () {
    GoRouter.of(context).push(AppRouter.kSearchView);
  },
  icon: const Icon(
    FontAwesomeIcons.magnifyingGlass,
    size: 22,
  ),
)

Architecture Insight

Architecture insight

Search is its own feature module — it gets its own lib/features/search/ tree. The temptation to nest it under home/ because it's accessed from the home screen is wrong: search has its own use cases (debounced query, result ranking, history) that don't apply to home browsing.

A good test for "is this its own feature?": does it have its own domain language? Search has *queries*, *results*, *suggestions*. Home has *featured*, *newest*. Different vocabularies → different features.

My Notes

Empty — fill this in later. Open the manifest and add content here.