Skip to content
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

[EPIC] Stacked Navigation: Milestone 1 (navigation components) #84018

Open
9 of 11 tasks
malwilley opened this issue Jan 24, 2025 · 0 comments
Open
9 of 11 tasks

[EPIC] Stacked Navigation: Milestone 1 (navigation components) #84018

malwilley opened this issue Jan 24, 2025 · 0 comments
Assignees

Comments

@malwilley
Copy link
Member

malwilley commented Jan 24, 2025

At present, items in the side nav are defined in a central location by a config object (see code here). These config items are quite rigid, only allowing for a label and a pathname. In order to support issue and other saved views with custom behavior, it would be beneficial to move the rendering of these items into the product areas themselves so that product teams can easily access and share state with the main content.

The system should be flexible enough to support all present feature in issue views (overflow menus, custom selection behavior based on variables other than the URL, drag and drop, etc), as well as future features that we cannot yet anticipate. Each individual product team should be able to render custom components without needing to modify any internal side nav components. In order to keep things looking consistent, there should be a suite of composable components to build the UI from.

Another requirement is that we need this solution to handle a collapsible sidebar. When collapsed (either by user action or because the screen is too small), the sidebar items should instead be rendered in a flyout. When the screen is even smaller, nav items will be rendered in a

Component Design

Proposed Structure

  • <SecondaryNav />
    • This component can be rendered anywhere in the component tree, but will use a portal so that it appears beside the main nav.
    • This portal will use a top-level NavContext to determine the portal target. The NavContext will contain a reference to the element, which may change based on screen size or collapsed state.
    • Props:
      • id: NavId - A unique identifier, like issues. Should match the id given to the top-level
      • children: ReactNode - Custom content
  • <SecondaryNav.Body />
    • Simple container component for the main sub nav content
    • Props:
      • children: ReactNode
  • <SecondaryNav.Footer />
    • Simple container component for content that should be displayed at the bottom of the sub nav (in the designs, this contains “Alerts” and “Crons”)
    • Props:
      • children: ReactNode
  • <SecondaryNav.BodySection />
    • Designates a section of secondary nav items (in the designs, this is used to separate issue views from the “All” and “Feedback” items).
    • Props:
      • title?: ReactNode
      • children: ReactNode
  • <SecondaryNav.Item />
    • This component provides the styling for a secondary nav item, such as an issue view. This component must change appearance based on where it is being rendered (expanded secondary nav, collapsed secondary nav flyout, or mobile secondary nav).
    • Props:
      • isActive?: boolean - Optionally control the active state of the item, if it is not as simple as a matching URL
      • to: To
      • children: ReactNode
  • <SecondaryNav.ItemProjectIcon />
    • Props:
      • projects: string[]

Example usage

// Top-level /issues component

return (
    <Fragment>
        <IssuesSecondaryNav />
        <IssueListOverview />
    </Fragment>
)

// IssuesSecondaryNav
// Located inside /views/issues/

function IssuesSecondaryNav() {
    const views = useApiQuery(...); // Custom data fetching
    const activeViewId = useActiveViewId(); // Custom selection logic

    return (
        <SecondaryNav>
            <SecondaryNav.Body>
                <SecondaryNav.BodySection>
                    <SecondaryNav.Item to="/issues/all/">
                        All
                    </SecondaryNav.Item>
                    <SecondaryNav.Item to="/issues/feedback/">
                        Feedback
                    </SecondaryNav.Item>
                </SecondaryNav.BodySection>
                <SecondaryNav.BodySection title="Views">
                    {views.map(view => (
                        <SecondaryNav.Item key={view.id} to={`/issues/views/${view.id}/`} isActive={view.id === activeViewId}>
                            <SecondaryNav.ItemProjectIcon projects={view.projects} />
                            {view.name}
                        </SecondaryNav.Item>
                    ))}
                </SecondaryNav.BodySection>
            </SecondaryNav.Body>
            <SecondaryNav.Footer>
                <SecondaryNav.Item to="/issues/alerts/">
                    Alerts
                </SecondaryNav.Item>
                <SecondaryNav.Item to="/issues/crons/">
                    Crons
                </SecondaryNav.Item>
            </SecondaryNav.Footer>
        </SecondaryNav>
    )
}
Designs

Image

Task list

  • Create framework and components for customizing navigation items
  • Add collapse/expand button to navigation
  • Support onboarding tooltips in new navigation component
  • Render navigation items in mobile view
  • Fix misc navigation bugs
  • Modify navigation structure to fit into Issues/Explore/Boards/Insights
  • Modify URL structure for /explore/ and /insights/ routes
  • Add redirects for /explore/ and /insights/ routes
  • Add ability to toggle the stacked nav on/off
  • Replace old onboarding panels
  • Create Storybook entries for navigation components
@malwilley malwilley self-assigned this Jan 24, 2025
malwilley added a commit that referenced this issue Jan 28, 2025
…84129)

Ref #84018

I wanted to add navigation components that would show up on both issues
stream and details, but currently issue details is not a child of the
`/issues` route which means I'd have to render it in two places.

I moved the issue details routes so that it is a child of the `/issues`
`Route`, which was relatively simple. The one thing I'm a bit worried
about is that I removed the customer domain logic. I _believe_ this is
okay because the `/issues` route has the prop `withOrgPath` which adds
the `/organizations/:orgSlug` path as well. Here's an example of this
being done before: #66747
andrewshie-sentry pushed a commit that referenced this issue Jan 29, 2025
…84129)

Ref #84018

I wanted to add navigation components that would show up on both issues
stream and details, but currently issue details is not a child of the
`/issues` route which means I'd have to render it in two places.

I moved the issue details routes so that it is a child of the `/issues`
`Route`, which was relatively simple. The one thing I'm a bit worried
about is that I removed the customer domain logic. I _believe_ this is
okay because the `/issues` route has the prop `withOrgPath` which adds
the `/organizations/:orgSlug` path as well. Here's an example of this
being done before: #66747
c298lee pushed a commit that referenced this issue Jan 29, 2025
…84129)

Ref #84018

I wanted to add navigation components that would show up on both issues
stream and details, but currently issue details is not a child of the
`/issues` route which means I'd have to render it in two places.

I moved the issue details routes so that it is a child of the `/issues`
`Route`, which was relatively simple. The one thing I'm a bit worried
about is that I removed the customer domain logic. I _believe_ this is
okay because the `/issues` route has the prop `withOrgPath` which adds
the `/organizations/:orgSlug` path as well. Here's an example of this
being done before: #66747
malwilley added a commit that referenced this issue Feb 11, 2025
Ref #84018

The new nav structure moves `/discover/` to `/explore/discover/`.

To facilitate the transition, I'm adding a util `makeDiscoverPathname()`
that will check a feature flag to decide which link to generate. In
order to use this I needed to change many function arguments from
`orgSlug` to `organization`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant