-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add catalog/explorer dropdown to anvil portal header (#2796)
- Loading branch information
Fran McDade
authored and
Fran McDade
committed
Nov 14, 2023
1 parent
20fcb12
commit 4f1a602
Showing
22 changed files
with
434 additions
and
22 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
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 |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { Header as HeaderProps, NavLinkItem } from "./entities"; | ||
|
||
/** | ||
* Returns the header navigation links for the site config and feature flag. | ||
* @param navLinks - Nav links. | ||
* @param isFeatureFlag - Flag indicating if feature is available to user. | ||
* @returns navigation links. | ||
*/ | ||
function filterFeatureFlagNavigation( | ||
navLinks: NavLinkItem[], | ||
isFeatureFlag: boolean | ||
): NavLinkItem[] { | ||
return navLinks.filter( | ||
({ featureFlag }) => | ||
featureFlag === undefined || featureFlag === isFeatureFlag | ||
); | ||
} | ||
|
||
/** | ||
* Returns the header properties for the site config and feature flag. | ||
* @param header - Site config header. | ||
* @param isFeatureFlag - Flag indicating if feature is available to user. | ||
* @returns header properties. | ||
*/ | ||
export function configureHeader( | ||
header: HeaderProps, | ||
isFeatureFlag: boolean | ||
): HeaderProps { | ||
const navLinks = filterFeatureFlagNavigation(header.navLinks, isFeatureFlag); | ||
return { | ||
...header, | ||
navLinks, | ||
}; | ||
} | ||
|
||
/** | ||
* Returns true if the given link is an internal link. | ||
* @param link - Link. | ||
* @returns true if the given link is an internal link. | ||
*/ | ||
export function isClientSideNavigation(link: string): boolean { | ||
return /^\/(?!\/)/.test(link); | ||
} |
32 changes: 32 additions & 0 deletions
32
src/components/header/components/nav-link-dropdown-button/nav-link-dropdown-button.styles.ts
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,32 @@ | ||
import { css } from "@emotion/react"; | ||
import styled from "@emotion/styled"; | ||
import { Button as MButton } from "@mui/material"; | ||
|
||
interface Props { | ||
isActive: boolean; | ||
} | ||
|
||
export const NavLinkDropdownButton = styled(MButton, { | ||
shouldForwardProp: (prop) => prop !== "isActive", | ||
})<Props>` | ||
background-color: ${({ theme }) => theme.palette.common.white}; | ||
color: inherit; | ||
gap: 0; | ||
&:active, | ||
&:hover { | ||
background-color: ${({ theme }) => theme.palette.smoke.light}; | ||
} | ||
// Button is "active" i.e. menu is open. | ||
${({ isActive, theme }) => | ||
isActive && | ||
css` | ||
background-color: ${theme.palette.smoke.light}; | ||
`}; | ||
.MuiButton-endIcon { | ||
margin-left: -3px; | ||
margin-right: -6px; | ||
} | ||
`; |
26 changes: 26 additions & 0 deletions
26
src/components/header/components/nav-link-dropdown-button/nav-link-dropdown-button.tsx
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,26 @@ | ||
import ArrowDropDownRoundedIcon from "@mui/icons-material/ArrowDropDownRounded"; | ||
import { ButtonProps as MButtonProps } from "@mui/material"; | ||
import React from "react"; | ||
import { NavLinkDropdownButton as Button } from "./nav-link-dropdown-button.styles"; | ||
|
||
export interface NavLinkDropdownButtonProps extends MButtonProps { | ||
isActive: boolean; | ||
} | ||
|
||
export const NavLinkDropdownButton = ({ | ||
children, | ||
isActive, | ||
...props /* Spread props to allow for Button specific props ButtonProps e.g. "onClick". */ | ||
}: NavLinkDropdownButtonProps): JSX.Element => { | ||
return ( | ||
<Button | ||
endIcon={<ArrowDropDownRoundedIcon />} | ||
isActive={isActive} | ||
sx={{ justifyContent: { desktop: "unset", mobile: "flex-start" } }} | ||
variant="nav" | ||
{...props} | ||
> | ||
{children} | ||
</Button> | ||
); | ||
}; |
21 changes: 21 additions & 0 deletions
21
...ponents/label-icon-menu-item/components/open-in-new/open-in-new-icon/open-in-new-icon.tsx
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,21 @@ | ||
import { SvgIcon, SvgIconProps } from "@mui/material"; | ||
import React from "react"; | ||
|
||
/** | ||
* Custom open in new icon. | ||
*/ | ||
|
||
export const OpenInNewIcon = ({ | ||
fontSize = "xsmall", | ||
viewBox = "0 0 18 18", | ||
...props /* Spread props to allow for Mui SvgIconProps specific prop overrides e.g. "htmlColor". */ | ||
}: SvgIconProps): JSX.Element => { | ||
return ( | ||
<SvgIcon fontSize={fontSize} viewBox={viewBox} {...props}> | ||
<path | ||
d="M3.75 15.75C3.3375 15.75 2.98438 15.6031 2.69063 15.3094C2.39688 15.0156 2.25 14.6625 2.25 14.25V3.75C2.25 3.3375 2.39688 2.98438 2.69063 2.69063C2.98438 2.39688 3.3375 2.25 3.75 2.25H8.25C8.4625 2.25 8.64063 2.32187 8.78438 2.46562C8.92813 2.60937 9 2.7875 9 3C9 3.2125 8.92813 3.39062 8.78438 3.53437C8.64063 3.67812 8.4625 3.75 8.25 3.75H3.75V14.25H14.25V9.75C14.25 9.5375 14.3219 9.35938 14.4656 9.21563C14.6094 9.07188 14.7875 9 15 9C15.2125 9 15.3906 9.07188 15.5344 9.21563C15.6781 9.35938 15.75 9.5375 15.75 9.75V14.25C15.75 14.6625 15.6031 15.0156 15.3094 15.3094C15.0156 15.6031 14.6625 15.75 14.25 15.75H3.75ZM6.75 11.25C6.6125 11.1125 6.54375 10.9375 6.54375 10.725C6.54375 10.5125 6.6125 10.3375 6.75 10.2L13.2 3.75H11.25C11.0375 3.75 10.8594 3.67812 10.7156 3.53437C10.5719 3.39062 10.5 3.2125 10.5 3C10.5 2.7875 10.5719 2.60937 10.7156 2.46562C10.8594 2.32187 11.0375 2.25 11.25 2.25H15C15.2125 2.25 15.3906 2.32187 15.5344 2.46562C15.6781 2.60937 15.75 2.7875 15.75 3V6.75C15.75 6.9625 15.6781 7.14063 15.5344 7.28438C15.3906 7.42813 15.2125 7.5 15 7.5C14.7875 7.5 14.6094 7.42813 14.4656 7.28438C14.3219 7.14063 14.25 6.9625 14.25 6.75V4.8L7.78125 11.2688C7.64375 11.4063 7.475 11.475 7.275 11.475C7.075 11.475 6.9 11.4 6.75 11.25Z" | ||
fill="currentColor" | ||
/> | ||
</SvgIcon> | ||
); | ||
}; |
7 changes: 7 additions & 0 deletions
7
...r/components/nav-link-menu/components/label-icon-menu-item/label-icon-menu-item.styles.ts
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,7 @@ | ||
import styled from "@emotion/styled"; | ||
|
||
export const Label = styled.div` | ||
align-items: center; | ||
display: flex; | ||
gap: 4px; | ||
`; |
22 changes: 22 additions & 0 deletions
22
.../header/components/nav-link-menu/components/label-icon-menu-item/label-icon-menu-item.tsx
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,22 @@ | ||
import React, { ElementType } from "react"; | ||
import { OpenInNewIcon } from "./components/open-in-new/open-in-new-icon/open-in-new-icon"; | ||
import { Label } from "./label-icon-menu-item.styles"; | ||
|
||
export interface LabelIconMenuItemProps { | ||
Icon?: ElementType; | ||
iconFontSize?: string; | ||
label: string; | ||
} | ||
|
||
export const LabelIconMenuItem = ({ | ||
Icon = OpenInNewIcon, | ||
iconFontSize = "xsmall", | ||
label, | ||
}: LabelIconMenuItemProps): JSX.Element => { | ||
return ( | ||
<Label> | ||
<div>{label}</div> | ||
<Icon color="inkLight" fontSize={iconFontSize} /> | ||
</Label> | ||
); | ||
}; |
25 changes: 25 additions & 0 deletions
25
src/components/header/components/nav-link-menu/nav-link-menu.styles.ts
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,25 @@ | ||
import styled from "@emotion/styled"; | ||
import { Menu } from "@mui/material"; | ||
|
||
export const NavLinkMenu = styled(Menu)` | ||
.MuiPaper-menu { | ||
margin: 4px 0; | ||
min-width: 144px; | ||
border-color: ${({ theme }) => theme.palette.smoke.main}; | ||
} | ||
&& .MuiMenuItem-root { | ||
margin: 0; | ||
} | ||
.MuiListItemText-root { | ||
display: grid; | ||
gap: 4px; | ||
.MuiListItemText-secondary { | ||
color: ${({ theme }) => theme.palette.ink.light}; | ||
max-width: 290px; | ||
white-space: normal; | ||
} | ||
} | ||
`; |
76 changes: 76 additions & 0 deletions
76
src/components/header/components/nav-link-menu/nav-link-menu.tsx
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,76 @@ | ||
import { ListItemText, MenuItem as MMenuItem } from "@mui/material"; | ||
import { navigate } from "gatsby"; | ||
import React, { MouseEvent, ReactNode, useState } from "react"; | ||
import { Target } from "../../../target/target.model"; | ||
import { MenuItem } from "../../common/entities"; | ||
import { isClientSideNavigation } from "../../common/utils"; | ||
import { NavLinkDropdownButton } from "../nav-link-dropdown-button/nav-link-dropdown-button"; | ||
import { NavLinkMenu as Menu } from "./nav-link-menu.styles"; | ||
|
||
export interface NavLinkMenuProps { | ||
menuItems: MenuItem[]; | ||
menuLabel: ReactNode; | ||
} | ||
|
||
export const NavLinkMenu = ({ | ||
menuItems, | ||
menuLabel, | ||
}: NavLinkMenuProps): JSX.Element => { | ||
const [anchorEl, setAnchorEl] = useState<null | HTMLButtonElement>(null); | ||
const open = Boolean(anchorEl); | ||
|
||
const onOpenMenu = (event: MouseEvent<HTMLButtonElement>): void => { | ||
setAnchorEl(event.currentTarget); | ||
}; | ||
|
||
const onCloseMenu = (): void => { | ||
setAnchorEl(null); | ||
}; | ||
|
||
return ( | ||
<> | ||
<NavLinkDropdownButton isActive={open} onClick={onOpenMenu}> | ||
{menuLabel} | ||
</NavLinkDropdownButton> | ||
<Menu | ||
anchorEl={anchorEl} | ||
anchorOrigin={{ horizontal: "left", vertical: "bottom" }} | ||
autoFocus={false} | ||
onClose={onCloseMenu} | ||
open={open} | ||
PaperProps={{ variant: "menu" }} | ||
transformOrigin={{ | ||
horizontal: "left", | ||
vertical: "top", | ||
}} | ||
> | ||
{menuItems.map( | ||
({ description, label, target = Target.SELF, url }, i) => ( | ||
<MMenuItem | ||
key={i} | ||
onClick={(): void => { | ||
setAnchorEl(null); | ||
if (isClientSideNavigation(url)) { | ||
navigate(url); | ||
} else { | ||
window.open(url, target); | ||
} | ||
}} | ||
> | ||
<ListItemText | ||
primary={label} | ||
primaryTypographyProps={{ | ||
variant: description ? "text-body-500" : "text-body-400", | ||
}} | ||
secondary={description} | ||
secondaryTypographyProps={{ | ||
variant: "text-body-small-400-2lines", | ||
}} | ||
/> | ||
</MMenuItem> | ||
) | ||
)} | ||
</Menu> | ||
</> | ||
); | ||
}; |
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.