Skip to content

Commit

Permalink
feat: add breadcrumbs component and add it to strategies (#1505)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsimao authored Aug 4, 2023
1 parent 64ebbcd commit 66677f7
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 1 deletion.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@polkadot/ui-keyring": "^2.9.7",
"@reach/tooltip": "^0.16.0",
"@react-aria/accordion": "^3.0.0-alpha.14",
"@react-aria/breadcrumbs": "^3.5.3",
"@react-aria/button": "^3.6.4",
"@react-aria/dialog": "^3.3.1",
"@react-aria/focus": "^3.6.1",
Expand Down
21 changes: 21 additions & 0 deletions src/assets/icons/ChevronRight.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { forwardRef } from 'react';

import { Icon, IconProps } from '@/component-library/Icon';

const ChevronRight = forwardRef<SVGSVGElement, IconProps>((props, ref) => (
<Icon
{...props}
ref={ref}
xmlns='http://www.w3.org/2000/svg'
fill='none'
viewBox='0 0 24 24'
strokeWidth='1.5'
stroke='currentColor'
>
<path strokeLinecap='round' strokeLinejoin='round' d='M8.25 4.5l7.5 7.5-7.5 7.5' />
</Icon>
));

ChevronRight.displayName = 'ChevronRight';

export { ChevronRight };
1 change: 1 addition & 0 deletions src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export { ArrowsUpDown } from './ArrowsUpDown';
export { ArrowTopRightOnSquare } from './ArrowTopRightOnSquare';
export { CheckCircle } from './CheckCircle';
export { ChevronDown } from './ChevronDown';
export { ChevronRight } from './ChevronRight';
export { Cog } from './Cog';
export { DocumentDuplicate } from './DocumentDuplicate';
export { InformationCircle } from './InformationCircle';
Expand Down
56 changes: 56 additions & 0 deletions src/component-library/Breadcrumbs/BreadcrumbItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { AriaBreadcrumbsProps, useBreadcrumbItem } from '@react-aria/breadcrumbs';
import { mergeProps } from '@react-aria/utils';
import { AnchorHTMLAttributes, Fragment, useRef } from 'react';

import { ChevronRight } from '@/assets/icons';

import { TextLinkProps } from '../TextLink';
import { StyledLinkBreadcrumb, StyledSpanBreadcrumb } from './Breadcrumbs.style';

type Props = {
isDisabled?: boolean;
isCurrent: boolean;
to: TextLinkProps['to'];
};

type InheritAttrs = Omit<AriaBreadcrumbsProps, keyof Props>;

type NativeAttrs = Omit<AnchorHTMLAttributes<unknown>, keyof (Props & InheritAttrs)>;

type BreadcrumbItemProps = Props & NativeAttrs & InheritAttrs;

const BreadcrumbItem = ({ children, isDisabled, isCurrent, to, ...props }: BreadcrumbItemProps): JSX.Element => {
const ref = useRef(null);
const { itemProps } = useBreadcrumbItem(
{
...props,
children,
isDisabled: isCurrent,
elementType: isCurrent ? 'span' : 'a'
},
ref
);

const commonProps: Pick<TextLinkProps, 'size' | 'color'> = {
size: 's',
color: isCurrent ? 'secondary' : 'tertiary'
};

return (
<Fragment>
{isCurrent ? (
<StyledSpanBreadcrumb ref={ref} {...mergeProps(commonProps, itemProps)}>
{children}
</StyledSpanBreadcrumb>
) : (
<StyledLinkBreadcrumb ref={ref} to={to} $isDisabled={isDisabled} {...mergeProps(commonProps, itemProps)}>
{children}
</StyledLinkBreadcrumb>
)}
{isCurrent === false && <ChevronRight size='xs' color='tertiary' />}
</Fragment>
);
};

export { BreadcrumbItem };
export type { BreadcrumbItemProps };
20 changes: 20 additions & 0 deletions src/component-library/Breadcrumbs/Breadcrumbs.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Meta, Story } from '@storybook/react';

import { BreadcrumbItem, Breadcrumbs, BreadcrumbsProps } from '.';

const Template: Story<BreadcrumbsProps> = (args) => (
<Breadcrumbs {...args}>
<BreadcrumbItem to='#'>Strategies</BreadcrumbItem>
<BreadcrumbItem to='#'>BTC Passive Income</BreadcrumbItem>
</Breadcrumbs>
);

const Default = Template.bind({});
Default.args = {};

export { Default };

export default {
title: 'Forms/Breadcrumbs',
component: Breadcrumbs
} as Meta;
40 changes: 40 additions & 0 deletions src/component-library/Breadcrumbs/Breadcrumbs.style.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import styled from 'styled-components';

import { Span } from '../Text';
import { TextLink } from '../TextLink';
import { theme } from '../theme';

type StyledBreadcrumbProps = {
$isDisabled?: boolean;
};

const StyledNav = styled.nav``;

