Skip to content

Commit

Permalink
update token and token base to css modules
Browse files Browse the repository at this point in the history
  • Loading branch information
randall-krauskopf authored Nov 13, 2024
1 parent 536d7ab commit 16e847e
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 43 deletions.
21 changes: 21 additions & 0 deletions packages/react/src/Token/Token.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.Token {
max-width: 100%;
color: var(--fgColor-muted);
background-color: var(--bgColor-neutral-muted);
border-color: var(--borderColor-muted);
border-style: 'solid';
}

.Token[data-interactive='true']:hover {
color: var(--fgColor-default);
background-color: var(--bgColor-neutral-muted);
box-shadow: var(--shadow-resting-medium);
}

.Token[data-is-selected='true'] {
color: var(--fgColor-default);
}

.Token[data-is-remove-btn='true'] {
padding-right: 0;
}
39 changes: 15 additions & 24 deletions packages/react/src/Token/Token.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type {MouseEventHandler} from 'react'
import React, {forwardRef} from 'react'
import Box from '../Box'
import type {BetterSystemStyleObject, SxProp} from '../sx'
import {merge} from '../sx'
import type {SxProp} from '../sx'
import {defaultSxProp} from '../utils/defaultSxProp'
import type {TokenBaseProps} from './TokenBase'
import TokenBase, {defaultTokenSize, isTokenInteractive} from './TokenBase'
import RemoveTokenButton from './_RemoveTokenButton'
import TokenTextContainer from './_TokenTextContainer'
import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic'
import VisuallyHidden from '../_VisuallyHidden'
import {useFeatureFlag} from '../FeatureFlags'

import classes from './Token.module.css'
import {clsx} from 'clsx'

// Omitting onResize and onResizeCapture because seems like React 18 types includes these menthod in the expansion but React 17 doesn't.
// TODO: This is a temporary solution until we figure out why these methods are causing type errors.
Expand All @@ -20,6 +23,8 @@ export interface TokenProps extends TokenBaseProps, SxProp {
leadingVisual?: React.ElementType
}

const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team'

const tokenBorderWidthPx = 1

const LeadingVisualContainer: React.FC<React.PropsWithChildren<Pick<TokenBaseProps, 'size'>>> = ({children, size}) => (
Expand All @@ -35,6 +40,8 @@ const LeadingVisualContainer: React.FC<React.PropsWithChildren<Pick<TokenBasePro
)

