Skip to content

Commit

Permalink
♻️ Refacto link
Browse files Browse the repository at this point in the history
  • Loading branch information
LEGRELLE, Félix committed Dec 20, 2024
1 parent 3b26dbb commit ddefd33
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 188 deletions.
13 changes: 4 additions & 9 deletions examples/react-template/screens/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import { IconName, Link, Section, Text, Title, TitleLevels } from '@trilogy-ds/react/components'
import { Divider } from '@trilogy-ds/react'
import { Link, Section, Text, Title, TitleLevels } from '@trilogy-ds/react/components'
import { Icon, IconName } from '@trilogy-ds/react'

export const LinkScreen = (): JSX.Element => {
return (
Expand All @@ -16,14 +16,9 @@ export const LinkScreen = (): JSX.Element => {
External link
</Link>
<Title level={TitleLevels.THREE}>Link with icon</Title>
<Link href='https://google.com' blank iconName={IconName.ARROW_RIGHT}>
<Link href='https://google.com' blank>
External link
</Link>

<Divider />

<Link href='https://example.com' iconName={IconName.SEARCH} data-testid={'test-icon'}>
Example
<Icon name={IconName.ARROW_RIGHT} />
</Link>
</Section>
)
Expand Down
75 changes: 15 additions & 60 deletions packages/react/components/link/Link.native.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import * as React from 'react'
import { Linking, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import { LinkProps } from './LinkProps'
import { TypographyAlign } from '@/objects'
import { getColorStyle, TrilogyColor } from '@/objects/facets/Color'
import { TextLevels } from '@/components/text'
import { Icon } from '@/components/icon'
import { Spacer, SpacerSize } from '@/components/spacer'
import { ComponentName } from '@/components/enumsComponentsName'

/**
Expand All @@ -16,55 +12,24 @@ import { ComponentName } from '@/components/enumsComponentsName'
* @param children {React.ReactNode}
* @param testId {string} id for test
* @param accessibilityLabel {string}
* @param inline {boolean} If link is inside paragraphe
* @param iconName {IconName} Adding Icon Link
* @param inverted {boolean} Inverted link
*/
const Link = ({
children,
to,
onClick,
testId,
accessibilityLabel,
inline,
iconName,
inverted,
...others
}: LinkProps): JSX.Element => {
const linkLevels = (level: TextLevels) => {
return (
(level && level == TextLevels.ONE && 16) ||
(level && level == TextLevels.TWO && 14) ||
(level && level == TextLevels.THREE && 12) ||
(level && level == TextLevels.FOUR && 10) ||
10
)
}

const getHeightLinkAndroid = (level: TextLevels) => {
return (
(level && level == TextLevels.ONE && 20) ||
(level && level == TextLevels.TWO && 18) ||
(level && level == TextLevels.THREE && 15) ||
(level && level == TextLevels.FOUR && 13) ||
14
)
}
const Link = ({ children, to, onClick, testId, accessibilityLabel, inverted, ...others }: LinkProps): JSX.Element => {

const styles = StyleSheet.create({
linkAlignement: {
alignSelf: 'baseline',
},
container: {
padding: inline ? 4 : 8,
marginTop: inline ? -4 : 0,
marginBottom: inline ? -3 : -10,
paddingLeft: inline ? 4 : 0,
paddingRight: inline ? 4 : 0,
padding: 8,
marginTop: 0,
marginBottom: -10,
paddingLeft: 0,
paddingRight: 0,
},
androidContainer: {
paddingLeft: inline ? 2 : 0,
paddingRight: inline ? 2 : 0,
paddingLeft: 0,
paddingRight: 0,
},
link: {
color: (inverted && getColorStyle(TrilogyColor.BACKGROUND)) || getColorStyle(TrilogyColor.MAIN),
Expand Down Expand Up @@ -122,23 +87,13 @@ const Link = ({
}
}}
>
{iconName ? (
<View style={styles.iconView}>
<Text accessibilityLabel={accessibilityLabel} style={[styles.link]} {...others}>
{children}
</Text>
<Spacer size={SpacerSize.ONE} horizontal />
<Icon color={TrilogyColor.MAIN} name={iconName} size='small' />
</View>
) : (
<Text
accessibilityLabel={accessibilityLabel}
style={Platform.OS === 'android' ? [styles.androidLink] : [styles.link]}
{...others}
>
{children}
</Text>
)}
<Text
accessibilityLabel={accessibilityLabel}
style={Platform.OS === 'android' ? [styles.androidLink] : [styles.link]}
{...others}
>
{children}
</Text>
</TouchableOpacity>
) : (
<TouchableOpacity
Expand Down
59 changes: 26 additions & 33 deletions packages/react/components/link/Link.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,53 @@
import * as React from "react";
import * as React from 'react'

import { Meta, Story } from "@storybook/react";
import Link from "./Link";
import { LinkProps } from "./LinkProps";
import { Divider } from "../divider";
import { Text } from "../text";
import { IconName } from "../icon";
import { Meta, Story } from '@storybook/react'
import Link from './Link'
import { LinkProps } from './LinkProps'
import { Divider } from '../divider'
import { Text } from '../text'

export default {
title: "Components/Link",
title: 'Components/Link',
component: Link,
} as Meta;
} as Meta

export const Base: Story<LinkProps> = (args) => (
<>
<Link {...args}> Mot de passe oublié ?</Link>
<Divider />
<Text>
Je suis dans un paragraphe et ceci est un{" "}
<Link inline>lien standard</Link> tandis que ceci est un
<Link inline> lien standard non souligné</Link>. ou bien
<Link inline>celui-ci non souligné</Link>.
Je suis dans un paragraphe et ceci est un <Link markup="span">lien standard</Link>
</Text>
</>
);
)

export const DansUnParagraphe: Story<LinkProps> = (args) => (
<Text>
Je suis dans un paragraphe et ceci est un{" "}
<Link {...args}>lien standard</Link> inline.
Je suis dans un paragraphe et ceci est un <Link {...args}>lien standard</Link> inline.
</Text>
);
)
DansUnParagraphe.args = {
inline: true,
};
markup: 'span',
}

export const LiensVersPageExterne: Story<LinkProps> = (args) => (
<Link {...args}>En savoir plus</Link>
);
export const LiensVersPageExterne: Story<LinkProps> = (args) => <Link {...args}>En savoir plus</Link>
LiensVersPageExterne.args = {
iconName: IconName.NEW_TABBED_PAGE,
href: "_blank",
};
blank: true,
href: 'https://github.com/BouyguesTelecom/trilogy',
}

export const LienAutonome: Story<LinkProps> = (args) => (
<Link {...args}>Mot de passe oublié</Link>
);
export const LienAutonome: Story<LinkProps> = (args) => <Link {...args}>Mot de passe oublié</Link>
LienAutonome.args = {
href: "_blank",
};
href: 'https://github.com/BouyguesTelecom/trilogy'

blank: true,
}

export const Inverted: Story<LinkProps> = (args) => (
<div style={{ backgroundColor: "#25465f", padding: 10 }}>
<div style={{ backgroundColor: '#25465f', padding: 10 }}>
<Link {...args}> Mot de passe oublié ?</Link>
</div>
);
)
Inverted.args = {
inverted: true,
};
}
93 changes: 23 additions & 70 deletions packages/react/components/link/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as React from 'react'
import clsx from 'clsx'
import { LinkProps } from './LinkProps'
import { has, is } from '@/services/classify'
import { Icon, IconSize } from '@/components/icon'
import { is } from '@/services/classify'
import { hashClass } from '@/helpers'
import { useTrilogyContext } from '@/context'

