Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions app/components/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* Copyright Oxide Computer Company
*/
import cn from 'classnames'
import { Link } from 'react-router-dom'

import { PrevArrow12Icon } from '@oxide/design-system/icons/react'

import { useCrumbs } from '~/hooks/use-crumbs'
import { Slash } from '~/ui/lib/Slash'
import { intersperse } from '~/util/array'

export function Breadcrumbs() {
const crumbs = useCrumbs()
const isTopLevel = crumbs.length <= 1
return (
<nav
className="flex items-center gap-0.5 overflow-clip pr-4 text-sans-md"
aria-label="Breadcrumbs"
>
<PrevArrow12Icon
className={cn('mx-1.5 flex-shrink-0 text-quinary', isTopLevel && 'opacity-40')}
/>

{intersperse(
crumbs.map(({ label, path }, i) => (
<Link
to={path}
className={cn(
'whitespace-nowrap text-sans-md hover:text-secondary',
// make the last breadcrumb brighter, but only if we're below the top level
!isTopLevel && i === crumbs.length - 1 ? 'text-secondary' : 'text-tertiary'
)}
key={`${label}|${path}`}
>
{label}
</Link>
)),
<Slash />
)}
</nav>
)
}
184 changes: 0 additions & 184 deletions app/components/TopBarBreadcrumbs.tsx

This file was deleted.

15 changes: 6 additions & 9 deletions app/hooks/use-title.ts → app/hooks/use-crumbs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,12 @@ function checkCrumbType(m: MatchWithCrumb): MatchWithCrumb {
return m
}

/**
* non top-level route: Instances / mock-project / Projects / maze-war / Oxide Console
* top-level route: Oxide Console
*/
export const useTitle = () =>
export const useCrumbs = () =>
useMatches()
.filter(hasCrumb)
.map(checkCrumbType)
.map((m) => (typeof m.handle.crumb === 'function' ? m.handle.crumb(m) : m.handle.crumb))
.reverse()
.concat('Oxide Console') // if there are no crumbs, we're still Oxide Console
.join(' / ')
.map((m) => {
const label =
typeof m.handle.crumb === 'function' ? m.handle.crumb(m) : m.handle.crumb
return { label, path: m.pathname }
})
4 changes: 2 additions & 2 deletions app/layouts/ProjectLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import {
Storage16Icon,
} from '@oxide/design-system/icons/react'

import { Breadcrumbs } from '~/components/Breadcrumbs'
import { TopBar } from '~/components/TopBar'
import { TopBarBreadcrumbs } from '~/components/TopBarBreadcrumbs'
import { SiloSystemPicker } from '~/components/TopBarPicker'
import { getProjectSelector, useProjectSelector } from '~/hooks/use-params'
import { useQuickActions } from '~/hooks/use-quick-actions'
Expand Down Expand Up @@ -79,7 +79,7 @@ export function ProjectLayout({ overrideContentPane }: ProjectLayoutProps) {
<PageContainer>
<TopBar>
<SiloSystemPicker value="silo" />
<TopBarBreadcrumbs />
<Breadcrumbs />
</TopBar>
<Sidebar>
<Sidebar.Nav>
Expand Down
13 changes: 12 additions & 1 deletion app/layouts/RootLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@ import { Outlet, useNavigation } from 'react-router-dom'

import { MswBanner } from '~/components/MswBanner'
import { ToastStack } from '~/components/ToastStack'
import { useTitle } from '~/hooks/use-title'
import { useCrumbs } from '~/hooks/use-crumbs'

/**
* non top-level route: Instances / mock-project / Projects / maze-war / Oxide Console
* top-level route: Oxide Console
*/
export const useTitle = () =>
useCrumbs()
.map((c) => c.label)
.reverse()
.concat('Oxide Console') // if there are no crumbs, we're still Oxide Console
.join(' / ')

/**
* Root layout that applies to the entire app. Modify sparingly. It's rare for
Expand Down
4 changes: 2 additions & 2 deletions app/layouts/SiloLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import {
Metrics16Icon,
} from '@oxide/design-system/icons/react'

import { Breadcrumbs } from '~/components/Breadcrumbs'
import { DocsLinkItem, NavLinkItem, Sidebar } from '~/components/Sidebar'
import { TopBar } from '~/components/TopBar'
import { TopBarBreadcrumbs } from '~/components/TopBarBreadcrumbs'
import { SiloSystemPicker } from '~/components/TopBarPicker'
import { useQuickActions } from '~/hooks/use-quick-actions'
import { Divider } from '~/ui/lib/Divider'
Expand Down Expand Up @@ -55,7 +55,7 @@ export function SiloLayout() {
<PageContainer>
<TopBar>
<SiloSystemPicker value="silo" />
<TopBarBreadcrumbs />
<Breadcrumbs />
</TopBar>
<Sidebar>
<Sidebar.Nav>
Expand Down
4 changes: 2 additions & 2 deletions app/layouts/SystemLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ import {
Servers16Icon,
} from '@oxide/design-system/icons/react'

import { Breadcrumbs } from '~/components/Breadcrumbs'
import { trigger404 } from '~/components/ErrorBoundary'
import { DocsLinkItem, NavLinkItem, Sidebar } from '~/components/Sidebar'
import { TopBar } from '~/components/TopBar'
import { TopBarBreadcrumbs } from '~/components/TopBarBreadcrumbs'
import { SiloSystemPicker } from '~/components/TopBarPicker'
import { useQuickActions } from '~/hooks/use-quick-actions'
import { Divider } from '~/ui/lib/Divider'
Expand Down Expand Up @@ -90,7 +90,7 @@ export function SystemLayout() {
<PageContainer>
<TopBar>
<SiloSystemPicker value="system" />
<TopBarBreadcrumbs />
<Breadcrumbs />
</TopBar>
<Sidebar>
<Sidebar.Nav>
Expand Down
Loading
Loading