-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: implement proper breadcrumbs via Remix handles (#64)
- Loading branch information
Showing
12 changed files
with
183 additions
and
128 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import * as React from 'react'; | ||
import { | ||
useLocation, | ||
useMatches, | ||
useSearchParams, | ||
type UIMatch, | ||
} from '@remix-run/react'; | ||
import Nav from './nav'; | ||
import NavLink from './nav-link'; | ||
import NavDivider from './nav-divider'; | ||
import type { SerializeFrom } from '@remix-run/node'; | ||
|
||
export default function Breadcrumbs() { | ||
const matches = useMatches(); | ||
const { pathname: currentPathname } = useLocation(); | ||
const [searchParams] = useSearchParams(); | ||
const q = searchParams.get('q'); | ||
const isSearching = currentPathname === '/search' && q; | ||
const matchesWithBreadcrumbData = matches.filter(hasHandleWithBreadcrumb); | ||
|
||
return ( | ||
<Nav> | ||
<ul> | ||
{matchesWithBreadcrumbData.map((match, matchIndex) => { | ||
const { title } = match.handle.breadcrumb(matches); | ||
const isActive = !isSearching && match.pathname === currentPathname; | ||
|
||
return ( | ||
<li key={match.id} className="inline"> | ||
{isActive ? ( | ||
title | ||
) : ( | ||
<NavLink to={match.pathname}>{title}</NavLink> | ||
)} | ||
{matchIndex < matchesWithBreadcrumbData.length - 1 ? ( | ||
<NavDivider /> | ||
) : null} | ||
</li> | ||
); | ||
})} | ||
{isSearching ? ( | ||
<> | ||
<NavDivider /> | ||
<span>"{q}"</span> | ||
</> | ||
) : null} | ||
</ul> | ||
</Nav> | ||
); | ||
} | ||
|
||
export type BreadcrumbHandle = { | ||
breadcrumb: (matches: ReturnType<typeof useMatches>) => { | ||
title: string | React.ReactElement; | ||
}; | ||
}; | ||
|
||
function hasHandleWithBreadcrumb( | ||
match: UIMatch, | ||
): match is UIMatch<any, BreadcrumbHandle> { | ||
return ( | ||
match.handle !== null && | ||
typeof match.handle === 'object' && | ||
'breadcrumb' in match.handle && | ||
typeof match.handle.breadcrumb === 'function' | ||
); | ||
} | ||
|
||
/** | ||
* Gets loader data for an ancestor route from a route id and the `matches` | ||
* object returned from the `useMatches` function. | ||
*/ | ||
export function getLoaderDataForHandle<Loader>( | ||
routeId: string, | ||
matches: ReturnType<typeof useMatches>, | ||
) { | ||
const match = matches.find((match) => match.id === routeId); | ||
if (!match) throw new Error(`No match found for route id "${routeId}"`); | ||
return match.data as SerializeFrom<Loader>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,3 @@ | ||
export default function Nav({ children }: { children: React.ReactNode }) { | ||
return ( | ||
<nav className="mb-6 px-4 text-gray-100 sm:mb-8 sm:p-0">{children}</nav> | ||
); | ||
return <nav className="px-4 text-gray-100 sm:p-0">{children}</nav>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.