const Token = forwardRef((props, forwardedRef) => {
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)

const {
as,
onRemove,
Expand All @@ -45,7 +52,8 @@ const Token = forwardRef((props, forwardedRef) => {
hideRemoveButton,
href,
onClick,
sx: sxProp = defaultSxProp,
sx = defaultSxProp,
className,
...rest
} = props
const hasMultipleActionTargets = isTokenInteractive(props) && Boolean(onRemove) && !hideRemoveButton
Expand All @@ -58,38 +66,21 @@ const Token = forwardRef((props, forwardedRef) => {
href,
onClick,
}
const sx = merge<BetterSystemStyleObject>(
{
backgroundColor: 'neutral.subtle',
borderColor: props.isSelected ? 'fg.default' : 'border.subtle',
borderStyle: 'solid',
borderWidth: `${tokenBorderWidthPx}px`,
color: props.isSelected ? 'fg.default' : 'fg.muted',
maxWidth: '100%',
paddingRight: !(hideRemoveButton || !onRemove) ? 0 : undefined,
...(isTokenInteractive(props)
? {
'&:hover': {
backgroundColor: 'neutral.muted',
boxShadow: 'shadow.medium',
color: 'fg.default',
},
}
: {}),
},
sxProp,
)

return (
<TokenBase
onRemove={onRemove}
id={id?.toString()}
className={clsx(enabled && className, classes.Token)}
text={text}
size={size}
sx={sx}
data-is-selected={props.isSelected}
data-is-remove-btn={!(hideRemoveButton || !onRemove)}
{...(!hasMultipleActionTargets ? interactiveTokenProps : {})}
{...rest}
ref={forwardedRef}
style={{borderWidth: `${tokenBorderWidthPx}px`}}
>
{LeadingVisual ? (
<LeadingVisualContainer size={size}>
Expand Down
60 changes: 60 additions & 0 deletions packages/react/src/Token/TokenBase.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
.TokenBase {
position: relative;
display: inline-flex;
font-family: inherit;
font-weight: var(--base-text-weight-semibold);
text-decoration: none;
white-space: nowrap;
border-radius: var(--borderRadius-full);
align-items: center;
}

.TokenBase[data-cursor-is-interactive='true'] {
cursor: pointer;
}

.TokenBase[data-cursor-is-interactive='false'] {
cursor: auto;
}

.TokenBase[data-size='small'] {
width: auto;
height: 16px;
padding-right: var(--base-size-4);
padding-left: var(--base-size-4);
font-size: var(--text-body-size-small);
/* stylelint-disable-next-line primer/typography */
line-height: 16px;
}

.TokenBase[data-size='medium'] {
width: auto;
height: 20px;
padding-right: var(--base-size-8);
padding-left: var(--base-size-8);
font-size: var(--text-body-size-small);
/* stylelint-disable-next-line primer/typography */
line-height: 20px;
}

.TokenBase[data-size='large'] {
width: auto;
height: 24px;
padding-right: var(--base-size-8);
padding-left: var(--base-size-8);
font-size: var(--text-body-size-small);
/* stylelint-disable-next-line primer/typography */
line-height: 24px;
}

.TokenBase[data-size='xlarge'] {
width: auto;
height: 32px;
padding-top: 0;
padding-right: var(--base-size-16);
padding-bottom: 0;
padding-left: var(--base-size-16);
font-size: var(--text-body-size-medium);
/* stylelint-disable-next-line primer/typography */
line-height: 32px;
}
52 changes: 33 additions & 19 deletions packages/react/src/Token/TokenBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@ import type {ComponentProps, KeyboardEvent} from 'react'
import React from 'react'
import styled from 'styled-components'
import {variant} from 'styled-system'
import {clsx} from 'clsx'
import {get} from '../constants'
import type {SxProp} from '../sx'
import sx from '../sx'
import type {ForwardRefComponent as PolymorphicForwardRefComponent} from '../utils/polymorphic'
import {useFeatureFlag} from '../FeatureFlags'
import classes from './TokenBase.module.css'
import {toggleStyledComponent} from '../internal/utils/toggleStyledComponent'

export type TokenSizeKeys = 'small' | 'medium' | 'large' | 'xlarge'

Expand Down Expand Up @@ -112,26 +116,34 @@ const variants = variant<
},
})

const StyledTokenBase = styled.span<
{
size?: TokenSizeKeys
} & SxProp
>`
align-items: center;
border-radius: 999px;
cursor: ${props => (isTokenInteractive(props) ? 'pointer' : 'auto')};
display: inline-flex;
font-weight: ${get('fontWeights.bold')};
font-family: inherit;
text-decoration: none;
position: relative;
white-space: nowrap;
${variants}
${sx}
`
const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_team'

const StyledTokenBase = toggleStyledComponent(
CSS_MODULES_FEATURE_FLAG,
'span',
styled.span<
{
size?: TokenSizeKeys
} & SxProp
>`
align-items: center;
border-radius: 999px;
cursor: ${props => (isTokenInteractive(props) ? 'pointer' : 'auto')};
display: inline-flex;
font-weight: ${get('fontWeights.bold')};
font-family: inherit;
text-decoration: none;
position: relative;
white-space: nowrap;
${variants}
${sx}
`,
)

const TokenBase = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | HTMLSpanElement | undefined, TokenBaseProps>(
({onRemove, onKeyDown, id, size = defaultTokenSize, ...rest}, forwardedRef) => {
({onRemove, onKeyDown, id, className, size = defaultTokenSize, ...rest}, forwardedRef) => {
const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG)

return (
<StyledTokenBase
onKeyDown={(event: KeyboardEvent<HTMLSpanElement & HTMLAnchorElement & HTMLButtonElement>) => {
Expand All @@ -141,10 +153,12 @@ const TokenBase = React.forwardRef<HTMLButtonElement | HTMLAnchorElement | HTMLS
onRemove()
}
}}
className={clsx(enabled && classes.TokenBase, className)}
data-cursor-is-interactive={isTokenInteractive(rest)}
data-size={size}
id={id?.toString()}
size={size}
{...rest}
// @ts-expect-error TokenBase wants Anchor, Button, and Span refs
ref={forwardedRef}
/>
)
Expand Down

0 comments on commit 16e847e

Please sign in to comment.