Conversation
…ed basic filter button component
…t for readability
… of their components
…icking experience
…is provided between cards
There was a problem hiding this comment.
Pull request overview
This pull request implements the UI components for a filtering feature in the favorites section. The PR adds interactive filter buttons and bottom sheets that allow users to select location type filters (Gyms, Eateries, Libraries, Printers, Other), with selected filters displayed as removable tags. The actual filtering functionality is intentionally deferred to a future PR, as stated in the "Next Steps" section.
Changes:
- Added UI components for filter button, filter row with removable tags, and modal bottom sheet for filter selection
- Introduced filter state management in HomeViewModel to track selected and applied filters
- Created new drawable resources for filter icons representing different location types
Reviewed changes
Copilot reviewed 18 out of 24 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/main/res/drawable/*.xml | New vector drawable icons for different location type filters (printer, other, library, gym, eatery, and main filter icon) |
| app/src/main/java/com/cornellappdev/transit/ui/viewmodels/FavoritesFilterSheetState.kt | New enum class defining the available filter types with their icons and labels |
| app/src/main/java/com/cornellappdev/transit/ui/viewmodels/FilterState.kt | Added trailing comma to last enum entry for consistency |
| app/src/main/java/com/cornellappdev/transit/ui/viewmodels/HomeViewModel.kt | Added state management for filter sheet visibility and selected/applied filters |
| app/src/main/java/com/cornellappdev/transit/ui/theme/Color.kt | Added MutedTransitBlue color for active filter background |
| app/src/main/java/com/cornellappdev/transit/ui/screens/HomeScreen.kt | Integrated filter sheet state into the home screen |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/FilterRow.kt | New component displaying the filter button and selected filter tags in a flow row |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/FilterButton.kt | New button component that triggers the filter bottom sheet |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterSheetItem.kt | New component for individual filter options in the bottom sheet grid |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt | Modal bottom sheet component displaying filter options with cancel/apply actions |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt | Integrated filter UI into the favorites view with conditional rendering |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/RoundedImagePlaceCard.kt | Removed horizontal and vertical padding to allow for spacing in parent component |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/AddFavoritesButton.kt | Added vertical content padding parameter |
| .DS_Store, app/.DS_Store, app/src/.DS_Store, app/src/main/.DS_Store, app/src/main/res/.DS_Store, app/src/main/res/drawable/.DS_Store | macOS system files that should not be committed |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
| onRemoveFilter = {} | ||
| ) | ||
|
|
||
|
|
There was a problem hiding this comment.
There are two blank lines at the end of this preview function. This is inconsistent with the codebase style, where preview functions typically have only one blank line after the closing brace (see line 98 or other preview functions in the codebase).
|
|
||
| } |
There was a problem hiding this comment.
There is an extra blank line after the closing brace. This is inconsistent with the codebase style where preview functions typically have only one blank line after the closing brace (see other preview functions in the codebase).
app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt
Outdated
Show resolved
Hide resolved
| color = if(isActive) TransitBlue else MetadataGray, | ||
| shape = RoundedCornerShape(8.dp) | ||
| ) | ||
| .background( | ||
| color = if(isActive) MutedTransitBlue | ||
| else Color.Transparent, | ||
| shape = RoundedCornerShape(8.dp) | ||
| ) | ||
| .clickable(onClick = itemOnClick) | ||
| .padding(vertical = 16.dp), | ||
| horizontalAlignment = Alignment.CenterHorizontally | ||
| ) { | ||
| Icon( | ||
| painterResource(id = iconId), | ||
| contentDescription = label, | ||
| modifier = Modifier | ||
| .size(34.dp), | ||
| tint = if(isActive) TransitBlue else Color.Unspecified | ||
| ) | ||
|
|
||
| Spacer(modifier = Modifier.height(8.dp)) | ||
|
|
||
| Text( | ||
| label, | ||
| color = if(isActive) TransitBlue else MetadataGray, |
There was a problem hiding this comment.
Missing space after 'if' keyword. The codebase consistently uses 'if (' with a space (see examples in BottomSheetFilterItem.kt:41, FilterRow.kt:48, EcosystemBottomSheetContent.kt:116). Please change 'if(isActive)' to 'if (isActive)' for consistency with the codebase style.
|
|
||
| @Preview(showBackground = true) | ||
| @Composable | ||
| private fun InactiveFavoritesFilterSheetItemInactive() { |
There was a problem hiding this comment.
The preview function name 'InactiveFavoritesFilterSheetItemInactive' is inconsistent with the preview naming convention used elsewhere in the codebase. Based on other preview functions like 'PreviewBottomSheetFilterItem' and 'InactivePreviewBottomSheetFilterItem' (from BottomSheetFilterItem.kt), the name should be 'InactivePreviewFavoritesFilterSheetItem' or 'PreviewFavoritesFilterSheetItemInactive' to maintain consistency.
| private fun InactiveFavoritesFilterSheetItemInactive() { | |
| private fun PreviewFavoritesFilterSheetItemInactive() { |
|
|
||
| } |
There was a problem hiding this comment.
There is an extra blank line after the closing brace. This is inconsistent with the codebase style where preview functions typically have only one blank line after the closing brace (see other preview functions in the codebase).
app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt
Outdated
Show resolved
Hide resolved
|
|
||
| ) { |
There was a problem hiding this comment.
Extra blank line in function signature. There's an unnecessary blank line between the parameter list and the closing brace. Remove line 28 for cleaner code formatting.
| ) { | |
| ) { |
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
|
Remove the .DS_Store files |
app/src/main/java/com/cornellappdev/transit/ui/components/home/AddFavoritesButton.kt
Outdated
Show resolved
Hide resolved
| showFilterSheet: Boolean, | ||
| onFilterSheetShow: () -> Unit, | ||
| onAddFavoritesClick: () -> Unit, | ||
| homeViewModel: HomeViewModel = hiltViewModel(), |
There was a problem hiding this comment.
We shouldn't be passing view models to composables, they should ideally only be used on the screen composable. You should just add whatever fields or functions you need from the vm to this composable as parameters
There was a problem hiding this comment.
If there are too many parameters, you can consider grouping some together into a data class
| ) | ||
| } | ||
|
|
||
| val selectedFilters by homeViewModel.selectedFavoritesFilters.collectAsStateWithLifecycle() |
There was a problem hiding this comment.
see above comment, but this should be passed in instead of using the home vm here
| if (showFilterSheet) { | ||
| ModalBottomSheet( | ||
| onDismissRequest = { | ||
| homeViewModel.cancelFavoritesFilters() |
There was a problem hiding this comment.
see above for all functions you are using from home view model
| when (currentFilter) { | ||
| FilterState.FAVORITES -> { | ||
| favoriteList(favorites, navigateToPlace, onAddFavoritesClick) | ||
| val appliedFilters by homeViewModel.appliedFavoritesFilters.collectAsStateWithLifecycle() |
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
| ) | ||
| } | ||
| } | ||
| val isFilterBarHidden = currentFilter == FilterState.FAVORITES && appliedFilters.isEmpty() |
There was a problem hiding this comment.
Nit: might be worth abstracting to vm or using some sort of derived value from the data class
| import androidx.compose.foundation.lazy.grid.LazyVerticalGrid | ||
| import androidx.compose.foundation.lazy.grid.items | ||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||
| import androidx.compose.material.Button |
There was a problem hiding this comment.
Should be using material3
There was a problem hiding this comment.
check other imports below for same reason
app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt
Show resolved
Hide resolved
| .padding(horizontal = 24.dp, vertical = 24.dp), | ||
| verticalAlignment = Alignment.CenterVertically | ||
| ) { | ||
| Text( |
There was a problem hiding this comment.
Nit: If you guys set up a typography system based on figma design system, might be easier to just use the typography style instead of manually including all the font styling all the time
app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/FavoritesFilterBottomSheet.kt
Outdated
Show resolved
Hide resolved
| text: String, | ||
| modifier : Modifier = Modifier | ||
| ){ | ||
| val isCancel = text == "Cancel" |
There was a problem hiding this comment.
I think there should be a better way than this? Maybe just have an optional parameter?
| } | ||
|
|
||
| @Composable | ||
| private fun FooterButton( |
There was a problem hiding this comment.
Nit: These button components can usually be boiled down to having one central reusable button component for the app that takes in various parameters when needed to customize it
|
|
||
| } | ||
|
|
||
| @Preview(showBackground = true) |
There was a problem hiding this comment.
Nit: you can use preview parameters instead of making 2 separate previews
| modifier: Modifier = Modifier | ||
| ) { | ||
| FlowRow( | ||
| modifier = modifier, |
There was a problem hiding this comment.
Add animateContentSize for more smooth animation when adding or removing filters
| containerColor = Color.Transparent, | ||
| contentColor = SecondaryText | ||
| ), | ||
| contentPadding = PaddingValues(horizontal = 8.dp, vertical = 0.dp) |
There was a problem hiding this comment.
I don't think vertical 0.dp does anything but test it out to be safe
| FilterLabel( | ||
| text = filter.label, | ||
| onRemove = { onRemoveFilter(filter) }, | ||
| modifier = Modifier.align(Alignment.CenterVertically) |
There was a problem hiding this comment.
This modifier might not be necessary. Pretty sure there is a way to do center vertically in the vertical arrangement + spaced by at the same time
| ) { | ||
| FilterButton( | ||
| onFilterClick = onFilterClick, | ||
| modifier = Modifier.align(Alignment.CenterVertically) |
There was a problem hiding this comment.
Not sure if necessary, see below comment
| var searchActive by remember { mutableStateOf(false) } | ||
|
|
||
| // Favorite filter bottom sheet state | ||
| val showFilterSheet by homeViewModel.showFilterSheet.collectAsState() |
There was a problem hiding this comment.
should be using collectAsStateWithLifecycle ideally
| } | ||
|
|
||
| fun removeAppliedFilter(filter: FavoritesFilterSheetState) { | ||
| _selectedFavoritesFilters.value = _selectedFavoritesFilters.value - filter |
| @@ -90,6 +90,13 @@ | |||
|
|
|||
There was a problem hiding this comment.
Nit: could be worth separating filter logic into separate vm or file for better separation and organization
| _showAddFavoritesSheet.value = show | ||
| } | ||
|
|
||
| val favoritesFilterList = listOf( |
There was a problem hiding this comment.
For constants like these, we can create some sort of specific constants file somewhere else instead of using home vm to store it
| */ | ||
| val defaultIthaca = LatLng(42.44, -76.50) | ||
|
|
||
| val filterList = listOf( |
There was a problem hiding this comment.
Same thing as below comment about constants in separate file
Overview
Changes Made
Test Coverage
Next Steps (delete if not applicable)
Screenshots (delete if not applicable)
The last button press was 'cancel' (e.g. do nothing)
Filter UI Screen Recording
filter_ui_demo.webm