Refactor UI folder (#2016)
* Added Overview page * Revised Getting Started page * Minor revision * Edited readme, minor modifications to docs * Removed sweep.yaml, .devcontainer, .ergomake * Moved security.md to .github, added contributing.md * changes as per code review * updated contributing.md * fixed broken links & added missing links in doc, improved structure * fixed link in wsl setup * fixed server link, added https cloning in yarn-setup * removed package-lock.json * added doc card, admonitions * removed underline from nav buttons * refactoring modules/ui * refactoring modules/ui * Change folder case * Fix theme location * Fix case 2 * Fix storybook --------- Co-authored-by: Nimra Ahmed <nimra1408@gmail.com> Co-authored-by: Nimra Ahmed <50912134+nimraahmed@users.noreply.github.com>
This commit is contained in:
@ -0,0 +1,43 @@
|
||||
import * as React from 'react';
|
||||
import { Link as ReactLink } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
type ContactLinkProps = {
|
||||
className?: string;
|
||||
href: string;
|
||||
children?: React.ReactNode;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
const StyledClickable = styled.div`
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: ${({ theme }) => theme.border.color.strong};
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:hover {
|
||||
text-decoration-color: ${({ theme }) => theme.font.color.primary};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const ContactLink = ({
|
||||
className,
|
||||
href,
|
||||
children,
|
||||
onClick,
|
||||
}: ContactLinkProps) => (
|
||||
<div>
|
||||
<StyledClickable className={className}>
|
||||
<ReactLink target="_blank" onClick={onClick} to={href}>
|
||||
{children}
|
||||
</ReactLink>
|
||||
</StyledClickable>
|
||||
</div>
|
||||
);
|
||||
37
front/src/modules/ui/navigation/link/components/RawLink.tsx
Normal file
37
front/src/modules/ui/navigation/link/components/RawLink.tsx
Normal file
@ -0,0 +1,37 @@
|
||||
import * as React from 'react';
|
||||
import { Link as ReactLink } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
type RawLinkProps = {
|
||||
className?: string;
|
||||
href: string;
|
||||
children?: React.ReactNode;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
const StyledClickable = styled.div`
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
`;
|
||||
|
||||
export const RawLink = ({
|
||||
className,
|
||||
href,
|
||||
children,
|
||||
onClick,
|
||||
}: RawLinkProps) => (
|
||||
<div>
|
||||
<StyledClickable className={className}>
|
||||
<ReactLink target="_blank" onClick={onClick} to={href}>
|
||||
{children}
|
||||
</ReactLink>
|
||||
</StyledClickable>
|
||||
</div>
|
||||
);
|
||||
@ -0,0 +1,41 @@
|
||||
import * as React from 'react';
|
||||
import { Link as ReactLink } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { Chip, ChipSize, ChipVariant } from '@/ui/display/chip/components/Chip';
|
||||
|
||||
type RoundedLinkProps = {
|
||||
href: string;
|
||||
children?: React.ReactNode;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
const StyledClickable = styled.div`
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
`;
|
||||
|
||||
export const RoundedLink = ({ children, href, onClick }: RoundedLinkProps) => (
|
||||
<div>
|
||||
{children !== '' ? (
|
||||
<StyledClickable>
|
||||
<ReactLink target="_blank" to={href} onClick={onClick}>
|
||||
<Chip
|
||||
label={`${children}`}
|
||||
variant={ChipVariant.Rounded}
|
||||
size={ChipSize.Small}
|
||||
/>
|
||||
</ReactLink>
|
||||
</StyledClickable>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@ -0,0 +1,64 @@
|
||||
import * as React from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RoundedLink } from './RoundedLink';
|
||||
|
||||
export enum LinkType {
|
||||
Url = 'url',
|
||||
LinkedIn = 'linkedin',
|
||||
Twitter = 'twitter',
|
||||
}
|
||||
|
||||
type SocialLinkProps = {
|
||||
href: string;
|
||||
children?: React.ReactNode;
|
||||
type?: LinkType;
|
||||
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
|
||||
};
|
||||
|
||||
const StyledRawLink = styled(RoundedLink)`
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
|
||||
export const SocialLink = ({
|
||||
children,
|
||||
href,
|
||||
onClick,
|
||||
type,
|
||||
}: SocialLinkProps) => {
|
||||
let displayValue = children;
|
||||
|
||||
if (type === 'linkedin') {
|
||||
const matches = href.match(
|
||||
/(?:https?:\/\/)?(?:www.)?linkedin.com\/(?:in|company)\/([-a-zA-Z0-9@:%_+.~#?&//=]*)/,
|
||||
);
|
||||
if (matches && matches[1]) {
|
||||
displayValue = matches[1];
|
||||
} else {
|
||||
displayValue = 'LinkedIn';
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'twitter') {
|
||||
const matches = href.match(
|
||||
/(?:https?:\/\/)?(?:www.)?twitter.com\/([-a-zA-Z0-9@:%_+.~#?&//=]*)/,
|
||||
);
|
||||
if (matches && matches[1]) {
|
||||
displayValue = `@${matches[1]}`;
|
||||
} else {
|
||||
displayValue = '@twitter';
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledRawLink href={href} onClick={onClick}>
|
||||
{displayValue}
|
||||
</StyledRawLink>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,36 @@
|
||||
import { jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||
|
||||
import { ContactLink } from '../ContactLink';
|
||||
|
||||
const meta: Meta<typeof ContactLink> = {
|
||||
title: 'UI/Link/ContactLink',
|
||||
component: ContactLink,
|
||||
decorators: [ComponentWithRouterDecorator],
|
||||
args: {
|
||||
className: 'ContactLink',
|
||||
href: '/test',
|
||||
children: 'Contact Link',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof ContactLink>;
|
||||
const clickJestFn = jest.fn();
|
||||
|
||||
export const Email: Story = {
|
||||
args: {
|
||||
href: `mailto:${'email@example.com'}`,
|
||||
children: 'email@example.com',
|
||||
onClick: clickJestFn,
|
||||
},
|
||||
};
|
||||
|
||||
export const Phone: Story = {
|
||||
args: {
|
||||
children: '11111111111',
|
||||
onClick: clickJestFn,
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,38 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/testing-library';
|
||||
|
||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||
|
||||
import { RawLink } from '../RawLink';
|
||||
|
||||
const meta: Meta<typeof RawLink> = {
|
||||
title: 'UI/Link/RawLink',
|
||||
component: RawLink,
|
||||
decorators: [ComponentWithRouterDecorator],
|
||||
args: {
|
||||
className: 'RawLink',
|
||||
href: '/test',
|
||||
children: 'Raw Link',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof RawLink>;
|
||||
const clickJestFn = jest.fn();
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onClick: clickJestFn,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
await expect(clickJestFn).toHaveBeenCalledTimes(0);
|
||||
const link = canvas.getByRole('link');
|
||||
await userEvent.click(link);
|
||||
|
||||
await expect(clickJestFn).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,37 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/testing-library';
|
||||
|
||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||
|
||||
import { RoundedLink } from '../RoundedLink';
|
||||
|
||||
const meta: Meta<typeof RoundedLink> = {
|
||||
title: 'UI/Link/RoundedLink',
|
||||
component: RoundedLink,
|
||||
decorators: [ComponentWithRouterDecorator],
|
||||
args: {
|
||||
href: '/test',
|
||||
children: 'Rounded chip',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof RoundedLink>;
|
||||
const clickJestFn = jest.fn();
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onClick: clickJestFn,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
await expect(clickJestFn).toHaveBeenCalledTimes(0);
|
||||
const link = canvas.getByRole('link');
|
||||
await userEvent.click(link);
|
||||
|
||||
await expect(clickJestFn).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,52 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { jest } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/testing-library';
|
||||
|
||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||
|
||||
import { LinkType, SocialLink } from '../SocialLink';
|
||||
|
||||
const meta: Meta<typeof SocialLink> = {
|
||||
title: 'UI/Link/SocialLink',
|
||||
component: SocialLink,
|
||||
decorators: [ComponentWithRouterDecorator],
|
||||
args: {
|
||||
href: '/test',
|
||||
children: 'Social Link',
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SocialLink>;
|
||||
const clickJestFn = jest.fn();
|
||||
|
||||
const linkedin: LinkType = LinkType.LinkedIn;
|
||||
const twitter: LinkType = LinkType.Twitter;
|
||||
|
||||
export const LinkedIn: Story = {
|
||||
args: {
|
||||
href: '/LinkedIn',
|
||||
children: 'LinkedIn',
|
||||
onClick: clickJestFn,
|
||||
type: linkedin,
|
||||
},
|
||||
};
|
||||
|
||||
export const Twitter: Story = {
|
||||
args: {
|
||||
href: '/Twitter',
|
||||
children: 'Twitter',
|
||||
onClick: clickJestFn,
|
||||
type: twitter,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
await expect(clickJestFn).toHaveBeenCalledTimes(0);
|
||||
const link = canvas.getByRole('link');
|
||||
await userEvent.click(link);
|
||||
|
||||
await expect(clickJestFn).toHaveBeenCalledTimes(1);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user