const StyledList = styled.ul`
flex-wrap: nowrap;
flex: 1 0;
justify-content: flex-start;
margin: 0;
padding: 0;
list-style-type: none;
display: flex;
`;

const StyledListItem = styled.li`
justify-content: flex-start;
align-items: center;
display: inline-flex;
position: relative;
`;

const StyledSpanBreadcrumb = styled(Span)<StyledBreadcrumbProps>`
padding: 0 ${theme.spacing.spacing2};
cursor: default;
`;

const StyledLinkBreadcrumb = styled(TextLink)<StyledBreadcrumbProps>`
padding: 0 ${theme.spacing.spacing2};
text-decoration: none;
`;

export { StyledLinkBreadcrumb, StyledList, StyledListItem, StyledNav, StyledSpanBreadcrumb };
55 changes: 55 additions & 0 deletions src/component-library/Breadcrumbs/Breadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { AriaBreadcrumbsProps, useBreadcrumbs } from '@react-aria/breadcrumbs';
import { Children, forwardRef, HTMLAttributes, isValidElement, ReactElement } from 'react';

import { useDOMRef } from '../utils/dom';
import { BreadcrumbItem } from './BreadcrumbItem';
import { StyledList, StyledListItem, StyledNav } from './Breadcrumbs.style';

type Props = {
onAction?: (key: React.Key) => void;
isDisabled?: boolean;
};

type NativeAttrs = Omit<HTMLAttributes<unknown>, keyof Props>;

type InheritAttrs = Omit<AriaBreadcrumbsProps, keyof Props>;

type BreadcrumbsProps = Props & NativeAttrs & InheritAttrs;

const Breadcrumbs = forwardRef<HTMLElement, BreadcrumbsProps>(
({ children, isDisabled, ...props }, ref): JSX.Element => {
const domRef = useDOMRef(ref);

const { navProps } = useBreadcrumbs(props);

const childArray: ReactElement[] = [];
Children.forEach(children, (child) => {
if (isValidElement(child)) {
childArray.push(child);
}
});

const lastIndex = childArray.length - 1;

const breadcrumbItems = childArray.map((child, index) => {
const isCurrent = index === lastIndex;

return (
<StyledListItem key={index}>
<BreadcrumbItem {...child.props} isCurrent={isCurrent} isDisabled={isDisabled} />
</StyledListItem>
);
});

return (
<StyledNav {...navProps} ref={domRef}>
<StyledList>{breadcrumbItems}</StyledList>
</StyledNav>
);
}
);

Breadcrumbs.displayName = 'Breadcrumbs';

export { Breadcrumbs };
export type { BreadcrumbsProps };
10 changes: 10 additions & 0 deletions src/component-library/Breadcrumbs/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { BreadcrumbItem as LibBreadcrumbItem, BreadcrumbItemProps as LibBreadcrumbItemProps } from './BreadcrumbItem';

type BreadcrumbItemProps = Omit<LibBreadcrumbItemProps, 'isCurrent'>;

const BreadcrumbItem = (props: BreadcrumbItemProps): JSX.Element => <LibBreadcrumbItem isCurrent={false} {...props} />;

