Skip to content

Commit

Permalink
[C-3885] Migrate to harmony text-link (#7746)
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanjeffers authored Mar 1, 2024
1 parent 82dd8c5 commit 6d6117f
Show file tree
Hide file tree
Showing 36 changed files with 351 additions and 722 deletions.
4 changes: 1 addition & 3 deletions packages/harmony/src/components/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import type { ComponentType, SVGProps } from 'react'

import type { IconColors } from '../foundations/color/semantic'
import type { ShadowOptions } from '../foundations/shadows'
import { iconSizes } from '../foundations/spacing'

type IconSize = keyof typeof iconSizes
import { IconSize } from '../foundations/spacing'

type SVGBaseProps = SVGProps<SVGSVGElement>

Expand Down
13 changes: 10 additions & 3 deletions packages/harmony/src/components/text-link/TextLink.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Ref, forwardRef } from 'react'

import { useTheme } from '@emotion/react'
import { Slot } from '@radix-ui/react-slot'

Expand All @@ -8,11 +10,12 @@ import type { TextLinkProps } from './types'
/**
* Also known as hyperlinks, these are words or phrases that can be clicked to navigate to a linked webpage.
*/
export const TextLink = (props: TextLinkProps) => {
export const TextLink = forwardRef((props: TextLinkProps, ref: Ref<'a'>) => {
const {
asChild = false,
children,
variant = 'default',
isActive,
isExternal = false,
onClick,
textVariant,
Expand All @@ -21,7 +24,7 @@ export const TextLink = (props: TextLinkProps) => {
...other
} = props

const { color } = useTheme()
const { color, spacing } = useTheme()

const variantColors = {
default: color.link.default,
Expand Down Expand Up @@ -53,14 +56,18 @@ export const TextLink = (props: TextLinkProps) => {

return (
<Text
ref={ref}
asChild
onClick={onClick}
tag='a'
css={{
display: 'inline-flex',
gap: spacing.s,
color: variantColors[variant],
textDecoration: 'none',
transition: 'none',
':hover': hoverStyles,
...(isActive && { ...hoverStyles, textDecoration: 'none' }),
...(showUnderline && hoverStyles)
}}
variant={textVariant}
Expand All @@ -78,4 +85,4 @@ export const TextLink = (props: TextLinkProps) => {
)}
</Text>
)
}
})
1 change: 1 addition & 0 deletions packages/harmony/src/components/text-link/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { TextLink } from './TextLink'
export type { TextLinkProps } from './types'
7 changes: 6 additions & 1 deletion packages/harmony/src/components/text-link/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { HTMLProps } from 'react'

import type { TextProps } from 'components/text/Text'

type TextLinkTextProps = Omit<TextProps, 'variant' | 'color'>
type TextLinkTextProps = Omit<TextProps<any>, 'variant' | 'color' | 'onClick'>

export type TextLinkProps = TextLinkTextProps &
Omit<
Expand Down Expand Up @@ -33,6 +33,11 @@ export type TextLinkProps = TextLinkTextProps &
*/
showUnderline?: boolean

/**
* When `true`, render link in active style (e.g. hover color)
*/
isActive?: boolean

/**
* Mark as true if the link destination is outside of the app. Causes the
* link to open in a new tab.
Expand Down
22 changes: 14 additions & 8 deletions packages/harmony/src/components/text/Text/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ export const Text = forwardRef(
tag,
asChild,
textAlign,
ellipses,
...other
} = props

const theme = useTheme()

const variantConfig = variant && variantStylesMap[variant]
const styles = {
const css = {
fontFamily: `'Avenir Next LT Pro', 'Helvetica Neue', Helvetica,
Arial, sans-serif`,
position: 'relative',
Expand All @@ -51,21 +52,26 @@ export const Text = forwardRef(
lineHeight: typography.lineHeight[variantConfig.lineHeight[size]],
// @ts-ignore
fontWeight: typography.weight[variantConfig.fontWeight[strength]],
...('css' in variantConfig && variantConfig.css),
...(shadow && {
textShadow: typography.shadow[shadow]
}),
textAlign
...('css' in variantConfig && variantConfig.css)
}),
...(shadow && {
textShadow: typography.shadow[shadow]
}),
textAlign,
...(ellipses && {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap'
})
}

// @ts-ignore
const variantTag = variant && variantTagMap[variant]?.[size]

const Tag: ElementType = asChild ? Slot : tag ?? variantTag ?? 'p'
const Tag: ElementType = asChild ? Slot : tag ?? variantTag ?? 'span'

return (
<Tag ref={ref} css={styles} {...other}>
<Tag ref={ref} css={css} {...other}>
{children}
</Tag>
)
Expand Down
1 change: 1 addition & 0 deletions packages/harmony/src/components/text/Text/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type BaseTextProps<TextComponentType extends ElementType = 'p'> = {
shadow?: TextShadow
asChild?: boolean
textAlign?: CSSProperties['textAlign']
ellipses?: boolean
}

export type TextProps<TextComponentType extends ElementType = 'p'> =
Expand Down
1 change: 1 addition & 0 deletions packages/harmony/src/foundations/spacing/spacing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,4 @@ export const iconSizes = {

export type Spacing = typeof spacing
export type SpacingOptions = keyof Spacing
export type IconSize = keyof typeof iconSizes
19 changes: 4 additions & 15 deletions packages/harmony/src/foundations/theme/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,10 @@
import type { ReactNode } from 'react'

import createCache from '@emotion/cache'
import {
CacheProvider,
ThemeProvider as EmotionThemeProvider
} from '@emotion/react'
import { ThemeProvider as EmotionThemeProvider } from '@emotion/react'

import { themes } from './theme'
import type { Theme } from './types'

const harmonyCache = createCache({
key: 'harmony',
prepend: true
})

type ThemeProviderProps = {
theme: Theme
children: ReactNode
Expand All @@ -23,10 +14,8 @@ export const ThemeProvider = (props: ThemeProviderProps) => {
const { children, theme } = props

return (
<CacheProvider value={harmonyCache}>
<EmotionThemeProvider theme={themes[theme]}>
{children}
</EmotionThemeProvider>
</CacheProvider>
<EmotionThemeProvider theme={themes[theme]}>
{children}
</EmotionThemeProvider>
)
}
5 changes: 4 additions & 1 deletion packages/web/src/components/artist/ArtistPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type ArtistPopoverProps = {
component?: 'div' | 'span'
onNavigateAway?: () => void
containerClassName?: string
className?: string
}

export const ArtistPopover = ({
Expand All @@ -53,7 +54,8 @@ export const ArtistPopover = ({
mouseEnterDelay = 0.5,
component: Component = 'div',
onNavigateAway,
containerClassName
containerClassName,
className
}: ArtistPopoverProps) => {
const [isPopupVisible, setIsPopupVisible] = useState(false)
const creator = useSelector((state: CommonState) =>
Expand Down Expand Up @@ -106,6 +108,7 @@ export const ArtistPopover = ({
return (
<Component
className={cn(
className,
styles.popoverContainer,
'artistPopover',
containerClassName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@
}

.titleHeader {
color: var(--neutral);
font-size: var(--font-4xl);
line-height: 40px;
font-weight: var(--font-bold);
transition: opacity var(--calm), color var(--quick);
}

Expand All @@ -106,35 +102,6 @@
opacity: 1;
}

.artistWrapper {
color: var(--neutral-light-4);
font-size: var(--font-m);
font-weight: var(--font-demi-bold);
display: flex;
user-select: none;
position: relative;
}

.artistWrapper :global(.artistPopover) {
display: inline;
}

.artistWrapper .artist {
display: inline;
color: var(--neutral);
font-size: var(--font-m);
font-weight: var(--font-demi-bold);
line-height: 18px;
min-height: 18px;
padding-left: 4px;
}

.artistWrapper .artist:hover {
color: var(--primary);
cursor: pointer;
text-decoration: underline;
}

.actionButtons {
margin-top: var(--unit-4);
display: flex;
Expand Down
49 changes: 31 additions & 18 deletions packages/web/src/components/collection/desktop/CollectionHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { ChangeEvent, useCallback, useState } from 'react'

import { useEditPlaylistModal } from '@audius/common/store'
import { formatSecondsAsText, formatDate } from '@audius/common/utils'
import { IconFilter, IconVisibilityHidden, IconPencil } from '@audius/harmony'
import {
Text,
IconFilter,
IconVisibilityHidden,
IconPencil,
Flex
} from '@audius/harmony'
import cn from 'classnames'

import { Input } from 'components/input'
Expand Down Expand Up @@ -122,26 +128,33 @@ export const CollectionHeader = (props: CollectionHeaderProps) => {
className={cn(styles.title, { [styles.editableTitle]: isOwner })}
onClick={isOwner ? handleClickEditTitle : undefined}
>
<h1 className={cn(styles.titleHeader, fadeIn)}>{title}</h1>
<Text
variant='heading'
size='xl'
className={cn(styles.titleHeader, fadeIn)}
>
{title}
</Text>
{isOwner ? <IconPencil className={styles.editIcon} /> : null}
{isLoading ? <Skeleton className={styles.skeleton} /> : null}
</TitleComponent>
{artistName && (
<div className={styles.artistWrapper}>
<div className={cn(fadeIn)}>
<span>By </span>
<UserLink
userId={userId}
strength='strong'
popover
textAs='h2'
/>
</div>
{isLoading && (
<Skeleton className={styles.skeleton} width='60%' />
)}
</div>
)}
<Flex>
{artistName ? (
<Text
variant='title'
strength='weak'
tag='h2'
className={cn(fadeIn)}
>
<Text color='subdued'>By </Text>
<UserLink userId={userId} popover />
</Text>
) : null}
{isLoading ? (
<Skeleton className={styles.skeleton} width='60%' />
) : null}
</Flex>

<div className={cn(styles.infoLabelsSection, fadeIn)}>
{modified && (
<InfoLabel
Expand Down
25 changes: 5 additions & 20 deletions packages/web/src/components/link/ExternalLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { MouseEvent, useCallback } from 'react'
import { Name } from '@audius/common/models'
import { useLeavingAudiusModal } from '@audius/common/store'
import { isAllowedExternalLink } from '@audius/common/utils'
import { TextLink, TextLinkProps } from '@audius/harmony'

import { make, useRecord } from 'common/store/analytics/actions'

import { Link, LinkProps } from './Link'

type ExternalLinkProps = LinkProps & {
type ExternalLinkProps = Omit<TextLinkProps, 'href'> & {
source?: 'profile page' | 'track page' | 'collection page'
ignoreWarning?: boolean
}
Expand All @@ -31,27 +30,13 @@ export const ExternalLink = (props: ExternalLinkProps) => {
})
)
}
if (
typeof to === 'string' &&
!ignoreWarning &&
!isAllowedExternalLink(to)
) {
if (to && !ignoreWarning && !isAllowedExternalLink(to)) {
event.preventDefault()
openLeavingAudiusModal({ link: to as string })
openLeavingAudiusModal({ link: to })
}
},
[onClick, record, source, openLeavingAudiusModal, to, ignoreWarning]
)

return (
// @ts-expect-error
<Link
tag='a'
href={to as string}
onClick={handleClick}
{...other}
target='_blank'
rel='noopener noreferrer'
/>
)
return <TextLink isExternal href={to} onClick={handleClick} {...other} />
}
11 changes: 0 additions & 11 deletions packages/web/src/components/link/Link.module.css

This file was deleted.

Loading

0 comments on commit 6d6117f

Please sign in to comment.