diff options
| author | Oliver <oliver@mohlin.dev> | 2025-05-26 13:35:22 +0200 |
|---|---|---|
| committer | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-05-27 21:33:16 +0200 |
| commit | 03a8ec21927cbcb9ef8bb5c855bddafff3c4af47 (patch) | |
| tree | 81cfbe810c40c57fc8c28c05c0ee54f9fe6a72b7 | |
| parent | c758efedaabd146b7ee0aa5b272d72bc1a72a2e5 (diff) | |
| download | mullvadvpn-03a8ec21927cbcb9ef8bb5c855bddafff3c4af47.tar.xz mullvadvpn-03a8ec21927cbcb9ef8bb5c855bddafff3c4af47.zip | |
Refactor Link to better handle icon alignment
3 files changed, 53 insertions, 47 deletions
diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/Link.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/Link.tsx index 40a598b666..5e1bef8d5f 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/Link.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/Link.tsx @@ -1,62 +1,66 @@ import React from 'react'; -import styled from 'styled-components'; +import styled, { css } from 'styled-components'; -import { Colors, colors, Radius } from '../../foundations'; -import { Text, TextProps } from '../typography'; -import { LinkIcon } from './components'; +import { Colors, colors, Radius, Typography } from '../../foundations'; +import { TransientProps } from '../../types'; +import { LinkIcon, LinkText, StyledIcon as StyledLinkIcon, StyledLinkText } from './components'; +import { useHoverColor } from './hooks'; +import { LinkProvider } from './LinkContext'; -export type LinkProps<T extends React.ElementType = 'a'> = TextProps<T> & { +type LinkBaseProps = { + variant?: Typography; + color?: Colors; onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void; }; -const StyledText = styled(Text)<{ - $hoverColor: Colors | undefined; -}>((props) => ({ - background: colors.transparent, - cursor: 'default', - textDecoration: 'none', - display: 'inline', +export type LinkProps = LinkBaseProps & + Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, keyof LinkBaseProps>; - '&&:hover': { - textDecorationLine: 'underline', - textUnderlineOffset: '2px', - color: props.$hoverColor, - }, - '&&:focus-visible': { - borderRadius: Radius.radius4, - outline: `2px solid ${colors.whiteAlpha60}`, - outlineOffset: '2px', - }, -})); - -const getHoverColor = (color: Colors | undefined) => { - switch (color) { - case 'whiteAlpha60': - return 'white'; - default: - return undefined; +const StyledLink = styled.a< + TransientProps<LinkProps> & { + $hoverColor?: Colors; } -}; +>(({ $hoverColor }) => { + return css` + cursor: default; + text-decoration: none; + display: inline; + width: fit-content; + + &&:hover > ${StyledLinkText} { + text-decoration-line: underline; + text-underline-offset: 2px; + color: ${$hoverColor}; + } + + &&:focus-visible > ${StyledLinkText} { + border-radius: ${Radius.radius4}; + outline: 2px solid ${colors.white}; + outline-offset: 2px; + } + + > ${StyledLinkIcon}:first-child:not(:only-child) { + margin-right: 2px; + } + > ${StyledLinkIcon}:last-child:not(:only-child) { + margin-left: 2px; + } + `; +}); -function Link<T extends React.ElementType = 'a'>({ - as: forwardedAs, - color, - ...props -}: LinkProps<T>) { - // If `as` is provided we need to pass it as `forwardedAs` for it to - // be correctly passed to the `Text` component. - const componentProps = forwardedAs ? { ...props, forwardedAs } : props; +function Link({ color, variant, children, ...props }: LinkProps) { + const hoverColor = useHoverColor(color); return ( - <StyledText - forwardedAs="a" - color={color} - $hoverColor={getHoverColor(color)} - {...componentProps} - /> + <LinkProvider variant={variant} color={color}> + <StyledLink $hoverColor={hoverColor} {...props}> + {children} + </StyledLink> + </LinkProvider> ); } const LinkNamespace = Object.assign(Link, { + Text: LinkText, Icon: LinkIcon, }); diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/components/LinkIcon.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/components/LinkIcon.tsx index 7af4b28045..3a82f11a4d 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/components/LinkIcon.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/components/LinkIcon.tsx @@ -5,8 +5,9 @@ import { Icon, IconProps } from '../../icon'; type LinkIconProps = IconProps; export const StyledIcon = styled(Icon)` - vertical-align: middle; - display: inline-flex; + vertical-align: text-bottom; + display: inline-block; + flex-shrink: 0; `; export function LinkIcon({ ...props }: LinkIconProps) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/index.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/index.ts new file mode 100644 index 0000000000..3db78f51f0 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/components/link/index.ts @@ -0,0 +1 @@ +export * from './Link'; |