export type { BreadcrumbsProps } from './Breadcrumbs';
export { Breadcrumbs } from './Breadcrumbs';
export { BreadcrumbItem };
export type { BreadcrumbItemProps };
2 changes: 2 additions & 0 deletions src/component-library/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export type { AccordionItemProps, AccordionProps } from './Accordion';
export { Accordion, AccordionItem } from './Accordion';
export type { AlertProps } from './Alert';
export { Alert } from './Alert';
export type { BreadcrumbItemProps, BreadcrumbsProps } from './Breadcrumbs';
export { BreadcrumbItem, Breadcrumbs } from './Breadcrumbs';
export type { CardProps } from './Card';
export { Card } from './Card';
export type { CoinIconProps } from './CoinIcon';
Expand Down
1 change: 1 addition & 0 deletions src/component-library/theme/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ const theme = {
},
icon: {
sizes: {
xs: 'var(--spacing-3)',
s: 'var(--spacing-4)',
md: 'var(--spacing-6)',
lg: 'var(--spacing-8)',
Expand Down
6 changes: 5 additions & 1 deletion src/pages/Strategies/Strategy/Strategy.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useTranslation } from 'react-i18next';
import { useHistory, useParams } from 'react-router';

import { Card, CoinIcon, Flex, H1, H2, P, TextLink } from '@/component-library';
import { BreadcrumbItem, Breadcrumbs, Card, CoinIcon, Flex, H1, H2, P, TextLink } from '@/component-library';
import { MainContainer } from '@/components';
import FullLoadingSpinner from '@/legacy-components/FullLoadingSpinner';
import { PAGES, URL_PARAMETERS } from '@/utils/constants/links';
Expand Down Expand Up @@ -39,6 +39,10 @@ const Strategy = (): JSX.Element | null => {
return (
<MainContainer>
<Flex direction='column' gap='spacing6'>
<Breadcrumbs>
<BreadcrumbItem to={PAGES.STRATEGIES}>{t('navigation.strategies')}</BreadcrumbItem>
<BreadcrumbItem to='#'>{title}</BreadcrumbItem>
</Breadcrumbs>
<H1 size='lg' weight='bold'>
<Flex elementType='span' alignItems='center' gap='spacing2'>
<CoinIcon ticker={strategy.currency.ticker} /> {title}
Expand Down
41 changes: 41 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3474,6 +3474,19 @@
"@react-types/shared" "^3.16.0"
"@swc/helpers" "^0.4.14"

"@react-aria/breadcrumbs@^3.5.3":
version "3.5.3"
resolved "https://registry.yarnpkg.com/@react-aria/breadcrumbs/-/breadcrumbs-3.5.3.tgz#05d4d811d7a665ccf6b0b411a2c0ab0f4fb4638e"
integrity sha512-rmkApAflZm7Finn3vxLGv7MbsMaPo5Bn7/lf8GBztNfzmLWP/dAA5bgvi1sj1T6sWJOuFJT8u04ImUwBCLh8cQ==
dependencies:
"@react-aria/i18n" "^3.8.0"
"@react-aria/interactions" "^3.16.0"
"@react-aria/link" "^3.5.2"
"@react-aria/utils" "^3.18.0"
"@react-types/breadcrumbs" "^3.6.0"
"@react-types/shared" "^3.18.1"
"@swc/helpers" "^0.5.0"

"@react-aria/button@^3.6.4":
version "3.6.4"
resolved "https://registry.yarnpkg.com/@react-aria/button/-/button-3.6.4.tgz#51927c9d968d0c1f741ee2081ca7f2e244abbc12"
Expand Down Expand Up @@ -3905,6 +3918,18 @@
"@react-types/shared" "^3.17.0"
"@swc/helpers" "^0.4.14"

"@react-aria/link@^3.5.2":
version "3.5.2"
resolved "https://registry.yarnpkg.com/@react-aria/link/-/link-3.5.2.tgz#68b99721eeddffb87c42541419f08333eada37d9"
integrity sha512-CCFP11Uietro6TUZpWBoq3Ql/6qss/ODC5XM6oNxckj72IHruFIj8V7Y0tL5x0aE6h38hlKcDf8NCxkQqz2edg==
dependencies:
"@react-aria/focus" "^3.13.0"
"@react-aria/interactions" "^3.16.0"
"@react-aria/utils" "^3.18.0"
"@react-types/link" "^3.4.3"
"@react-types/shared" "^3.18.1"
"@swc/helpers" "^0.5.0"

"@react-aria/listbox@^3.8.0":
version "3.9.0"
resolved "https://registry.yarnpkg.com/@react-aria/listbox/-/listbox-3.9.0.tgz#243d9a863d2592f003aa2c7604962e4db1d57dee"
Expand Down Expand Up @@ -4680,6 +4705,14 @@
dependencies:
"@react-types/shared" "^3.16.0"

"@react-types/breadcrumbs@^3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@react-types/breadcrumbs/-/breadcrumbs-3.6.0.tgz#6a5b5e459597172d7f23f2ecbc9e11c94d2a3f2a"
integrity sha512-EnZk/f59yMQUmH2DW21uo3ajQ7nLEZ/sIMSfEZYP69CFe1by0RKi9aFRjJSrYjxRC0PSHTVPTjIG72KeBSsUGA==
dependencies:
"@react-types/link" "^3.4.3"
"@react-types/shared" "^3.18.1"

"@react-types/button@^3.7.0":
version "3.7.0"
resolved "https://registry.yarnpkg.com/@react-types/button/-/button-3.7.0.tgz#774c043d8090a505e60fdf26f026d5f0cc968f0f"
Expand Down Expand Up @@ -4766,6 +4799,14 @@
"@react-aria/interactions" "^3.14.0"
"@react-types/shared" "^3.17.0"

"@react-types/link@^3.4.3":
version "3.4.3"
resolved "https://registry.yarnpkg.com/@react-types/link/-/link-3.4.3.tgz#51534673ea35cf6583b950319bafd16ff76296dc"
integrity sha512-opKfkcaeV0cir64jPcy7DS0BrmdfuWMjua+MSeNv7FfT/b65rFgPfAOKZcvLWDsaxT5HYb7pivYPBfjKqHsQKw==
dependencies:
"@react-aria/interactions" "^3.16.0"
"@react-types/shared" "^3.18.1"

"@react-types/listbox@^3.4.0", "@react-types/listbox@^3.4.1":
version "3.4.1"
resolved "https://registry.yarnpkg.com/@react-types/listbox/-/listbox-3.4.1.tgz#3d9f5859ad4eb550a6c1c532042316b32e43b606"
Expand Down

2 comments on commit 66677f7

@vercel
Copy link

@vercel vercel bot commented on 66677f7 Aug 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 66677f7 Aug 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.