A collection of Router-y things: pick one or two that sound interesting and try them out!
This last section is like that part of a long video game where you could either go to the final boss or perform a bunch of side quests to buff up your characters. I don't know who the final boss is in this case, but these are the side quests!
These are a little more self-guided and some are better documented than others. All of them are organized like a user story/ fit critera/ tasking, along with some documentation resources, so you can see if you can figure them out on your own. A handful have some sample code that you can use to walk your way to a solution (those might be the best ones to try if figuring these out yourself sounds a little complicated).
Difficulty: lower, more guidance offered
Unlocked after module 01 (standard tab navigator) or 03 (headless tabs version)
As a mobile user, when navigating to an exhibit from the Exhibits tab, keeping the tab bar visible feels too busy. If it wasn't there, I could see more artwork, and it's easy enough to back out to the top screen of the Exhibits tab if I want to go to another tab.
- For native mobile users, hide the tab bar when on
exhibit/[exhibitName]
You can also follow along with a step by step with code examples
- Follow the split triggers guide to decouple available tab routes from the tab bar UI.
- Inside of the tabs layout, use Expo Router's
useSegments
to read the segments of the URL, so you can see when you're onexhibits
vsexhibits/[exhibitName]
- Set the
hideTabs
variable based on being on a non-index route of a tab and when the platform isn't web - Hide the "visual tabs" when
hideTabs
is true.
Unlocked after module 03
As a mbile web user, bottom tabs don't seem like what I would typically use on a site like this. How about a hamburger menu with a drawer?
- When on web and less than the
sm
width, show a hamburger menu with the same links as you would see on the tab bar
You can also follow along with a step by step with code examples
- Follow the split triggers guide to decouple available tab routes from the tab bar UI.
npm install react-native-drawer-layout
- It's going to be hard to do this entirely with Nativewind selectors, so just import
useMediaQuery
and create an alternate return statement in the tabs layout file if this is a mobile width and we're on web. - Wrap this new mobile web-specific layout in
Drawer
fromreact-native-drawer-layout
. - Make the drawer open when a hamburger button in the top left is pressed (
FontAwesome
has such an icon). Use a state variable to control the drawer open status. - Add the tab links in the drawer. You'll have to use regular
Link
's becauseTabTrigger
's cannot be outside of theTabs
navigator, which has to be inside of theDrawer
. - To close the drawer after navigating, import
usePathname
fromexpo-router
, and use auseEffect
to set the tab open variable to false when the pathname changes.
Unlocked after Module 01
As a user, I'd like to search for artwork by name when looking inside an exhibit.
- Use
Stack.Screen
within [exhibitName].tsx to add the search bar within the header for that screen. - Follow the directions for adding the search bar below.
- Based on the text input, filter works by their names.
As a user, too much space is taken up by tabs when in landscape on my phone. Put those tabs on the right side. Also use the native tabs, I like them better. Maybe animate the transitions, too.
- Resurrect your React Navigation tabs from pre-Module 03. Conditionally render them in the tabs layout file if you're on iOS or Android.
- Remove the
portrait
lock from app.json. - Add a simple landscape orientation check in the tabs layout file (e.g., import
useScreenDimensions
fromreact-native
and check if width > height) - When in landscape, apply the
left
tab bar position as described in the docs below - Make that left tab sidebar compact (icons over the name)
- Maybe try adding that swooshy animation described below.
- (?) While you're here, if you wanted to add that tasty frosted glass translucency, I don't think anyone will complain.
Difficulty: still not that hard, but now you need to build your native app
Unlocked after Module 01
As a user, I would like to have a quick shortcut from my home screen to the visit
tab, so I can quickly see the museum hours and how to get there. I typically think, "It's midnight and I want to go to the museum", and then I just go there and find out it's not open. Maybe if I could just long press the icon and get an option to check the times, I wouldn't do this.
- Add an iOS quick action / Android app shortcut that goes directly to the Visit tab
Follow the quick actions tutorial here
Difficulty: pretty tricky, a good bit of route refactoring
Unlocked after Module 02
As a user, I should be able to browse all the exhibits even if I'm not logged in.
- Don't force users to the login screen if they're not logged in
- Hide the
profile
route when the user isn't logged in - Add a login button on the Home tab that takes you back to the login screen
- Don't allow favoriting if you're not logged in
- Remove the unauthenticated redirect in (app)/_layout.tsx.
- In (tabs)/_layout.tsx, use the
useAuth
hook to hide the profile tab by removing it from the list of tag triggers. - In works/[workId].tsx, use the
useAuth
hook to hide the favorite button. - Add a simple Login button on the Home tab. Use
router.replace
to navigate to the/login
route.
Unlocked after Module 02
As a user, if someone sends me a link to a work of art, but I'm not logged in, I should be able to login and then still go directly to that artwork.
- Instead of redirecting to the login screen when logged out, present it as a modal over the rest of the app.
- Dismiss the modal once the user is logged in
- Remove the unauthenticated redirect in (app)/_layout.tsx.
- Import
Modal
fromreact-native
in (app)/_layout.tsx. - If
authToken
is undefined, show the modal. If it's defined, hide the modal. - Put the contents of login.tsx into the modal (or just use the whole thing as a component).
- Remove any navigation calls from the login page/ component.
Difficulty: probably not that hard, but takes longer than the Vercel/Netlify instructions due to my poor decisions in building this demo
Unlocked anytime, but you probably wouldn't know the API routes worked until after module 02
_Due to me building the data layer as just some JSON files, this app is server-ful. Your supported deployment option without refactoring is an Express.js app.