From b0fcedc089428f6aa54bcb974ea52a46764c1195 Mon Sep 17 00:00:00 2001 From: pietro-maximoff <pietro.maxim.official@protonmail.com> Date: Tue, 21 Nov 2023 12:50:51 +0100 Subject: [PATCH] SOV-3389: Context Link component --- .../ContextLink/ContextLink.module.css | 8 ++++ .../ContextLink/ContextLink.stories.tsx | 48 +++++++++++++++++++ .../ContextLink/ContextLink.test.tsx | 41 ++++++++++++++++ .../2_molecules/ContextLink/ContextLink.tsx | 32 +++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 packages/ui/src/2_molecules/ContextLink/ContextLink.module.css create mode 100644 packages/ui/src/2_molecules/ContextLink/ContextLink.stories.tsx create mode 100644 packages/ui/src/2_molecules/ContextLink/ContextLink.test.tsx create mode 100644 packages/ui/src/2_molecules/ContextLink/ContextLink.tsx diff --git a/packages/ui/src/2_molecules/ContextLink/ContextLink.module.css b/packages/ui/src/2_molecules/ContextLink/ContextLink.module.css new file mode 100644 index 000000000..491031dcb --- /dev/null +++ b/packages/ui/src/2_molecules/ContextLink/ContextLink.module.css @@ -0,0 +1,8 @@ +.link { + @apply text-gray-10 text-base font-semibold leading-5 cursor-pointer + underline-offset-[0.4rem] underline decoration-gray-30 decoration-dashed decoration-1; +} + +.link:hover { + @apply text-gray-30; +} diff --git a/packages/ui/src/2_molecules/ContextLink/ContextLink.stories.tsx b/packages/ui/src/2_molecules/ContextLink/ContextLink.stories.tsx new file mode 100644 index 000000000..6f9e5f922 --- /dev/null +++ b/packages/ui/src/2_molecules/ContextLink/ContextLink.stories.tsx @@ -0,0 +1,48 @@ +import { Story } from '@storybook/react'; + +import React, { ComponentProps } from 'react'; + +import { ContextLink } from './ContextLink'; + +export default { + title: 'Molecule/ContextLink', + component: ContextLink, +}; + +const Template: Story<ComponentProps<typeof ContextLink>> = args => ( + <div className="mt-20 flex justify-center"> + <ContextLink {...args} /> + </div> +); + +export const Basic = Template.bind({}); +Basic.args = { + children: <div>Up to 8.55% APR</div>, + tooltipContent: ( + <div> + <p>Before liquidity mining rewards: 2%</p> + <p>After liquidity mining rewards: 8.55%</p> + </div> + ), +}; +Basic.argTypes = { + tooltipContent: { + control: 'text', + description: + 'The content of the context link tooltip. Can be text, other components, or HTML elements.', + }, + children: { + control: 'text', + description: + 'The content of the context link. Can be text, other components, or HTML elements.', + }, + className: { + control: 'text', + description: 'The class to apply to the context link', + }, + dataAttribute: { + control: 'text', + description: + 'The data id to apply as HTML attribute to this component instance. This should be unique per component instance on the page', + }, +}; diff --git a/packages/ui/src/2_molecules/ContextLink/ContextLink.test.tsx b/packages/ui/src/2_molecules/ContextLink/ContextLink.test.tsx new file mode 100644 index 000000000..fc9932d04 --- /dev/null +++ b/packages/ui/src/2_molecules/ContextLink/ContextLink.test.tsx @@ -0,0 +1,41 @@ +import { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import React from 'react'; + +import { ContextLink } from './ContextLink'; + +describe('ContextLink', () => { + it('should render children and show tooltip on hover', () => { + const { getByText } = render( + <ContextLink tooltipContent="Tooltip">Link</ContextLink>, + ); + const link = getByText('Link'); + userEvent.hover(link); + const tooltip = getByText('Tooltip'); + expect(tooltip).toBeInTheDocument(); + }); + + it('should render tooltip with a custom class', () => { + const { getByText } = render( + <ContextLink tooltipContent="Tooltip" className="custom-class"> + Link + </ContextLink>, + ); + const link = getByText('Link'); + const classes = link.getAttribute('class'); + expect(classes).toContain('custom-class'); + }); + + it('should render tooltip with a data attribute', () => { + const { getByText, getByTestId } = render( + <ContextLink tooltipContent="Tooltip" dataAttribute="tooltip-data"> + Link + </ContextLink>, + ); + const link = getByText('Link'); + userEvent.hover(link); + const tooltip = getByTestId('tooltip-data'); + expect(tooltip).toBeInTheDocument(); + }); +}); diff --git a/packages/ui/src/2_molecules/ContextLink/ContextLink.tsx b/packages/ui/src/2_molecules/ContextLink/ContextLink.tsx new file mode 100644 index 000000000..529424a87 --- /dev/null +++ b/packages/ui/src/2_molecules/ContextLink/ContextLink.tsx @@ -0,0 +1,32 @@ +import React, { FC, ReactNode } from 'react'; + +import classNames from 'classnames'; + +import { Tooltip } from '../Tooltip'; +import styles from './ContextLink.module.css'; + +export type ContextLinkProps = { + /** + * The content of the context link. + **/ + children: ReactNode; + tooltipContent: ReactNode; + className?: string; + dataAttribute?: string; +}; + +export const ContextLink: FC<ContextLinkProps> = ({ + children, + tooltipContent, + className, + dataAttribute, +}) => ( + <Tooltip + content={tooltipContent} + className={classNames(styles.link, className)} + tooltipClassName={styles.tooltip} + dataAttribute={dataAttribute} + > + <div>{children}</div> + </Tooltip> +);