Expand All @@ -15,7 +14,6 @@ import { useTrilogyContext } from '@/context'
* @param title {string} Title attribute
* @param onClick {Function} onClick Event
* @param accessibilityLabel {string} Accessibility label
* @param iconName {IconName} Adding Icon Link
* @param inverted {boolean} Inverted link
* @param others
* - -------------------------- WEB PROPERTIES -------------------------------
Expand All @@ -27,75 +25,30 @@ import { useTrilogyContext } from '@/context'
*/

const Link = ({
children,
className,
id,
to,
href,
onClick,
accessibilityLabel,
routerLink,
iconName,
inverted,
blank,
title,
...others
}: LinkProps): JSX.Element => {
children,
className,
accessibilityLabel,
markup: LinkComponent = 'a',
inverted,
blank,
...others
}: LinkProps): JSX.Element => {
const { styled } = useTrilogyContext()

const classes = hashClass(styled, clsx('link', iconName && has('icon'), inverted && is('inverted'), className))

if (routerLink && to) {
const RouterLink = (routerLink ? routerLink : 'a') as React.ElementType

const RouterLinkTrilogy = (): JSX.Element => {
return (
<RouterLink
id={id}
aria-label={accessibilityLabel}
onClick={onClick && onClick}
className={hashClass(styled, clsx(classes))}
to={to || ''}
{...(blank && {
target: '_blank',
})}
{...others}
>
{children}
</RouterLink>
)
}

return <RouterLinkTrilogy />
}

const LinkTrilogy = (): JSX.Element => {
return (
<a
id={id}
aria-label={accessibilityLabel}
onClick={onClick && onClick}
className={classes}
title={title}
href={href}
{...(blank && {
target: '_blank',
})}
{...others}
>
{iconName ? (
<>
<span>{children}</span>
<Icon name={iconName} size={IconSize.SMALL} />
</>
) : (
children
)}
</a>
)
}

return <LinkTrilogy />
const classes = hashClass(styled, clsx('link', inverted && is('inverted'), className))

return (
<LinkComponent
aria-label={accessibilityLabel}
className={classes}
{...(blank && {
target: '_blank',
})}
{...others}
>
{children}
</LinkComponent>
)
}

export default Link
5 changes: 1 addition & 4 deletions packages/react/components/link/LinkProps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { IconName, IconNameValues } from '../../components/icon'
import { Accessibility, Clickable, Dev } from '../../objects/facets'
import { CommonProps } from '../../objects/facets/CommonProps'

Expand All @@ -9,9 +8,7 @@ export interface LinkProps extends Accessibility, Clickable, Dev, CommonProps {
children?: React.ReactNode
to?: string
href?: string
routerLink?: React.ElementType
iconName?: IconName | IconNameValues
inline?: boolean
markup?: React.ElementType
inverted?: boolean
blank?: boolean
title?: string
Expand Down
13 changes: 1 addition & 12 deletions packages/react/components/link/test/link.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,10 @@ describe('Link component', () => {
expect(handleClick).toHaveBeenCalled()
})

test('displays an icon when iconName is passed', async () => {
const { findByTestId } = render(
<Link href='https://example.com' iconName={IconName.SEARCH} data-testid={'test-icon'}>
Example
</Link>,
)
const icon = await findByTestId('test-icon')
expect(icon).toHaveClass('link has-icon')
expect(icon).toBeInTheDocument()
})

test('should have link with routerlink', () => {
const fn = jest.fn()
const { getByTestId } = render(
<Link onClick={fn} accessibilityLabel='label' data-testid='routerlink' routerLink={'a'} to='https://Example.com'>
<Link onClick={fn} accessibilityLabel='label' data-testid='routerlink' markup={'a'} to='https://Example.com'>
example
</Link>,
)
Expand Down

0 comments on commit ddefd33

Please sign in to comment.