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

feat: make header configuration support different component for grouping (#308) #405

Merged
merged 5 commits into from
Oct 13, 2023
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import styled from "@emotion/styled";
import { Socials as DXSocials } from "../../../common/Socials/socials";

export const Socials = styled(DXSocials)`
gap: 8px;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import { AppBar, Link, Toolbar } from "@mui/material";
import NLink from "next/link";
import React from "react";
import { IconButtonSocialsFooter } from "../../../common/IconButton/iconButton.styles";
import { Social, Socials } from "../../../common/Socials/socials";
import { Social } from "../../../common/Socials/socials";
import { Stack } from "../../../common/Stack/stack";
import { Logo, LogoProps } from "../Header/components/Logo/logo";
import { NavLinkItem } from "../Header/components/NavLinks/navLinks";
import {
Logo,
LogoProps,
} from "../Header/components/Content/components/Logo/logo";
import { NavLinkItem } from "../Header/components/Content/components/Navigation/navigation";
import { Socials } from "./footer.styles";

export interface FooterProps {
feedbackForm?: boolean;
Expand Down Expand Up @@ -39,8 +43,8 @@ export const Footer = ({
))}
</Stack>
<Stack alignItems="stretch" direction="row" gap={6}>
{navLinks.map(({ label, url }) => (
<NLink key={label} href={url} passHref>
{navLinks.map(({ label, url }, i) => (
<NLink key={`${url}${i}`} href={url} passHref>
<Link
alignItems="center"
color="ink.main"
Expand All @@ -56,7 +60,6 @@ export const Footer = ({
buttonSize="small"
IconButtonElType={IconButtonSocialsFooter}
socials={socials}
sx={{ gap: 2 }}
/>
</Stack>
</Toolbar>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const HEADER_HEIGHT = 56;
export const HEADER_FADE_TIMEOUT = 0;

export const FADE_TRANSITION_PROPS = {
timeout: HEADER_FADE_TIMEOUT,
unmountOnExit: true,
};

export const HEADER_NAVIGATION_LABEL = {
MORE: "More",
SOCIALS: "Follow Us",
};

export const SWITCH_TRANSITION_PROPS = {
timeout: 0,
unmountOnExit: true,
};
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { CustomIcon } from "../../../../common/CustomIcon/customIcon";
import { Social } from "../../../../common/Socials/socials";
import { ANCHOR_TARGET } from "../../../../Links/common/entities";
import { MenuItem } from "../components/NavLinkMenu/navLinkMenu";
import { NavLinkItem } from "../components/NavLinks/navLinks";
import { MenuItem } from "../components/Content/components/Navigation/components/NavigationMenuItems/navigationMenuItems";
import { NavLinkItem } from "../components/Content/components/Navigation/navigation";
import { HEADER_NAVIGATION_LABEL } from "./constants";

/**
* Returns header navigation links for the specified media breakpoint query.
* Returns the navigation links as configured, where the "More" menu is flattened.
* @param links - Header navigation links.
* @returns header navigation links, without links grouped under the "More" menu.
*/
export function flattenMoreLink(links: NavLinkItem[]): NavLinkItem[] {
return links.flatMap((link: NavLinkItem) => {
if (link.label === HEADER_NAVIGATION_LABEL.MORE) {
return link.menuItems as NavLinkItem[];
}
return link;
});
}

/**
* Returns header navigation links with socials appended with the corresponding label "Follow Us".
* @param links - Header navigation links.
* @param socials - Header socials.
* @param onlySmDesktop - Media breakpoint query is "true" for small desktop only.
Expand All @@ -20,15 +35,15 @@ export function getHeaderNavigationLinks(
const navLinks = [...links];
if (socials) {
navLinks.push({
label: "Follow Us",
label: HEADER_NAVIGATION_LABEL.SOCIALS,
menuItems: getFollowUsMenuItems(socials),
url: "",
});
}
return navLinks;
}
// Return the links without the "More" or "Follow Us" menu.
return links.flatMap((link) => link.menuItems || link);
return flattenMoreLink(links);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styled from "@emotion/styled";
import { DESKTOP_SM } from "../../../../../../../../theme/common/breakpoints";

export const HeaderActions = styled.div`
align-items: center;
display: flex;
flex: 1;
gap: 12px;
justify-content: flex-end;

${({ theme }) => theme.breakpoints.up(DESKTOP_SM)} {
flex: none;
gap: 8px;
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React, { ReactNode } from "react";
import { HeaderActions } from "./actions.styles";

export interface ActionsProps {
children: ReactNode | ReactNode[];
showActions?: boolean;
}

export const Actions = ({
children,
showActions = true,
}: ActionsProps): JSX.Element => {
return <>{showActions && <HeaderActions>{children}</HeaderActions>}</>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useRouter } from "next/router";
import React, { useCallback } from "react";
import { useAuthentication } from "../../../../../../../../../../hooks/useAuthentication";
import { AuthenticationMenu } from "./components/AuthenticationMenu/authenticationMenu";
import { RequestAuthentication } from "./components/RequestAuthentication/requestAuthentication";

export interface AuthenticationProps {
authenticationEnabled?: boolean;
closeMenu: () => void;
}

export const Authentication = ({
authenticationEnabled,
closeMenu,
}: AuthenticationProps): JSX.Element => {
const { isAuthenticated, requestAuthentication, userProfile } =
useAuthentication();
const router = useRouter();
const onLogout = useCallback((): void => {
location.href = router.basePath;
}, [router]);
return (
<>
{authenticationEnabled &&
(isAuthenticated && userProfile ? (
<AuthenticationMenu onLogout={onLogout} userProfile={userProfile} />
) : (
<RequestAuthentication
closeMenu={closeMenu}
requestAuthorization={requestAuthentication}
/>
))}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { MenuItem } from "@mui/material";
import React, { MouseEvent, useState } from "react";
import { UserProfile } from "../../../../../../../../providers/authentication";
import { UserProfile } from "../../../../../../../../../../../../providers/authentication";
import {
AuthenticationMenu as Menu,
Avatar,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import styled from "@emotion/styled";
import { Button as MButton } from "@mui/material";
import { textBody500 } from "../../../../../../../../../../../../styles/common/mixins/fonts";

export const Button = styled(MButton)`
& {
${textBody500};
padding: 6px 12px;
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import LoginRoundedIcon from "@mui/icons-material/LoginRounded";
import { Fade, IconButton } from "@mui/material";
import React from "react";
import {
BREAKPOINT_FN_NAME,
useBreakpointHelper,
} from "../../../../../../../../../../../../hooks/useBreakpointHelper";
import { DESKTOP_SM } from "../../../../../../../../../../../../theme/common/breakpoints";
import { SWITCH_TRANSITION_PROPS } from "../../../../../../../../common/constants";
import { Button } from "./requestAuthentication.styles";

export interface RequestAuthenticationProps {
closeMenu: () => void;
requestAuthorization: () => void;
}

export const RequestAuthentication = ({
closeMenu,
requestAuthorization,
}: RequestAuthenticationProps): JSX.Element => {
const smDesktop = useBreakpointHelper(BREAKPOINT_FN_NAME.UP, DESKTOP_SM);
const switchProps = SWITCH_TRANSITION_PROPS;
return (
<>
<Fade in={smDesktop} {...switchProps}>
<Button
onClick={requestAuthorization}
startIcon={<LoginRoundedIcon />}
variant="nav"
>
Sign in
</Button>
</Fade>
<Fade in={!smDesktop} {...switchProps}>
<IconButton
color="ink"
onClick={(): void => {
closeMenu();
requestAuthorization();
}}
>
<LoginRoundedIcon />
</IconButton>
</Fade>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import styled from "@emotion/styled";
import {
textBody500,
textBodyLarge500,
} from "../../../../../../../../../../../../../../styles/common/mixins/fonts";
import { Navigation as DXNavigation } from "../../../../../../../Navigation/navigation";

export const Navigation = styled(DXNavigation)`
display: flex;
flex: 1;
flex-direction: column;
gap: 4px;
margin: 0;
justify-content: flex-start;

.MuiButton-nav {
${textBodyLarge500};
justify-content: space-between;
padding: 12px 24px;

.MuiButton-endIcon {
transform: rotate(-90deg);
}
}
`;

export const DrawerNavigation = styled(Navigation)`
gap: 0;

.MuiButton-nav {
${textBody500};
padding: 14px 24px;
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from "@emotion/styled";
import { textBody400 } from "../../../../../../../../../../../../../../styles/common/mixins/fonts";

export const Slogan = styled.div`
${textBody400};
padding: 8px 24px;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from "@emotion/styled";
import { Socials as DXSocials } from "../../../../../../../../../../../../../common/Socials/socials";

export const Socials = styled(DXSocials)`
gap: 16px;
padding: 8px 16px;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import CloseRoundedIcon from "@mui/icons-material/CloseRounded";
import { IconButton } from "@mui/material";
import React from "react";
import { Toolbar as DXToolbar } from "../../../../../../../../header.styles";
import { Logo, LogoProps } from "../../../../../Logo/logo";
import { Actions } from "../../../../actions";
import { Authentication } from "../../../Authentication/authentication";
import { Search } from "../../../Search/search";

export interface DialogTitleProps {
authenticationEnabled?: boolean;
logo?: LogoProps;
onClose: () => void;
searchEnabled?: boolean;
searchURL?: string;
}

export const Toolbar = ({
authenticationEnabled,
logo,
onClose,
searchEnabled,
searchURL,
}: DialogTitleProps): JSX.Element => {
return (
<DXToolbar>
{logo && <Logo {...logo} />}
<Actions>
{/* Search */}
<Search
closeMenu={onClose}
searchEnabled={searchEnabled}
searchURL={searchURL}
/>
{/* Authentication */}
<Authentication
authenticationEnabled={authenticationEnabled}
closeMenu={onClose}
/>
{/* Close menu */}
<IconButton color="ink" onClick={onClose}>
<CloseRoundedIcon />
</IconButton>
</Actions>
</DXToolbar>
);
};
Loading
Loading