-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Track selected school across map views and map state for back-button return to map from school detail #241
Conversation
Merge Develop to Main
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Here's a screen grab of the interaction map.context.mov |
@@ -30,6 +30,7 @@ yarn-error.log* | |||
|
|||
# vercel | |||
.vercel | |||
.vscode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be standard in our .gitignore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missed this ... we need to whitelist some files. will demo in upcoming PR.
@@ -4,7 +4,7 @@ import { School } from "@/types/school"; | |||
|
|||
type MapListProps = { | |||
schools: School[]; | |||
setSelectedSchool: (school: School | false | null) => void; | |||
setSelectedSchool: (school: School | null) => void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
false no longer needed/valid
const handleTransitionEnd = (e: React.TransitionEvent<HTMLDivElement>) => { | ||
if (e.propertyName === "max-height" && isExpanded) { | ||
cardRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }); | ||
} | ||
}; | ||
|
||
function onClick(e: React.MouseEvent<HTMLDivElement>) { | ||
if (learnMoreRef.current && learnMoreRef.current.contains(e.target as Node)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this was causing a setSelectedSchool(null), which we don't want because then we lose the context
if (isExpanded) { | ||
setSelectedSchool(null); | ||
} else { | ||
setSelectedSchool(school); | ||
} | ||
} | ||
|
||
useEffect(() => { | ||
if (selectedSchool && selectedSchool.id === school.id) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scrolls to selected school on back-button return
@@ -56,7 +63,8 @@ const MapboxMap = ({ | |||
|
|||
mapRef.current = map; | |||
map.on("click", () => { | |||
setSelectedSchool(false); | |||
setSelectedSchool(null); | |||
userHasInteracted.current = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needed to differentiate between back-button return and hard landing on the map
@@ -20,7 +20,8 @@ | |||
], | |||
"paths": { | |||
"@/*": ["./src/*"] | |||
} | |||
}, | |||
"sourceMap": true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enables front-end debugging inside vscode
}); | ||
|
||
return () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
teardown function tears down mapbox on close, avoiding memory leaks, etc.
@@ -169,26 +179,49 @@ const MapboxMap = ({ | |||
new mapboxgl.Marker(bayBridgeEl) | |||
.setLngLat([-122.3778, 37.7983]) | |||
.addTo(map); | |||
|
|||
setMapLoaded(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to avoid race condition where useEffect runs before map.on("load") which prevented scrolling to correct school in list on back-button refresh
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look good. Thanks for the breakdown of everything in the PR!
useEffect(() => { | ||
if (mapRef.current && selectedSchool && typeof selectedSchool !== 'boolean') { | ||
// check mapLoaded to avoid race condition where markersRef is not yet initialized | ||
if (mapLoaded && mapRef.current && selectedSchool) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
very nice
const userHasInteracted = useRef(false); | ||
|
||
const flyToOptions = useMemo(() => ({ | ||
zoom: 14, // zoom level to fly to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm noticing that we are always zooming. I think it's best not to change zoom unless the user explicitly requests it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah @nickvisut, it can get zoomy, happy to change anything. I already worked on the settings to slow down the zoom effect to make it less dizzying,. But we can remove the auto-zoom completely. Design team didn't ask for any changes, but maybe they don't know how easy it is to change, not sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe with 100+ schools it might actually make more sense to auto-zoom as the pins will be right on top of each other. i still can't imagine so many pins in my mind's eye, it is going to look awfully crowded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that that could be a future problem, but the experience as of now is suboptimal. Consider: A user arrives at the map and clicks on a school. How do they then click on another school? They will have to manually zoom out in most cases.
There may be a good solution that is the best of both worlds, but let's lean towards best UX w/current set of schools while we figure that out.
// the empty instruction card) | ||
/* TODO: consider using something more descriptive like an enum instead */ | ||
setSelectedSchool(false); | ||
setSelectedSchool(null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double checking here: Is this no longer needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(false vs null as per the comments)
Thanks for putting up with my post-hoc code review 🙂 |
💯 on the detailed breakdown! |
MapContext keeps track of the selected school and the state of the map. This enables a ux where once a user clicks through to a school and then uses the browser back button, they are returned to exactly where they were. Note that MapContext is available across back-button refresh of pages via a combination of React + Next.js caching. Typically of course this would not work as a back-button navigation bootstraps the entire app again, clearing any context. A hard-refresh or nav-landing onto a page will not preserve context, which is what we want.
Details:
div id="root"
element from the map, instead we can also useMapContext
fromRootLayout
to determine how to set theh-auto
andh-dvh-with-fallback
css classes.