Skip to content

Commit

Permalink
Migrate Breadcrumbs to Ant (#5610)
Browse files Browse the repository at this point in the history
  • Loading branch information
gilluminate authored Dec 18, 2024
1 parent 12bc0f9 commit 5fc96af
Show file tree
Hide file tree
Showing 75 changed files with 1,053 additions and 958 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The types of changes are:
### Changed
- Adjusted Ant's Select component colors and icon [#5594](https://github.com/ethyca/fides/pull/5594)
- Replaced taxonomies page with new UI based on an interactive tree visualization [#5602](https://github.com/ethyca/fides/pull/5602)
- Migrated breadcrumbs to Ant Design [#5610](https://github.com/ethyca/fides/pull/5610)

### Fixed
- Fixing quickstart.py script [#5585](https://github.com/ethyca/fides/pull/5585)
Expand Down
1 change: 0 additions & 1 deletion clients/admin-ui/src/app/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import type { AppDispatch, RootState } from "./store";

export const useAppDispatch: () => AppDispatch = useDispatch;
// eslint-disable-next-line import/prefer-default-export
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
3 changes: 2 additions & 1 deletion clients/admin-ui/src/features/common/FixedLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ const FixedLayout = ({
<link rel="icon" href="/favicon.ico" />
</Head>
<Flex
pt={6}
px={10}
py={6}
as="main"
overflow="auto"
direction="column"
Expand Down
92 changes: 63 additions & 29 deletions clients/admin-ui/src/features/common/PageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,88 @@
import { Box, BoxProps, Flex } from "fidesui";
import { isArray } from "lodash";
import { isValidElement, ReactElement } from "react";
import { AntFlex as Flex, Heading } from "fidesui";
import { ComponentProps, ReactNode } from "react";

import Breadcrumbs, { BreadcrumbsProps } from "~/features/common/Breadcrumbs";
import { NextBreadcrumb, NextBreadcrumbProps } from "./nav/v2/NextBreadcrumb";

interface PageHeaderProps extends BoxProps {
breadcrumbs: BreadcrumbsProps["breadcrumbs"] | ReactElement | false;
interface PageHeaderProps extends ComponentProps<"div"> {
heading?: ReactNode;
breadcrumbItems?: NextBreadcrumbProps["items"];
isSticky?: boolean;
rightContent?: ReactElement;
rightContent?: ReactNode;
children?: ReactNode;
}

/**
* A header component for pages.
*
* @param breadcrumbs - The breadcrumbs to display in the page header.
* @param heading - The main heading to display in the page header. Can be a string or a React element. String will be rendered as an H1.
* @param breadcrumbItems - Extends Ant Design Breadcrumb component `items` property. If an item has a `href` property, it will be wrapped in a Next.js link.
* Can be an array of breadcrumb items (more information on Breadcrumbs component), a React element
* if you want to render something else, or false to not show any breadcrumbs.
* @param isSticky - Whether the page header should stick to the top of the page while scrolling. Defaults to true.
* @param children - Additional content to display in the header at the bottom.
* @param children - Additional content to display in the header below the heading and breadcrumb.
* @param rightContent - Additional content to display in the header on the right side. Usually for displaying buttons.
*/
const PageHeader = ({
breadcrumbs,
heading,
breadcrumbItems,
isSticky = true,
children,
rightContent,
...otherProps
style,
...props
}: PageHeaderProps): JSX.Element => (
<Box
bgColor="white"
paddingY={5}
{...(isSticky ? { position: "sticky", top: 0, left: 0, zIndex: 10 } : {})}
{...otherProps}
<div
{...props}
style={
isSticky
? {
position: "sticky",
top: "-24px",
paddingTop: "24px",
paddingBottom: "24px",
paddingLeft: "40px",
marginLeft: "-40px",
paddingRight: "40px",
marginRight: "-40px",
marginTop: "-24px",
left: 0,
zIndex: 20, // needs to be above Table header but below popovers, modals, drawers, etc.
backgroundColor: "white",
...style,
}
: {
paddingBottom: "24px",
...style,
}
}
>
<Flex alignItems="flex-start">
<Box flex={1}>
{/* If breadcrumbs is an array, render the Breadcrumbs component. */}
{isArray(breadcrumbs) && (
<Box marginBottom={children ? 4 : 0}>
<Breadcrumbs breadcrumbs={breadcrumbs} />
</Box>
)}
{/* If breadcrumbs is a React element, render it. */}
{isValidElement(breadcrumbs) && breadcrumbs}
</Box>
{rightContent && <Box>{rightContent}</Box>}
<Flex justify="space-between">
{typeof heading === "string" ? (
<Heading
className={!!breadcrumbItems || !!children ? "pb-4" : undefined}
fontSize="2xl"
data-testid="page-heading"
>
{heading}
</Heading>
) : (
heading
)}
{rightContent && (
<div data-testid="page-header-right-content">{rightContent}</div>
)}
</Flex>

{!!breadcrumbItems && (
<NextBreadcrumb
className={children ? "pb-4" : undefined}
items={breadcrumbItems}
data-testid="page-breadcrumb"
/>
)}

{children}
</Box>
</div>
);

export default PageHeader;
79 changes: 79 additions & 0 deletions clients/admin-ui/src/features/common/nav/v2/NextBreadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/* eslint-disable tailwindcss/no-custom-classname */
import {
AntBreadcrumb as Breadcrumb,
AntBreadcrumbItemType as BreadcrumbItemType,
AntBreadcrumbProps as BreadcrumbProps,
AntTypography as Typography,
} from "fidesui";
import { Url } from "next/dist/shared/lib/router/router";
import NextLink from "next/link";
import { ReactNode, useMemo } from "react";

const { Text } = Typography;

// Too difficult to make `path` work with Next.js links so we'll just remove it from the type
interface NextBreadcrumbItemType
extends Omit<BreadcrumbItemType, "path" | "href"> {
/**
* becomes NextJS link href
*/
href?: Url;
icon?: ReactNode;
}

export interface NextBreadcrumbProps extends Omit<BreadcrumbProps, "items"> {
items?: NextBreadcrumbItemType[];
}

/**
* Extends the Ant Design Breadcrumb component to allow for Next.js links. If an item has a `href` property, it will be wrapped in a Next.js link.
*
* Note: Since Next.js link is used to wrap the entire item, we cannot do these other customizations as an HOC in FidesUI due to the order of operations. HOC would be applied AFTER the Next.js link is applied, but we want the Next.js link to wrap the entire item after all other customizations. And, of course, we can't use Next.js links in FidesUI.
*/
export const NextBreadcrumb = ({ items, ...props }: NextBreadcrumbProps) => {
const formattedItems = useMemo(
() =>
items?.map((item, i) => {
const isCurrentPage = i === items.length - 1;
const modifiedItem = { ...item };
if (typeof modifiedItem.title === "string") {
// for everything except the current page, truncate the title if it's too long
modifiedItem.title = (
<Text
style={{
color: "inherit",
maxWidth: !isCurrentPage ? 400 : undefined,
}}
ellipsis={!isCurrentPage}
>
{modifiedItem.title}
</Text>
);
}
if (modifiedItem.icon) {
modifiedItem.title = (
<>
<span className="anticon align-text-bottom">
{modifiedItem.icon}
</span>
{modifiedItem.title}
</>
);
}
if (modifiedItem.href && modifiedItem.title) {
// repeat the ant breadcrumb link class to match the style and margin of the ant breadcrumb item
modifiedItem.title = (
<NextLink href={modifiedItem.href} className="ant-breadcrumb-link">
{modifiedItem.title}
</NextLink>
);
delete modifiedItem.href;
}
return modifiedItem;
}),
[items],
);
return (
<Breadcrumb items={formattedItems as BreadcrumbItemType[]} {...props} />
);
};
2 changes: 1 addition & 1 deletion clients/admin-ui/src/features/config-wizard/AddSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const AddSystem = () => {
return (
<Stack spacing={9} data-testid="add-systems">
<Stack spacing={6} maxWidth="600px">
<Heading as="h3" size="lg" fontWeight="semibold">
<Heading as="h3" size="md" fontWeight="semibold">
Fides helps you map your systems to manage your privacy
</Heading>
<Text>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AntButton as Button, Heading, HStack, Stack } from "fidesui";
import { AntButton as Button, Box, HStack, Stack, Text } from "fidesui";
import { Form, Formik } from "formik";
import { useState } from "react";
import * as Yup from "yup";
Expand All @@ -20,6 +20,7 @@ import {
import { RTKErrorResult } from "~/types/errors";

import { ControlledSelect } from "../common/form/ControlledSelect";
import { NextBreadcrumb } from "../common/nav/v2/NextBreadcrumb";
import {
changeStep,
selectOrganizationFidesKey,
Expand Down Expand Up @@ -129,12 +130,27 @@ const AuthenticateAwsForm = () => {
) : null}
{!isSubmitting && !scannerError ? (
<>
<Heading size="lg">Authenticate AWS Scanner</Heading>
<h2>
To use the scanner to inventory systems in AWS, you must first
authenticate to your AWS cloud by providing the following
information:
</h2>
<Box>
<NextBreadcrumb
className="mb-4"
items={[
{
title: "Add systems",
href: "",
onClick: (e) => {
e.preventDefault();
handleCancel();
},
},
{ title: "Authenticate AWS Scanner" },
]}
/>
<Text>
To use the scanner to inventory systems in AWS, you must
first authenticate to your AWS cloud by providing the
following information:
</Text>
</Box>
<Stack>
<CustomTextInput
name="aws_access_key_id"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AntButton as Button, Heading, HStack, Stack } from "fidesui";
import { AntButton as Button, Box, HStack, Stack, Text } from "fidesui";
import { Form, Formik } from "formik";
import { useState } from "react";
import * as Yup from "yup";
Expand All @@ -19,6 +19,7 @@ import {
} from "~/types/api";
import { RTKErrorResult } from "~/types/errors";

import { NextBreadcrumb } from "../common/nav/v2/NextBreadcrumb";
import {
changeStep,
selectOrganizationFidesKey,
Expand Down Expand Up @@ -113,12 +114,27 @@ const AuthenticateOktaForm = () => {
{scannerError ? <ScannerError error={scannerError} /> : null}
{!isSubmitting && !scannerError ? (
<>
<Heading size="lg">Authenticate Okta Scanner</Heading>
<h2>
To use the scanner to inventory systems in Okta, you must
first authenticate to your Okta account by providing the
following information:
</h2>
<Box>
<NextBreadcrumb
className="mb-4"
items={[
{
title: "Add systems",
href: "",
onClick: (e) => {
e.preventDefault();
handleCancel();
},
},
{ title: "Authenticate Okta Scanner" },
]}
/>
<Text>
To use the scanner to inventory systems in Okta, you must
first authenticate to your Okta account by providing the
following information:
</Text>
</Box>
<Stack>
<CustomTextInput
name="orgUrl"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ConfigWizardWalkthrough = () => {

return (
<Stack direction={["column", "row"]} bg="white">
<Box display="flex" justifyContent="center" w="100%">
<Box display="flex" justifyContent="flex-start" w="100%">
{step === 1 ? <OrganizationInfoForm /> : null}
{step === 2 ? <AddSystem /> : null}
{step === 3 ? <AuthenticateScanner /> : null}
Expand Down
22 changes: 17 additions & 5 deletions clients/admin-ui/src/features/config-wizard/ScanResults.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
AntButton as Button,
Box,
Heading,
HStack,
Stack,
Text,
Expand All @@ -22,6 +21,7 @@ import { SystemsCheckboxTable } from "~/features/common/SystemsCheckboxTable";
import { useUpsertSystemsMutation } from "~/features/system";
import { System } from "~/types/api";

import { NextBreadcrumb } from "../common/nav/v2/NextBreadcrumb";
import {
changeStep,
reset,
Expand Down Expand Up @@ -95,10 +95,22 @@ const ScanResults = () => {

return (
<Box maxW="full">
<Stack spacing={10}>
<Heading as="h3" size="lg" data-testid="scan-results">
Scan results
</Heading>
<Stack spacing={10} data-testid="scan-results">
<NextBreadcrumb
className="mb-4"
items={[
{
title: "Add systems",
href: "",
onClick: (e) => {
e.preventDefault();
handleCancel();
},
},
{ title: "Authenticate" },
{ title: "Scan results" },
]}
/>

{systems.length === 0 ? (
<>
Expand Down
Loading

0 comments on commit 5fc96af

Please sign in to comment.